Show "unplayed" dot on incoming audio messages

This commit is contained in:
Evan Hahn 2021-08-12 13:15:55 -05:00 committed by GitHub
parent 9fd191ae00
commit b0750e5f4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 812 additions and 175 deletions

View file

@ -52,6 +52,7 @@ import { handleMessageSend } from '../util/handleMessageSend';
import { getConversationMembers } from '../util/getConversationMembers';
import { sendReadReceiptsFor } from '../util/sendReadReceiptsFor';
import { updateConversationsWithUuidLookup } from '../updateConversationsWithUuidLookup';
import { ReadStatus } from '../messages/MessageReadStatus';
import { SendStatus } from '../messages/MessageSendState';
import {
concat,
@ -2454,7 +2455,7 @@ export class ConversationModel extends window.Backbone
sent_at: receivedAt,
received_at: receivedAtCounter,
received_at_ms: receivedAt,
unread: 1,
readStatus: ReadStatus.Unread,
// TODO: DESKTOP-722
// this type does not fully implement the interface it is expected to
} as unknown) as typeof window.Whisper.MessageAttributesType;
@ -2494,7 +2495,7 @@ export class ConversationModel extends window.Backbone
sent_at: receivedAt,
received_at: receivedAtCounter,
received_at_ms: receivedAt,
unread: 1,
readStatus: ReadStatus.Unread,
// TODO: DESKTOP-722
// this type does not fully implement the interface it is expected to
} as unknown) as typeof window.Whisper.MessageAttributesType;
@ -2529,7 +2530,7 @@ export class ConversationModel extends window.Backbone
received_at: window.Signal.Util.incrementMessageCounter(),
received_at_ms: timestamp,
key_changed: keyChangedId,
unread: 1,
readStatus: ReadStatus.Unread,
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
// TODO: DESKTOP-722
// this type does not fully implement the interface it is expected to
@ -2589,7 +2590,7 @@ export class ConversationModel extends window.Backbone
verifiedChanged: verifiedChangeId,
verified,
local: options.local,
unread: 1,
readStatus: ReadStatus.Unread,
// TODO: DESKTOP-722
} as unknown) as typeof window.Whisper.MessageAttributesType;
@ -2647,7 +2648,7 @@ export class ConversationModel extends window.Backbone
sent_at: timestamp,
received_at: window.Signal.Util.incrementMessageCounter(),
received_at_ms: timestamp,
unread,
readStatus: unread ? ReadStatus.Unread : ReadStatus.Read,
callHistoryDetails: detailsToSave,
// TODO: DESKTOP-722
} as unknown) as typeof window.Whisper.MessageAttributesType;
@ -2697,7 +2698,7 @@ export class ConversationModel extends window.Backbone
sent_at: now,
received_at: window.Signal.Util.incrementMessageCounter(),
received_at_ms: now,
unread: false,
readStatus: ReadStatus.Read,
changedId: conversationId || this.id,
profileChange,
// TODO: DESKTOP-722
@ -2738,7 +2739,7 @@ export class ConversationModel extends window.Backbone
sent_at: now,
received_at: window.Signal.Util.incrementMessageCounter(),
received_at_ms: now,
unread: false,
readStatus: ReadStatus.Read,
};
const id = await window.Signal.Data.saveMessage(
@ -4163,7 +4164,7 @@ export class ConversationModel extends window.Backbone
const model = new window.Whisper.Message(({
// Even though this isn't reflected to the user, we want to place the last seen
// indicator above it. We set it to 'unread' to trigger that placement.
unread: 1,
readStatus: ReadStatus.Unread,
conversationId: this.id,
// No type; 'incoming' messages are specially treated by conversation.markRead()
sent_at: timestamp,
@ -4266,7 +4267,7 @@ export class ConversationModel extends window.Backbone
type: 'message-history-unsynced',
// Even though this isn't reflected to the user, we want to place the last seen
// indicator above it. We set it to 'unread' to trigger that placement.
unread: 1,
readStatus: ReadStatus.Unread,
conversationId: this.id,
sent_at: timestamp,
received_at: window.Signal.Util.incrementMessageCounter(),

View file

@ -44,6 +44,7 @@ import * as Stickers from '../types/Stickers';
import { AttachmentType, isImage, isVideo } from '../types/Attachment';
import { IMAGE_WEBP, stringToMIMEType } from '../types/MIME';
import { ourProfileKeyService } from '../services/ourProfileKey';
import { ReadStatus } from '../messages/MessageReadStatus';
import {
SendActionType,
SendStateByConversationId,
@ -53,9 +54,10 @@ import {
sendStateReducer,
someSendStatus,
} from '../messages/MessageSendState';
import { migrateLegacyReadStatus } from '../messages/migrateLegacyReadStatus';
import { migrateLegacySendAttributes } from '../messages/migrateLegacySendAttributes';
import { getOwn } from '../util/getOwn';
import { markRead } from '../services/MessageUpdater';
import { markRead, markViewed } from '../services/MessageUpdater';
import { isMessageUnread } from '../util/isMessageUnread';
import {
isDirectConversation,
@ -104,6 +106,7 @@ import {
import { Deletes } from '../messageModifiers/Deletes';
import { Reactions } from '../messageModifiers/Reactions';
import { ReadSyncs } from '../messageModifiers/ReadSyncs';
import { ViewSyncs } from '../messageModifiers/ViewSyncs';
import { ViewOnceOpenSyncs } from '../messageModifiers/ViewOnceOpenSyncs';
import * as AttachmentDownloads from '../messageModifiers/AttachmentDownloads';
import * as LinkPreview from '../types/LinkPreview';
@ -194,6 +197,11 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
);
}
const readStatus = migrateLegacyReadStatus(this.attributes);
if (readStatus !== undefined) {
this.set('readStatus', readStatus, { silent: true });
}
const sendStateByConversationId = migrateLegacySendAttributes(
this.attributes,
window.ConversationController.get.bind(window.ConversationController),
@ -835,8 +843,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
return;
}
if (isMessageUnread(this.attributes)) {
this.set(markRead(this.attributes));
if (this.get('readStatus') !== ReadStatus.Viewed) {
this.set(markViewed(this.attributes));
}
await this.eraseContents();
@ -3269,19 +3277,41 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
}
if (type === 'incoming') {
// In a followup (see DESKTOP-2100), we want to make `ReadSyncs#forMessage` return
// an array, not an object. This array wrapping makes that future a bit easier.
const readSync = ReadSyncs.getSingleton().forMessage(message);
if (readSync) {
if (
message.get('expireTimer') &&
!message.get('expirationStartTimestamp')
) {
message.set(
'expirationStartTimestamp',
Math.min(readSync.get('readAt'), Date.now())
);
}
const readSyncs = readSync ? [readSync] : [];
message.unset('unread');
const viewSyncs = ViewSyncs.getSingleton().forMessage(message);
if (message.get('expireTimer')) {
const existingExpirationStartTimestamp = message.get(
'expirationStartTimestamp'
);
const candidateTimestamps: Array<number> = [
Date.now(),
...(existingExpirationStartTimestamp
? [existingExpirationStartTimestamp]
: []),
...readSyncs.map(sync => sync.get('readAt')),
...viewSyncs.map(sync => sync.get('viewedAt')),
];
message.set(
'expirationStartTimestamp',
Math.min(...candidateTimestamps)
);
changed = true;
}
let newReadStatus: undefined | ReadStatus.Read | ReadStatus.Viewed;
if (viewSyncs.length) {
newReadStatus = ReadStatus.Viewed;
} else if (readSyncs.length) {
newReadStatus = ReadStatus.Read;
}
if (newReadStatus !== undefined) {
message.set('readStatus', newReadStatus);
// This is primarily to allow the conversation to mark all older
// messages as read, as is done when we receive a read sync for
// a message we already know about.
@ -3290,22 +3320,24 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
c.onReadMessage(message);
}
changed = true;
} else if (isFirstRun) {
}
if (isFirstRun && !viewSyncs.length && !readSyncs.length) {
conversation.set({
unreadCount: (conversation.get('unreadCount') || 0) + 1,
isArchived: false,
});
}
}
// Check for out-of-order view once open syncs
if (type === 'incoming' && isTapToView(message.attributes)) {
const viewOnceOpenSync = ViewOnceOpenSyncs.getSingleton().forMessage(
message
);
if (viewOnceOpenSync) {
await message.markViewOnceMessageViewed({ fromSync: true });
changed = true;
// Check for out-of-order view once open syncs
if (isTapToView(message.attributes)) {
const viewOnceOpenSync = ViewOnceOpenSyncs.getSingleton().forMessage(
message
);
if (viewOnceOpenSync) {
await message.markViewOnceMessageViewed({ fromSync: true });
changed = true;
}
}
}