Fix view-once sync and quote descriptions.

This commit is contained in:
Greyson Parrelli 2020-01-09 12:03:52 -05:00
parent e2a48d1714
commit fd7aa9ccfa
17 changed files with 87 additions and 38 deletions

View file

@ -154,10 +154,9 @@ public class InputPanel extends LinearLayout
long id, long id,
@NonNull Recipient author, @NonNull Recipient author,
@NonNull String body, @NonNull String body,
@NonNull SlideDeck attachments, @NonNull SlideDeck attachments)
boolean isViewOnce)
{ {
this.quoteView.setQuote(glideRequests, id, author, body, false, attachments, isViewOnce); this.quoteView.setQuote(glideRequests, id, author, body, false, attachments);
this.quoteView.setVisibility(View.VISIBLE); this.quoteView.setVisibility(View.VISIBLE);
if (this.linkPreview.getVisibility() == View.VISIBLE) { if (this.linkPreview.getVisibility() == View.VISIBLE) {

View file

@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver; import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
@ -149,8 +150,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
@NonNull Recipient author, @NonNull Recipient author,
@Nullable String body, @Nullable String body,
boolean originalMissing, boolean originalMissing,
@NonNull SlideDeck attachments, @NonNull SlideDeck attachments)
boolean isViewOnce)
{ {
if (this.author != null) this.author.removeForeverObserver(this); if (this.author != null) this.author.removeForeverObserver(this);
@ -161,7 +161,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
this.author.observeForever(this); this.author.observeForever(this);
setQuoteAuthor(author); setQuoteAuthor(author);
setQuoteText(body, attachments, isViewOnce); setQuoteText(body, attachments);
setQuoteAttachment(glideRequests, attachments); setQuoteAttachment(glideRequests, attachments);
setQuoteMissingFooter(originalMissing); setQuoteMissingFooter(originalMissing);
} }
@ -197,7 +197,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
mainView.setBackgroundColor(author.getColor().toQuoteBackgroundColor(getContext(), outgoing)); mainView.setBackgroundColor(author.getColor().toQuoteBackgroundColor(getContext(), outgoing));
} }
private void setQuoteText(@Nullable String body, @NonNull SlideDeck attachments, boolean isViewOnce) { private void setQuoteText(@Nullable String body, @NonNull SlideDeck attachments) {
if (!TextUtils.isEmpty(body) || !attachments.containsMediaSlide()) { if (!TextUtils.isEmpty(body) || !attachments.containsMediaSlide()) {
bodyView.setVisibility(VISIBLE); bodyView.setVisibility(VISIBLE);
bodyView.setText(body == null ? "" : body); bodyView.setText(body == null ? "" : body);
@ -213,9 +213,10 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
List<Slide> imageSlides = Stream.of(attachments.getSlides()).filter(Slide::hasImage).limit(1).toList(); List<Slide> imageSlides = Stream.of(attachments.getSlides()).filter(Slide::hasImage).limit(1).toList();
List<Slide> videoSlides = Stream.of(attachments.getSlides()).filter(Slide::hasVideo).limit(1).toList(); List<Slide> videoSlides = Stream.of(attachments.getSlides()).filter(Slide::hasVideo).limit(1).toList();
List<Slide> stickerSlides = Stream.of(attachments.getSlides()).filter(Slide::hasSticker).limit(1).toList(); List<Slide> stickerSlides = Stream.of(attachments.getSlides()).filter(Slide::hasSticker).limit(1).toList();
List<Slide> viewOnceSlides = Stream.of(attachments.getSlides()).filter(Slide::hasViewOnce).limit(1).toList();
// Given that most types have images, we specifically check images last // Given that most types have images, we specifically check images last
if (isViewOnce) { if (!viewOnceSlides.isEmpty()) {
mediaDescriptionText.setText(R.string.QuoteView_media); mediaDescriptionText.setText(R.string.QuoteView_media);
} else if (!audioSlides.isEmpty()) { } else if (!audioSlides.isEmpty()) {
mediaDescriptionText.setText(R.string.QuoteView_audio); mediaDescriptionText.setText(R.string.QuoteView_audio);
@ -233,10 +234,14 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
private void setQuoteAttachment(@NonNull GlideRequests glideRequests, @NonNull SlideDeck slideDeck) { private void setQuoteAttachment(@NonNull GlideRequests glideRequests, @NonNull SlideDeck slideDeck) {
List<Slide> imageVideoSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasImage() || s.hasVideo() || s.hasSticker()).limit(1).toList(); List<Slide> imageVideoSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasImage() || s.hasVideo() || s.hasSticker()).limit(1).toList();
List<Slide> documentSlides = Stream.of(attachments.getSlides()).filter(Slide::hasDocument).limit(1).toList(); List<Slide> documentSlides = Stream.of(attachments.getSlides()).filter(Slide::hasDocument).limit(1).toList();
List<Slide> viewOnceSlides = Stream.of(attachments.getSlides()).filter(Slide::hasViewOnce).limit(1).toList();
attachmentVideoOverlayView.setVisibility(GONE); attachmentVideoOverlayView.setVisibility(GONE);
if (!imageVideoSlides.isEmpty() && imageVideoSlides.get(0).getThumbnailUri() != null) { if (!viewOnceSlides.isEmpty()) {
thumbnailView.setVisibility(GONE);
attachmentContainerView.setVisibility(GONE);
} else if (!imageVideoSlides.isEmpty() && imageVideoSlides.get(0).getThumbnailUri() != null) {
thumbnailView.setVisibility(VISIBLE); thumbnailView.setVisibility(VISIBLE);
attachmentContainerView.setVisibility(GONE); attachmentContainerView.setVisibility(GONE);
dismissView.setBackgroundResource(R.drawable.dismiss_background); dismissView.setBackgroundResource(R.drawable.dismiss_background);

View file

@ -2836,8 +2836,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
messageRecord.getDateSent(), messageRecord.getDateSent(),
author, author,
body, body,
slideDeck, slideDeck);
messageRecord.isViewOnce());
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) { } else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0); LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
@ -2851,8 +2850,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
messageRecord.getDateSent(), messageRecord.getDateSent(),
author, author,
messageRecord.getBody(), messageRecord.getBody(),
slideDeck, slideDeck);
messageRecord.isViewOnce());
} else { } else {
SlideDeck slideDeck = messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(); SlideDeck slideDeck = messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck();
@ -2866,8 +2864,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
messageRecord.getDateSent(), messageRecord.getDateSent(),
author, author,
messageRecord.getBody(), messageRecord.getBody(),
slideDeck, slideDeck);
messageRecord.isViewOnce());
} }
inputPanel.clickOnComposeInput(); inputPanel.clickOnComposeInput();

