diff --git a/briar-android/res/layout/fragment_blog_post.xml b/briar-android/res/layout/fragment_blog_post.xml index bc1b87c2ab7a43e35c3190850344563bb49734e7..18ec1f417cd1f72ba54f917eabb8913ea2c04631 100644 --- a/briar-android/res/layout/fragment_blog_post.xml +++ b/briar-android/res/layout/fragment_blog_post.xml @@ -20,6 +20,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"/> + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + </FrameLayout> </ScrollView> diff --git a/briar-android/res/layout/fragment_blog_post_pager.xml b/briar-android/res/layout/fragment_blog_post_pager.xml index fe1c2568a1dd52acca61bb24414fd13a106e081b..626dcaf26e21df50e8349d692406ef4f0c4c3a4c 100644 --- a/briar-android/res/layout/fragment_blog_post_pager.xml +++ b/briar-android/res/layout/fragment_blog_post_pager.xml @@ -1,6 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.v4.view.ViewPager - android:id="@+id/pager" +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent"/> \ No newline at end of file + android:layout_height="match_parent"> + + <android.support.v4.view.ViewPager + android:id="@+id/pager" + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + +</FrameLayout> \ No newline at end of file diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 8ba94a5da8a251447bd9aeb4d4225a5eb074f0fe..e866545097665ba4ad001540e73f0e50ce157360 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -73,6 +73,7 @@ <string name="offline">Offline</string> <string name="send">Send</string> <string name="no_data">No data</string> + <string name="ellipsis">…</string> <!-- Contacts and Private Conversations--> <string name="no_contacts">It seems that you are new here and have no contacts yet.\n\nTap the + icon at the top and follow the instructions to add some friends to your list.\n\nPlease remember: You can only add new contacts face-to-face to prevent anyone from impersonating you or reading your messages in the future.</string> diff --git a/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java b/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java index ab513217afa2a58a0dea5220a7b8275e247a3921..3c4f1bc21bbee32c2be22b73ae56f772acb96c5a 100644 --- a/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java +++ b/briar-android/src/org/briarproject/android/blogs/BaseControllerImpl.java @@ -59,6 +59,9 @@ abstract class BaseControllerImpl extends DbControllerImpl @Override @CallSuper public void onStart() { + if (listener == null) + throw new IllegalStateException( + "OnBlogPostAddedListener needs to be attached"); eventBus.addListener(this); } diff --git a/briar-android/src/org/briarproject/android/blogs/BasePostFragment.java b/briar-android/src/org/briarproject/android/blogs/BasePostFragment.java index e340a3fcbacaae6337da5d22c3fc099b88a61ffd..06153e422f286c8278c811af08c4d1b53e32a9d0 100644 --- a/briar-android/src/org/briarproject/android/blogs/BasePostFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/BasePostFragment.java @@ -3,10 +3,12 @@ package org.briarproject.android.blogs; import android.os.Bundle; import android.support.annotation.CallSuper; import android.support.annotation.Nullable; +import android.support.annotation.UiThread; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.ProgressBar; import org.briarproject.R; import org.briarproject.android.fragment.BaseFragment; @@ -14,6 +16,8 @@ import org.briarproject.api.db.DbException; import java.util.logging.Logger; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; import static org.briarproject.android.util.AndroidUtils.MIN_RESOLUTION; public abstract class BasePostFragment extends BaseFragment { @@ -22,6 +26,7 @@ public abstract class BasePostFragment extends BaseFragment { Logger.getLogger(BasePostFragment.class.getName()); private View view; + private ProgressBar progressBar; private BlogPostViewHolder ui; private BlogPostItem post; private Runnable refresher; @@ -35,6 +40,8 @@ public abstract class BasePostFragment extends BaseFragment { view = inflater.inflate(R.layout.fragment_blog_post, container, false); + progressBar = (ProgressBar) view.findViewById(R.id.progressBar); + progressBar.setVisibility(VISIBLE); ui = new BlogPostViewHolder(view); return view; } @@ -46,6 +53,7 @@ public abstract class BasePostFragment extends BaseFragment { startPeriodicUpdate(); } + @CallSuper @Override public void onStop() { super.onStop(); @@ -63,12 +71,14 @@ public abstract class BasePostFragment extends BaseFragment { } } + @UiThread protected void onBlogPostLoaded(BlogPostItem post) { - listener.hideLoadingScreen(); + progressBar.setVisibility(INVISIBLE); this.post = post; ui.bindItem(post); } + @UiThread protected void onBlogPostLoadException(DbException exception) { // TODO: Decide how to handle errors in the UI finish(); diff --git a/briar-android/src/org/briarproject/android/blogs/BasePostPagerFragment.java b/briar-android/src/org/briarproject/android/blogs/BasePostPagerFragment.java index b24f6be3a9b424b8663a3d620e2507829060197c..e27c1470f5fe09d2e401b53189a5a8da3dfea3c9 100644 --- a/briar-android/src/org/briarproject/android/blogs/BasePostPagerFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/BasePostPagerFragment.java @@ -10,10 +10,10 @@ import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ProgressBar; import org.briarproject.R; import org.briarproject.android.blogs.BaseController.OnBlogPostAddedListener; -import org.briarproject.android.controller.handler.UiResultExceptionHandler; import org.briarproject.android.fragment.BaseFragment; import org.briarproject.api.blogs.BlogPostHeader; import org.briarproject.api.db.DbException; @@ -24,13 +24,17 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; import static org.briarproject.android.blogs.BasePostPagerFragment.BlogPostPagerAdapter.INVALID_POSITION; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; abstract class BasePostPagerFragment extends BaseFragment implements OnBlogPostAddedListener { + static final String POST_ID = "briar.POST_ID"; + private ViewPager pager; + private ProgressBar progressBar; private BlogPostPagerAdapter postPagerAdapter; private MessageId postId; @@ -49,9 +53,11 @@ abstract class BasePostPagerFragment extends BaseFragment View v = inflater.inflate(R.layout.fragment_blog_post_pager, container, false); + progressBar = (ProgressBar) v.findViewById(R.id.progressBar); + progressBar.setVisibility(VISIBLE); + pager = (ViewPager) v.findViewById(R.id.pager); postPagerAdapter = new BlogPostPagerAdapter(getChildFragmentManager()); - listener.showLoadingScreen(false, R.string.progress_title_please_wait); return v; } @@ -82,7 +88,7 @@ abstract class BasePostPagerFragment extends BaseFragment abstract void loadBlogPosts(final MessageId select); - abstract BaseController getController(); + abstract void loadBlogPost(BlogPostHeader header); protected void onBlogPostsLoaded(MessageId select, Collection<BlogPostItem> posts) { @@ -97,23 +103,6 @@ abstract class BasePostPagerFragment extends BaseFragment finish(); } - private void loadBlogPost(BlogPostHeader header) { - getController().loadBlogPost(header, - new UiResultExceptionHandler<BlogPostItem, DbException>( - getActivity()) { - @Override - public void onResultUi(BlogPostItem post) { - addPost(post); - } - - @Override - public void onExceptionUi(DbException exception) { - // TODO: Decide how to handle errors in the UI - finish(); - } - }); - } - @Nullable private MessageId getSelectedPost() { if (postPagerAdapter.getCount() == 0) return null; @@ -124,6 +113,7 @@ abstract class BasePostPagerFragment extends BaseFragment private void selectPost(MessageId m) { int pos = postPagerAdapter.getPostPosition(m); if (pos != INVALID_POSITION) { + progressBar.setVisibility(INVISIBLE); pager.setAdapter(postPagerAdapter); pager.setCurrentItem(pos); } diff --git a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java b/briar-android/src/org/briarproject/android/blogs/BlogActivity.java index 34ba66f98202769f694840933ec0e6247b7f0ee3..bb7a5cc8d3ec4f6f3f86ba492e8606591aaa0fe0 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogActivity.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogActivity.java @@ -7,10 +7,8 @@ import android.widget.ProgressBar; import org.briarproject.R; import org.briarproject.android.ActivityComponent; import org.briarproject.android.BriarActivity; -import org.briarproject.android.blogs.BaseController.OnBlogPostAddedListener; import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener; import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener; -import org.briarproject.api.blogs.BlogPostHeader; import org.briarproject.api.sync.GroupId; import javax.inject.Inject; @@ -19,13 +17,12 @@ import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; public class BlogActivity extends BriarActivity implements - OnBlogPostAddedListener, OnBlogPostClickListener, BaseFragmentListener { + OnBlogPostClickListener, BaseFragmentListener { static final int REQUEST_WRITE_POST = 1; static final int REQUEST_SHARE = 2; static final String BLOG_NAME = "briar.BLOG_NAME"; static final String IS_NEW_BLOG = "briar.IS_NEW_BLOG"; - static final String POST_ID = "briar.POST_ID"; private ProgressBar progressBar; @@ -61,22 +58,11 @@ public class BlogActivity extends BriarActivity implements } } - @Override - public void onResume() { - super.onResume(); - } - @Override public void injectActivity(ActivityComponent component) { component.inject(this); } - @Override - public void onBlogPostAdded(BlogPostHeader header, boolean local) { - // all our fragments are implementing and registering that hook, - // so we don't need to do that ourselves - } - @Override public void onBlogPostClick(BlogPostItem post) { BlogPostPagerFragment f = BlogPostPagerFragment.newInstance(post.getId()); diff --git a/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java b/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java index 55615009f60918b2dc099440f63fca873c48ef4e..ad7b7597d2e40387fb7acb3f0e1f518d68810fa8 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogControllerImpl.java @@ -35,13 +35,6 @@ public class BlogControllerImpl extends BaseControllerImpl @Override public void onActivityCreate() { - if (activity instanceof OnBlogPostAddedListener) { - listener = (OnBlogPostAddedListener) activity; - } else { - throw new IllegalStateException( - "An activity that injects the BlogController must " + - "implement the OnBlogPostAddedListener"); - } } @Override diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java b/briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java index b70a360625afa89b6754c3212768efa03db68b0f..39c1bf3a5d80e8688e0aa6675b87321f5c22c673 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogPostFragment.java @@ -13,7 +13,7 @@ import org.briarproject.api.sync.MessageId; import javax.inject.Inject; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; +import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID; public class BlogPostFragment extends BasePostFragment { diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostPagerFragment.java b/briar-android/src/org/briarproject/android/blogs/BlogPostPagerFragment.java index 54e646f9cf58ea37ed1c0b108782ffceefc512ce..3a68030a1ea45446331531d3777025a2884f656a 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogPostPagerFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogPostPagerFragment.java @@ -4,6 +4,7 @@ import android.os.Bundle; import org.briarproject.android.ActivityComponent; import org.briarproject.android.controller.handler.UiResultExceptionHandler; +import org.briarproject.api.blogs.BlogPostHeader; import org.briarproject.api.db.DbException; import org.briarproject.api.sync.MessageId; @@ -11,8 +12,6 @@ import java.util.Collection; import javax.inject.Inject; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; - public class BlogPostPagerFragment extends BasePostPagerFragment { @@ -42,10 +41,6 @@ public class BlogPostPagerFragment extends BasePostPagerFragment { return TAG; } - @Override - BaseController getController() { - return blogController; - } void loadBlogPosts(final MessageId select) { blogController.loadBlogPosts( @@ -63,4 +58,21 @@ public class BlogPostPagerFragment extends BasePostPagerFragment { }); } + void loadBlogPost(BlogPostHeader header) { + blogController.loadBlogPost(header, + new UiResultExceptionHandler<BlogPostItem, DbException>( + getActivity()) { + @Override + public void onResultUi(BlogPostItem post) { + addPost(post); + } + + @Override + public void onExceptionUi(DbException exception) { + // TODO: Decide how to handle errors in the UI + finish(); + } + }); + } + } diff --git a/briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java b/briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java index e9a99449e0fde91ba61b2468449f6f3394fd4956..13a1b3f177215d6b94b9bf23f689bf3891cd4316 100644 --- a/briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java +++ b/briar-android/src/org/briarproject/android/blogs/BlogPostViewHolder.java @@ -6,13 +6,8 @@ import android.content.Intent; import android.support.annotation.UiThread; import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; -import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewCompat; import android.support.v7.widget.RecyclerView; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -32,14 +27,14 @@ import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAn import static android.view.View.GONE; import static android.view.View.VISIBLE; import static org.briarproject.android.BriarActivity.GROUP_ID; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; +import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID; +import static org.briarproject.android.util.AndroidUtils.TEASER_LENGTH; +import static org.briarproject.android.util.AndroidUtils.getTeaser; import static org.briarproject.api.blogs.MessageType.POST; @UiThread class BlogPostViewHolder extends RecyclerView.ViewHolder { - private static final int TEASER_LENGTH = 240; - private final Context ctx; private final ViewGroup layout; private final AuthorView reblogger; @@ -119,7 +114,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder { } else { body.setTextIsSelectable(false); if (item.getBody().length() > TEASER_LENGTH) - bodyText = getTeaser(item.getBody()); + bodyText = getTeaser(ctx, item.getBody()); } body.setText(bodyText); @@ -176,20 +171,4 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder { commentContainer.addView(v); } } - - private SpannableStringBuilder getTeaser(String body) { - SpannableStringBuilder builder = - new SpannableStringBuilder(body.substring(0, TEASER_LENGTH)); - builder.append("… "); - - Spannable readMore = - new SpannableString(ctx.getString(R.string.read_more) + "…"); - ForegroundColorSpan fg = new ForegroundColorSpan( - ContextCompat.getColor(ctx, R.color.briar_text_link)); - readMore.setSpan(fg, 0, readMore.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - builder.append(readMore); - - return builder; - } } diff --git a/briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java b/briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java index 5b4841cd4167507839f21fccf10755d99e9d4111..807bcd6e34f69b06d1a971b54f44d2516df0514e 100644 --- a/briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/FeedPostFragment.java @@ -15,7 +15,7 @@ import org.briarproject.api.sync.MessageId; import javax.inject.Inject; import static org.briarproject.android.BriarActivity.GROUP_ID; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; +import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID; public class FeedPostFragment extends BasePostFragment { diff --git a/briar-android/src/org/briarproject/android/blogs/FeedPostPagerFragment.java b/briar-android/src/org/briarproject/android/blogs/FeedPostPagerFragment.java index db30ac1f3cd06cbeeeeaa8b39af95d275f3101b5..df2c4e33ecc1c33ea7ef4b0c19e973cede142cc5 100644 --- a/briar-android/src/org/briarproject/android/blogs/FeedPostPagerFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/FeedPostPagerFragment.java @@ -4,6 +4,7 @@ import android.os.Bundle; import org.briarproject.android.ActivityComponent; import org.briarproject.android.controller.handler.UiResultExceptionHandler; +import org.briarproject.api.blogs.BlogPostHeader; import org.briarproject.api.db.DbException; import org.briarproject.api.sync.MessageId; @@ -11,8 +12,6 @@ import java.util.Collection; import javax.inject.Inject; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; - public class FeedPostPagerFragment extends BasePostPagerFragment { public final static String TAG = FeedPostPagerFragment.class.getName(); @@ -41,10 +40,6 @@ public class FeedPostPagerFragment extends BasePostPagerFragment { return TAG; } - @Override - BaseController getController() { - return feedController; - } void loadBlogPosts(final MessageId select) { feedController.loadBlogPosts( @@ -62,4 +57,21 @@ public class FeedPostPagerFragment extends BasePostPagerFragment { }); } + void loadBlogPost(BlogPostHeader header) { + feedController.loadBlogPost(header, + new UiResultExceptionHandler<BlogPostItem, DbException>( + getActivity()) { + @Override + public void onResultUi(BlogPostItem post) { + addPost(post); + } + + @Override + public void onExceptionUi(DbException exception) { + // TODO: Decide how to handle errors in the UI + finish(); + } + }); + } + } diff --git a/briar-android/src/org/briarproject/android/blogs/ReblogActivity.java b/briar-android/src/org/briarproject/android/blogs/ReblogActivity.java index 923d520a65053f6d7adfc3c2e7ab03c977acf2f8..6b4afb89bac8121f8dfac031bc6c60b783cf2512 100644 --- a/briar-android/src/org/briarproject/android/blogs/ReblogActivity.java +++ b/briar-android/src/org/briarproject/android/blogs/ReblogActivity.java @@ -15,7 +15,7 @@ import org.briarproject.android.fragment.BaseFragment.BaseFragmentListener; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; +import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID; public class ReblogActivity extends BriarActivity implements BaseFragmentListener { diff --git a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java b/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java index 1fee6c6473124c6d2893cbcb5bd01d3e33fe6274..87ac6138050e313e02938d23e2e877f54df0f830 100644 --- a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java +++ b/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java @@ -27,7 +27,7 @@ import static android.view.View.GONE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static org.briarproject.android.BriarActivity.GROUP_ID; -import static org.briarproject.android.blogs.BlogActivity.POST_ID; +import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID; public class ReblogFragment extends BaseFragment { diff --git a/briar-android/src/org/briarproject/android/util/AndroidUtils.java b/briar-android/src/org/briarproject/android/util/AndroidUtils.java index 610e480e51bb684d2a03cef9f590dc92bb484436..66593d0f8281c64d45d9ea9517bf9655840756c1 100644 --- a/briar-android/src/org/briarproject/android/util/AndroidUtils.java +++ b/briar-android/src/org/briarproject/android/util/AndroidUtils.java @@ -6,7 +6,12 @@ import android.content.Context; import android.os.Build; import android.provider.Settings; import android.support.design.widget.TextInputLayout; +import android.support.v4.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; import android.text.format.DateUtils; +import android.text.style.ForegroundColorSpan; import org.briarproject.R; import org.briarproject.util.IoUtils; @@ -31,6 +36,7 @@ import static android.text.format.DateUtils.WEEK_IN_MILLIS; public class AndroidUtils { public static final long MIN_RESOLUTION = MINUTE_IN_MILLIS; + public static final int TEASER_LENGTH = 240; // Fake Bluetooth address returned by BluetoothAdapter on API 23 and later private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00"; @@ -115,4 +121,25 @@ public class AndroidUtils { MIN_RESOLUTION, flags).toString(); } + public static SpannableStringBuilder getTeaser(Context ctx, String body) { + if (body.length() < TEASER_LENGTH) + throw new IllegalArgumentException( + "String is shorter than TEASER_LENGTH"); + + SpannableStringBuilder builder = + new SpannableStringBuilder(body.substring(0, TEASER_LENGTH)); + String ellipsis = ctx.getString(R.string.ellipsis); + builder.append(ellipsis).append(" "); + + Spannable readMore = new SpannableString( + ctx.getString(R.string.read_more) + ellipsis); + ForegroundColorSpan fg = new ForegroundColorSpan( + ContextCompat.getColor(ctx, R.color.briar_text_link)); + readMore.setSpan(fg, 0, readMore.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.append(readMore); + + return builder; + } + }