That fuck shit the fascists are using
1package org.tm.archive.messagedetails;
2
3import android.content.DialogInterface;
4import android.os.Bundle;
5import android.view.View;
6import android.widget.FrameLayout;
7
8import androidx.annotation.NonNull;
9import androidx.annotation.Nullable;
10import androidx.fragment.app.DialogFragment;
11import androidx.lifecycle.ViewModelProvider;
12import androidx.recyclerview.widget.RecyclerView;
13
14import com.bumptech.glide.Glide;
15import com.bumptech.glide.RequestManager;
16
17import org.tm.archive.R;
18import org.tm.archive.components.FullScreenDialogFragment;
19import org.tm.archive.conversation.colors.Colorizer;
20import org.tm.archive.conversation.colors.RecyclerViewColorizer;
21import org.tm.archive.conversation.ui.edit.EditMessageHistoryDialog;
22import org.tm.archive.database.model.MessageRecord;
23import org.tm.archive.giph.mp4.GiphyMp4PlaybackController;
24import org.tm.archive.giph.mp4.GiphyMp4ProjectionPlayerHolder;
25import org.tm.archive.giph.mp4.GiphyMp4ProjectionRecycler;
26import org.tm.archive.messagedetails.MessageDetailsAdapter.MessageDetailsViewState;
27import org.tm.archive.messagedetails.MessageDetailsViewModel.Factory;
28import org.tm.archive.recipients.RecipientId;
29import org.tm.archive.safety.SafetyNumberBottomSheet;
30import org.tm.archive.util.Material3OnScrollHelper;
31import org.tm.archive.util.MessageRecordUtil;
32
33import java.util.ArrayList;
34import java.util.Collection;
35import java.util.List;
36
37public final class MessageDetailsFragment extends FullScreenDialogFragment implements MessageDetailsAdapter.Callbacks {
38
39 private static final String MESSAGE_ID_EXTRA = "message_id";
40 private static final String RECIPIENT_EXTRA = "recipient_id";
41
42 private RequestManager requestManager;
43 private MessageDetailsViewModel viewModel;
44 private MessageDetailsAdapter adapter;
45 private Colorizer colorizer;
46 private RecyclerViewColorizer recyclerViewColorizer;
47
48 public static @NonNull DialogFragment create(@NonNull MessageRecord message, @NonNull RecipientId recipientId) {
49 DialogFragment dialogFragment = new MessageDetailsFragment();
50 Bundle args = new Bundle();
51
52 args.putLong(MESSAGE_ID_EXTRA, message.getId());
53 args.putParcelable(RECIPIENT_EXTRA, recipientId);
54
55 dialogFragment.setArguments(args);
56
57 return dialogFragment;
58 }
59
60 @Override
61 protected int getTitle() {
62 return R.string.AndroidManifest__message_details;
63 }
64
65 @Override
66 protected int getDialogLayoutResource() {
67 return R.layout.message_details_fragment;
68 }
69
70 @Override
71 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
72 requestManager = Glide.with(this);
73
74 initializeList(view);
75 initializeViewModel();
76 initializeVideoPlayer(view);
77 }
78
79 @Override
80 public void onDismiss(@NonNull DialogInterface dialog) {
81 super.onDismiss(dialog);
82
83 if (getActivity() instanceof Callback) {
84 ((Callback) getActivity()).onMessageDetailsFragmentDismissed();
85 } else if (getParentFragment() instanceof Callback) {
86 ((Callback) getParentFragment()).onMessageDetailsFragmentDismissed();
87 }
88 }
89
90 private void initializeList(@NonNull View view) {
91 RecyclerView list = view.findViewById(R.id.message_details_list);
92 View toolbarShadow = view.findViewById(R.id.toolbar_shadow);
93
94 colorizer = new Colorizer();
95 adapter = new MessageDetailsAdapter(getViewLifecycleOwner(), requestManager, colorizer, this);
96 recyclerViewColorizer = new RecyclerViewColorizer(list);
97
98 list.setAdapter(adapter);
99 list.setItemAnimator(null);
100 new Material3OnScrollHelper(requireActivity(), toolbarShadow, getViewLifecycleOwner()).attach(list);
101 }
102
103 private void initializeViewModel() {
104 final RecipientId recipientId = requireArguments().getParcelable(RECIPIENT_EXTRA);
105 final Long messageId = requireArguments().getLong(MESSAGE_ID_EXTRA, -1);
106 final Factory factory = new Factory(recipientId, messageId);
107
108 viewModel = new ViewModelProvider(this, factory).get(MessageDetailsViewModel.class);
109 viewModel.getMessageDetails().observe(this, details -> {
110 if (details == null) {
111 dismissAllowingStateLoss();
112 } else {
113 adapter.submitList(convertToRows(details));
114 }
115 });
116 viewModel.getRecipient().observe(this, recipient -> recyclerViewColorizer.setChatColors(recipient.getChatColors()));
117 }
118
119 private void initializeVideoPlayer(@NonNull View view) {
120 FrameLayout videoContainer = view.findViewById(R.id.video_container);
121 RecyclerView recyclerView = view.findViewById(R.id.message_details_list);
122 List<GiphyMp4ProjectionPlayerHolder> holders = GiphyMp4ProjectionPlayerHolder.injectVideoViews(requireContext(), getLifecycle(), videoContainer, 1);
123 GiphyMp4ProjectionRecycler callback = new GiphyMp4ProjectionRecycler(holders);
124
125 GiphyMp4PlaybackController.attach(recyclerView, callback, 1);
126 }
127
128 private List<MessageDetailsViewState<?>> convertToRows(MessageDetails details) {
129 List<MessageDetailsViewState<?>> list = new ArrayList<>();
130
131 list.add(new MessageDetailsViewState<>(details.getConversationMessage(), MessageDetailsViewState.MESSAGE_HEADER));
132
133 if (MessageRecordUtil.isEditMessage(details.getConversationMessage().getMessageRecord())) {
134 list.add(new MessageDetailsViewState<>(details.getConversationMessage().getMessageRecord(), MessageDetailsViewState.EDIT_HISTORY));
135 }
136
137 if (details.getConversationMessage().getMessageRecord().isOutgoing()) {
138 addRecipients(list, RecipientHeader.NOT_SENT, details.getNotSent());
139 addRecipients(list, RecipientHeader.VIEWED, details.getViewed());
140 addRecipients(list, RecipientHeader.READ, details.getRead());
141 addRecipients(list, RecipientHeader.DELIVERED, details.getDelivered());
142 addRecipients(list, RecipientHeader.SENT_TO, details.getSent());
143 addRecipients(list, RecipientHeader.PENDING, details.getPending());
144 addRecipients(list, RecipientHeader.SKIPPED, details.getSkipped());
145 } else {
146 addRecipients(list, RecipientHeader.SENT_FROM, details.getSent());
147 }
148
149 return list;
150 }
151
152 private boolean addRecipients(List<MessageDetailsViewState<?>> list, RecipientHeader header, Collection<RecipientDeliveryStatus> recipients) {
153 if (recipients.isEmpty()) {
154 return false;
155 }
156
157 list.add(new MessageDetailsViewState<>(header, MessageDetailsViewState.RECIPIENT_HEADER));
158 for (RecipientDeliveryStatus status : recipients) {
159 list.add(new MessageDetailsViewState<>(status, MessageDetailsViewState.RECIPIENT));
160 }
161 return true;
162 }
163
164 @Override
165 public void onErrorClicked(@NonNull MessageRecord messageRecord) {
166 SafetyNumberBottomSheet
167 .forMessageRecord(requireContext(), messageRecord)
168 .show(getChildFragmentManager());
169 }
170
171 @Override
172 public void onViewEditHistoryClicked(MessageRecord record) {
173 if (record.isOutgoing()) {
174 EditMessageHistoryDialog.show(getParentFragmentManager(), record.getToRecipient().getId(), record);
175 } else {
176 EditMessageHistoryDialog.show(getParentFragmentManager(), record.getFromRecipient().getId(), record);
177 }
178 }
179
180 @Override
181 public void onInternalDetailsClicked(MessageRecord record) {
182 InternalMessageDetailsFragment.create(record).show(getParentFragmentManager(), InternalMessageDetailsFragment.class.getSimpleName());
183 }
184
185 public interface Callback {
186 void onMessageDetailsFragmentDismissed();
187 }
188}