diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 1618f97e3462bad1490e8c0c05bc40a51254b947..6e1ed6026b1e69b2e9f220c6bcf21fc3baf767ba 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -38,6 +38,7 @@ <string name="forums_button">Forums</string> <string name="settings_button">Settings</string> <string name="sign_out_button">Sign Out</string> + <string name="now">now</string> <string name="contact_list_title">Contacts</string> <string name="no_contacts">No contacts</string> <string name="add_contact_title">Add a Contact</string> diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java index e76c39e86fc229ad968cc6917318507e08905144..117191f2205faa8437af3107b626428d7a9b4a11 100644 --- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java +++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java @@ -146,6 +146,7 @@ public class ContactListFragment extends BaseFragment implements EventListener { list.setLayoutManager(new LinearLayoutManager(getContext())); list.setAdapter(adapter); list.setEmptyText(getString(R.string.no_contacts)); + list.periodicallyUpdateContent(); // Show a floating action button FloatingActionButton fab = diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index 46a40ba0f7512c3232e1a2124736a37da5a849cb..647cea18314fdbef2d7efe8c39729ab00fc8d129 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -167,6 +167,7 @@ public class ConversationActivity extends BriarActivity list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); list.setEmptyText(getString(R.string.no_private_messages)); + list.periodicallyUpdateContent(); content = (EditText) findViewById(R.id.input_text); sendButton = findViewById(R.id.btn_send); diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java index 2657715b2d036169a1ba4b1b3c2ae1dda97f6247..665b80e49573c5d3415f8f7c6fdeadb2a66233a7 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java +++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java @@ -121,6 +121,7 @@ public class ForumActivity extends BriarActivity implements forumAdapter = new ForumAdapter( forumController.getForumEntries()); recyclerView.setAdapter(forumAdapter); + recyclerView.periodicallyUpdateContent(); if (state != null) { byte[] replyId = state.getByteArray(KEY_REPLY_ID); diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java index 0a1cb32ef58ca3c17f7a59aceb71602ca97f5157..d8c5c81bde9058b91ddcda96eb0df4837ea51298 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java +++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java @@ -86,6 +86,7 @@ public class ForumListFragment extends BaseEventFragment implements list.setLayoutManager(new LinearLayoutManager(getActivity())); list.setAdapter(adapter); list.setEmptyText(getString(R.string.no_forums)); + list.periodicallyUpdateContent(); snackbar = Snackbar.make(list, "", LENGTH_INDEFINITE); snackbar.getView().setBackgroundResource(R.color.briar_primary); diff --git a/briar-android/src/org/briarproject/android/util/AndroidUtils.java b/briar-android/src/org/briarproject/android/util/AndroidUtils.java index af9cc2ae05019165d74a0df10f6fe17d4039a8d4..252d955749a925f725aacaf44432ef6d3ac78fe4 100644 --- a/briar-android/src/org/briarproject/android/util/AndroidUtils.java +++ b/briar-android/src/org/briarproject/android/util/AndroidUtils.java @@ -8,6 +8,7 @@ import android.provider.Settings; import android.support.design.widget.TextInputLayout; import android.text.format.DateUtils; +import org.briarproject.R; import org.briarproject.util.FileUtils; import org.briarproject.util.StringUtils; @@ -91,13 +92,15 @@ public class AndroidUtils { } public static String formatDate(Context ctx, long time) { + // update BriarRecyclerView#DEFAULT_REFRESH_INTERVAL along with this long minResolution = MINUTE_IN_MILLIS; int flags = FORMAT_ABBREV_RELATIVE | FORMAT_SHOW_DATE | FORMAT_ABBREV_TIME | FORMAT_ABBREV_MONTH; - // also show time when older than a day, but newer than a week long diff = System.currentTimeMillis() - time; + if (diff < minResolution) return ctx.getString(R.string.now); if (diff >= DAY_IN_MILLIS && diff < WEEK_IN_MILLIS) { + // also show time when older than a day, but newer than a week return DateUtils.getRelativeDateTimeString(ctx, time, minResolution, WEEK_IN_MILLIS, flags).toString(); } diff --git a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java index e399ecda03ff693693a86c8cfa30b2c6e11bf3dc..7563354b65a1e335961c3348f76e52d424705259 100644 --- a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java +++ b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.os.Build; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.Adapter; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -13,34 +14,51 @@ import android.widget.TextView; import org.briarproject.R; +import java.util.logging.Logger; + +import static android.text.format.DateUtils.MINUTE_IN_MILLIS; + public class BriarRecyclerView extends FrameLayout { private RecyclerView recyclerView; private TextView emptyView; private ProgressBar progressBar; private RecyclerView.AdapterDataObserver emptyObserver; + private Runnable refresher = null; private boolean isScrollingToEnd = false; + private final Logger LOG = Logger.getLogger(getClass().getName()); + private final long DEFAULT_REFRESH_INTERVAL = MINUTE_IN_MILLIS; + public BriarRecyclerView(Context context) { - super(context); + this(context, null, 0); } public BriarRecyclerView(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); + } + + public BriarRecyclerView(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.BriarRecyclerView); isScrollingToEnd = attributes .getBoolean(R.styleable.BriarRecyclerView_scrollToEnd, true); + attributes.recycle(); } - public BriarRecyclerView(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (refresher != null) { + LOG.info("Removing Handler Callback"); + removeCallbacks(refresher); + } } private void initViews() { - View v = LayoutInflater.from(getContext()).inflate( R.layout.briar_recycler_view, this, true); @@ -86,10 +104,10 @@ public class BriarRecyclerView extends FrameLayout { recyclerView.setLayoutManager(layout); } - public void setAdapter(RecyclerView.Adapter adapter) { + public void setAdapter(Adapter adapter) { if (recyclerView == null) initViews(); - RecyclerView.Adapter oldAdapter = recyclerView.getAdapter(); + Adapter oldAdapter = recyclerView.getAdapter(); if (oldAdapter != null) { oldAdapter.unregisterAdapterDataObserver(emptyObserver); } @@ -121,7 +139,7 @@ public class BriarRecyclerView extends FrameLayout { public void showData() { if (recyclerView == null) initViews(); - RecyclerView.Adapter adapter = recyclerView.getAdapter(); + Adapter adapter = recyclerView.getAdapter(); if (adapter != null) { if (adapter.getItemCount() == 0) { emptyView.setVisibility(VISIBLE); @@ -144,4 +162,20 @@ public class BriarRecyclerView extends FrameLayout { return this.recyclerView; } + public void periodicallyUpdateContent() { + if (recyclerView == null || recyclerView.getAdapter() == null) { + throw new IllegalStateException("Need to call setAdapter() first!"); + } + refresher = new Runnable() { + @Override + public void run() { + LOG.info("Updating Content..."); + recyclerView.getAdapter().notifyDataSetChanged(); + postDelayed(refresher, DEFAULT_REFRESH_INTERVAL); + } + }; + LOG.info("Adding Handler Callback"); + postDelayed(refresher, DEFAULT_REFRESH_INTERVAL); + } + }