That fuck shit the fascists are using
at master 221 lines 10 kB view raw
1package org.tm.archive.database; 2 3import android.content.Context; 4import android.text.SpannableStringBuilder; 5import android.text.TextUtils; 6 7import androidx.annotation.NonNull; 8import androidx.annotation.Nullable; 9import androidx.annotation.StringRes; 10 11import org.signal.core.util.logging.Log; 12import org.tm.archive.R; 13import org.tm.archive.components.emoji.EmojiStrings; 14import org.tm.archive.contactshare.Contact; 15import org.tm.archive.contactshare.ContactUtil; 16import org.tm.archive.database.model.MessageRecord; 17import org.tm.archive.database.model.MmsMessageRecord; 18import org.tm.archive.mms.GifSlide; 19import org.tm.archive.mms.Slide; 20import org.tm.archive.mms.StickerSlide; 21import org.tm.archive.util.MessageRecordUtil; 22import org.tm.archive.util.Util; 23 24import java.util.Collections; 25import java.util.List; 26import java.util.Objects; 27 28public final class ThreadBodyUtil { 29 30 private static final String TAG = Log.tag(ThreadBodyUtil.class); 31 32 private ThreadBodyUtil() { 33 } 34 35 public static @NonNull ThreadBody getFormattedBodyFor(@NonNull Context context, @NonNull MessageRecord record) { 36 if (record.isMms()) { 37 return getFormattedBodyForMms(context, (MmsMessageRecord) record, null); 38 } 39 40 return new ThreadBody(record.getBody()); 41 } 42 43 public static @NonNull CharSequence getFormattedBodyForNotification(@NonNull Context context, @NonNull MessageRecord record, @Nullable CharSequence bodyOverride) { 44 return getFormattedBodyForMms(context, (MmsMessageRecord) record, bodyOverride).body; 45 } 46 47 private static @NonNull ThreadBody getFormattedBodyForMms(@NonNull Context context, @NonNull MmsMessageRecord record, @Nullable CharSequence bodyOverride) { 48 if (record.getSharedContacts().size() > 0) { 49 Contact contact = record.getSharedContacts().get(0); 50 51 return new ThreadBody(ContactUtil.getStringSummary(context, contact).toString()); 52 } else if (record.getSlideDeck().getDocumentSlide() != null) { 53 return format(context, record, EmojiStrings.FILE, R.string.ThreadRecord_file, bodyOverride); 54 } else if (record.getSlideDeck().getAudioSlide() != null) { 55 return format(context, record, EmojiStrings.AUDIO, R.string.ThreadRecord_voice_message, bodyOverride); 56 } else if (MessageRecordUtil.hasSticker(record)) { 57 String emoji = getStickerEmoji(record); 58 return format(context, record, emoji, R.string.ThreadRecord_sticker, bodyOverride); 59 } else if (MessageRecordUtil.hasGiftBadge(record)) { 60 return format(EmojiStrings.GIFT, getGiftSummary(context, record)); 61 } else if (MessageRecordUtil.isStoryReaction(record)) { 62 return new ThreadBody(getStoryReactionSummary(context, record)); 63 } else if (record.isPaymentNotification()) { 64 return format(EmojiStrings.CARD, context.getString(R.string.ThreadRecord_payment)); 65 } else if (record.isPaymentsRequestToActivate()) { 66 return format(EmojiStrings.CARD, getPaymentActivationRequestSummary(context, record)); 67 } else if (record.isPaymentsActivated()) { 68 return format(EmojiStrings.CARD, getPaymentActivatedSummary(context, record)); 69 } else if (record.isCallLog() && !record.isGroupCall()) { 70 return new ThreadBody(getCallLogSummary(context, record)); 71 } else if (MessageRecordUtil.isScheduled(record)) { 72 return new ThreadBody(context.getString(R.string.ThreadRecord_scheduled_message)); 73 } 74 75 boolean hasImage = false; 76 boolean hasVideo = false; 77 boolean hasGif = false; 78 79 for (Slide slide : record.getSlideDeck().getSlides()) { 80 hasVideo |= slide.hasVideo(); 81 hasImage |= slide.hasImage(); 82 hasGif |= slide instanceof GifSlide || slide.isVideoGif(); 83 } 84 85 if (hasGif) { 86 return format(context, record, EmojiStrings.GIF, R.string.ThreadRecord_gif, bodyOverride); 87 } else if (hasVideo) { 88 return format(context, record, EmojiStrings.VIDEO, R.string.ThreadRecord_video, bodyOverride); 89 } else if (hasImage) { 90 return format(context, record, EmojiStrings.PHOTO, R.string.ThreadRecord_photo, bodyOverride); 91 } else if (TextUtils.isEmpty(record.getBody())) { 92 return new ThreadBody(context.getString(R.string.ThreadRecord_media_message)); 93 } else { 94 return getBody(context, record); 95 } 96 } 97 98 private static @NonNull String getGiftSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) { 99 if (messageRecord.isOutgoing()) { 100 return context.getString(R.string.ThreadRecord__you_donated_for_s, messageRecord.getToRecipient().getShortDisplayName(context)); 101 } else if (messageRecord.isViewed()) { 102 return context.getString(R.string.ThreadRecord__you_redeemed_a_badge); 103 } else { 104 return context.getString(R.string.ThreadRecord__s_donated_for_you, messageRecord.getFromRecipient().getShortDisplayName(context)); 105 } 106 } 107 108 private static @NonNull String getStoryReactionSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) { 109 if (messageRecord.isOutgoing()) { 110 return context.getString(R.string.ThreadRecord__reacted_s_to_their_story, messageRecord.getDisplayBody(context)); 111 } else { 112 return context.getString(R.string.ThreadRecord__reacted_s_to_your_story, messageRecord.getDisplayBody(context)); 113 } 114 } 115 116 private static @NonNull String getPaymentActivationRequestSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) { 117 if (messageRecord.isOutgoing()) { 118 return context.getString(R.string.ThreadRecord_you_sent_request); 119 } else { 120 return context.getString(R.string.ThreadRecord_wants_you_to_activate_payments, messageRecord.getFromRecipient().getShortDisplayName(context)); 121 } 122 } 123 124 private static @NonNull String getPaymentActivatedSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) { 125 if (messageRecord.isOutgoing()) { 126 return context.getString(R.string.ThreadRecord_you_activated_payments); 127 } else { 128 return context.getString(R.string.ThreadRecord_can_accept_payments, messageRecord.getFromRecipient().getShortDisplayName(context)); 129 } 130 } 131 132 private static @NonNull String getCallLogSummary(@NonNull Context context, @NonNull MessageRecord record) { 133 CallTable.Call call = SignalDatabase.calls().getCallByMessageId(record.getId()); 134 if (call != null) { 135 boolean accepted = call.getEvent() == CallTable.Event.ACCEPTED; 136 if (call.getDirection() == CallTable.Direction.OUTGOING) { 137 if (call.getType() == CallTable.Type.AUDIO_CALL) { 138 return context.getString(accepted ? R.string.MessageRecord_outgoing_voice_call : R.string.MessageRecord_unanswered_voice_call); 139 } else { 140 return context.getString(accepted ? R.string.MessageRecord_outgoing_video_call : R.string.MessageRecord_unanswered_video_call); 141 } 142 } else { 143 boolean isVideoCall = call.getType() == CallTable.Type.VIDEO_CALL; 144 boolean isMissed = call.getEvent().isMissedCall(); 145 146 if (accepted) { 147 return context.getString(isVideoCall ? R.string.MessageRecord_incoming_video_call : R.string.MessageRecord_incoming_voice_call); 148 } else if (isMissed) { 149 if (call.getEvent() == CallTable.Event.MISSED_NOTIFICATION_PROFILE) { 150 return isVideoCall ? context.getString(R.string.MessageRecord_missed_video_call_notification_profile) : context.getString(R.string.MessageRecord_missed_voice_call_notification_profile); 151 } else { 152 return isVideoCall ? context.getString(R.string.MessageRecord_missed_video_call) : context.getString(R.string.MessageRecord_missed_voice_call); 153 } 154 } else { 155 return isVideoCall ? context.getString(R.string.MessageRecord_you_declined_a_video_call) : context.getString(R.string.MessageRecord_you_declined_a_voice_call); 156 } 157 } 158 } else { 159 return ""; 160 } 161 } 162 163 private static @NonNull ThreadBody format(@NonNull Context context, 164 @NonNull MessageRecord record, 165 @NonNull String emoji, 166 @StringRes int defaultStringRes, 167 @Nullable CharSequence bodyOverride) 168 { 169 CharSequence body = !TextUtils.isEmpty(bodyOverride) ? bodyOverride 170 : TextUtils.isEmpty(record.getBody()) ? context.getString(defaultStringRes) 171 : getBody(context, record).getBody(); 172 return format(emoji, body); 173 } 174 175 private static @NonNull ThreadBody format(@NonNull CharSequence prefix, @NonNull CharSequence body) { 176 SpannableStringBuilder builder = new SpannableStringBuilder(); 177 builder.append(prefix) 178 .append(" ") 179 .append(body); 180 return new ThreadBody(builder, prefix.length() + 1); 181 } 182 183 private static @NonNull ThreadBody getBody(@NonNull Context context, @NonNull MessageRecord record) { 184 MentionUtil.UpdatedBodyAndMentions updated = MentionUtil.updateBodyWithDisplayNames(context, record, record.getBody()); 185 //noinspection ConstantConditions 186 return new ThreadBody(updated.getBody(), updated.getBodyAdjustments()); 187 } 188 189 private static @NonNull String getStickerEmoji(@NonNull MessageRecord record) { 190 StickerSlide slide = Objects.requireNonNull(((MmsMessageRecord) record).getSlideDeck().getStickerSlide()); 191 192 return Util.isEmpty(slide.getEmoji()) ? EmojiStrings.STICKER 193 : slide.getEmoji(); 194 } 195 196 public static class ThreadBody { 197 private final CharSequence body; 198 private final List<BodyAdjustment> bodyAdjustments; 199 200 public ThreadBody(@NonNull CharSequence body) { 201 this(body, 0); 202 } 203 204 public ThreadBody(@NonNull CharSequence body, int startOffset) { 205 this(body, startOffset == 0 ? Collections.emptyList() : Collections.singletonList(new BodyAdjustment(0, 0, startOffset))); 206 } 207 208 public ThreadBody(@NonNull CharSequence body, @NonNull List<BodyAdjustment> bodyAdjustments) { 209 this.body = body; 210 this.bodyAdjustments = bodyAdjustments; 211 } 212 213 public @NonNull CharSequence getBody() { 214 return body; 215 } 216 217 public @NonNull List<BodyAdjustment> getBodyAdjustments() { 218 return bodyAdjustments; 219 } 220 } 221}