diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index ba3c1426..12570935 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -37,7 +37,6 @@ import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.squareup.picasso.Picasso; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; public class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRemover { @@ -56,6 +55,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte private StatusActionListener statusListener; private NotificationActionListener notificationActionListener; private FooterState footerState = FooterState.END; + private boolean mediaPreviewEnabled; public NotificationsAdapter(StatusActionListener statusListener, NotificationActionListener notificationActionListener) { @@ -63,15 +63,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte notifications = new ArrayList<>(); this.statusListener = statusListener; this.notificationActionListener = notificationActionListener; - } - - - public void setFooterState(FooterState newFooterState) { - FooterState oldValue = footerState; - footerState = newFooterState; - if (footerState != oldValue) { - notifyItemChanged(notifications.size()); - } + mediaPreviewEnabled = true; } @Override @@ -126,7 +118,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte case MENTION: { StatusViewHolder holder = (StatusViewHolder) viewHolder; Status status = notification.status; - holder.setupWithStatus(status, statusListener); + holder.setupWithStatus(status, statusListener, mediaPreviewEnabled); break; } case FAVOURITE: @@ -139,8 +131,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte } case FOLLOW: { FollowViewHolder holder = (FollowViewHolder) viewHolder; - holder.setMessage(notification.account.getDisplayName(), notification.account.username, - notification.account.avatar); + holder.setMessage(notification.account.getDisplayName(), + notification.account.username, notification.account.avatar); holder.setupButtons(notificationActionListener, notification.account.id); break; } @@ -175,6 +167,25 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte } } + @Override + public void removeItem(int position) { + notifications.remove(position); + notifyItemChanged(position); + } + + @Override + public void removeAllByAccountId(String id) { + for (int i = 0; i < notifications.size();) { + Notification notification = notifications.get(i); + if (id.equals(notification.account.id)) { + notifications.remove(i); + notifyItemRemoved(i); + } else { + i += 1; + } + } + } + public @Nullable Notification getItem(int position) { if (position >= 0 && position < notifications.size()) { return notifications.get(position); @@ -209,25 +220,23 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte notifyItemRangeInserted(end, new_notifications.size()); } - @Override - public void removeItem(int position) { - notifications.remove(position); - notifyItemChanged(position); + public void clear() { + notifications.clear(); + notifyDataSetChanged(); } - @Override - public void removeAllByAccountId(String id) { - for (int i = 0; i < notifications.size();) { - Notification notification = notifications.get(i); - if (id.equals(notification.account.id)) { - notifications.remove(i); - notifyItemRemoved(i); - } else { - i += 1; - } + public void setFooterState(FooterState newFooterState) { + FooterState oldValue = footerState; + footerState = newFooterState; + if (footerState != oldValue) { + notifyItemChanged(notifications.size()); } } + public void setMediaPreviewEnabled(boolean enabled) { + mediaPreviewEnabled = enabled; + } + public interface NotificationActionListener { void onViewAccount(String id); } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java index d529cf04..60900824 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java @@ -16,8 +16,11 @@ package com.keylesspalace.tusky.adapter; import android.content.Context; +import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; +import android.support.annotation.DrawableRes; import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.text.Spanned; import android.view.View; @@ -60,6 +63,7 @@ class StatusViewHolder extends RecyclerView.ViewHolder { private ImageView mediaPreview2; private ImageView mediaPreview3; private View sensitiveMediaWarning; + private TextView mediaLabel; private View contentWarningBar; private TextView contentWarningDescription; private ToggleButton contentWarningButton; @@ -85,6 +89,7 @@ class StatusViewHolder extends RecyclerView.ViewHolder { mediaPreview2 = (ImageView) itemView.findViewById(R.id.status_media_preview_2); mediaPreview3 = (ImageView) itemView.findViewById(R.id.status_media_preview_3); sensitiveMediaWarning = itemView.findViewById(R.id.status_sensitive_media_warning); + mediaLabel = (TextView) itemView.findViewById(R.id.status_media_label); contentWarningBar = itemView.findViewById(R.id.status_content_warning_bar); contentWarningDescription = (TextView) itemView.findViewById(R.id.status_content_warning_description); @@ -187,8 +192,8 @@ class StatusViewHolder extends RecyclerView.ViewHolder { favouriteButton.setChecked(favourited); } - private void setMediaPreviews(final Status.MediaAttachment[] attachments, - boolean sensitive, final StatusActionListener listener) { + private void setMediaPreviews(final Status.MediaAttachment[] attachments, boolean sensitive, + final StatusActionListener listener) { final ImageView[] previews = { mediaPreview0, mediaPreview1, @@ -212,7 +217,7 @@ class StatusViewHolder extends RecyclerView.ViewHolder { previews[i].setVisibility(View.VISIBLE); - if(previewUrl == null || previewUrl.isEmpty()) { + if (previewUrl == null || previewUrl.isEmpty()) { Picasso.with(context) .load(mediaPreviewUnloadedId) .into(previews[i]); @@ -254,6 +259,62 @@ class StatusViewHolder extends RecyclerView.ViewHolder { } } + private static String getLabelTypeText(Context context, Status.MediaAttachment.Type type) { + switch (type) { + default: + case IMAGE: return context.getString(R.string.status_media_images); + case GIFV: + case VIDEO: return context.getString(R.string.status_media_video); + } + } + + private static @DrawableRes int getLabelIcon(Status.MediaAttachment.Type type) { + switch (type) { + default: + case IMAGE: return R.drawable.ic_photo_24dp; + case GIFV: + case VIDEO: return R.drawable.ic_videocam_24dp; + } + } + + private void setMediaLabel(Status.MediaAttachment[] attachments, boolean sensitive, + final StatusActionListener listener) { + if (attachments.length == 0) { + mediaLabel.setVisibility(View.GONE); + return; + } + mediaLabel.setVisibility(View.VISIBLE); + + // Set the label's text. + Context context = itemView.getContext(); + String labelText = getLabelTypeText(context, attachments[0].type); + if (sensitive) { + String sensitiveText = context.getString(R.string.status_sensitive_media_title); + labelText += String.format(" (%s)", sensitiveText); + } + mediaLabel.setText(labelText); + + // Set the icon next to the label. + int drawableId = getLabelIcon(attachments[0].type); + Drawable drawable = ContextCompat.getDrawable(context, drawableId); + ThemeUtils.setDrawableTint(context, drawable, android.R.attr.textColorTertiary); + mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); + + // Set the listener for the media view action. + int n = Math.min(attachments.length, Status.MAX_MEDIA_ATTACHMENTS); + final String[] urls = new String[n]; + for (int i = 0; i < n; i++) { + urls[i] = attachments[i].url; + } + final Status.MediaAttachment.Type type = attachments[0].type; + mediaLabel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onViewMedia(urls, 0, type); + } + }); + } + private void hideSensitiveMediaWarning() { sensitiveMediaWarning.setVisibility(View.GONE); } @@ -302,20 +363,20 @@ class StatusViewHolder extends RecyclerView.ViewHolder { } }); reblogButton.setEventListener(new SparkEventListener() { - @Override - public void onEvent(ImageView button, boolean buttonState) { - int position = getAdapterPosition(); - if (position != RecyclerView.NO_POSITION) { - listener.onReblog(!reblogged, position); - } - } + @Override + public void onEvent(ImageView button, boolean buttonState) { + int position = getAdapterPosition(); + if (position != RecyclerView.NO_POSITION) { + listener.onReblog(!reblogged, position); + } + } - @Override - public void onEventAnimationEnd(ImageView button, boolean buttonState) {} + @Override + public void onEventAnimationEnd(ImageView button, boolean buttonState) {} - @Override - public void onEventAnimationStart(ImageView button, boolean buttonState) {} - }); + @Override + public void onEventAnimationStart(ImageView button, boolean buttonState) {} + }); favouriteButton.setEventListener(new SparkEventListener() { @Override public void onEvent(ImageView button, boolean buttonState) { @@ -357,7 +418,8 @@ class StatusViewHolder extends RecyclerView.ViewHolder { container.setOnClickListener(viewThreadListener); } - void setupWithStatus(Status status, StatusActionListener listener) { + void setupWithStatus(Status status, StatusActionListener listener, + boolean mediaPreviewEnabled) { Status realStatus = status.getActionableStatus(); setDisplayName(realStatus.account.getDisplayName()); @@ -375,12 +437,25 @@ class StatusViewHolder extends RecyclerView.ViewHolder { } Status.MediaAttachment[] attachments = realStatus.attachments; boolean sensitive = realStatus.sensitive; - setMediaPreviews(attachments, sensitive, listener); - /* A status without attachments is sometimes still marked sensitive, so it's necessary to - * check both whether there are any attachments and if it's marked sensitive. */ - if (!sensitive || attachments.length == 0) { + if (mediaPreviewEnabled) { + setMediaPreviews(attachments, sensitive, listener); + /* A status without attachments is sometimes still marked sensitive, so it's necessary + * to check both whether there are any attachments and if it's marked sensitive. */ + if (!sensitive || attachments.length == 0) { + hideSensitiveMediaWarning(); + } + // Hide the unused label. + mediaLabel.setVisibility(View.GONE); + } else { + setMediaLabel(attachments, sensitive, listener); + // Hide all unused views. + mediaPreview0.setVisibility(View.GONE); + mediaPreview1.setVisibility(View.GONE); + mediaPreview2.setVisibility(View.GONE); + mediaPreview3.setVisibility(View.GONE); hideSensitiveMediaWarning(); } + setupButtons(listener, realStatus.account.id); setRebloggingEnabled(status.rebloggingAllowed()); if (realStatus.spoilerText.isEmpty()) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java index 9c885280..2b9dddfa 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java @@ -32,11 +32,13 @@ public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRe private List statuses; private StatusActionListener statusActionListener; private int statusIndex; + private boolean mediaPreviewEnabled; public ThreadAdapter(StatusActionListener listener) { this.statusActionListener = listener; this.statuses = new ArrayList<>(); this.statusIndex = 0; + mediaPreviewEnabled = true; } @Override @@ -50,7 +52,7 @@ public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRe public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { StatusViewHolder holder = (StatusViewHolder) viewHolder; Status status = statuses.get(position); - holder.setupWithStatus(status, statusActionListener); + holder.setupWithStatus(status, statusActionListener, mediaPreviewEnabled); } @Override @@ -58,10 +60,6 @@ public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRe return statuses.size(); } - public Status getItem(int position) { - return statuses.get(position); - } - @Override public void removeItem(int position) { statuses.remove(position); @@ -81,6 +79,10 @@ public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRe } } + public Status getItem(int position) { + return statuses.get(position); + } + public int setStatus(Status status) { if (statuses.size() > 0 && statusIndex < statuses.size() @@ -124,4 +126,14 @@ public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRe statuses.addAll(descendants); notifyItemRangeInserted(end, descendants.size()); } + + public void clear() { + statuses.clear(); + notifyDataSetChanged(); + statusIndex = 0; + } + + public void setMediaPreviewEnabled(boolean enabled) { + mediaPreviewEnabled = enabled; + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java index 5fb3c873..7424c581 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java @@ -42,11 +42,13 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem private List statuses; private StatusActionListener statusListener; private FooterState footerState = FooterState.END; + private boolean mediaPreviewEnabled; public TimelineAdapter(StatusActionListener statusListener) { super(); statuses = new ArrayList<>(); this.statusListener = statusListener; + mediaPreviewEnabled = true; } @Override @@ -82,20 +84,12 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem } } - 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()) { StatusViewHolder holder = (StatusViewHolder) viewHolder; Status status = statuses.get(position); - holder.setupWithStatus(status, statusListener); + holder.setupWithStatus(status, statusListener, mediaPreviewEnabled); } } @@ -113,6 +107,25 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem } } + @Override + public void removeItem(int position) { + statuses.remove(position); + notifyItemRemoved(position); + } + + @Override + public void removeAllByAccountId(String accountId) { + for (int i = 0; i < statuses.size();) { + Status status = statuses.get(i); + if (accountId.equals(status.account.id)) { + statuses.remove(i); + notifyItemRemoved(i); + } else { + i += 1; + } + } + } + public void update(List newStatuses) { if (newStatuses == null || newStatuses.isEmpty()) { return; @@ -140,25 +153,6 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem notifyItemRangeInserted(end, newStatuses.size()); } - @Override - public void removeItem(int position) { - statuses.remove(position); - notifyItemRemoved(position); - } - - @Override - public void removeAllByAccountId(String accountId) { - for (int i = 0; i < statuses.size();) { - Status status = statuses.get(i); - if (accountId.equals(status.account.id)) { - statuses.remove(i); - notifyItemRemoved(i); - } else { - i += 1; - } - } - } - public void clear() { statuses.clear(); notifyDataSetChanged(); @@ -171,4 +165,16 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem } return null; } + + public void setFooterState(FooterState newFooterState) { + FooterState oldValue = footerState; + footerState = newFooterState; + if (footerState != oldValue) { + notifyItemChanged(statuses.size()); + } + } + + public void setMediaPreviewEnabled(boolean enabled) { + mediaPreviewEnabled = enabled; + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java index 54ef1bbf..490c242a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -95,9 +95,27 @@ public class NotificationsFragment extends SFragment implements recyclerView.addItemDecoration(divider); adapter = new NotificationsAdapter(this, this); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( + getActivity()); + boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); + adapter.setMediaPreviewEnabled(mediaPreviewEnabled); recyclerView.setAdapter(adapter); - TabLayout layout = (TabLayout) getActivity().findViewById(R.id.tab_layout); + timelineReceiver = new TimelineReceiver(adapter); + LocalBroadcastManager.getInstance(context.getApplicationContext()) + .registerReceiver(timelineReceiver, TimelineReceiver.getFilter(null)); + + return rootView; + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + MainActivity activity = (MainActivity) getActivity(); + + // MainActivity's layout is guaranteed to be inflated until onCreate returns. + TabLayout layout = (TabLayout) activity.findViewById(R.id.tab_layout); onTabSelectedListener = new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) {} @@ -112,22 +130,10 @@ public class NotificationsFragment extends SFragment implements }; layout.addOnTabSelectedListener(onTabSelectedListener); - timelineReceiver = new TimelineReceiver(adapter); - LocalBroadcastManager.getInstance(context.getApplicationContext()) - .registerReceiver(timelineReceiver, TimelineReceiver.getFilter(null)); - - return rootView; - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - /* This is delayed until onActivityCreated solely because MainActivity.composeButton isn't * guaranteed to be set until then. * Use a modified scroll listener that both loads more notifications as it goes, and hides * the compose button on down-scroll. */ - MainActivity activity = (MainActivity) getActivity(); final FloatingActionButton composeButton = activity.composeButton; final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( activity); @@ -167,7 +173,9 @@ public class NotificationsFragment extends SFragment implements @Override public void onDestroy() { super.onDestroy(); - if (listCall != null) listCall.cancel(); + if (listCall != null) { + listCall.cancel(); + } } @Override @@ -195,7 +203,8 @@ public class NotificationsFragment extends SFragment implements listCall.enqueue(new Callback>() { @Override - public void onResponse(Call> call, Response> response) { + public void onResponse(Call> call, + Response> response) { if (response.isSuccessful()) { onFetchNotificationsSuccess(response.body(), fromId); } else { @@ -231,7 +240,9 @@ public class NotificationsFragment extends SFragment implements // Set last update id for pull notifications so that we don't get notified // about things we already loaded here - SharedPreferences preferences = getActivity().getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE); + SharedPreferences preferences = getActivity() + .getSharedPreferences(getString(R.string.preferences_file_key), + Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString("lastUpdateId", notifications.get(0).id); editor.apply(); @@ -309,8 +320,22 @@ public class NotificationsFragment extends SFragment implements @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if(key.equals("fabHide")) { - hideFab = sharedPreferences.getBoolean("fabHide", false); + switch (key) { + case "fabHide": { + hideFab = sharedPreferences.getBoolean("fabHide", false); + break; + } + case "mediaPreviewEnabled": { + boolean enabled = sharedPreferences.getBoolean("mediaPreviewEnabled", true); + adapter.setMediaPreviewEnabled(enabled); + fullyRefresh(); + break; + } } } + + private void fullyRefresh() { + adapter.clear(); + sendFetchNotificationsRequest(null, null); + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java index d160cf6f..a3cfeec6 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -98,7 +98,6 @@ public class TimelineFragment extends SFragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Bundle arguments = getArguments(); kind = Kind.valueOf(arguments.getString("kind")); if (kind == Kind.TAG || kind == Kind.USER) { @@ -123,22 +122,18 @@ public class TimelineFragment extends SFragment implements divider.setDrawable(drawable); recyclerView.addItemDecoration(divider); adapter = new TimelineAdapter(this); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( + getActivity()); + preferences.registerOnSharedPreferenceChangeListener(this); + boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); + adapter.setMediaPreviewEnabled(mediaPreviewEnabled); recyclerView.setAdapter(adapter); timelineReceiver = new TimelineReceiver(adapter, this); LocalBroadcastManager.getInstance(context.getApplicationContext()) .registerReceiver(timelineReceiver, TimelineReceiver.getFilter(kind)); - return rootView; - } - private void onLoadMore(RecyclerView view) { - TimelineAdapter adapter = (TimelineAdapter) view.getAdapter(); - Status status = adapter.getItem(adapter.getItemCount() - 2); - if (status != null) { - sendFetchTimelineRequest(status.id, null); - } else { - sendFetchTimelineRequest(null, null); - } + return rootView; } @Override @@ -171,7 +166,6 @@ public class TimelineFragment extends SFragment implements final FloatingActionButton composeButton = activity.composeButton; final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( activity); - preferences.registerOnSharedPreferenceChangeListener(this); hideFab = preferences.getBoolean("fabHide", false); scrollListener = new EndlessOnScrollListener(layoutManager) { @Override @@ -218,6 +212,102 @@ public class TimelineFragment extends SFragment implements super.onDestroyView(); } + @Override + public void onResume() { + super.onResume(); + setFiltersFromSettings(); + } + + @Override + public void onRefresh() { + Status status = adapter.getItem(0); + if (status != null) { + sendFetchTimelineRequest(null, status.id); + } else { + sendFetchTimelineRequest(null, null); + } + } + + @Override + public void onReply(int position) { + super.reply(adapter.getItem(position)); + } + + @Override + public void onReblog(final boolean reblog, final int position) { + super.reblog(adapter.getItem(position), reblog, adapter, position); + } + + @Override + public void onFavourite(final boolean favourite, final int position) { + super.favourite(adapter.getItem(position), favourite, adapter, position); + } + + @Override + public void onMore(View view, final int position) { + super.more(adapter.getItem(position), view, adapter, position); + } + + @Override + public void onViewMedia(String[] urls, int urlIndex, Status.MediaAttachment.Type type) { + super.viewMedia(urls, urlIndex, type); + } + + @Override + public void onViewThread(int position) { + super.viewThread(adapter.getItem(position)); + } + + @Override + public void onViewTag(String tag) { + if (kind == Kind.TAG && hashtagOrId.equals(tag)) { + // If already viewing a tag page, then ignore any request to view that tag again. + return; + } + super.viewTag(tag); + } + + @Override + public void onViewAccount(String id) { + if (kind == Kind.USER && hashtagOrId.equals(id)) { + /* If already viewing an account page, then any requests to view that account page + * should be ignored. */ + return; + } + super.viewAccount(id); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + switch (key) { + case "fabHide": { + hideFab = sharedPreferences.getBoolean("fabHide", false); + break; + } + case "mediaPreviewEnabled": { + boolean enabled = sharedPreferences.getBoolean("mediaPreviewEnabled", true); + adapter.setMediaPreviewEnabled(enabled); + fullyRefresh(); + break; + } + } + } + + private void onLoadMore(RecyclerView view) { + TimelineAdapter adapter = (TimelineAdapter) view.getAdapter(); + Status status = adapter.getItem(adapter.getItemCount() - 2); + if (status != null) { + sendFetchTimelineRequest(status.id, null); + } else { + sendFetchTimelineRequest(null, null); + } + } + + private void fullyRefresh() { + adapter.clear(); + sendFetchTimelineRequest(null, null); + } + private boolean jumpToTopAllowed() { return kind != Kind.TAG && kind != Kind.FAVOURITES; } @@ -310,17 +400,10 @@ public class TimelineFragment extends SFragment implements filterRemoveReblogs = (kind == Kind.HOME && !preferences.getBoolean("tabFilterHomeBoosts", true)); if (adapter.getItemCount() > 1 && (oldRemoveReblogs != filterRemoveReblogs || oldRemoveReplies != filterRemoveReplies)) { - adapter.clear(); - sendFetchTimelineRequest(null, null); + fullyRefresh(); } } - @Override - public void onResume() { - super.onResume(); - setFiltersFromSettings(); - } - public void onFetchTimelineSuccess(List statuses, String fromId) { filterStatuses(statuses); if (fromId != null) { @@ -342,70 +425,4 @@ public class TimelineFragment extends SFragment implements swipeRefreshLayout.setRefreshing(false); Log.e(TAG, "Fetch Failure: " + exception.getMessage()); } - - @Override - public void onRefresh() { - Status status = adapter.getItem(0); - if (status != null) { - sendFetchTimelineRequest(null, status.id); - } else { - sendFetchTimelineRequest(null, null); - } - } - - @Override - public void onReply(int position) { - super.reply(adapter.getItem(position)); - } - - @Override - public void onReblog(final boolean reblog, final int position) { - super.reblog(adapter.getItem(position), reblog, adapter, position); - } - - @Override - public void onFavourite(final boolean favourite, final int position) { - super.favourite(adapter.getItem(position), favourite, adapter, position); - } - - @Override - public void onMore(View view, final int position) { - super.more(adapter.getItem(position), view, adapter, position); - } - - @Override - public void onViewMedia(String[] urls, int urlIndex, Status.MediaAttachment.Type type) { - super.viewMedia(urls, urlIndex, type); - } - - @Override - public void onViewThread(int position) { - super.viewThread(adapter.getItem(position)); - } - - @Override - public void onViewTag(String tag) { - if (kind == Kind.TAG && hashtagOrId.equals(tag)) { - // If already viewing a tag page, then ignore any request to view that tag again. - return; - } - super.viewTag(tag); - } - - @Override - public void onViewAccount(String id) { - if (kind == Kind.USER && hashtagOrId.equals(id)) { - /* If already viewing an account page, then any requests to view that account page - * should be ignored. */ - return; - } - super.viewAccount(id); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if(key.equals("fabHide")) { - hideFab = sharedPreferences.getBoolean("fabHide", false); - } - } } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java index 327edcd0..dc0dd0e3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java @@ -16,8 +16,10 @@ package com.keylesspalace.tusky.fragment; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; @@ -89,6 +91,10 @@ public class ViewThreadFragment extends SFragment implements recyclerView.addItemDecoration(new ConversationLineItemDecoration(context, ContextCompat.getDrawable(context, R.drawable.conversation_divider_dark))); adapter = new ThreadAdapter(this); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( + getActivity()); + boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); + adapter.setMediaPreviewEnabled(mediaPreviewEnabled); recyclerView.setAdapter(adapter); mastodonApi = null; diff --git a/app/src/main/res/drawable/ic_photo_24dp.xml b/app/src/main/res/drawable/ic_photo_24dp.xml new file mode 100644 index 00000000..d0ebff06 --- /dev/null +++ b/app/src/main/res/drawable/ic_photo_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_videocam_24dp.xml b/app/src/main/res/drawable/ic_videocam_24dp.xml new file mode 100644 index 00000000..1614d026 --- /dev/null +++ b/app/src/main/res/drawable/ic_videocam_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/item_status.xml b/app/src/main/res/layout/item_status.xml index 1287c55f..7beb4a92 100644 --- a/app/src/main/res/layout/item_status.xml +++ b/app/src/main/res/layout/item_status.xml @@ -233,7 +233,15 @@ android:textAlignment="center" android:text="@string/status_sensitive_media_directions" android:textColor="@android:color/white" /> + + + + Share toot URL to… Share toot to… - Search accounts… - Toot! Sent! User unblocked @@ -168,6 +166,7 @@ Tabs Show boosts Show replies + Show media previews %s mentioned you %1$s, %2$s, %3$s and %4$d others @@ -191,6 +190,8 @@ Share content of toot Share link to toot + Images + Video Follow requested diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 8b6006e7..6b2d0747 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -14,6 +14,11 @@ android:title="@string/pref_title_hide_follow_button" android:defaultValue="false" /> + +