mirror of https://github.com/M66B/FairEmail.git
Added day headers, relative time
This commit is contained in:
parent
f721285d7c
commit
42357a257b
|
@ -79,6 +79,7 @@ import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -108,6 +109,8 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||||
|
|
||||||
|
import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
||||||
|
|
||||||
public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHolder> {
|
public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHolder> {
|
||||||
private Context context;
|
private Context context;
|
||||||
private LayoutInflater inflater;
|
private LayoutInflater inflater;
|
||||||
|
@ -141,11 +144,13 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
|
|
||||||
enum ViewType {UNIFIED, FOLDER, THREAD, SEARCH}
|
enum ViewType {UNIFIED, FOLDER, THREAD, SEARCH}
|
||||||
|
|
||||||
|
private static DateFormat tf = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT);
|
||||||
private static DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
|
private static DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG);
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder implements
|
public class ViewHolder extends RecyclerView.ViewHolder implements
|
||||||
View.OnClickListener, BottomNavigationView.OnNavigationItemSelectedListener {
|
View.OnClickListener, BottomNavigationView.OnNavigationItemSelectedListener {
|
||||||
private View itemView;
|
private View itemView;
|
||||||
|
private TextView tvDay;
|
||||||
private View vwColor;
|
private View vwColor;
|
||||||
private ImageView ivExpander;
|
private ImageView ivExpander;
|
||||||
private ImageView ivFlagged;
|
private ImageView ivFlagged;
|
||||||
|
@ -198,6 +203,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
|
|
||||||
private RecyclerView rvImage;
|
private RecyclerView rvImage;
|
||||||
|
|
||||||
|
private Group grpDay;
|
||||||
private Group grpAddress;
|
private Group grpAddress;
|
||||||
private Group grpHeaders;
|
private Group grpHeaders;
|
||||||
private Group grpAttachments;
|
private Group grpAttachments;
|
||||||
|
@ -212,6 +218,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
|
||||||
this.itemView = itemView.findViewById(R.id.clItem);
|
this.itemView = itemView.findViewById(R.id.clItem);
|
||||||
|
tvDay = itemView.findViewById(R.id.tvDay);
|
||||||
vwColor = itemView.findViewById(R.id.vwColor);
|
vwColor = itemView.findViewById(R.id.vwColor);
|
||||||
ivExpander = itemView.findViewById(R.id.ivExpander);
|
ivExpander = itemView.findViewById(R.id.ivExpander);
|
||||||
ivFlagged = itemView.findViewById(R.id.ivFlagged);
|
ivFlagged = itemView.findViewById(R.id.ivFlagged);
|
||||||
|
@ -278,6 +285,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
adapterImage = new AdapterImage(context, owner);
|
adapterImage = new AdapterImage(context, owner);
|
||||||
rvImage.setAdapter(adapterImage);
|
rvImage.setAdapter(adapterImage);
|
||||||
|
|
||||||
|
grpDay = itemView.findViewById(R.id.grpDay);
|
||||||
grpAddress = itemView.findViewById(R.id.grpAddress);
|
grpAddress = itemView.findViewById(R.id.grpAddress);
|
||||||
grpHeaders = itemView.findViewById(R.id.grpHeaders);
|
grpHeaders = itemView.findViewById(R.id.grpHeaders);
|
||||||
grpAttachments = itemView.findViewById(R.id.grpAttachments);
|
grpAttachments = itemView.findViewById(R.id.grpAttachments);
|
||||||
|
@ -285,8 +293,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
}
|
}
|
||||||
|
|
||||||
private void wire() {
|
private void wire() {
|
||||||
if (viewType == ViewType.THREAD) {
|
final View touch = (viewType == ViewType.THREAD && threading ? ivExpander : vwColor);
|
||||||
final View touch = (threading ? ivExpander : vwColor);
|
|
||||||
touch.setOnClickListener(this);
|
touch.setOnClickListener(this);
|
||||||
itemView.post(new Runnable() {
|
itemView.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -300,8 +307,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
itemView.setTouchDelegate(new TouchDelegate(rect, touch));
|
itemView.setTouchDelegate(new TouchDelegate(rect, touch));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else
|
|
||||||
itemView.setOnClickListener(this);
|
|
||||||
|
|
||||||
ivSnoozed.setOnClickListener(this);
|
ivSnoozed.setOnClickListener(this);
|
||||||
ivFlagged.setOnClickListener(this);
|
ivFlagged.setOnClickListener(this);
|
||||||
|
@ -376,6 +381,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
|
|
||||||
rvImage.setVisibility(View.GONE);
|
rvImage.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
grpDay.setVisibility(View.GONE);
|
||||||
grpAddress.setVisibility(View.GONE);
|
grpAddress.setVisibility(View.GONE);
|
||||||
ivAddContact.setVisibility(View.GONE);
|
ivAddContact.setVisibility(View.GONE);
|
||||||
grpHeaders.setVisibility(View.GONE);
|
grpHeaders.setVisibility(View.GONE);
|
||||||
|
@ -391,6 +397,34 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
|
|
||||||
pbLoading.setVisibility(View.GONE);
|
pbLoading.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if (textSize != 0) {
|
||||||
|
tvDay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
|
||||||
|
tvFrom.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
|
||||||
|
tvSubject.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean day;
|
||||||
|
TupleMessageEx prev = (position == 0 ? null : differ.getItem(position - 1));
|
||||||
|
if (prev == null)
|
||||||
|
day = true;
|
||||||
|
else {
|
||||||
|
Calendar cal0 = Calendar.getInstance();
|
||||||
|
Calendar cal1 = Calendar.getInstance();
|
||||||
|
cal0.setTimeInMillis(prev.received);
|
||||||
|
cal1.setTimeInMillis(message.received);
|
||||||
|
int day0 = cal0.get(Calendar.DAY_OF_YEAR);
|
||||||
|
int day1 = cal1.get(Calendar.DAY_OF_YEAR);
|
||||||
|
day = (day0 != day1);
|
||||||
|
}
|
||||||
|
if (day)
|
||||||
|
tvDay.setText(
|
||||||
|
DateUtils.getRelativeTimeSpanString(
|
||||||
|
message.received,
|
||||||
|
new Date().getTime(),
|
||||||
|
DAY_IN_MILLIS, 0));
|
||||||
|
grpDay.setVisibility(day ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
|
||||||
itemView.setAlpha(message.uid == null && !EntityFolder.OUTBOX.equals(message.folderType)
|
itemView.setAlpha(message.uid == null && !EntityFolder.OUTBOX.equals(message.folderType)
|
||||||
? Helper.LOW_LIGHT : 1.0f);
|
? Helper.LOW_LIGHT : 1.0f);
|
||||||
|
|
||||||
|
@ -496,7 +530,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
tvFrom.setText(MessageHelper.formatAddresses(outgoing ? message.to : message.from, !compact, false));
|
tvFrom.setText(MessageHelper.formatAddresses(outgoing ? message.to : message.from, !compact, false));
|
||||||
tvSize.setText(message.size == null ? null : Helper.humanReadableByteCount(message.size, true));
|
tvSize.setText(message.size == null ? null : Helper.humanReadableByteCount(message.size, true));
|
||||||
tvSize.setVisibility(message.size == null || message.content ? View.GONE : View.VISIBLE);
|
tvSize.setVisibility(message.size == null || message.content ? View.GONE : View.VISIBLE);
|
||||||
tvTime.setText(DateUtils.getRelativeTimeSpanString(context, message.received));
|
tvTime.setText(tf.format(message.received));
|
||||||
|
|
||||||
ivDraft.setVisibility(message.drafts > 0 ? View.VISIBLE : View.GONE);
|
ivDraft.setVisibility(message.drafts > 0 ? View.VISIBLE : View.GONE);
|
||||||
ivSnoozed.setVisibility(message.ui_snoozed == null ? View.GONE : View.VISIBLE);
|
ivSnoozed.setVisibility(message.ui_snoozed == null ? View.GONE : View.VISIBLE);
|
||||||
|
@ -563,11 +597,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
tvSubject.setTypeface(null, typeface);
|
tvSubject.setTypeface(null, typeface);
|
||||||
tvCount.setTypeface(null, typeface);
|
tvCount.setTypeface(null, typeface);
|
||||||
|
|
||||||
if (textSize != 0) {
|
|
||||||
tvFrom.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
|
|
||||||
tvSubject.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
int colorUnseen = (message.unseen > 0 ? colorUnread : textColorSecondary);
|
int colorUnseen = (message.unseen > 0 ? colorUnread : textColorSecondary);
|
||||||
tvFrom.setTextColor(colorUnseen);
|
tvFrom.setTextColor(colorUnseen);
|
||||||
tvSize.setTextColor(colorUnseen);
|
tvSize.setTextColor(colorUnseen);
|
||||||
|
|
|
@ -10,6 +10,28 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/drawableItemBackground">
|
android:background="?attr/drawableItemBackground">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDay"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Today"
|
||||||
|
android:padding="6dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/vSeparatorDay"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/colorSeparator"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvDay" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/vwColor"
|
android:id="@+id/vwColor"
|
||||||
android:layout_width="6dp"
|
android:layout_width="6dp"
|
||||||
|
@ -17,7 +39,7 @@
|
||||||
android:background="@color/colorAccent"
|
android:background="@color/colorAccent"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/vSeparatorAddress"
|
app:layout_constraintBottom_toTopOf="@+id/vSeparatorAddress"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toBottomOf="@id/vSeparatorDay" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/paddingTop"
|
android:id="@+id/paddingTop"
|
||||||
|
@ -26,7 +48,7 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toBottomOf="@id/vSeparatorDay" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ivExpander"
|
android:id="@+id/ivExpander"
|
||||||
|
@ -724,6 +746,12 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/rvImage" />
|
app:layout_constraintTop_toBottomOf="@id/rvImage" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Group
|
||||||
|
android:id="@+id/grpDay"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:constraint_referenced_ids="tvDay,vSeparatorDay" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
<androidx.constraintlayout.widget.Group
|
||||||
android:id="@+id/grpAddress"
|
android:id="@+id/grpAddress"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
|
@ -10,6 +10,28 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/drawableItemBackground">
|
android:background="?attr/drawableItemBackground">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDay"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="Today"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/vSeparatorDay"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/colorSeparator"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvDay" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/vwColor"
|
android:id="@+id/vwColor"
|
||||||
android:layout_width="6dp"
|
android:layout_width="6dp"
|
||||||
|
@ -17,7 +39,7 @@
|
||||||
android:background="@color/colorAccent"
|
android:background="@color/colorAccent"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/vSeparatorAddress"
|
app:layout_constraintBottom_toTopOf="@+id/vSeparatorAddress"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toBottomOf="@id/vSeparatorDay" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/paddingTop"
|
android:id="@+id/paddingTop"
|
||||||
|
@ -25,7 +47,7 @@
|
||||||
android:layout_height="12dp"
|
android:layout_height="12dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toBottomOf="@id/vSeparatorDay" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ivExpander"
|
android:id="@+id/ivExpander"
|
||||||
|
@ -720,6 +742,12 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:constraint_referenced_ids="tvFromExTitle,tvFromEx,tvToTitle,tvTo,tvReplyToTitle,tvReplyTo,tvCcTitle,tvCc,tvBccTitle,tvBcc,tvTimeExTitle,tvTimeEx,tvSizeExTitle,tvSizeEx,tvSubjectEx" />
|
app:constraint_referenced_ids="tvFromExTitle,tvFromEx,tvToTitle,tvTo,tvReplyToTitle,tvReplyTo,tvCcTitle,tvCc,tvBccTitle,tvBcc,tvTimeExTitle,tvTimeEx,tvSizeExTitle,tvSizeEx,tvSubjectEx" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Group
|
||||||
|
android:id="@+id/grpDay"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:constraint_referenced_ids="tvDay,vSeparatorDay" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
<androidx.constraintlayout.widget.Group
|
||||||
android:id="@+id/grpHeaders"
|
android:id="@+id/grpHeaders"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
Loading…
Reference in New Issue