From 128d4e1c039250fb4bf2b82b676e4981e88b352d Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 16 Sep 2021 18:20:15 +0200 Subject: [PATCH] Added display option for fixed date header --- .../eu/faircode/email/FragmentMessages.java | 86 ++++++++++++------- .../eu/faircode/email/FragmentOptions.java | 2 +- .../email/FragmentOptionsDisplay.java | 19 +++- app/src/main/res/layout/fragment_messages.xml | 11 ++- .../res/layout/fragment_options_display.xml | 14 ++- app/src/main/res/values/strings.xml | 1 + 6 files changed, 97 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 17c25630a9..4d3558697c 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -304,6 +304,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. private boolean cards; private boolean date; + private boolean date_fixed; private boolean date_bold; private boolean threading; private boolean swipenav; @@ -426,6 +427,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. swipenav = prefs.getBoolean("swipenav", true); cards = prefs.getBoolean("cards", true); date = prefs.getBoolean("date", true); + date_fixed = (!date && prefs.getBoolean("date_fixed", false)); date_bold = prefs.getBoolean("date_bold", false); threading = (prefs.getBoolean("threading", true) || args.getBoolean("force_threading")); @@ -663,18 +665,42 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. rvMessage.addItemDecoration(itemDecorator); } + View inDate = view.findViewById(R.id.inDate); + TextView tvFixedDate = inDate.findViewById(R.id.tvDate); + View vSeparatorDate = inDate.findViewById(R.id.vSeparatorDate); + + String sort = prefs.getString("sort", "time"); + inDate.setVisibility(date_fixed && "time".equals(sort) ? View.INVISIBLE : View.GONE); + if (date_bold) + tvFixedDate.setTypeface(Typeface.DEFAULT_BOLD); + DividerItemDecoration dateDecorator = new DividerItemDecoration(getContext(), llm.getOrientation()) { @Override public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - for (int i = 0; i < parent.getChildCount(); i++) { + int count = parent.getChildCount(); + if (date_fixed) + if ("time".equals(adapter.getSort())) + inDate.setVisibility(count > 0 ? View.VISIBLE : View.INVISIBLE); + else + inDate.setVisibility(View.GONE); + + for (int i = 0; i < count; i++) { View view = parent.getChildAt(i); int pos = parent.getChildAdapterPosition(view); - View header = getView(view, parent, pos); - if (header != null) { - canvas.save(); - canvas.translate(0, parent.getChildAt(i).getTop() - header.getMeasuredHeight()); - header.draw(canvas); - canvas.restore(); + + if (i == 0 && date_fixed && "time".equals(adapter.getSort())) { + TupleMessageEx top = adapter.getItemAtPosition(pos); + tvFixedDate.setVisibility(top == null ? View.GONE : View.VISIBLE); + vSeparatorDate.setVisibility(top == null || cards ? View.GONE : View.VISIBLE); + tvFixedDate.setText(top == null ? null : getRelativeDate(top.received, parent.getContext())); + } else { + View header = getView(view, parent, pos); + if (header != null) { + canvas.save(); + canvas.translate(0, parent.getChildAt(i).getTop() - header.getMeasuredHeight()); + header.draw(canvas); + canvas.restore(); + } } } } @@ -690,7 +716,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } private View getView(View view, RecyclerView parent, int pos) { - if (!date || !SORT_DATE_HEADER.contains(adapter.getSort())) + if (!date || !SORT_DATE_HEADER.contains(adapter.getSort()) || date_fixed) return null; if (pos == NO_POSITION) @@ -716,7 +742,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. return null; } - View header = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_date, parent, false); + View header = inflater.inflate(R.layout.item_message_date, parent, false); TextView tvDate = header.findViewById(R.id.tvDate); tvDate.setTextSize(TypedValue.COMPLEX_UNIT_PX, Helper.getTextSize(parent.getContext(), adapter.getZoom())); if (date_bold) @@ -727,26 +753,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. vSeparatorDate.setVisibility(View.GONE); } - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date()); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - cal.add(Calendar.DAY_OF_MONTH, -1); - if (message.received <= cal.getTimeInMillis()) - tvDate.setText( - DateUtils.formatDateRange( - parent.getContext(), - message.received, - message.received, - FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_DATE)); - else - tvDate.setText( - DateUtils.getRelativeTimeSpanString( - message.received, - new Date().getTime(), - DAY_IN_MILLIS, 0)); + tvDate.setText(getRelativeDate(message.received, parent.getContext())); view.setContentDescription(tvDate.getText().toString()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) @@ -758,6 +765,26 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. return header; } + + CharSequence getRelativeDate(long time, Context context) { + Date now = new Date(); + Calendar cal = Calendar.getInstance(); + cal.setTime(now); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.add(Calendar.DAY_OF_MONTH, -1); + + if (time <= cal.getTimeInMillis()) + return DateUtils.formatDateRange(context, + time, time, + FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_DATE); + else + return DateUtils.getRelativeTimeSpanString( + time, now.getTime(), + DAY_IN_MILLIS, 0); + } }; rvMessage.addItemDecoration(dateDecorator); @@ -783,7 +810,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. boolean compact = prefs.getBoolean("compact", false); int zoom = prefs.getInt("view_zoom", compact ? 0 : 1); - String sort = prefs.getString("sort", "time"); boolean ascending = prefs.getBoolean( viewType == AdapterMessage.ViewType.THREAD ? "ascending_thread" : "ascending_list", false); boolean filter_duplicates = prefs.getBoolean("filter_duplicates", true); diff --git a/app/src/main/java/eu/faircode/email/FragmentOptions.java b/app/src/main/java/eu/faircode/email/FragmentOptions.java index 9de78c315b..a70c685799 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptions.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptions.java @@ -127,7 +127,7 @@ public class FragmentOptions extends FragmentBase { "send_pending", "startup", "cards", "beige", "tabular_card_bg", "shadow_unread", "portrait2", "portrait2c", "landscape", "nav_count", "navbar_colorize", - "indentation", "date", "date_bold", "threading", "threading_unread", + "indentation", "date", "date_fixed", "date_bold", "threading", "threading_unread", "highlight_unread", "highlight_color", "color_stripe", "avatars", "bimi", "gravatars", "favicons", "generated_icons", "identicons", "circular", "saturation", "brightness", "threshold", "email_format", "prefer_contact", "only_contact", "distinguish_contacts", "show_recipients", diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java b/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java index 721c2b5045..76c9d54fc0 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java @@ -64,6 +64,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer private SwitchCompat swTabularBackground; private SwitchCompat swShadow; private SwitchCompat swDate; + private SwitchCompat swDateFixed; private SwitchCompat swDateBold; private SwitchCompat swNavBarColorize; private SwitchCompat swPortrait2; @@ -154,7 +155,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer private final static String[] RESET_OPTIONS = new String[]{ "theme", "startup", "cards", "beige", "tabular_card_bg", "shadow_unread", - "date", "date_bold", + "date", "date_fixed", "date_bold", "portrait2", "portrait2c", "landscape", "nav_options", "nav_count", "navbar_colorize", "threading", "threading_unread", "indentation", "seekbar", "actionbar", "actionbar_color", "highlight_unread", "highlight_color", "color_stripe", @@ -188,6 +189,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer swTabularBackground = view.findViewById(R.id.swTabularCardBackground); swShadow = view.findViewById(R.id.swShadow); swDate = view.findViewById(R.id.swDate); + swDateFixed = view.findViewById(R.id.swDateFixed); swDateBold = view.findViewById(R.id.swDateBold); swPortrait2 = view.findViewById(R.id.swPortrait2); swPortrait2c = view.findViewById(R.id.swPortrait2c); @@ -334,7 +336,16 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { prefs.edit().putBoolean("date", checked).apply(); - swDateBold.setEnabled(checked); + swDateFixed.setEnabled(!checked); + swDateBold.setEnabled(checked || swDateFixed.isChecked()); + } + }); + + swDateFixed.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("date_fixed", checked).apply(); + swDateBold.setEnabled(swDate.isChecked() || checked); } }); @@ -1029,8 +1040,10 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer swTabularBackground.setEnabled(!swCards.isChecked()); swShadow.setEnabled(swCards.isChecked()); swDate.setChecked(prefs.getBoolean("date", true)); + swDateFixed.setChecked(prefs.getBoolean("date_fixed", false)); + swDateFixed.setEnabled(!swDate.isChecked()); swDateBold.setChecked(prefs.getBoolean("date_bold", false)); - swDateBold.setEnabled(swDate.isChecked()); + swDateBold.setEnabled(swDate.isChecked() || swDateFixed.isChecked()); swPortrait2.setChecked(prefs.getBoolean("portrait2", false)); swPortrait2c.setChecked(prefs.getBoolean("portrait2c", false) && !swPortrait2.isChecked()); swLandscape.setChecked(prefs.getBoolean("landscape", true)); diff --git a/app/src/main/res/layout/fragment_messages.xml b/app/src/main/res/layout/fragment_messages.xml index 3a11cfc8df..7ebb57cc4b 100644 --- a/app/src/main/res/layout/fragment_messages.xml +++ b/app/src/main/res/layout/fragment_messages.xml @@ -135,6 +135,15 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvHintSelect" /> + + + app:layout_constraintTop_toBottomOf="@id/inDate" /> + + Use card color as background color when using tabular style Use shadow for unread messages when using card style Group by date + Show fixed date header at the top Show date in bold Conversation threading Show number of unread messages in conversations