diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 0c7292f51..0249275b5 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -182,6 +182,27 @@
/>
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/res/layout/activity_rss_feed_import.xml b/briar-android/res/layout/activity_rss_feed_import.xml
new file mode 100644
index 000000000..cf00f260f
--- /dev/null
+++ b/briar-android/res/layout/activity_rss_feed_import.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/res/layout/activity_rss_feed_manage.xml b/briar-android/res/layout/activity_rss_feed_manage.xml
new file mode 100644
index 000000000..a9fc464d9
--- /dev/null
+++ b/briar-android/res/layout/activity_rss_feed_manage.xml
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/list_item_rss_feed.xml b/briar-android/res/layout/list_item_rss_feed.xml
new file mode 100644
index 000000000..ffac010d0
--- /dev/null
+++ b/briar-android/res/layout/list_item_rss_feed.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/res/menu/blogs_feed_actions.xml b/briar-android/res/menu/blogs_feed_actions.xml
index 38721c812..22cf36961 100644
--- a/briar-android/res/menu/blogs_feed_actions.xml
+++ b/briar-android/res/menu/blogs_feed_actions.xml
@@ -9,4 +9,14 @@
android:title="@string/blogs_write_blog_post"
app:showAsAction="always"/>
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/menu/rss_feed_manage_actions.xml b/briar-android/res/menu/rss_feed_manage_actions.xml
new file mode 100644
index 000000000..c51bb7051
--- /dev/null
+++ b/briar-android/res/menu/rss_feed_manage_actions.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/briar-android/res/values/attrs.xml b/briar-android/res/values/attrs.xml
index 380379e9e..0de786b4b 100644
--- a/briar-android/res/values/attrs.xml
+++ b/briar-android/res/values/attrs.xml
@@ -2,6 +2,7 @@
+
\ No newline at end of file
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index c80a5d7b7..0c9ce8a08 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -309,4 +309,17 @@
Available Blogs
Drafts
+
+ Import RSS Feed
+ Import
+ Enter the URL of the RSS feed
+ We are sorry! There was an error importing your feed.
+ Manage RSS Feeds
+ Imported:
+ Author:
+ Last Updated:
+ The feed could not be deleted!
+ You haven\'t imported any RSS feeds.\n\nWhy don\'t you click the plus in the top right screen corner to add your first?
+ There was a problem loading your feeds. Please try again later.
+
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
index 3f3368b57..7d902e6b4 100644
--- a/briar-android/src/org/briarproject/android/ActivityComponent.java
+++ b/briar-android/src/org/briarproject/android/ActivityComponent.java
@@ -10,6 +10,8 @@ import org.briarproject.android.blogs.BlogsFragment;
import org.briarproject.android.blogs.CreateBlogActivity;
import org.briarproject.android.blogs.FeedFragment;
import org.briarproject.android.blogs.MyBlogsFragment;
+import org.briarproject.android.blogs.RssFeedImportActivity;
+import org.briarproject.android.blogs.RssFeedManageActivity;
import org.briarproject.android.blogs.WriteBlogPostActivity;
import org.briarproject.android.contact.ContactListFragment;
import org.briarproject.android.contact.ConversationActivity;
@@ -87,6 +89,10 @@ public interface ActivityComponent {
void inject(IntroductionActivity activity);
+ void inject(RssFeedImportActivity activity);
+
+ void inject(RssFeedManageActivity activity);
+
// Fragments
void inject(ContactListFragment fragment);
void inject(ForumListFragment fragment);
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
index accd45a4c..dbe923c95 100644
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -16,6 +16,7 @@ import org.briarproject.api.crypto.PasswordStrengthEstimator;
import org.briarproject.api.db.DatabaseConfig;
import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.event.EventBus;
+import org.briarproject.api.feed.FeedManager;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumPostFactory;
import org.briarproject.api.forum.ForumSharingManager;
@@ -112,6 +113,8 @@ public interface AndroidComponent extends CoreEagerSingletons {
AndroidExecutor androidExecutor();
+ FeedManager feedManager();
+
@IoExecutor
Executor ioExecutor();
diff --git a/briar-android/src/org/briarproject/android/blogs/FeedFragment.java b/briar-android/src/org/briarproject/android/blogs/FeedFragment.java
index 47d0cc427..30e8b6dae 100644
--- a/briar-android/src/org/briarproject/android/blogs/FeedFragment.java
+++ b/briar-android/src/org/briarproject/android/blogs/FeedFragment.java
@@ -140,20 +140,31 @@ public class FeedFragment extends BaseFragment implements
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
+ if (personalBlog == null) return false;
+ ActivityOptionsCompat options =
+ makeCustomAnimation(getActivity(), android.R.anim.slide_in_left,
+ android.R.anim.slide_out_right);
switch (item.getItemId()) {
case R.id.action_write_blog_post:
- if (personalBlog == null) return false;
- Intent i =
+ Intent i1 =
new Intent(getActivity(), WriteBlogPostActivity.class);
- i.putExtra(GROUP_ID, personalBlog.getId().getBytes());
- i.putExtra(BLOG_NAME, personalBlog.getName());
- ActivityOptionsCompat options =
- makeCustomAnimation(getActivity(),
- android.R.anim.slide_in_left,
- android.R.anim.slide_out_right);
- startActivityForResult(i, REQUEST_WRITE_POST,
+ i1.putExtra(GROUP_ID, personalBlog.getId().getBytes());
+ i1.putExtra(BLOG_NAME, personalBlog.getName());
+ startActivityForResult(i1, REQUEST_WRITE_POST,
options.toBundle());
return true;
+ case R.id.action_rss_feeds_import:
+ Intent i2 =
+ new Intent(getActivity(), RssFeedImportActivity.class);
+ i2.putExtra(GROUP_ID, personalBlog.getId().getBytes());
+ startActivity(i2, options.toBundle());
+ return true;
+ case R.id.action_rss_feeds_manage:
+ Intent i3 =
+ new Intent(getActivity(), RssFeedManageActivity.class);
+ i3.putExtra(GROUP_ID, personalBlog.getId().getBytes());
+ startActivity(i3, options.toBundle());
+ return true;
default:
return super.onOptionsItemSelected(item);
}
diff --git a/briar-android/src/org/briarproject/android/blogs/RssFeedAdapter.java b/briar-android/src/org/briarproject/android/blogs/RssFeedAdapter.java
new file mode 100644
index 000000000..2ad13eb34
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/blogs/RssFeedAdapter.java
@@ -0,0 +1,192 @@
+package org.briarproject.android.blogs;
+
+import android.app.Activity;
+import android.support.annotation.Nullable;
+import android.support.v7.util.SortedList;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.briarproject.R;
+import org.briarproject.android.util.AndroidUtils;
+import org.briarproject.api.feed.Feed;
+import org.briarproject.api.sync.GroupId;
+
+import java.util.Collection;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+class RssFeedAdapter extends
+ RecyclerView.Adapter {
+
+ private SortedList feeds = new SortedList<>(
+ Feed.class, new SortedList.Callback() {
+
+ @Override
+ public int compare(Feed a, Feed b) {
+ if (a == b) return 0;
+ long aTime = a.getAdded(), bTime = b.getAdded();
+ if (aTime > bTime) return -1;
+ if (aTime < bTime) return 1;
+ return 0;
+ }
+
+ @Override
+ public void onInserted(int position, int count) {
+ notifyItemRangeInserted(position, count);
+ }
+
+ @Override
+ public void onRemoved(int position, int count) {
+ notifyItemRangeRemoved(position, count);
+ }
+
+ @Override
+ public void onMoved(int fromPosition, int toPosition) {
+ notifyItemMoved(fromPosition, toPosition);
+ }
+
+ @Override
+ public void onChanged(int position, int count) {
+ notifyItemRangeChanged(position, count);
+ }
+
+ @Override
+ public boolean areContentsTheSame(Feed a, Feed b) {
+ return a.getUpdated() == b.getUpdated();
+ }
+
+ @Override
+ public boolean areItemsTheSame(Feed a, Feed b) {
+ return a.getUrl().equals(b.getUrl()) &&
+ a.getBlogId().equals(b.getBlogId()) &&
+ a.getAdded() == b.getAdded();
+ }
+ });
+
+ private final Activity ctx;
+ private final RssFeedListener listener;
+
+ RssFeedAdapter(Activity ctx, RssFeedListener listener) {
+ this.ctx = ctx;
+ this.listener = listener;
+ }
+
+ @Override
+ public FeedViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(ctx).inflate(
+ R.layout.list_item_rss_feed, parent, false);
+ return new FeedViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(FeedViewHolder ui, int position) {
+ final Feed item = getItem(position);
+
+ // Feed Title
+ if (item.getTitle() != null) {
+ ui.title.setText(item.getTitle());
+ ui.title.setVisibility(VISIBLE);
+ } else {
+ ui.title.setVisibility(GONE);
+ }
+
+ // Delete Button
+ ui.delete.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ listener.onDeleteClick(item);
+ }
+ });
+
+ // Author
+ if (item.getAuthor() != null) {
+ ui.author.setText(item.getAuthor());
+ ui.author.setVisibility(VISIBLE);
+ ui.authorLabel.setVisibility(VISIBLE);
+ } else {
+ ui.author.setVisibility(GONE);
+ ui.authorLabel.setVisibility(GONE);
+ }
+
+ // Imported and Last Updated
+ ui.imported.setText(AndroidUtils.formatDate(ctx, item.getAdded()));
+ ui.updated.setText(AndroidUtils.formatDate(ctx, item.getUpdated()));
+
+ // Description
+ if (item.getDescription() != null) {
+ ui.description.setText(item.getDescription());
+ ui.description.setVisibility(VISIBLE);
+ } else {
+ ui.description.setVisibility(GONE);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return feeds.size();
+ }
+
+ public Feed getItem(int position) {
+ return feeds.get(position);
+ }
+
+ @Nullable
+ public Feed getItem(GroupId g) {
+ for (int i = 0; i < feeds.size(); i++) {
+ Feed item = feeds.get(i);
+ if (item.getBlogId().equals(g)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public void addAll(Collection items) {
+ feeds.addAll(items);
+ }
+
+ public void remove(Feed item) {
+ feeds.remove(item);
+ }
+
+ public void clear() {
+ feeds.clear();
+ }
+
+ public boolean isEmpty() {
+ return feeds.size() == 0;
+ }
+
+ static class FeedViewHolder extends RecyclerView.ViewHolder {
+ private final TextView title;
+ private final ImageView delete;
+ private final TextView imported;
+ private final TextView updated;
+ private final TextView author;
+ private final TextView authorLabel;
+ private final TextView description;
+
+ FeedViewHolder(View v) {
+ super(v);
+
+ title = (TextView) v.findViewById(R.id.titleView);
+ delete = (ImageView) v.findViewById(R.id.deleteButton);
+ imported = (TextView) v.findViewById(R.id.importedView);
+ updated = (TextView) v.findViewById(R.id.updatedView);
+ author = (TextView) v.findViewById(R.id.authorView);
+ authorLabel = (TextView) v.findViewById(R.id.author);
+ description = (TextView) v.findViewById(R.id.descriptionView);
+ }
+ }
+
+ interface RssFeedListener {
+ void onDeleteClick(Feed feed);
+ }
+
+}
diff --git a/briar-android/src/org/briarproject/android/blogs/RssFeedImportActivity.java b/briar-android/src/org/briarproject/android/blogs/RssFeedImportActivity.java
new file mode 100644
index 000000000..c7d772cba
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/blogs/RssFeedImportActivity.java
@@ -0,0 +1,178 @@
+package org.briarproject.android.blogs;
+
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ProgressBar;
+
+import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
+import org.briarproject.android.BriarActivity;
+import org.briarproject.api.db.DbException;
+import org.briarproject.api.feed.FeedManager;
+import org.briarproject.api.lifecycle.IoExecutor;
+import org.briarproject.api.sync.GroupId;
+
+import java.io.IOException;
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static java.util.logging.Level.WARNING;
+
+public class RssFeedImportActivity extends BriarActivity {
+
+ private static final Logger LOG =
+ Logger.getLogger(RssFeedImportActivity.class.getName());
+
+ private EditText urlInput;
+ private Button importButton;
+ private ProgressBar progressBar;
+
+ @Inject
+ @IoExecutor
+ protected Executor ioExecutor;
+
+ // Fields that are accessed from background threads must be volatile
+ private volatile GroupId groupId = null;
+ @Inject
+ @SuppressWarnings("WeakerAccess")
+ volatile FeedManager feedManager;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // GroupId from Intent
+ Intent i = getIntent();
+ byte[] b = i.getByteArrayExtra(GROUP_ID);
+ if (b == null) throw new IllegalStateException("No Group in intent.");
+ groupId = new GroupId(b);
+
+ setContentView(R.layout.activity_rss_feed_import);
+
+ urlInput = (EditText) findViewById(R.id.urlInput);
+ urlInput.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before,
+ int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ enableOrDisableImportButton();
+ }
+ });
+
+ importButton = (Button) findViewById(R.id.importButton);
+ importButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ publish();
+ }
+ });
+
+ progressBar = (ProgressBar) findViewById(R.id.progressBar);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void injectActivity(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ private void enableOrDisableImportButton() {
+ String url = urlInput.getText().toString();
+ if (url.startsWith("http://") || url.startsWith("https://"))
+ importButton.setEnabled(true);
+ else
+ importButton.setEnabled(false);
+ }
+
+ private void publish() {
+ // hide import button, show progress bar
+ importButton.setVisibility(GONE);
+ progressBar.setVisibility(VISIBLE);
+
+ importFeed(urlInput.getText().toString());
+ }
+
+ private void importFeed(final String url) {
+ ioExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ feedManager.addFeed(url, groupId);
+ feedImported();
+ } catch (DbException | IOException e) {
+ if (LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ importFailed();
+ }
+ }
+ });
+ }
+
+ private void feedImported() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ supportFinishAfterTransition();
+ }
+ });
+ }
+
+ private void importFailed() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // hide progress bar, show publish button
+ progressBar.setVisibility(GONE);
+ importButton.setVisibility(VISIBLE);
+
+ // show error dialog
+ AlertDialog.Builder builder =
+ new AlertDialog.Builder(RssFeedImportActivity.this,
+ R.style.BriarDialogTheme);
+ builder.setMessage(R.string.blogs_rss_feeds_import_error);
+ builder.setNegativeButton(R.string.cancel_button, null);
+ builder.setPositiveButton(R.string.try_again_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ publish();
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+ });
+ }
+
+}
+
diff --git a/briar-android/src/org/briarproject/android/blogs/RssFeedManageActivity.java b/briar-android/src/org/briarproject/android/blogs/RssFeedManageActivity.java
new file mode 100644
index 000000000..69c50dde6
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/blogs/RssFeedManageActivity.java
@@ -0,0 +1,167 @@
+package org.briarproject.android.blogs;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.ActivityOptionsCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+
+import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
+import org.briarproject.android.BriarActivity;
+import org.briarproject.android.blogs.RssFeedAdapter.RssFeedListener;
+import org.briarproject.android.util.BriarRecyclerView;
+import org.briarproject.api.db.DbException;
+import org.briarproject.api.feed.Feed;
+import org.briarproject.api.feed.FeedManager;
+import org.briarproject.api.sync.GroupId;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static android.support.design.widget.Snackbar.LENGTH_LONG;
+import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
+import static java.util.logging.Level.WARNING;
+
+public class RssFeedManageActivity extends BriarActivity
+ implements RssFeedListener {
+
+ private static final Logger LOG =
+ Logger.getLogger(RssFeedManageActivity.class.getName());
+
+ private BriarRecyclerView list;
+ private RssFeedAdapter adapter;
+
+ // Fields that are accessed from background threads must be volatile
+ private volatile GroupId groupId = null;
+ @Inject
+ @SuppressWarnings("WeakerAccess")
+ volatile FeedManager feedManager;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // GroupId from Intent
+ Intent i = getIntent();
+ byte[] b = i.getByteArrayExtra(GROUP_ID);
+ if (b == null) throw new IllegalStateException("No Group in intent.");
+ groupId = new GroupId(b);
+
+ setContentView(R.layout.activity_rss_feed_manage);
+
+ adapter = new RssFeedAdapter(this, this);
+
+ list = (BriarRecyclerView) findViewById(R.id.feedList);
+ list.setLayoutManager(new LinearLayoutManager(this));
+ list.setAdapter(adapter);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ loadFeeds();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.rss_feed_manage_actions, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.action_rss_feeds_import:
+ Intent i =
+ new Intent(this, RssFeedImportActivity.class);
+ i.putExtra(GROUP_ID, groupId.getBytes());
+ ActivityOptionsCompat options =
+ makeCustomAnimation(this, android.R.anim.slide_in_left,
+ android.R.anim.slide_out_right);
+ ActivityCompat.startActivity(this, i, options.toBundle());
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public void injectActivity(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Override
+ public void onDeleteClick(final Feed feed) {
+ runOnDbThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ feedManager.removeFeed(feed.getUrl());
+ onFeedDeleted(feed);
+ } catch (DbException e) {
+ if (LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ onDeleteError();
+ }
+ }
+ });
+ }
+
+ private void loadFeeds() {
+ runOnDbThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ addFeeds(feedManager.getFeeds());
+ } catch (DbException e) {
+ if (LOG.isLoggable(WARNING))
+ LOG.log(WARNING, e.toString(), e);
+ list.setEmptyText(R.string.blogs_rss_feeds_manage_error);
+ list.showData();
+ }
+ }
+ });
+ }
+
+ private void addFeeds(final List feeds) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (feeds.size() == 0) list.showData();
+ else adapter.addAll(feeds);
+ }
+ });
+ }
+
+ private void onFeedDeleted(final Feed feed) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ adapter.remove(feed);
+ }
+ });
+ }
+
+ private void onDeleteError() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Snackbar.make(list,
+ R.string.blogs_rss_feeds_manage_delete_error,
+ LENGTH_LONG).show();
+ }
+ });
+ }
+}
+
diff --git a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
index 6c403747f..4c68c6fe1 100644
--- a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
+++ b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
@@ -47,6 +47,9 @@ public class BriarRecyclerView extends FrameLayout {
R.styleable.BriarRecyclerView);
isScrollingToEnd = attributes
.getBoolean(R.styleable.BriarRecyclerView_scrollToEnd, true);
+ String emtpyText =
+ attributes.getString(R.styleable.BriarRecyclerView_emptyText);
+ if (emtpyText != null) setEmptyText(emtpyText);
attributes.recycle();
}
@@ -94,6 +97,11 @@ public class BriarRecyclerView extends FrameLayout {
super.onItemRangeInserted(positionStart, itemCount);
if (itemCount > 0) showData();
}
+ @Override
+ public void onItemRangeRemoved(int positionStart, int itemCount) {
+ super.onItemRangeRemoved(positionStart, itemCount);
+ if (itemCount > 0) showData();
+ }
};
}