diff --git a/app/src/main/java/com/keylesspalace/tusky/FooterViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/FooterViewHolder.java index 6ebe217ff..e39ca44af 100644 --- a/app/src/main/java/com/keylesspalace/tusky/FooterViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/FooterViewHolder.java @@ -23,6 +23,8 @@ class FooterViewHolder extends RecyclerView.ViewHolder { FooterViewHolder(View itemView) { super(itemView); ProgressBar progressBar = (ProgressBar) itemView.findViewById(R.id.footer_progress_bar); - progressBar.setIndeterminate(true); + if (progressBar != null) { + progressBar.setIndeterminate(true); + } } } \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/NotificationsAdapter.java index ea45b0782..64ecb722a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/NotificationsAdapter.java @@ -42,9 +42,16 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe private static final int VIEW_TYPE_STATUS_NOTIFICATION = 2; private static final int VIEW_TYPE_FOLLOW = 3; + enum FooterState { + EMPTY, + END, + LOADING + } + private List notifications; private StatusActionListener statusListener; private NotificationActionListener notificationActionListener; + private FooterState footerState = FooterState.END; NotificationsAdapter(StatusActionListener statusListener, NotificationActionListener notificationActionListener) { @@ -54,6 +61,15 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe this.notificationActionListener = notificationActionListener; } + + public void setFooterState(FooterState newFooterState) { + FooterState oldValue = footerState; + footerState = newFooterState; + if (footerState != oldValue) { + notifyItemChanged(notifications.size()); + } + } + @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { @@ -64,8 +80,24 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe return new StatusViewHolder(view); } case VIEW_TYPE_FOOTER: { - View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.item_footer, parent, false); + View view; + switch (footerState) { + default: + case LOADING: + view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_footer, parent, false); + break; + case END: { + view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_footer_end, parent, false); + break; + } + case EMPTY: { + view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_footer_empty, parent, false); + break; + } + } return new FooterViewHolder(view); } case VIEW_TYPE_STATUS_NOTIFICATION: { diff --git a/app/src/main/java/com/keylesspalace/tusky/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/NotificationsFragment.java index 152a67eed..b754e6c41 100644 --- a/app/src/main/java/com/keylesspalace/tusky/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/NotificationsFragment.java @@ -144,6 +144,10 @@ public class NotificationsFragment extends SFragment implements private void sendFetchNotificationsRequest(final String fromId, String uptoId) { MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI; + if (fromId != null || adapter.getItemCount() <= 1) { + adapter.setFooterState(NotificationsAdapter.FooterState.LOADING); + } + listCall = api.notifications(fromId, uptoId, null); listCall.enqueue(new Callback>() { @@ -192,6 +196,11 @@ public class NotificationsFragment extends SFragment implements } else { adapter.update(notifications); } + if (notifications.size() == 0 && adapter.getItemCount() == 1) { + adapter.setFooterState(NotificationsAdapter.FooterState.EMPTY); + } else if (fromId != null) { + adapter.setFooterState(NotificationsAdapter.FooterState.END); + } swipeRefreshLayout.setRefreshing(false); } diff --git a/app/src/main/java/com/keylesspalace/tusky/TimelineAdapter.java b/app/src/main/java/com/keylesspalace/tusky/TimelineAdapter.java index 8f8fc5460..a6c1367ee 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TimelineAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/TimelineAdapter.java @@ -30,8 +30,15 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover private static final int VIEW_TYPE_STATUS = 0; private static final int VIEW_TYPE_FOOTER = 1; + enum FooterState { + EMPTY, + END, + LOADING + } + private List statuses; private StatusActionListener statusListener; + private FooterState footerState = FooterState.END; TimelineAdapter(StatusActionListener statusListener) { super(); @@ -49,13 +56,37 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover return new StatusViewHolder(view); } case VIEW_TYPE_FOOTER: { - View view = LayoutInflater.from(viewGroup.getContext()) - .inflate(R.layout.item_footer, viewGroup, false); + View view; + switch (footerState) { + default: + case LOADING: + view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_footer, viewGroup, false); + break; + case END: { + view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_footer_end, viewGroup, false); + break; + } + case EMPTY: { + view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_footer_empty, viewGroup, false); + break; + } + } return new FooterViewHolder(view); } } } + public void setFooterState(FooterState newFooterState) { + FooterState oldValue = footerState; + footerState = newFooterState; + if (footerState != oldValue) { + notifyItemChanged(statuses.size()); + } + } + @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { if (position < statuses.size()) { diff --git a/app/src/main/java/com/keylesspalace/tusky/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/TimelineFragment.java index 4f1b6e205..be220cfe9 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/TimelineFragment.java @@ -214,6 +214,10 @@ public class TimelineFragment extends SFragment implements private void sendFetchTimelineRequest(@Nullable final String fromId, @Nullable String uptoId) { MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI; + if (fromId != null || adapter.getItemCount() <= 1) { + adapter.setFooterState(TimelineAdapter.FooterState.LOADING); + } + Callback> cb = new Callback>() { @Override public void onResponse(Call> call, retrofit2.Response> response) { @@ -282,6 +286,11 @@ public class TimelineFragment extends SFragment implements } else { adapter.update(statuses); } + if (statuses.size() == 0 && adapter.getItemCount() == 1) { + adapter.setFooterState(TimelineAdapter.FooterState.EMPTY); + } else if(fromId != null) { + adapter.setFooterState(TimelineAdapter.FooterState.END); + } swipeRefreshLayout.setRefreshing(false); } diff --git a/app/src/main/res/layout/item_footer_empty.xml b/app/src/main/res/layout/item_footer_empty.xml new file mode 100644 index 000000000..1c5606d22 --- /dev/null +++ b/app/src/main/res/layout/item_footer_empty.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_footer_end.xml b/app/src/main/res/layout/item_footer_end.xml new file mode 100644 index 000000000..584de324b --- /dev/null +++ b/app/src/main/res/layout/item_footer_end.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d053474e..534693cab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -38,6 +38,7 @@ end of the statuses end of the notifications end of the accounts + There are no toots here so far. Pull down to refresh! %s boosted your toot %s favourited your toot