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 464d2bc6..f21e0f4c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java @@ -39,6 +39,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter { } private static final int VIEW_TYPE_STATUS = 0; + private static final int VIEW_TYPE_STATUS_MUTED = 1; private static final int VIEW_TYPE_PLACEHOLDER = 2; private final AdapterDataSource dataSource; @@ -77,6 +78,11 @@ public final class TimelineAdapter extends RecyclerView.Adapter { .inflate(R.layout.item_status, viewGroup, false); return new StatusViewHolder(view); } + case VIEW_TYPE_STATUS_MUTED: { + View view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.item_status_muted, viewGroup, false); + return new MutedStatusViewHolder(view); + } case VIEW_TYPE_PLACEHOLDER: { View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.item_status_placeholder, viewGroup, false); @@ -102,11 +108,16 @@ public final class TimelineAdapter extends RecyclerView.Adapter { PlaceholderViewHolder holder = (PlaceholderViewHolder) viewHolder; holder.setup(statusListener, ((StatusViewData.Placeholder) status).isLoading()); } else if (status instanceof StatusViewData.Concrete) { - StatusViewHolder holder = (StatusViewHolder) viewHolder; - holder.setupWithStatus((StatusViewData.Concrete) status, - statusListener, - statusDisplayOptions, + StatusViewData.Concrete concrete = (StatusViewData.Concrete)status; + if(concrete.isThreadMuted()) { + MutedStatusViewHolder holder = (MutedStatusViewHolder) viewHolder; + holder.setupWithStatus(concrete, statusListener, statusDisplayOptions, + payloads != null && !payloads.isEmpty() ? payloads.get(0) : null); + } else { + StatusViewHolder holder = (StatusViewHolder) viewHolder; + holder.setupWithStatus(concrete, statusListener, statusDisplayOptions, payloads != null && !payloads.isEmpty() ? payloads.get(0) : null); + } } } @@ -120,7 +131,12 @@ public final class TimelineAdapter extends RecyclerView.Adapter { if (dataSource.getItemAt(position) instanceof StatusViewData.Placeholder) { return VIEW_TYPE_PLACEHOLDER; } else { - return VIEW_TYPE_STATUS; + StatusViewData.Concrete concrete = (StatusViewData.Concrete)dataSource.getItemAt(position); + if(concrete.isThreadMuted()) { + return VIEW_TYPE_STATUS_MUTED; + } else { + return VIEW_TYPE_STATUS; + } } } 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 80b4619b..1d819207 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -330,7 +330,7 @@ public class NotificationsFragment extends SFragment implements if (posAndNotification == null) return; - int conversaionId = posAndNotification.second.getStatus().getConversationId(); + int conversationId = posAndNotification.second.getStatus().getConversationId(); if(conversationId == -1) { // invalid conversation ID setMutedStatusForStatus(posAndNotification.first, posAndNotification.second.getStatus(), event.getMute()); @@ -341,7 +341,7 @@ public class NotificationsFragment extends SFragment implements Notification notification = notifications.get(i).asRightOrNull(); if (notification != null && notification.getStatus() != null && notification.getType() == Notification.Type.MENTION && - notification.getStatus().getConversationId() == conversaionId) { + notification.getStatus().getConversationId() == conversationId) { setMutedStatusForStatus(i, notification.getStatus(), event.getMute()); } } 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 a1c6bf49..efea31ef 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -48,17 +48,7 @@ import com.keylesspalace.tusky.BaseActivity; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.adapter.StatusBaseViewHolder; import com.keylesspalace.tusky.adapter.TimelineAdapter; -import com.keylesspalace.tusky.appstore.BlockEvent; -import com.keylesspalace.tusky.appstore.BookmarkEvent; -import com.keylesspalace.tusky.appstore.DomainMuteEvent; -import com.keylesspalace.tusky.appstore.EventHub; -import com.keylesspalace.tusky.appstore.FavoriteEvent; -import com.keylesspalace.tusky.appstore.MuteEvent; -import com.keylesspalace.tusky.appstore.PreferenceChangedEvent; -import com.keylesspalace.tusky.appstore.ReblogEvent; -import com.keylesspalace.tusky.appstore.StatusComposedEvent; -import com.keylesspalace.tusky.appstore.StatusDeletedEvent; -import com.keylesspalace.tusky.appstore.UnfollowEvent; +import com.keylesspalace.tusky.appstore.*; import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.di.Injectable; import com.keylesspalace.tusky.entity.Filter; @@ -508,6 +498,10 @@ public class TimelineFragment extends SFragment implements String id = ((BlockEvent) event).getAccountId(); removeAllByAccountId(id); } + } else if (event instanceof MuteStatusEvent) { + if (kind != Kind.USER && kind != Kind.USER_WITH_REPLIES && kind != Kind.USER_PINNED) { + handleMuteStatusEvent((MuteStatusEvent)event); + } } else if (event instanceof MuteEvent) { if (kind != Kind.USER && kind != Kind.USER_WITH_REPLIES && kind != Kind.USER_PINNED) { String id = ((MuteEvent) event).getAccountId(); @@ -667,6 +661,26 @@ public class TimelineFragment extends SFragment implements statuses.setPairedItem(actual.second, newViewData); updateAdapter(); } + + @Override + public void onMute(int position, boolean isMuted) { + StatusViewData.Concrete statusViewData = + new StatusViewData.Builder((StatusViewData.Concrete)statuses.getPairedItem(position)) + .setThreadMuted(isMuted) + .createStatusViewData(); + statuses.setPairedItem(position, statusViewData); + updateAdapter(); + } + + private void setMutedStatusForStatus(int position, Status status, boolean muted) { + status.setThreadMuted(muted); + + StatusViewData.Builder statusViewData = new StatusViewData.Builder((StatusViewData.Concrete)statuses.getPairedItem(position)); + statusViewData.setThreadMuted(muted); + statusViewData.setThreadMutedOnBackend(muted); + + statuses.setPairedItem(position, statusViewData.createStatusViewData()); + } public void onVoteInPoll(int position, @NonNull List choices) { @@ -1325,6 +1339,29 @@ public class TimelineFragment extends SFragment implements } onRefresh(); } + + private void handleMuteStatusEvent(MuteStatusEvent event) { + int pos = findStatusOrReblogPositionById(event.getStatusId()); + + if (pos < 0) + return; + + Status eventStatus = statuses.get(pos).asRight(); + int conversationId = eventStatus.getConversationId(); + + if(conversationId == -1) { // invalid conversation ID + setMutedStatusForStatus(pos, eventStatus, event.getMute()); + } else { + //noinspection ConstantConditions + for (int i = 0; i < statuses.size(); i++) { + Status status = statuses.get(i).asRightOrNull(); + if (status != null && status.getConversationId() == conversationId) { + setMutedStatusForStatus(i, status, event.getMute()); + } + } + } + updateAdapter(); + } private List> liftStatusList(List list) { return CollectionsKt.map(list, statusLifter);