diff --git a/briar-android/res/drawable-hdpi/message_delivered.png b/briar-android/res/drawable-hdpi/message_delivered.png deleted file mode 100644 index efade6391..000000000 Binary files a/briar-android/res/drawable-hdpi/message_delivered.png and /dev/null differ diff --git a/briar-android/res/drawable-hdpi/message_sent.png b/briar-android/res/drawable-hdpi/message_sent.png deleted file mode 100644 index 6edef05a9..000000000 Binary files a/briar-android/res/drawable-hdpi/message_sent.png and /dev/null differ diff --git a/briar-android/res/drawable-hdpi/message_stored.png b/briar-android/res/drawable-hdpi/message_stored.png deleted file mode 100644 index 8bf1ee459..000000000 Binary files a/briar-android/res/drawable-hdpi/message_stored.png and /dev/null differ diff --git a/briar-android/res/drawable-hdpi/msg_in.9.png b/briar-android/res/drawable-hdpi/msg_in.9.png new file mode 100644 index 000000000..974d60e2d Binary files /dev/null and b/briar-android/res/drawable-hdpi/msg_in.9.png differ diff --git a/briar-android/res/drawable-hdpi/msg_in_unread.9.png b/briar-android/res/drawable-hdpi/msg_in_unread.9.png new file mode 100644 index 000000000..c22cc8632 Binary files /dev/null and b/briar-android/res/drawable-hdpi/msg_in_unread.9.png differ diff --git a/briar-android/res/drawable-hdpi/msg_out.9.png b/briar-android/res/drawable-hdpi/msg_out.9.png new file mode 100644 index 000000000..08fd35b4c Binary files /dev/null and b/briar-android/res/drawable-hdpi/msg_out.9.png differ diff --git a/briar-android/res/drawable-hdpi/social_send_now.png b/briar-android/res/drawable-hdpi/social_send_now.png deleted file mode 100644 index d6ebbaedd..000000000 Binary files a/briar-android/res/drawable-hdpi/social_send_now.png and /dev/null differ diff --git a/briar-android/res/drawable-mdpi/message_delivered.png b/briar-android/res/drawable-mdpi/message_delivered.png deleted file mode 100644 index 938c50d90..000000000 Binary files a/briar-android/res/drawable-mdpi/message_delivered.png and /dev/null differ diff --git a/briar-android/res/drawable-mdpi/message_sent.png b/briar-android/res/drawable-mdpi/message_sent.png deleted file mode 100644 index 1f3807209..000000000 Binary files a/briar-android/res/drawable-mdpi/message_sent.png and /dev/null differ diff --git a/briar-android/res/drawable-mdpi/message_stored.png b/briar-android/res/drawable-mdpi/message_stored.png deleted file mode 100644 index 01858ffc6..000000000 Binary files a/briar-android/res/drawable-mdpi/message_stored.png and /dev/null differ diff --git a/briar-android/res/drawable-mdpi/msg_in.9.png b/briar-android/res/drawable-mdpi/msg_in.9.png new file mode 100644 index 000000000..f9a0267b6 Binary files /dev/null and b/briar-android/res/drawable-mdpi/msg_in.9.png differ diff --git a/briar-android/res/drawable-mdpi/msg_in_unread.9.png b/briar-android/res/drawable-mdpi/msg_in_unread.9.png new file mode 100644 index 000000000..6e5418856 Binary files /dev/null and b/briar-android/res/drawable-mdpi/msg_in_unread.9.png differ diff --git a/briar-android/res/drawable-mdpi/msg_out.9.png b/briar-android/res/drawable-mdpi/msg_out.9.png new file mode 100644 index 000000000..f22c541f7 Binary files /dev/null and b/briar-android/res/drawable-mdpi/msg_out.9.png differ diff --git a/briar-android/res/drawable-mdpi/social_send_now.png b/briar-android/res/drawable-mdpi/social_send_now.png deleted file mode 100644 index 90b17a017..000000000 Binary files a/briar-android/res/drawable-mdpi/social_send_now.png and /dev/null differ diff --git a/briar-android/res/drawable-xhdpi/message_delivered.png b/briar-android/res/drawable-xhdpi/message_delivered.png deleted file mode 100644 index 991091136..000000000 Binary files a/briar-android/res/drawable-xhdpi/message_delivered.png and /dev/null differ diff --git a/briar-android/res/drawable-xhdpi/message_sent.png b/briar-android/res/drawable-xhdpi/message_sent.png deleted file mode 100644 index a40d4d94c..000000000 Binary files a/briar-android/res/drawable-xhdpi/message_sent.png and /dev/null differ diff --git a/briar-android/res/drawable-xhdpi/message_stored.png b/briar-android/res/drawable-xhdpi/message_stored.png deleted file mode 100644 index b8eb1384a..000000000 Binary files a/briar-android/res/drawable-xhdpi/message_stored.png and /dev/null differ diff --git a/briar-android/res/drawable-xhdpi/msg_in.9.png b/briar-android/res/drawable-xhdpi/msg_in.9.png new file mode 100644 index 000000000..f5db8372d Binary files /dev/null and b/briar-android/res/drawable-xhdpi/msg_in.9.png differ diff --git a/briar-android/res/drawable-xhdpi/msg_in_unread.9.png b/briar-android/res/drawable-xhdpi/msg_in_unread.9.png new file mode 100644 index 000000000..341ec4f72 Binary files /dev/null and b/briar-android/res/drawable-xhdpi/msg_in_unread.9.png differ diff --git a/briar-android/res/drawable-xhdpi/msg_out.9.png b/briar-android/res/drawable-xhdpi/msg_out.9.png new file mode 100644 index 000000000..d7c2816f1 Binary files /dev/null and b/briar-android/res/drawable-xhdpi/msg_out.9.png differ diff --git a/briar-android/res/drawable-xhdpi/social_send_now.png b/briar-android/res/drawable-xhdpi/social_send_now.png deleted file mode 100644 index 6fa26d165..000000000 Binary files a/briar-android/res/drawable-xhdpi/social_send_now.png and /dev/null differ diff --git a/briar-android/res/drawable-xxhdpi/message_stored.png b/briar-android/res/drawable-xxhdpi/message_stored.png deleted file mode 100644 index 153650a1f..000000000 Binary files a/briar-android/res/drawable-xxhdpi/message_stored.png and /dev/null differ diff --git a/briar-android/res/drawable-xxhdpi/msg_in.9.png b/briar-android/res/drawable-xxhdpi/msg_in.9.png new file mode 100644 index 000000000..3db9979cf Binary files /dev/null and b/briar-android/res/drawable-xxhdpi/msg_in.9.png differ diff --git a/briar-android/res/drawable-xxhdpi/msg_in_unread.9.png b/briar-android/res/drawable-xxhdpi/msg_in_unread.9.png new file mode 100644 index 000000000..3a3bb3e7e Binary files /dev/null and b/briar-android/res/drawable-xxhdpi/msg_in_unread.9.png differ diff --git a/briar-android/res/drawable-xxhdpi/msg_out.9.png b/briar-android/res/drawable-xxhdpi/msg_out.9.png new file mode 100644 index 000000000..b7aa02377 Binary files /dev/null and b/briar-android/res/drawable-xxhdpi/msg_out.9.png differ diff --git a/briar-android/res/drawable-xxxhdpi/message_stored.png b/briar-android/res/drawable-xxxhdpi/message_stored.png deleted file mode 100644 index b3833bc3e..000000000 Binary files a/briar-android/res/drawable-xxxhdpi/message_stored.png and /dev/null differ diff --git a/briar-android/res/drawable/message_delivered.xml b/briar-android/res/drawable/message_delivered.xml new file mode 100644 index 000000000..7df040f3c --- /dev/null +++ b/briar-android/res/drawable/message_delivered.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/drawable/message_sent.xml b/briar-android/res/drawable/message_sent.xml new file mode 100644 index 000000000..8a074e0fc --- /dev/null +++ b/briar-android/res/drawable/message_sent.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/drawable/message_stored.xml b/briar-android/res/drawable/message_stored.xml new file mode 100644 index 000000000..b91196f03 --- /dev/null +++ b/briar-android/res/drawable/message_stored.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/drawable/social_send_now.xml b/briar-android/res/drawable/social_send_now.xml new file mode 100644 index 000000000..bd34e7fc2 --- /dev/null +++ b/briar-android/res/drawable/social_send_now.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/layout/activity_conversation.xml b/briar-android/res/layout/activity_conversation.xml index 1a07f07eb..673dd14f9 100644 --- a/briar-android/res/layout/activity_conversation.xml +++ b/briar-android/res/layout/activity_conversation.xml @@ -1,12 +1,18 @@ - + + android:indeterminate="true" + android:visibility="gone"/> + android:text="@string/no_private_messages" + android:visibility="gone"/> + android:paddingStart="@dimen/margin_medium"> + android:paddingRight="@dimen/margin_medium" + android:paddingEnd="@dimen/margin_medium" + android:paddingBottom="@dimen/margin_medium"/> \ No newline at end of file diff --git a/briar-android/res/layout/list_item_msg_in.xml b/briar-android/res/layout/list_item_msg_in.xml new file mode 100644 index 000000000..d93d269e7 --- /dev/null +++ b/briar-android/res/layout/list_item_msg_in.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/layout/list_item_msg_out.xml b/briar-android/res/layout/list_item_msg_out.xml new file mode 100644 index 000000000..a82a07f1e --- /dev/null +++ b/briar-android/res/layout/list_item_msg_out.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml index 01b15430a..0ecc0f1ba 100644 --- a/briar-android/res/values/color.xml +++ b/briar-android/res/values/color.xml @@ -5,7 +5,6 @@ #2D3E50 #FFFFFF #FFFFFF - #FFFFFF #AAAAAA #FFFFFF #CCCCCC diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index 98dcd179f..f00647318 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -2,30 +2,27 @@ package org.briarproject.android.contact; import android.content.DialogInterface; import android.content.Intent; -import android.content.res.Resources; import android.graphics.PorterDuff; -import android.graphics.drawable.ColorDrawable; +import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; import android.widget.EditText; import android.widget.ImageButton; -import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import org.briarproject.R; import org.briarproject.android.BriarActivity; -import org.briarproject.android.util.LayoutUtils; import org.briarproject.api.android.AndroidNotificationManager; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -77,12 +74,11 @@ import static android.widget.Toast.LENGTH_SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.contact.ReadPrivateMessageActivity.RESULT_PREV_NEXT; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; import static org.briarproject.api.messaging.PrivateMessageHeader.Status.DELIVERED; import static org.briarproject.api.messaging.PrivateMessageHeader.Status.SENT; public class ConversationActivity extends BriarActivity -implements EventListener, OnClickListener, OnItemClickListener { + implements EventListener, OnClickListener { private static final int REQUEST_READ = 2; private static final Logger LOG = @@ -95,7 +91,7 @@ implements EventListener, OnClickListener, OnItemClickListener { private TextView empty = null; private ProgressBar loading = null; private ConversationAdapter adapter = null; - private ListView list = null; + private RecyclerView list = null; private EditText content = null; private ImageButton sendButton = null; @@ -133,27 +129,29 @@ implements EventListener, OnClickListener, OnItemClickListener { loading.setVisibility(VISIBLE); adapter = new ConversationAdapter(this); - list = new ListView(this) { - @Override - public void onSizeChanged(int w, int h, int oldw, int oldh) { - // Scroll to the bottom when the keyboard is shown - super.onSizeChanged(w, h, oldw, oldh); - setSelection(getCount() - 1); - } - }; - list.setLayoutParams(MATCH_WRAP_1); - int pad = LayoutUtils.getPadding(this); - list.setPadding(0, pad, 0, pad); - list.setClipToPadding(false); - // Make the dividers the same colour as the background - Resources res = getResources(); - int background = res.getColor(android.R.color.transparent); - list.setDivider(new ColorDrawable(background)); - list.setDividerHeight(pad); + list = (RecyclerView) findViewById(R.id.conversationView); + list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); - list.setOnItemClickListener(this); - list.setEmptyView(loading); - layout.addView(list, 0); + list.setVisibility(GONE); + // scroll down when opening keyboard + if (Build.VERSION.SDK_INT >= 11) { + list.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, + int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (bottom < oldBottom) { + list.postDelayed(new Runnable() { + @Override + public void run() { + list.scrollToPosition( + adapter.getItemCount() - 1); + } + }, 100); + } + } + }); + } content = (EditText) findViewById(R.id.contentView); sendButton = (ImageButton) findViewById(R.id.sendButton); @@ -267,12 +265,10 @@ implements EventListener, OnClickListener, OnItemClickListener { runOnUiThread(new Runnable() { public void run() { loading.setVisibility(GONE); - empty.setVisibility(VISIBLE); - list.setEmptyView(empty); - displayContactDetails(); sendButton.setEnabled(true); - adapter.clear(); if (!headers.isEmpty()) { + list.setVisibility(VISIBLE); + empty.setVisibility(GONE); for (PrivateMessageHeader h : headers) { ConversationItem item = new ConversationItem(h); byte[] body = bodyCache.get(h.getId()); @@ -280,11 +276,12 @@ implements EventListener, OnClickListener, OnItemClickListener { else item.setBody(body); adapter.add(item); } - adapter.sort(ConversationItemComparator.INSTANCE); // Scroll to the bottom - list.setSelection(adapter.getCount() - 1); + list.scrollToPosition(adapter.getItemCount() - 1); + } else { + empty.setVisibility(VISIBLE); + list.setVisibility(GONE); } - adapter.notifyDataSetChanged(); } }); } @@ -313,14 +310,18 @@ implements EventListener, OnClickListener, OnItemClickListener { runOnUiThread(new Runnable() { public void run() { bodyCache.put(m, body); - int count = adapter.getCount(); + int count = adapter.getItemCount(); + for (int i = 0; i < count; i++) { ConversationItem item = adapter.getItem(i); + if (item.getHeader().getId().equals(m)) { item.setBody(body); - adapter.notifyDataSetChanged(); + adapter.notifyItemChanged(i); + // Scroll to the bottom - list.setSelection(count - 1); + list.scrollToPosition(count - 1); + return; } } @@ -333,7 +334,7 @@ implements EventListener, OnClickListener, OnItemClickListener { super.onActivityResult(request, result, data); if (request == REQUEST_READ && result == RESULT_PREV_NEXT) { int position = data.getIntExtra("briar.POSITION", -1); - if (position >= 0 && position < adapter.getCount()) + if (position >= 0 && position < adapter.getItemCount()) displayMessage(position); } } @@ -348,7 +349,7 @@ implements EventListener, OnClickListener, OnItemClickListener { private void markMessagesRead() { notificationManager.clearPrivateMessageNotification(contactId); List unread = new ArrayList(); - int count = adapter.getCount(); + int count = adapter.getItemCount(); for (int i = 0; i < count; i++) { PrivateMessageHeader h = adapter.getItem(i).getHeader(); if (!h.isRead()) unread.add(h.getId()); @@ -388,6 +389,8 @@ implements EventListener, OnClickListener, OnItemClickListener { GroupId g = ((MessageAddedEvent) e).getGroupId(); if (g.equals(groupId)) { LOG.info("Message added, reloading"); + // TODO: find a way of not needing to reload the entire + // conversation just because one message was added loadHeaders(); } } else if (e instanceof MessagesSentEvent) { @@ -424,16 +427,14 @@ implements EventListener, OnClickListener, OnItemClickListener { runOnUiThread(new Runnable() { public void run() { Set messages = new HashSet(messageIds); - boolean changed = false; - int count = adapter.getCount(); + int count = adapter.getItemCount(); for (int i = 0; i < count; i++) { ConversationItem item = adapter.getItem(i); if (messages.contains(item.getHeader().getId())) { item.setStatus(status); - changed = true; + adapter.notifyItemChanged(i); } } - if (changed) adapter.notifyDataSetChanged(); } }); } @@ -451,7 +452,7 @@ implements EventListener, OnClickListener, OnItemClickListener { private long getMinTimestampForNewMessage() { // Don't use an earlier timestamp than the newest message long timestamp = 0; - int count = adapter.getCount(); + int count = adapter.getItemCount(); for (int i = 0; i < count; i++) { long t = adapter.getItem(i).getHeader().getTimestamp(); if (t > timestamp) timestamp = t; @@ -492,11 +493,6 @@ implements EventListener, OnClickListener, OnItemClickListener { }); } - public void onItemClick(AdapterView parent, View view, int position, - long id) { - displayMessage(position); - } - private void displayMessage(int position) { ConversationItem item = adapter.getItem(position); PrivateMessageHeader header = item.getHeader(); diff --git a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java index a95b00e47..0e183a63b 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationAdapter.java @@ -1,115 +1,199 @@ package org.briarproject.android.contact; import android.content.Context; -import android.content.res.Resources; +import android.support.v7.util.SortedList; +import android.support.v7.widget.RecyclerView; import android.text.format.DateUtils; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import org.briarproject.R; -import org.briarproject.android.util.ElasticHorizontalSpace; -import org.briarproject.android.util.LayoutUtils; import org.briarproject.api.messaging.PrivateMessageHeader; import org.briarproject.util.StringUtils; -import java.util.ArrayList; - -import static android.view.Gravity.BOTTOM; -import static android.view.Gravity.LEFT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; import static org.briarproject.api.messaging.PrivateMessageHeader.Status.DELIVERED; import static org.briarproject.api.messaging.PrivateMessageHeader.Status.SENT; -class ConversationAdapter extends ArrayAdapter { +class ConversationAdapter extends + RecyclerView.Adapter { - private final int pad; + private static final int MSG_OUT = 0; + private static final int MSG_IN = 1; + private static final int MSG_IN_UNREAD = 2; - ConversationAdapter(Context ctx) { - super(ctx, android.R.layout.simple_expandable_list_item_1, - new ArrayList()); - pad = LayoutUtils.getPadding(ctx); + private SortedList messages = + new SortedList(ConversationItem.class, + new SortedList.Callback() { + @Override + public void onInserted(int position, int count) { + notifyItemRangeInserted(position, count); + } + + @Override + public void onChanged(int position, int count) { + notifyItemRangeChanged(position, count); + } + + @Override + public void onMoved(int fromPosition, int toPosition) { + notifyItemMoved(fromPosition, toPosition); + } + + @Override + public void onRemoved(int position, int count) { + notifyItemRangeRemoved(position, count); + } + + @Override + public int compare(ConversationItem c1, + ConversationItem c2) { + long time1 = c1.getHeader().getTimestamp(); + long time2 = c2.getHeader().getTimestamp(); + if (time1 < time2) return -1; + if (time1 > time2) return 1; + return 0; + } + + @Override + public boolean areItemsTheSame(ConversationItem c1, + ConversationItem c2) { + return c1.getHeader().getId() + .equals(c2.getHeader().getId()); + } + + @Override + public boolean areContentsTheSame(ConversationItem c1, + ConversationItem c2) { + return c1.equals(c2); + } + }); + private Context ctx; + + public ConversationAdapter(Context context) { + ctx = context; } @Override - public View getView(int position, View convertView, ViewGroup parent) { + public int getItemViewType(int position) { + // return different type for incoming and outgoing (local) messages + PrivateMessageHeader header = getItem(position).getHeader(); + if (header.isLocal()) { + return MSG_OUT; + } else if (header.isRead()) { + return MSG_IN; + } else { + return MSG_IN_UNREAD; + } + } + + @Override + public MessageHolder onCreateViewHolder(ViewGroup viewGroup, int type) { + View v; + + // outgoing message (local) + if (type == MSG_OUT) { + v = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.list_item_msg_out, viewGroup, false); + } + // incoming message (non-local) + else { + v = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.list_item_msg_in, viewGroup, false); + } + + return new MessageHolder(v, type); + } + + @Override + public void onBindViewHolder(final MessageHolder ui, final int position) { ConversationItem item = getItem(position); PrivateMessageHeader header = item.getHeader(); - Context ctx = getContext(); - Resources res = ctx.getResources(); - - LinearLayout layout = new LinearLayout(ctx); - layout.setOrientation(VERTICAL); - if (header.isLocal()) layout.setPadding(3 * pad, 0, 0, 0); - else layout.setPadding(0, 0, 3 * pad, 0); - - int background = res.getColor(R.color.private_message_background); - - View content; - if (item.getBody() == null) { - TextView ellipsis = new TextView(ctx); - ellipsis.setText("\u2026"); - content = ellipsis; - } else if (header.getContentType().equals("text/plain")) { - TextView text = new TextView(ctx); - text.setText(StringUtils.fromUtf8(item.getBody())); - content = text; - } else { - ImageButton attachment = new ImageButton(ctx); - attachment.setImageResource(R.drawable.content_attachment); - content = attachment; - } - content.setLayoutParams(MATCH_WRAP); - content.setBackgroundColor(background); - content.setPadding(pad, pad, pad, 0); - layout.addView(content); if (header.isLocal()) { - LinearLayout footer = new LinearLayout(ctx); - footer.setLayoutParams(MATCH_WRAP); - footer.setOrientation(HORIZONTAL); - footer.setGravity(BOTTOM); - footer.setPadding(pad, 0, pad, pad); - footer.setBackgroundColor(background); - - footer.addView(new ElasticHorizontalSpace(ctx)); - - ImageView status = new ImageView(ctx); - status.setPadding(0, 0, pad, 0); if (item.getStatus() == DELIVERED) { - status.setImageResource(R.drawable.message_delivered); + ui.status.setImageResource(R.drawable.message_delivered); } else if (item.getStatus() == SENT) { - status.setImageResource(R.drawable.message_sent); + ui.status.setImageResource(R.drawable.message_sent); } else { - status.setImageResource(R.drawable.message_stored); + ui.status.setImageResource(R.drawable.message_stored); } - footer.addView(status); + } else if (!header.isRead()) { + int bottom = ui.layout.getPaddingBottom(); + int top = ui.layout.getPaddingTop(); + int right = ui.layout.getPaddingRight(); + int left = ui.layout.getPaddingLeft(); - TextView date = new TextView(ctx); - date.setTextColor(res.getColor(R.color.private_message_date)); - long timestamp = header.getTimestamp(); - date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp)); - footer.addView(date); + // show unread messages in different color to not miss them + ui.layout.setBackgroundResource(R.drawable.msg_in_unread); - layout.addView(footer); - } else { - TextView date = new TextView(ctx); - date.setLayoutParams(MATCH_WRAP); - date.setGravity(LEFT); - date.setTextColor(res.getColor(R.color.private_message_date)); - date.setBackgroundColor(background); - date.setPadding(pad, 0, pad, pad); - long timestamp = header.getTimestamp(); - date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp)); - layout.addView(date); + // re-apply the previous padding due to bug in some Android versions + // see: https://code.google.com/p/android/issues/detail?id=17885 + ui.layout.setPadding(left, top, right, bottom); } - return layout; + if (item.getBody() == null) { + ui.body.setText("\u2026"); + } else if (header.getContentType().equals("text/plain")) { + ui.body.setText(StringUtils.fromUtf8(item.getBody())); + } else { + // TODO support other content types + } + + long timestamp = header.getTimestamp(); + ui.date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp)); + } + + @Override + public int getItemCount() { + return messages == null ? 0 : messages.size(); + } + + public boolean isEmpty() { + return messages == null || messages.size() == 0; + } + + public ConversationItem getItem(int position) { + return messages.get(position); + } + + public void add(final ConversationItem message) { + this.messages.add(message); + } + + public void remove(final ConversationItem message) { + this.messages.remove(message); + } + + public void clear() { + this.messages.beginBatchedUpdates(); + + while(messages.size() != 0) { + messages.removeItemAt(0); + } + + this.messages.endBatchedUpdates(); + } + + public static class MessageHolder extends RecyclerView.ViewHolder { + public ViewGroup layout; + public TextView body; + public TextView date; + public ImageView status; + + public MessageHolder(View v, int type) { + super(v); + + layout = (ViewGroup) v.findViewById(R.id.msgLayout); + body = (TextView) v.findViewById(R.id.msgBody); + date = (TextView) v.findViewById(R.id.msgTime); + + // outgoing message (local) + if (type == MSG_OUT) { + status = (ImageView) v.findViewById(R.id.msgStatus); + } + } } } \ No newline at end of file diff --git a/briar-android/src/org/briarproject/android/contact/ConversationItemComparator.java b/briar-android/src/org/briarproject/android/contact/ConversationItemComparator.java deleted file mode 100644 index 76eb1d28d..000000000 --- a/briar-android/src/org/briarproject/android/contact/ConversationItemComparator.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.briarproject.android.contact; - -import java.util.Comparator; - -class ConversationItemComparator implements Comparator { - - static final ConversationItemComparator INSTANCE = - new ConversationItemComparator(); - - public int compare(ConversationItem a, ConversationItem b) { - // The oldest message comes first - long aTime = a.getHeader().getTimestamp(); - long bTime = b.getHeader().getTimestamp(); - if (aTime < bTime) return -1; - if (aTime > bTime) return 1; - return 0; - } -} diff --git a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java index 7ece03b02..01ba00303 100644 --- a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java @@ -40,6 +40,7 @@ import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1; import static org.briarproject.api.identity.Author.Status.VERIFIED; +@Deprecated public class ReadPrivateMessageActivity extends BriarActivity implements OnClickListener {