That fuck shit the fascists are using
1package org.tm.archive.longmessage;
2
3import android.graphics.PorterDuff;
4import android.os.Bundle;
5import android.text.SpannableString;
6import android.util.TypedValue;
7import android.view.View;
8import android.view.ViewGroup;
9import android.widget.Toast;
10
11import androidx.annotation.NonNull;
12import androidx.annotation.Nullable;
13import androidx.core.content.ContextCompat;
14import androidx.fragment.app.DialogFragment;
15import androidx.lifecycle.ViewModelProvider;
16
17import org.tm.archive.R;
18import org.tm.archive.components.ConversationItemFooter;
19import org.tm.archive.components.FullScreenDialogFragment;
20import org.tm.archive.components.emoji.EmojiTextView;
21import org.tm.archive.conversation.ConversationItemDisplayMode;
22import org.tm.archive.conversation.colors.ColorizerView;
23import org.tm.archive.conversation.v2.items.V2ConversationItemUtils;
24import org.tm.archive.keyvalue.SignalStore;
25import org.tm.archive.recipients.Recipient;
26import org.tm.archive.util.CommunicationActions;
27import org.tm.archive.util.LongClickMovementMethod;
28import org.tm.archive.util.Projection;
29import org.tm.archive.util.ThemeUtil;
30import org.tm.archive.util.views.Stub;
31
32import java.util.Collections;
33import java.util.Locale;
34
35public class LongMessageFragment extends FullScreenDialogFragment {
36
37 private static final String KEY_MESSAGE_ID = "message_id";
38 private static final String KEY_IS_MMS = "is_mms";
39
40 private static final int MAX_DISPLAY_LENGTH = 64 * 1024;
41
42 private Stub<ViewGroup> sentBubble;
43 private Stub<ViewGroup> receivedBubble;
44 private ColorizerView colorizerView;
45 private BubbleLayoutListener bubbleLayoutListener;
46
47 private LongMessageViewModel viewModel;
48
49 public static DialogFragment create(long messageId, boolean isMms) {
50 DialogFragment fragment = new LongMessageFragment();
51 Bundle args = new Bundle();
52
53 args.putLong(KEY_MESSAGE_ID, messageId);
54 args.putBoolean(KEY_IS_MMS, isMms);
55
56 fragment.setArguments(args);
57
58 return fragment;
59 }
60
61
62 @Override
63 protected int getTitle() {
64 return -1;
65 }
66
67 @Override
68 protected int getDialogLayoutResource() {
69 return R.layout.longmessage_fragment;
70 }
71
72 @Override
73 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
74 sentBubble = new Stub<>(view.findViewById(R.id.longmessage_sent_stub));
75 receivedBubble = new Stub<>(view.findViewById(R.id.longmessage_received_stub));
76 colorizerView = view.findViewById(R.id.colorizer);
77
78 bubbleLayoutListener = new BubbleLayoutListener();
79
80 initViewModel(requireArguments().getLong(KEY_MESSAGE_ID, -1), requireArguments().getBoolean(KEY_IS_MMS, false));
81 }
82
83 private void initViewModel(long messageId, boolean isMms) {
84 viewModel = new ViewModelProvider(this,
85 new LongMessageViewModel.Factory(requireActivity().getApplication(),
86 new LongMessageRepository(), messageId, isMms))
87 .get(LongMessageViewModel.class);
88
89 viewModel.getMessage().observe(this, message -> {
90 if (message == null) return;
91
92 if (!message.isPresent()) {
93 Toast.makeText(requireContext(), R.string.LongMessageActivity_unable_to_find_message, Toast.LENGTH_SHORT).show();
94 dismissAllowingStateLoss();
95 return;
96 }
97
98
99 if (message.get().getMessageRecord().isOutgoing()) {
100 toolbar.setTitle(getString(R.string.LongMessageActivity_your_message));
101 } else {
102 Recipient recipient = message.get().getMessageRecord().getFromRecipient();
103 String name = recipient.getDisplayName(requireContext());
104
105 toolbar.setTitle(getString(R.string.LongMessageActivity_message_from_s, name));
106 }
107
108 ViewGroup bubble;
109
110 if (message.get().getMessageRecord().isOutgoing()) {
111 bubble = sentBubble.get();
112 colorizerView.setVisibility(View.VISIBLE);
113 colorizerView.setBackground(message.get().getMessageRecord().getToRecipient().getChatColors().getChatBubbleMask());
114 bubble.getBackground().setColorFilter(message.get().getMessageRecord().getToRecipient().getChatColors().getChatBubbleColorFilter());
115 bubble.addOnLayoutChangeListener(bubbleLayoutListener);
116 bubbleLayoutListener.onLayoutChange(bubble, 0, 0, 0, 0, 0, 0, 0, 0);
117 } else {
118 bubble = receivedBubble.get();
119 bubble.getBackground().setColorFilter(ContextCompat.getColor(requireContext(), R.color.signal_background_secondary), PorterDuff.Mode.MULTIPLY);
120 }
121
122 EmojiTextView text = bubble.findViewById(R.id.longmessage_text);
123 ConversationItemFooter footer = bubble.findViewById(R.id.longmessage_footer);
124
125 SpannableString body = new SpannableString(getTrimmedBody(message.get().getFullBody(requireContext())));
126 V2ConversationItemUtils.linkifyUrlLinks(body,
127 true,
128 url -> CommunicationActions.handlePotentialGroupLinkUrl(requireActivity(), url) ||
129 CommunicationActions.handlePotentialProxyLinkUrl(requireActivity(), url));
130
131 bubble.setVisibility(View.VISIBLE);
132 text.setText(body);
133 text.setMovementMethod(LongClickMovementMethod.getInstance(getContext()));
134 text.setTextSize(TypedValue.COMPLEX_UNIT_SP, SignalStore.settings().getMessageFontSize());
135 if (!message.get().getMessageRecord().isOutgoing()) {
136 text.setMentionBackgroundTint(ContextCompat.getColor(requireContext(), ThemeUtil.isDarkTheme(requireActivity()) ? R.color.core_grey_60 : R.color.core_grey_20));
137 } else {
138 text.setMentionBackgroundTint(ContextCompat.getColor(requireContext(), R.color.transparent_black_40));
139 }
140 footer.setMessageRecord(message.get().getMessageRecord(), Locale.getDefault(), ConversationItemDisplayMode.Standard.INSTANCE);
141 });
142 }
143
144 private CharSequence getTrimmedBody(@NonNull CharSequence text) {
145 return text.length() <= MAX_DISPLAY_LENGTH ? text
146 : text.subSequence(0, MAX_DISPLAY_LENGTH);
147 }
148
149 private final class BubbleLayoutListener implements View.OnLayoutChangeListener {
150 @Override
151 public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
152 Projection projection = Projection.relativeToViewWithCommonRoot(v, colorizerView, new Projection.Corners(16));
153
154 colorizerView.setProjections(Collections.singletonList(projection));
155 }
156 }
157}