View file

@ -1077,7 +1077,7 @@ public class ConversationFragment extends Fragment
.withMimeType(thumbnailSlide.getContentType()) .withMimeType(thumbnailSlide.getContentType())
.createForSingleSessionOnDisk(requireContext()); .createForSingleSessionOnDisk(requireContext());
DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForMessage(messageRecord.getId()); DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForViewOnceMessage(messageRecord.getId());
ApplicationContext.getInstance(requireContext()) ApplicationContext.getInstance(requireContext())
.getViewOnceMessageManager() .getViewOnceMessageManager()
@ -1095,7 +1095,7 @@ public class ConversationFragment extends Fragment
} else { } else {
Log.w(TAG, "Failed to open view-once photo. Showing a toast and deleting the attachments for the message just in case."); Log.w(TAG, "Failed to open view-once photo. Showing a toast and deleting the attachments for the message just in case.");
Toast.makeText(requireContext(), R.string.ConversationFragment_failed_to_open_message, Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), R.string.ConversationFragment_failed_to_open_message, Toast.LENGTH_SHORT).show();
SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForMessage(messageRecord.getId())); SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForViewOnceMessage(messageRecord.getId()));
} }
}); });
} }

View file

@ -855,7 +855,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati
if (current.isMms() && !current.isMmsNotification() && ((MediaMmsMessageRecord)current).getQuote() != null) { if (current.isMms() && !current.isMmsNotification() && ((MediaMmsMessageRecord)current).getQuote() != null) {
Quote quote = ((MediaMmsMessageRecord)current).getQuote(); Quote quote = ((MediaMmsMessageRecord)current).getQuote();
//noinspection ConstantConditions //noinspection ConstantConditions
quoteView.setQuote(glideRequests, quote.getId(), Recipient.live(quote.getAuthor()).get(), quote.getText(), quote.isOriginalMissing(), quote.getAttachment(), messageRecord.isViewOnce()); quoteView.setQuote(glideRequests, quote.getId(), Recipient.live(quote.getAuthor()).get(), quote.getText(), quote.isOriginalMissing(), quote.getAttachment());
quoteView.setVisibility(View.VISIBLE); quoteView.setVisibility(View.VISIBLE);
quoteView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; quoteView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;

View file

@ -320,8 +320,8 @@ public class AttachmentDatabase extends Database {
notifyAttachmentListeners(); notifyAttachmentListeners();
} }
public void deleteAttachmentFilesForMessage(long mmsId) { public void deleteAttachmentFilesForViewOnceMessage(long mmsId) {
Log.d(TAG, "[deleteAttachmentFilesForMessage] mmsId: " + mmsId); Log.d(TAG, "[deleteAttachmentFilesForViewOnceMessage] mmsId: " + mmsId);
SQLiteDatabase database = databaseHelper.getWritableDatabase(); SQLiteDatabase database = databaseHelper.getWritableDatabase();
Cursor cursor = null; Cursor cursor = null;
@ -355,6 +355,7 @@ public class AttachmentDatabase extends Database {
values.put(HEIGHT, 0); values.put(HEIGHT, 0);
values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE); values.put(TRANSFER_STATE, TRANSFER_PROGRESS_DONE);
values.put(BLUR_HASH, (String) null); values.put(BLUR_HASH, (String) null);
values.put(CONTENT_TYPE, MediaUtil.VIEW_ONCE);
database.update(TABLE_NAME, values, MMS_ID + " = ?", new String[] {mmsId + ""}); database.update(TABLE_NAME, values, MMS_ID + " = ?", new String[] {mmsId + ""});
notifyAttachmentListeners(); notifyAttachmentListeners();
@ -365,7 +366,6 @@ public class AttachmentDatabase extends Database {
} }
} }
public void deleteAttachment(@NonNull AttachmentId id) { public void deleteAttachment(@NonNull AttachmentId id) {
Log.d(TAG, "[deleteAttachment] attachmentId: " + id); Log.d(TAG, "[deleteAttachment] attachmentId: " + id);

View file

@ -145,7 +145,9 @@ public class ThreadRecord extends DisplayRecord {
} }
private String getViewOnceDescription(@NonNull Context context, @Nullable String contentType) { private String getViewOnceDescription(@NonNull Context context, @Nullable String contentType) {
if (MediaUtil.isVideoType(contentType)) { if (MediaUtil.isViewOnceType(contentType)) {
return context.getString(R.string.ThreadRecord_disappearing_media);
} else if (MediaUtil.isVideoType(contentType)) {
return context.getString(R.string.ThreadRecord_disappearing_video); return context.getString(R.string.ThreadRecord_disappearing_video);
} else { } else {
return context.getString(R.string.ThreadRecord_disappearing_photo); return context.getString(R.string.ThreadRecord_disappearing_photo);

View file

@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo; import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo;
import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException; import org.thoughtcrime.securesms.database.NoSuchMessageException;
@ -203,7 +202,7 @@ public class PushGroupSendJob extends PushSendJob {
} }
if (message.isViewOnce()) { if (message.isViewOnce()) {
DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForMessage(messageId); DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForViewOnceMessage(messageId);
} }
} else if (!networkFailures.isEmpty()) { } else if (!networkFailures.isEmpty()) {
throw new RetryLaterException(); throw new RetryLaterException();

View file

@ -150,7 +150,7 @@ public class PushMediaSendJob extends PushSendJob {
} }
if (message.isViewOnce()) { if (message.isViewOnce()) {
DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForMessage(messageId); DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForViewOnceMessage(messageId);
} }
log(TAG, "Sent message: " + messageId); log(TAG, "Sent message: " + messageId);

View file

@ -656,7 +656,7 @@ public final class PushProcessMessageJob extends BaseJob {
handleReaction(content, message.getMessage()); handleReaction(content, message.getMessage());
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message)); threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message));
threadId = threadId != -1 ? threadId : null; threadId = threadId != -1 ? threadId : null;
} else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent()) { } else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent() || message.getMessage().isViewOnce()) {
threadId = handleSynchronizeSentMediaMessage(message); threadId = handleSynchronizeSentMediaMessage(message);
} else { } else {
threadId = handleSynchronizeSentTextMessage(message); threadId = handleSynchronizeSentTextMessage(message);
@ -742,7 +742,7 @@ public final class PushProcessMessageJob extends BaseJob {
MessageRecord record = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(timestamp, author); MessageRecord record = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(timestamp, author);
if (record != null && record.isMms()) { if (record != null && record.isMms()) {
DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForMessage(record.getId()); DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForViewOnceMessage(record.getId());
} }
MessageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp); MessageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
@ -842,7 +842,8 @@ public final class PushProcessMessageJob extends BaseJob {
Optional<List<Contact>> sharedContacts = getContacts(message.getMessage().getSharedContacts()); Optional<List<Contact>> sharedContacts = getContacts(message.getMessage().getSharedContacts());
Optional<List<LinkPreview>> previews = getLinkPreviews(message.getMessage().getPreviews(), message.getMessage().getBody().or("")); Optional<List<LinkPreview>> previews = getLinkPreviews(message.getMessage().getPreviews(), message.getMessage().getBody().or(""));
boolean viewOnce = message.getMessage().isViewOnce(); boolean viewOnce = message.getMessage().isViewOnce();
List<Attachment> syncAttachments = viewOnce ? Collections.emptyList() : PointerAttachment.forPointers(message.getMessage().getAttachments()); List<Attachment> syncAttachments = viewOnce ? Collections.singletonList(new TombstoneAttachment(MediaUtil.VIEW_ONCE, false))
: PointerAttachment.forPointers(message.getMessage().getAttachments());
if (sticker.isPresent()) { if (sticker.isPresent()) {
syncAttachments.add(sticker.get()); syncAttachments.add(sticker.get());
@ -1289,7 +1290,9 @@ public final class PushProcessMessageJob extends BaseJob {
if (message.isMms()) { if (message.isMms()) {
MmsMessageRecord mmsMessage = (MmsMessageRecord) message; MmsMessageRecord mmsMessage = (MmsMessageRecord) message;
if (!mmsMessage.isViewOnce()) { if (mmsMessage.isViewOnce()) {
attachments.add(new TombstoneAttachment(MediaUtil.VIEW_ONCE, true));
} else {
attachments = mmsMessage.getSlideDeck().asAttachments(); attachments = mmsMessage.getSlideDeck().asAttachments();
if (attachments.isEmpty()) { if (attachments.isEmpty()) {
@ -1298,8 +1301,6 @@ public final class PushProcessMessageJob extends BaseJob {
.map(lp -> lp.getThumbnail().get()) .map(lp -> lp.getThumbnail().get())
.toList()); .toList());
} }
} else if (quote.get().getAttachments().size() > 0) {
attachments.add(new TombstoneAttachment(quote.get().getAttachments().get(0).getContentType(), true));
} }
} }

View file

@ -221,8 +221,11 @@ public abstract class PushSendJob extends SendJob {
String quoteBody = message.getOutgoingQuote().getText(); String quoteBody = message.getOutgoingQuote().getText();
RecipientId quoteAuthor = message.getOutgoingQuote().getAuthor(); RecipientId quoteAuthor = message.getOutgoingQuote().getAuthor();
List<SignalServiceDataMessage.Quote.QuotedAttachment> quoteAttachments = new LinkedList<>(); List<SignalServiceDataMessage.Quote.QuotedAttachment> quoteAttachments = new LinkedList<>();
List<Attachment> filteredAttachments = Stream.of(message.getOutgoingQuote().getAttachments())
.filterNot(a -> MediaUtil.isViewOnceType(a.getContentType()))
.toList();
for (Attachment attachment : message.getOutgoingQuote().getAttachments()) { for (Attachment attachment : filteredAttachments) {
BitmapUtil.ScaleResult thumbnailData = null; BitmapUtil.ScaleResult thumbnailData = null;
SignalServiceAttachment thumbnail = null; SignalServiceAttachment thumbnail = null;
String thumbnailType = MediaUtil.IMAGE_JPEG; String thumbnailType = MediaUtil.IMAGE_JPEG;

View file

@ -105,6 +105,10 @@ public abstract class Slide {
return false; return false;
} }
public boolean hasViewOnce() {
return false;
}
public @NonNull String getContentDescription() { return ""; } public @NonNull String getContentDescription() { return ""; }
public @NonNull Attachment asAttachment() { public @NonNull Attachment asAttachment() {

View file

@ -88,7 +88,7 @@ public class SlideDeck {
public boolean containsMediaSlide() { public boolean containsMediaSlide() {
for (Slide slide : slides) { for (Slide slide : slides) {
if (slide.hasImage() || slide.hasVideo() || slide.hasAudio() || slide.hasDocument() || slide.hasSticker()) { if (slide.hasImage() || slide.hasVideo() || slide.hasAudio() || slide.hasDocument() || slide.hasSticker() || slide.hasViewOnce()) {
return true; return true;
} }
} }

View file

@ -0,0 +1,28 @@
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.util.MediaUtil;
/**
* Slide used for attachments with contentType {@link MediaUtil#VIEW_ONCE}.
* Attachments will only get this type *after* they've been viewed, or if they were synced from a
* linked device. Incoming unviewed messages will have the appropriate image/video contentType.
*/
public class ViewOnceSlide extends Slide {
public ViewOnceSlide(@NonNull Context context, @NonNull Attachment attachment) {
super(context, attachment);
}
@Override
public boolean hasViewOnce() {
return true;
}
}

View file

@ -54,7 +54,7 @@ public class ViewOnceMessageManager extends TimedEventManager<ViewOnceExpiration
@Override @Override
protected void executeEvent(@NonNull ViewOnceExpirationInfo event) { protected void executeEvent(@NonNull ViewOnceExpirationInfo event) {
Log.i(TAG, "Deleting attachments for message " + event.getMessageId()); Log.i(TAG, "Deleting attachments for message " + event.getMessageId());
attachmentDatabase.deleteAttachmentFilesForMessage(event.getMessageId()); attachmentDatabase.deleteAttachmentFilesForViewOnceMessage(event.getMessageId());
} }
@WorkerThread @WorkerThread

View file

@ -34,6 +34,7 @@ import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.StickerSlide; import org.thoughtcrime.securesms.mms.StickerSlide;
import org.thoughtcrime.securesms.mms.TextSlide; import org.thoughtcrime.securesms.mms.TextSlide;
import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.mms.ViewOnceSlide;
import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.providers.BlobProvider;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -56,6 +57,7 @@ public class MediaUtil {
public static final String VIDEO_UNSPECIFIED = "video/*"; public static final String VIDEO_UNSPECIFIED = "video/*";
public static final String VCARD = "text/x-vcard"; public static final String VCARD = "text/x-vcard";
public static final String LONG_TEXT = "text/x-signal-plain"; public static final String LONG_TEXT = "text/x-signal-plain";
public static final String VIEW_ONCE = "application/x-signal-view-once";
public static SlideType getSlideTypeFromContentType(@NonNull String contentType) { public static SlideType getSlideTypeFromContentType(@NonNull String contentType) {
if (isGif(contentType)) { if (isGif(contentType)) {
@ -70,6 +72,8 @@ public class MediaUtil {
return SlideType.MMS; return SlideType.MMS;
} else if (isLongTextType(contentType)) { } else if (isLongTextType(contentType)) {
return SlideType.LONG_TEXT; return SlideType.LONG_TEXT;
} else if (isViewOnceType(contentType)) {
return SlideType.VIEW_ONCE;
} else { } else {
return SlideType.DOCUMENT; return SlideType.DOCUMENT;
} }
@ -87,6 +91,7 @@ public class MediaUtil {
case AUDIO : return new AudioSlide(context, attachment); case AUDIO : return new AudioSlide(context, attachment);
case MMS : return new MmsSlide(context, attachment); case MMS : return new MmsSlide(context, attachment);
case LONG_TEXT : return new TextSlide(context, attachment); case LONG_TEXT : return new TextSlide(context, attachment);
case VIEW_ONCE : return new ViewOnceSlide(context, attachment);
case DOCUMENT : return new DocumentSlide(context, attachment); case DOCUMENT : return new DocumentSlide(context, attachment);
default : throw new AssertionError(); default : throw new AssertionError();
} }
@ -269,6 +274,10 @@ public class MediaUtil {
return (null != contentType) && contentType.equals(LONG_TEXT); return (null != contentType) && contentType.equals(LONG_TEXT);
} }
public static boolean isViewOnceType(String contentType) {
return (null != contentType) && contentType.equals(VIEW_ONCE);
}
public static boolean hasVideoThumbnail(Uri uri) { public static boolean hasVideoThumbnail(Uri uri) {
if (BlobProvider.isAuthority(uri) && MediaUtil.isVideo(BlobProvider.getMimeType(uri)) && Build.VERSION.SDK_INT >= 23) { if (BlobProvider.isAuthority(uri) && MediaUtil.isVideo(BlobProvider.getMimeType(uri)) && Build.VERSION.SDK_INT >= 23) {
return true; return true;
@ -373,6 +382,7 @@ public class MediaUtil {
AUDIO, AUDIO,
MMS, MMS,
LONG_TEXT, LONG_TEXT,
VIEW_ONCE,
DOCUMENT DOCUMENT
} }
} }

View file

@ -819,6 +819,7 @@
<string name="ThreadRecord_sticker">Sticker</string> <string name="ThreadRecord_sticker">Sticker</string>
<string name="ThreadRecord_disappearing_photo">Disappearing photo</string> <string name="ThreadRecord_disappearing_photo">Disappearing photo</string>
<string name="ThreadRecord_disappearing_video">Disappearing video</string> <string name="ThreadRecord_disappearing_video">Disappearing video</string>
<string name="ThreadRecord_disappearing_media">Disappearing media</string>
<string name="ThreadRecord_s_is_on_signal">%s is on Signal!</string> <string name="ThreadRecord_s_is_on_signal">%s is on Signal!</string>
<string name="ThreadRecord_disappearing_messages_disabled">Disappearing messages disabled</string> <string name="ThreadRecord_disappearing_messages_disabled">Disappearing messages disabled</string>
<string name="ThreadRecord_disappearing_message_time_updated_to_s">Disappearing message time set to %s</string> <string name="ThreadRecord_disappearing_message_time_updated_to_s">Disappearing message time set to %s</string>