Mark sent gift viewed when opened.

This commit is contained in:
Alex Hart
2022-05-16 10:24:48 -03:00
committed by Cody Henthorne
parent 15af1d3bd1
commit 425a13e68c
13 changed files with 276 additions and 10 deletions

View File

@@ -105,5 +105,6 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
boolean onUrlClicked(@NonNull String url);
void onViewGiftBadgeClicked(@NonNull MessageRecord messageRecord);
void onGiftBadgeRevealed(@NonNull MessageRecord messageRecord);
}
}

View File

@@ -9,7 +9,7 @@ interface OpenableGift {
/**
* Returns a projection to draw a top, or null to not do so.
*/
fun getOpenableGiftProjection(): Projection?
fun getOpenableGiftProjection(isAnimating: Boolean): Projection?
/**
* Returns a unique id assosicated with this gift.

View File

@@ -70,12 +70,12 @@ class OpenableGiftItemDecoration(context: Context) : RecyclerView.ItemDecoration
val notAnimated = openableChildren.filterNot { animationState.containsKey(it.getGiftId()) }
notAnimated.filterNot { messageIdsOpenedThisSession.contains(it.getGiftId()) }.forEach { child ->
val projection = child.getOpenableGiftProjection()
val projection = child.getOpenableGiftProjection(false)
if (projection != null) {
if (messageIdsShakenThisSession.contains(child.getGiftId())) {
child.setOpenGiftCallback {
child.clearOpenGiftCallback()
val proj = it.getOpenableGiftProjection()
val proj = it.getOpenableGiftProjection(true)
if (proj != null) {
messageIdsOpenedThisSession.add(it.getGiftId())
startOpenAnimation(it)
@@ -210,7 +210,7 @@ class OpenableGiftItemDecoration(context: Context) : RecyclerView.ItemDecoration
}
fun update(animatorDurationScale: Float, canvas: Canvas, drawBox: (Canvas, Projection) -> Unit, drawBow: (Canvas, Projection) -> Unit): Boolean {
val projection = openableGift.getOpenableGiftProjection() ?: return false
val projection = openableGift.getOpenableGiftProjection(true) ?: return false
if (animatorDurationScale <= 0f) {
update(canvas, projection, 0f, 0f, drawBox, drawBow)

View File

@@ -1977,6 +1977,13 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
ViewReceivedGiftBottomSheet.show(getChildFragmentManager(), (MmsMessageRecord) messageRecord);
}
}
@Override
public void onGiftBadgeRevealed(@NonNull MessageRecord messageRecord) {
if (messageRecord.isOutgoing() && MessageRecordUtil.hasGiftBadge(messageRecord)) {
conversationViewModel.markGiftBadgeRevealed(messageRecord.getId());
}
}
}
public void refreshList() {

View File

@@ -2041,9 +2041,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
}
@Override
public @Nullable Projection getOpenableGiftProjection() {
boolean isViewedAndIncoming = !messageRecord.isOutgoing() && messageRecord.getViewedReceiptCount() > 0;
if (!isGiftMessage(messageRecord) || messageRecord.isRemoteDelete() || isViewedAndIncoming) {
public @Nullable Projection getOpenableGiftProjection(boolean isAnimating) {
if (!isGiftMessage(messageRecord) || messageRecord.isRemoteDelete() || (messageRecord.getViewedReceiptCount() > 0 && !isAnimating)) {
return null;
}
@@ -2061,7 +2060,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
@Override
public void setOpenGiftCallback(@NonNull Function1<? super OpenableGift, Unit> openGift) {
if (giftViewStub.resolved()) {
bodyBubble.setOnClickListener(unused -> openGift.invoke(this));
bodyBubble.setOnClickListener(unused -> {
openGift.invoke(this);
eventListener.onGiftBadgeRevealed(messageRecord);
});
giftViewStub.get().onGiftNotOpened();
}
}

View File

@@ -9,17 +9,21 @@ import androidx.annotation.WorkerThread;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.MessageDatabase;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobs.MultiDeviceViewedUpdateJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.BubbleUtil;
import org.thoughtcrime.securesms.util.ConversationUtil;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
class ConversationRepository {
@@ -98,4 +102,17 @@ class ConversationRepository {
return new ConversationData(threadId, lastSeen, lastSeenPosition, lastScrolledPosition, jumpToPosition, threadSize, messageRequestData, showUniversalExpireTimerUpdate);
}
void markGiftBadgeRevealed(long messageId) {
SignalExecutors.BOUNDED_IO.execute(() -> {
List<MessageDatabase.MarkedMessageInfo> markedMessageInfo = SignalDatabase.mms().setOutgoingGiftsRevealed(Collections.singletonList(messageId));
if (!markedMessageInfo.isEmpty()) {
Log.d(TAG, "Marked gift badge revealed. Sending view sync message.");
MultiDeviceViewedUpdateJob.enqueue(
markedMessageInfo.stream()
.map(MessageDatabase.MarkedMessageInfo::getSyncMessageId)
.collect(Collectors.toList()));
}
});
}
}

View File

@@ -276,6 +276,10 @@ public class ConversationViewModel extends ViewModel {
searchQuery.setValue(query);
}
void markGiftBadgeRevealed(long messageId) {
conversationRepository.markGiftBadgeRevealed(messageId);
}
@NonNull LiveData<String> getSearchQuery() {
return searchQuery;
}

View File

@@ -135,6 +135,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract @NonNull List<MarkedMessageInfo> getViewedIncomingMessages(long threadId);
public abstract @Nullable MarkedMessageInfo setIncomingMessageViewed(long messageId);
public abstract @NonNull List<MarkedMessageInfo> setIncomingMessagesViewed(@NonNull List<Long> messageIds);
public abstract @NonNull List<MarkedMessageInfo> setOutgoingGiftsRevealed(@NonNull List<Long> messageIds);
public abstract void addFailures(long messageId, List<NetworkFailure> failure);
public abstract void setNetworkFailures(long messageId, Set<NetworkFailure> failures);

View File

@@ -449,6 +449,44 @@ public class MmsDatabase extends MessageDatabase {
return results;
}
@Override
public @NonNull List<MarkedMessageInfo>
setOutgoingGiftsRevealed(@NonNull List<Long> messageIds) {
String[] projection = SqlUtil.buildArgs(ID, RECIPIENT_ID, DATE_SENT, THREAD_ID);
String where = ID + " IN (" + Util.join(messageIds, ",") + ") AND (" + getOutgoingTypeClause() + ") AND (" + getTypeField() + " & " + Types.SPECIAL_TYPES_MASK + " = " + Types.SPECIAL_TYPE_GIFT_BADGE + ") AND " + VIEWED_RECEIPT_COUNT + " = 0";
List<MarkedMessageInfo> results = new LinkedList<>();
getWritableDatabase().beginTransaction();
try (Cursor cursor = getWritableDatabase().query(TABLE_NAME, projection, where, null, null, null, null)) {
while (cursor.moveToNext()) {
long messageId = CursorUtil.requireLong(cursor, ID);
long threadId = CursorUtil.requireLong(cursor, THREAD_ID);
RecipientId recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID));
long dateSent = CursorUtil.requireLong(cursor, DATE_SENT);
SyncMessageId syncMessageId = new SyncMessageId(recipientId, dateSent);
results.add(new MarkedMessageInfo(threadId, syncMessageId, new MessageId(messageId, true), null));
ContentValues contentValues = new ContentValues();
contentValues.put(VIEWED_RECEIPT_COUNT, 1);
contentValues.put(RECEIPT_TIMESTAMP, System.currentTimeMillis());
getWritableDatabase().update(TABLE_NAME, contentValues, ID_WHERE, SqlUtil.buildArgs(messageId));
}
getWritableDatabase().setTransactionSuccessful();
} finally {
getWritableDatabase().endTransaction();
}
Set<Long> threadsUpdated = Stream.of(results)
.map(MarkedMessageInfo::getThreadId)
.collect(Collectors.toSet());
notifyConversationListeners(threadsUpdated);
return results;
}
@Override
public @NonNull Pair<Long, Long> insertReceivedCall(@NonNull RecipientId address, boolean isVideoOffer) {
throw new UnsupportedOperationException();

View File

@@ -658,6 +658,11 @@ public class SmsDatabase extends MessageDatabase {
return Collections.emptyList();
}
@Override
public @NonNull List<MarkedMessageInfo> setOutgoingGiftsRevealed(@NonNull List<Long> messageIds) {
throw new UnsupportedOperationException();
}
private InsertResult updateMessageBodyAndType(long messageId, String body, long maskOff, long maskOn) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
db.execSQL("UPDATE " + TABLE_NAME + " SET " + BODY + " = ?, " +

View File

@@ -1379,6 +1379,7 @@ public final class MessageContentProcessor {
.toList();
SignalDatabase.mms().setIncomingMessagesViewed(toMarkViewed);
SignalDatabase.mms().setOutgoingGiftsRevealed(toMarkViewed);
MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier();
messageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);