Browse Source

feat: better layout for the message list

This is to close #8 issue.
The new interface is much more "material" and ergonomic.
The sender is displayed (either compact or with full address) below.
Then, a quick & small email summary is shown.
The thread message count is only displayed if there is more than a single message.
I'm using light font here, and the same color for both unread & read messages. Unread messages are using bold font.
main
X-Ryl669 6 years ago
parent
commit
73aa80d900
3 changed files with 122 additions and 70 deletions
  1. +38
    -15
      app/src/main/java/org/dystopia/email/AdapterMessage.java
  2. +37
    -23
      app/src/main/res/layout/item_message_compact.xml
  3. +47
    -32
      app/src/main/res/layout/item_message_normal.xml

+ 38
- 15
app/src/main/java/org/dystopia/email/AdapterMessage.java View File

@ -97,6 +97,9 @@ import java.util.List;
import java.util.Locale;
import javax.mail.Address;
import javax.mail.internet.InternetAddress;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.xml.sax.XMLReader;
public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMessage.ViewHolder> {
@ -134,6 +137,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
private ImageView ivFlagged;
private ImageView ivAvatar;
private TextView tvFrom;
private TextView tvSummary;
private ImageView ivAddContact;
private TextView tvSize;
private TextView tvTime;
@ -183,6 +187,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
ivFlagged = itemView.findViewById(R.id.ivFlagged);
ivAvatar = itemView.findViewById(R.id.ivAvatar);
tvFrom = itemView.findViewById(R.id.tvFrom);
tvSummary = itemView.findViewById(R.id.tvSummary);
ivAddContact = itemView.findViewById(R.id.ivAddContact);
tvSize = itemView.findViewById(R.id.tvSize);
tvTime = itemView.findViewById(R.id.tvTime);
@ -317,18 +322,19 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
if (EntityFolder.DRAFTS.equals(message.folderType)
|| EntityFolder.OUTBOX.equals(message.folderType)
|| EntityFolder.SENT.equals(message.folderType)) {
tvFrom.setText(MessageHelper.getFormattedAddresses(message.to, !compact));
tvFrom.setText(MessageHelper.getFormattedAddresses(message.to, show_expanded));
tvTime.setText(
DateUtils.getRelativeTimeSpanString(
context, message.sent == null ? message.received : message.sent));
} else {
tvFrom.setText(MessageHelper.getFormattedAddresses(message.from, !compact));
tvFrom.setText(MessageHelper.getFormattedAddresses(message.from, show_expanded));
tvTime.setText(DateUtils.getRelativeTimeSpanString(context, message.received));
}
tvSize.setText(
message.size == null ? null : Helper.humanReadableByteCount(message.size, true));
tvSize.setAlpha(message.content ? 1.0f : 0.5f);
tvSize.setVisibility(compact && !show_expanded ? View.GONE : View.VISIBLE);
ivAttachments.setVisibility(message.attachments > 0 ? View.VISIBLE : View.GONE);
tvSubject.setText(message.subject);
@ -336,25 +342,41 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
tvFolder.setVisibility(View.GONE);
tvAccount.setVisibility(View.GONE);
if (viewType == ViewType.UNIFIED || viewType == ViewType.FOLDER) {
tvAccount.setText(message.accountName);
tvAccount.setVisibility(View.VISIBLE);
} else {
tvFolder.setText(
message.folderDisplay == null
? Helper.localizeFolderName(context, message.folderName)
: message.folderDisplay);
tvFolder.setVisibility(View.VISIBLE);
if (!compact || show_expanded) {
if (viewType == ViewType.UNIFIED || viewType == ViewType.FOLDER) {
tvAccount.setText(message.accountName);
tvAccount.setVisibility(View.VISIBLE);
} else {
tvFolder.setText(
message.folderDisplay == null
? Helper.localizeFolderName(context, message.folderName)
: message.folderDisplay);
tvFolder.setVisibility(View.VISIBLE);
}
}
if (viewType == ViewType.THREAD) {
if (viewType == ViewType.THREAD || message.count == 1) {
tvCount.setVisibility(View.GONE);
ivThread.setVisibility(View.GONE);
} else {
tvCount.setText(Integer.toString(message.count));
tvCount.setVisibility(View.VISIBLE);
ivThread.setVisibility(View.VISIBLE);
}
tvSummary.setVisibility(View.GONE);
if (message.content && !show_expanded)
{
try {
String body = message.read(context);
Document doc = Jsoup.parse(body);
String plainText = doc.body().text();
int limit = compact ? 60 : 120;
tvSummary.setText(plainText.substring(0, Math.min(plainText.length(), limit)) + "...");
tvSummary.setVisibility(View.VISIBLE);
} catch(IOException e) { }
}
if (debug) {
db.operation().getOperationsByMessage(message.id).removeObservers(owner);
db.operation()
@ -406,11 +428,11 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
tvSubject.setTypeface(null, typeface);
tvCount.setTypeface(null, typeface);
int colorUnseen =
Helper.resolveColor(
context, message.unseen > 0 ? R.attr.colorUnread : android.R.attr.textColorSecondary);
int colorUnseen = Helper.resolveColor(context, R.attr.colorUnread);
tvSubject.setTextColor(colorUnseen);
tvFrom.setTextColor(colorUnseen);
tvTime.setTextColor(colorUnseen);
tvSummary.setTextColor(Helper.resolveColor(context, android.R.attr.textColorSecondary));
grpExpanded.setVisibility(
viewType == ViewType.THREAD && show_expanded ? View.VISIBLE : View.GONE);
@ -711,6 +733,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
}
};
private Spanned decodeHtml(final EntityMessage message, String body) {
return Html.fromHtml(
HtmlHelper.sanitize(body),


+ 37
- 23
app/src/main/res/layout/item_message_compact.xml View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -65,10 +66,11 @@
android:layout_marginStart="6dp"
android:layout_marginEnd="20dp"
android:ellipsize="end"
android:fontFamily="sans-serif-light"
android:maxLines="1"
android:text="From"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toStartOf="@+id/tvSize"
app:layout_constraintEnd_toStartOf="@id/tvTime"
app:layout_constraintStart_toEndOf="@id/ivAvatar"
app:layout_constraintTop_toBottomOf="@id/paddingTop" />
@ -80,7 +82,6 @@
android:maxLines="1"
android:text="Time"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintBottom_toBottomOf="@id/tvFrom"
app:layout_constraintEnd_toStartOf="@+id/ivFlagged"
app:layout_constraintTop_toTopOf="@id/tvFrom" />
@ -110,13 +111,14 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
android:ellipsize="end"
android:fontFamily="sans-serif-light"
android:maxLines="1"
android:minLines="1"
android:text="Subject"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toEndOf="@id/ivAttachments"
app:layout_constraintEnd_toStartOf="@id/paddingEnd"
app:layout_constraintStart_toEndOf="@id/ivAttachments"
app:layout_constraintTop_toBottomOf="@id/tvFrom" />
<TextView
@ -125,59 +127,72 @@
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:maxLines="1"
android:text="acount"
android:text="account"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toEndOf="@id/paddingStart"
app:layout_constraintTop_toBottomOf="@id/tvSubject" />
app:layout_constraintTop_toBottomOf="@id/tvSummary" />
<TextView
android:id="@+id/tvFolder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:background="@color/colorAccent"
android:maxLines="1"
android:text="folder"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="@color/colorActionForeground"
android:background="@color/colorAccent"
android:text="folder"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/colorActionForeground"
app:layout_constraintStart_toEndOf="@id/tvAccount"
app:layout_constraintTop_toBottomOf="@id/tvSubject" />
app:layout_constraintTop_toBottomOf="@id/tvSummary" />
<TextView
android:id="@+id/tvCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="0.5dp"
android:maxLines="1"
android:text="3"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintTop_toBottomOf="@id/tvSubject"
app:layout_constraintStart_toEndOf="@id/tvFolder" />
app:layout_constraintEnd_toStartOf="@id/ivThread"
app:layout_constraintTop_toTopOf="@+id/tvTime" />
<ImageView
android:id="@+id/ivThread"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="3dp"
android:layout_marginTop="1dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="6dp"
android:paddingStart="2dp"
android:src="@drawable/baseline_message_24"
app:layout_constraintBottom_toBottomOf="@id/tvCount"
app:layout_constraintStart_toEndOf="@id/tvCount"
app:layout_constraintTop_toTopOf="@id/tvCount" />
app:layout_constraintEnd_toStartOf="@id/tvTime"
app:layout_constraintTop_toTopOf="@id/tvTime" />
<TextView
android:id="@+id/tvSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:layout_marginEnd="4dp"
android:maxLines="1"
android:text="123 KB"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintTop_toBottomOf="@id/tvSubject"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toEndOf="@id/paddingEnd"
app:layout_constraintEnd_toStartOf="@+id/paddingEnd"
app:layout_constraintTop_toBottomOf="@id/tvSummary" />
<TextView
android:id="@+id/tvSummary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:fontFamily="sans-serif-light"
android:maxLines="1"
android:minLines="1"
android:text="Summary"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="@id/paddingEnd"
app:layout_constraintStart_toEndOf="@id/paddingStart"
app:layout_constraintTop_toBottomOf="@id/tvSubject" />
<TextView
android:id="@+id/tvError"
@ -461,7 +476,6 @@
android:layout_marginStart="6dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="6dp"
android:fontFamily="monospace"
android:minHeight="60dp"
android:text="Body"
android:textAppearance="@style/TextAppearance.AppCompat.Small"


+ 47
- 32
app/src/main/res/layout/item_message_normal.xml View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -56,6 +57,21 @@
app:layout_constraintStart_toEndOf="@id/paddingStart"
app:layout_constraintTop_toTopOf="@+id/tvFrom" />
<TextView
android:id="@+id/tvSubject"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:ellipsize="end"
android:fontFamily="sans-serif-light"
android:maxLines="1"
android:minLines="1"
android:text="Subject"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintEnd_toStartOf="@id/paddingEnd"
app:layout_constraintStart_toEndOf="@id/ivAttachments"
app:layout_constraintTop_toBottomOf="@id/tvFrom" />
<TextView
android:id="@+id/tvFrom"
android:layout_width="0dp"
@ -63,6 +79,8 @@
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
android:ellipsize="end"
android:fontFamily="sans-serif-light"
android:maxLines="1"
android:text="From"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toStartOf="@+id/tvTime"
@ -102,78 +120,76 @@
app:layout_constraintStart_toEndOf="@id/paddingStart"
app:layout_constraintTop_toTopOf="@+id/tvSubject" />
<TextView
android:id="@+id/tvSubject"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:ellipsize="end"
android:text="Subject"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toEndOf="@id/ivAttachments"
app:layout_constraintEnd_toStartOf="@id/paddingEnd"
app:layout_constraintTop_toBottomOf="@id/tvFrom" />
<TextView
android:id="@+id/tvAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginStart="8dp"
android:maxLines="1"
android:text="acount"
android:text="account"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toEndOf="@id/paddingStart"
app:layout_constraintTop_toBottomOf="@id/tvSubject" />
app:layout_constraintTop_toBottomOf="@id/tvSummary" />
<TextView
android:id="@+id/tvFolder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:background="@color/colorAccent"
android:maxLines="1"
android:text="folder"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="@color/colorActionForeground"
android:background="@color/colorAccent"
android:text="folder"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/colorActionForeground"
app:layout_constraintStart_toEndOf="@id/tvAccount"
app:layout_constraintTop_toBottomOf="@id/tvSubject" />
app:layout_constraintTop_toBottomOf="@id/tvSummary" />
<TextView
android:id="@+id/tvCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="0.5dp"
android:layout_marginStart="28dp"
android:maxLines="1"
android:text="3"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintTop_toBottomOf="@id/tvSubject"
app:layout_constraintStart_toEndOf="@id/tvFolder" />
app:layout_constraintStart_toEndOf="@id/tvFolder"
app:layout_constraintTop_toTopOf="@id/tvFolder" />
<ImageView
android:id="@+id/ivThread"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="3dp"
android:layout_marginTop="1dp"
android:layout_marginTop="2dp"
android:paddingStart="2dp"
android:src="@drawable/baseline_message_24"
app:layout_constraintBottom_toBottomOf="@id/tvCount"
app:layout_constraintStart_toEndOf="@id/tvCount"
app:layout_constraintTop_toTopOf="@id/tvCount" />
app:layout_constraintTop_toTopOf="@id/tvFolder" />
<TextView
android:id="@+id/tvSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:layout_marginEnd="4dp"
android:maxLines="1"
android:text="123 KB"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="@+id/paddingEnd"
app:layout_constraintTop_toBottomOf="@id/tvSummary" />
<TextView
android:id="@+id/tvSummary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:fontFamily="sans-serif-light"
android:maxLines="2"
android:minLines="1"
android:text="Summary"
android:textStyle="italic"
app:layout_constraintEnd_toStartOf="@id/paddingEnd"
app:layout_constraintStart_toStartOf="@id/paddingStart"
app:layout_constraintTop_toBottomOf="@id/tvSubject" />
<TextView
@ -457,7 +473,6 @@
android:layout_marginStart="6dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="6dp"
android:fontFamily="monospace"
android:minHeight="60dp"
android:text="Body"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"


Loading…
Cancel
Save