Fix view-once sync and quote descriptions.

fork-5.53.8
Greyson Parrelli 2020-01-09 12:03:52 -05:00
rodzic e2a48d1714
commit fd7aa9ccfa
17 zmienionych plików z 87 dodań i 38 usunięć

Wyświetl plik

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

Wyświetl plik

@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
@ -149,8 +150,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
@NonNull Recipient author,
@Nullable String body,
boolean originalMissing,
@NonNull SlideDeck attachments,
boolean isViewOnce)
@NonNull SlideDeck attachments)
{
if (this.author != null) this.author.removeForeverObserver(this);
@ -161,7 +161,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
this.author.observeForever(this);
setQuoteAuthor(author);
setQuoteText(body, attachments, isViewOnce);
setQuoteText(body, attachments);
setQuoteAttachment(glideRequests, attachments);
setQuoteMissingFooter(originalMissing);
}
@ -197,7 +197,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
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()) {
bodyView.setVisibility(VISIBLE);
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> 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> viewOnceSlides = Stream.of(attachments.getSlides()).filter(Slide::hasViewOnce).limit(1).toList();
// Given that most types have images, we specifically check images last
if (isViewOnce) {
if (!viewOnceSlides.isEmpty()) {
mediaDescriptionText.setText(R.string.QuoteView_media);
} else if (!audioSlides.isEmpty()) {
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) {
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> viewOnceSlides = Stream.of(attachments.getSlides()).filter(Slide::hasViewOnce).limit(1).toList();
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);
attachmentContainerView.setVisibility(GONE);
dismissView.setBackgroundResource(R.drawable.dismiss_background);

Wyświetl plik

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

Wyświetl plik

@ -1077,7 +1077,7 @@ public class ConversationFragment extends Fragment
.withMimeType(thumbnailSlide.getContentType())
.createForSingleSessionOnDisk(requireContext());
DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForMessage(messageRecord.getId());
DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForViewOnceMessage(messageRecord.getId());
ApplicationContext.getInstance(requireContext())
.getViewOnceMessageManager()
@ -1095,7 +1095,7 @@ public class ConversationFragment extends Fragment
} else {
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();
SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForMessage(messageRecord.getId()));
SignalExecutors.BOUNDED.execute(() -> DatabaseFactory.getAttachmentDatabase(requireContext()).deleteAttachmentFilesForViewOnceMessage(messageRecord.getId()));
}
});
}

Wyświetl plik

@ -855,7 +855,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati
if (current.isMms() && !current.isMmsNotification() && ((MediaMmsMessageRecord)current).getQuote() != null) {
Quote quote = ((MediaMmsMessageRecord)current).getQuote();
//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.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;

Wyświetl plik

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

Wyświetl plik

@ -145,7 +145,9 @@ public class ThreadRecord extends DisplayRecord {
}
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);
} else {
return context.getString(R.string.ThreadRecord_disappearing_photo);

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -217,12 +217,15 @@ public abstract class PushSendJob extends SendJob {
protected Optional<SignalServiceDataMessage.Quote> getQuoteFor(OutgoingMediaMessage message) {
if (message.getOutgoingQuote() == null) return Optional.absent();
long quoteId = message.getOutgoingQuote().getId();
String quoteBody = message.getOutgoingQuote().getText();
RecipientId quoteAuthor = message.getOutgoingQuote().getAuthor();
List<SignalServiceDataMessage.Quote.QuotedAttachment> quoteAttachments = new LinkedList<>();
long quoteId = message.getOutgoingQuote().getId();
String quoteBody = message.getOutgoingQuote().getText();
RecipientId quoteAuthor = message.getOutgoingQuote().getAuthor();
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;
SignalServiceAttachment thumbnail = null;
String thumbnailType = MediaUtil.IMAGE_JPEG;

Wyświetl plik

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

Wyświetl plik

@ -88,7 +88,7 @@ public class SlideDeck {
public boolean containsMediaSlide() {
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;
}
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -819,6 +819,7 @@
<string name="ThreadRecord_sticker">Sticker</string>
<string name="ThreadRecord_disappearing_photo">Disappearing photo</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_disappearing_messages_disabled">Disappearing messages disabled</string>
<string name="ThreadRecord_disappearing_message_time_updated_to_s">Disappearing message time set to %s</string>