show day in non-scrolling headers, tackles #29

This commit is contained in:
B. Petersen
2018-09-21 15:20:33 +02:00
parent c2c7a3173b
commit 6729c099cd
4 changed files with 69 additions and 89 deletions
@@ -20,7 +20,6 @@ import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
@@ -39,14 +38,14 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.LRUCache;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.whispersystems.libsignal.util.guava.Optional;
import java.lang.ref.SoftReference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
@@ -89,7 +88,6 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
private final @NonNull LayoutInflater inflater;
private final @NonNull Context context;
private final @NonNull Calendar calendar;
private final @NonNull MessageDigest digest;
private ApplicationDcContext dcContext;
private @NonNull int[] dcMsgList = new int[0];
@@ -110,6 +108,11 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
}
}
public boolean isActive() {
return dcMsgList.length > 0;
}
@Override
public int getItemCount() {
return dcMsgList.length;
@@ -122,6 +125,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
return new DcMsg(0);
}
static class HeaderViewHolder extends RecyclerView.ViewHolder {
TextView textView;
@@ -146,44 +150,21 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
void onItemLongClick(DcMsg item);
}
@SuppressWarnings("ConstantConditions")
@VisibleForTesting
ConversationAdapter(Context context) {
try {
this.glideRequests = null;
this.locale = null;
this.clickListener = null;
this.recipient = null;
this.inflater = null;
this.calendar = null;
this.context = context;
this.digest = MessageDigest.getInstance("SHA1");
this.dcContext = DcHelper.getContext(context);
} catch (NoSuchAlgorithmException nsae) {
throw new AssertionError("SHA1 isn't supported!");
}
}
public ConversationAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable ItemClickListener clickListener,
@NonNull Recipient recipient) {
try {
this.glideRequests = glideRequests;
this.locale = locale;
this.clickListener = clickListener;
this.recipient = recipient;
this.context = context;
this.inflater = LayoutInflater.from(context);
this.calendar = Calendar.getInstance();
this.digest = MessageDigest.getInstance("SHA1");
this.dcContext = DcHelper.getContext(context);
this.glideRequests = glideRequests;
this.locale = locale;
this.clickListener = clickListener;
this.recipient = recipient;
this.context = context;
this.inflater = LayoutInflater.from(context);
this.calendar = Calendar.getInstance();
this.dcContext = DcHelper.getContext(context);
setHasStableIds(true);
} catch (NoSuchAlgorithmException nsae) {
throw new AssertionError("SHA1 isn't supported!");
}
setHasStableIds(true);
}
@Override
@@ -255,7 +236,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
public int findLastSeenPosition(long lastSeen) {
/* TODO -- we shoud do this without loading all messages in the chat
if (lastSeen <= 0) return -1;
if (isActive()) return -1;
if (!isActive()) return -1;
int count = getItemCount();
@@ -291,39 +272,8 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
}
}
protected boolean isFooterPosition(int position) {
// return hasFooterView() && position == getItemCount() - 1;
return false;
}
protected boolean isHeaderPosition(int position) {
// return hasHeaderView() && position == 0;
return false;
}
@Override
public long getHeaderId(int position) {
return -1; // no header Id.
// if (isActive()) return -1;
// if (isHeaderPosition(position)) return -1;
// if (isFooterPosition(position)) return -1;
// if (position >= getItemCount()) return -1;
// if (position < 0) return -1;
//
// MessageRecord record = getRecordForPositionOrThrow(position);
//
// calendar.setTime(new Date(record.getDateSent()));
// return Util.hashCode(calendar.get(Calendar.YEAR), calendar.get(Calendar.DAY_OF_YEAR));
}
public boolean isActive() {
return dcMsgList.length > 0;
}
public long getReceivedTimestamp(int position) {
if (isActive()) return 0;
if (isHeaderPosition(position)) return 0;
if (isFooterPosition(position)) return 0;
if (!isActive()) return 0;
if (position >= getItemCount()) return 0;
if (position < 0) return 0;
@@ -336,21 +286,10 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
return context;
}
@Override
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.conversation_item_header, parent, false));
}
public HeaderViewHolder onCreateLastSeenViewHolder(ViewGroup parent) {
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.conversation_item_last_seen, parent, false));
}
@Override
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
DcMsg msg = getMsg(position);
viewHolder.setText(DateUtils.getRelativeDate(getContext(), locale, msg.getTimestamp()));
}
public void onBindLastSeenViewHolder(HeaderViewHolder viewHolder, int position) {
viewHolder.setText(getContext().getResources().getQuantityString(R.plurals.ConversationAdapter_n_unread_messages, (position + 1), (position + 1)));
}
@@ -405,14 +344,40 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
}
}
public void changeData(@Nullable int[] dcMsgList) {
this.dcMsgList = dcMsgList==null? new int[0] : dcMsgList;
messageRecordCache.clear();
notifyDataSetChanged();
@Override
public long getHeaderId(int position) {
if (position >= getItemCount()) return -1;
if (position < 0) return -1;
DcMsg dcMsg = getMsg(position);
calendar.setTime(new Date(dcMsg.getTimestamp()));
return Util.hashCode(calendar.get(Calendar.YEAR), calendar.get(Calendar.DAY_OF_YEAR));
}
public void setHeaderView(@Nullable View headerView) {
// TODO: must not be implemented, remove calls to this function
@Override
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.conversation_item_header, parent, false));
}
@Override
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
DcMsg msg = getMsg(position);
viewHolder.setText(DateUtils.getRelativeDate(getContext(), locale, msg.getTimestamp()));
}
public void changeData(@Nullable int[] dcMsgList) {
// should be called when there are new messages
this.dcMsgList = dcMsgList==null? new int[0] : dcMsgList;
reloadData();
}
public void reloadData() {
// should be called when some items in a message are changed, eg. seen-state
messageRecordCache.clear();
notifyDataSetChanged();
}
public void addFastRecord(@NonNull MessageRecord record) {
@@ -549,7 +549,7 @@ public class ConversationFragment extends Fragment
MessageRecord messageRecord = DatabaseFactory.getMmsDatabase(getContext()).readerFor(message, threadId).getCurrent();
if (getListAdapter() != null) {
getListAdapter().setHeaderView(null);
//getListAdapter().setHeaderView(null);
setLastSeen(0);
getListAdapter().addFastRecord(messageRecord);
}
@@ -561,7 +561,7 @@ public class ConversationFragment extends Fragment
MessageRecord messageRecord = DatabaseFactory.getSmsDatabase(getContext()).readerFor(message, threadId).getCurrent();
if (getListAdapter() != null) {
getListAdapter().setHeaderView(null);
//getListAdapter().setHeaderView(null);
setLastSeen(0);
getListAdapter().addFastRecord(messageRecord);
}
@@ -99,7 +99,7 @@ public class ConversationItemFooter extends LinearLayout {
if (messageRecord.isFailed()) {
dateView.setText(R.string.ConversationItem_error_not_delivered);
} else {
dateView.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
dateView.setText(DateUtils.getTimeOfDayTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
}
}
@@ -91,6 +91,21 @@ public class DateUtils extends android.text.format.DateUtils {
}
}
public static String getTimeOfDayTimeSpanString(final Context c, final Locale locale, final long timestamp) {
if (isWithin(timestamp, 1, TimeUnit.MINUTES)) {
return c.getString(R.string.DateUtils_just_now);
} else if (isWithin(timestamp, 1, TimeUnit.HOURS)) {
int mins = (int)TimeUnit.MINUTES.convert(System.currentTimeMillis() - timestamp, TimeUnit.MILLISECONDS);
return c.getResources().getString(R.string.DateUtils_minutes_ago, mins);
} else {
StringBuilder format = new StringBuilder();
if (DateFormat.is24HourFormat(c)) format.append("HH:mm");
else format.append("hh:mm a");
return getFormattedDateTime(timestamp, format.toString(), locale);
}
}
public static String getDayPrecisionTimeSpanString(Context context, Locale locale, long timestamp) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");