Adds option to hide media previews if reduced data usage is desired Closes #56.
This commit is contained in:
		
					parent
					
						
							
								3a4ef00dab
							
						
					
				
			
			
				commit
				
					
						3f54ead962
					
				
			
		
					 12 changed files with 368 additions and 186 deletions
				
			
		|  | @ -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); | ||||
|     } | ||||
|  |  | |||
|  | @ -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()) { | ||||
|  |  | |||
|  | @ -32,11 +32,13 @@ public class ThreadAdapter extends RecyclerView.Adapter implements AdapterItemRe | |||
|     private List<Status> 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; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -42,11 +42,13 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem | |||
|     private List<Status> 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<Status> 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; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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<List<Notification>>() { | ||||
|             @Override | ||||
|             public void onResponse(Call<List<Notification>> call, Response<List<Notification>> response) { | ||||
|             public void onResponse(Call<List<Notification>> call, | ||||
|                     Response<List<Notification>> 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); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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<Status> 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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										9
									
								
								app/src/main/res/drawable/ic_photo_24dp.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/drawable/ic_photo_24dp.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         android:width="24dp" | ||||
|         android:height="24dp" | ||||
|         android:viewportWidth="24.0" | ||||
|         android:viewportHeight="24.0"> | ||||
|     <path | ||||
|         android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z" | ||||
|         android:fillColor="#FFFFFF"/> | ||||
| </vector> | ||||
							
								
								
									
										9
									
								
								app/src/main/res/drawable/ic_videocam_24dp.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/drawable/ic_videocam_24dp.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         android:width="24dp" | ||||
|         android:height="24dp" | ||||
|         android:viewportWidth="24.0" | ||||
|         android:viewportHeight="24.0"> | ||||
|     <path | ||||
|         android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z" | ||||
|         android:fillColor="#FFFFFF"/> | ||||
| </vector> | ||||
|  | @ -233,7 +233,15 @@ | |||
|                 android:textAlignment="center" | ||||
|                 android:text="@string/status_sensitive_media_directions" | ||||
|                 android:textColor="@android:color/white" /> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:id="@+id/status_media_label" | ||||
|             android:visibility="gone" /> | ||||
| 
 | ||||
|     </FrameLayout> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|  |  | |||
|  | @ -105,8 +105,6 @@ | |||
|     <string name="send_status_link_to">Share toot URL to…</string> | ||||
|     <string name="send_status_content_to">Share toot to…</string> | ||||
| 
 | ||||
|     <string name="search">Search accounts…</string> | ||||
| 
 | ||||
|     <string name="confirmation_send">Toot!</string> | ||||
|     <string name="confirmation_reported">Sent!</string> | ||||
|     <string name="confirmation_unblocked">User unblocked</string> | ||||
|  | @ -168,6 +166,7 @@ | |||
|     <string name="pref_title_status_tabs">Tabs</string> | ||||
|     <string name="pref_title_show_boosts">Show boosts</string> | ||||
|     <string name="pref_title_show_replies">Show replies</string> | ||||
|     <string name="pref_title_show_media_preview">Show media previews</string> | ||||
| 
 | ||||
|     <string name="notification_mention_format">%s mentioned you</string> | ||||
|     <string name="notification_summary_large">%1$s, %2$s, %3$s and %4$d others</string> | ||||
|  | @ -191,6 +190,8 @@ | |||
| 
 | ||||
|     <string name="status_share_content">Share content of toot</string> | ||||
|     <string name="status_share_link">Share link to toot</string> | ||||
|     <string name="status_media_images">Images</string> | ||||
|     <string name="status_media_video">Video</string> | ||||
| 
 | ||||
|     <string name="state_follow_requested">Follow requested</string> | ||||
| </resources> | ||||
|  |  | |||
|  | @ -14,6 +14,11 @@ | |||
|             android:title="@string/pref_title_hide_follow_button" | ||||
|             android:defaultValue="false" /> | ||||
| 
 | ||||
|         <CheckBoxPreference | ||||
|             android:key="mediaPreviewEnabled" | ||||
|             android:title="@string/pref_title_show_media_preview" | ||||
|             android:defaultValue="true" /> | ||||
| 
 | ||||
|     </PreferenceCategory> | ||||
|     <PreferenceCategory android:title="@string/pref_title_browser_settings"> | ||||
|         <CheckBoxPreference | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue