diff --git a/js/background.js b/js/background.js index 7648e5553..7ec8803d4 100644 --- a/js/background.js +++ b/js/background.js @@ -740,15 +740,6 @@ } }); - Whisper.events.on('calculatingPoW', ({ pubKey, timestamp }) => { - try { - const conversation = window.getConversationController().get(pubKey); - conversation.onCalculatingPoW(pubKey, timestamp); - } catch (e) { - window.log.error('Error showing PoW cog'); - } - }); - Whisper.events.on('password-updated', () => { if (appView && appView.inboxView) { appView.inboxView.trigger('password-updated'); diff --git a/js/expiring_messages.js b/js/expiring_messages.js index fe676b4a1..f18feec33 100644 --- a/js/expiring_messages.js +++ b/js/expiring_messages.js @@ -37,7 +37,7 @@ const conversation = message.getConversation(); if (conversation) { - conversation.trigger('expired', message); + conversation.onExpired(message); } }) ); diff --git a/ts/components/conversation/message/MessageMetadata.tsx b/ts/components/conversation/message/MessageMetadata.tsx index f11b87b06..25802ff18 100644 --- a/ts/components/conversation/message/MessageMetadata.tsx +++ b/ts/components/conversation/message/MessageMetadata.tsx @@ -22,7 +22,7 @@ type Props = { direction: 'incoming' | 'outgoing'; timestamp: number; serverTimestamp?: number; - status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error' | 'pow'; + status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error'; expirationLength?: number; expirationTimestamp?: number; isPublic?: boolean; diff --git a/ts/components/conversation/message/OutgoingMessageStatus.tsx b/ts/components/conversation/message/OutgoingMessageStatus.tsx index 0a4e4c5f6..225c057be 100644 --- a/ts/components/conversation/message/OutgoingMessageStatus.tsx +++ b/ts/components/conversation/message/OutgoingMessageStatus.tsx @@ -94,13 +94,12 @@ const MessageStatusError = (props: { theme: DefaultTheme }) => { }; export const OutgoingMessageStatus = (props: { - status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error' | 'pow'; + status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error'; theme: DefaultTheme; iconColor: string; isInMessageView?: boolean; }) => { switch (props.status) { - case 'pow': case 'sending': return ; case 'sent': diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index d3e05d082..63d005cbd 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -312,18 +312,6 @@ class SettingsViewInner extends React.Component { } } - private getPubkeyName(pubKey: string | null) { - if (!pubKey) { - return {}; - } - - const secretWords = window.mnemonic.pubkey_to_secret_words(pubKey); - const conv = ConversationController.getInstance().get(pubKey); - const deviceAlias = conv ? conv.getNickname() : 'Unnamed Device'; - - return { deviceAlias, secretWords }; - } - // tslint:disable-next-line: max-func-body-length private getLocalSettings(): Array { const { Settings } = window.Signal.Types; diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index f007a59a6..92848a3a7 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -140,7 +140,6 @@ export const fillConvoAttributesWithDefaults = ( export class ConversationModel extends Backbone.Model { public updateLastMessage: () => any; - public messageCollection: MessageCollection; public throttledBumpTyping: any; public throttledNotify: any; public markRead: any; @@ -158,10 +157,6 @@ export class ConversationModel extends Backbone.Model { // This may be overridden by ConversationController.getOrCreate, and signify // our first save to the database. Or first fetch from the database. this.initialPromise = Promise.resolve(); - - this.messageCollection = new MessageCollection([], { - conversation: this, - }); autoBind(this); this.throttledBumpTyping = _.throttle(this.bumpTyping, 300); @@ -170,10 +165,9 @@ export class ConversationModel extends Backbone.Model { 1000 ); this.throttledNotify = _.debounce(this.notify, 500, { maxWait: 1000 }); - this.markRead = _.debounce(this.markReadBouncy, 1000); + //start right away the function is called, and wait 1sec before calling it again + this.markRead = _.debounce(this.markReadBouncy, 1000, { leading: true }); // Listening for out-of-band data updates - this.on('expired', this.onExpired); - this.on('ourAvatarChanged', avatar => this.updateAvatarOnPublicChat(avatar) ); @@ -376,42 +370,10 @@ export class ConversationModel extends Backbone.Model { } } - public async onExpired(message: any) { + public async onExpired(message: MessageModel) { await this.updateLastMessage(); - const removeMessage = () => { - const { id } = message; - const existing = this.messageCollection.get(id); - if (!existing) { - return; - } - - window.log.info('Remove expired message from collection', { - sentAt: existing.get('sent_at'), - }); - - this.messageCollection.remove(id); - existing.trigger('expired'); - }; - - removeMessage(); - } - - // Get messages with the given timestamp - public getMessagesWithTimestamp(pubKey: string, timestamp: number) { - if (this.id !== pubKey) { - return []; - } - - // Go through our messages and find the one that we need to update - return this.messageCollection.models.filter( - (m: any) => m.get('sent_at') === timestamp - ); - } - - public async onCalculatingPoW(pubKey: string, timestamp: number) { - const messages = this.getMessagesWithTimestamp(pubKey, timestamp); - await Promise.all(messages.map((m: any) => m.setCalculatingPoW())); + // removeMessage(); } public getGroupAdmins() { @@ -915,7 +877,7 @@ export class ConversationModel extends Backbone.Model { const messageAttributes = { // 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: true, + unread: 1, conversationId: this.id, // No type; 'incoming' messages are specially treated by conversation.markRead() sent_at: timestamp, @@ -1048,37 +1010,29 @@ export class ConversationModel extends Backbone.Model { ); let read = []; - console.time('markReadNOCommit'); // Build the list of updated message models so we can mark them all as read on a single sqlite call for (const nowRead of oldUnreadNowRead) { - const m = MessageController.getInstance().register(nowRead.id, nowRead); - await m.markRead(options.readAt); + nowRead.markReadNoCommit(options.readAt); - const errors = m.get('errors'); + const errors = nowRead.get('errors'); read.push({ - sender: m.get('source'), - timestamp: m.get('sent_at'), + sender: nowRead.get('source'), + timestamp: nowRead.get('sent_at'), hasErrors: Boolean(errors && errors.length), }); } - console.timeEnd('markReadNOCommit'); - - console.warn('oldUnreadNowRead', oldUnreadNowRead); const oldUnreadNowReadAttrs = oldUnreadNowRead.map(m => m.attributes); - console.warn('oldUnreadNowReadAttrs', oldUnreadNowReadAttrs); await saveMessages(oldUnreadNowReadAttrs); - console.time('trigger'); for (const nowRead of oldUnreadNowRead) { nowRead.generateProps(false); } window.inboxStore?.dispatch( conversationActions.messagesChanged(oldUnreadNowRead) ); - console.timeEnd('trigger'); // Some messages we're marking read are local notifications with no sender read = _.filter(read, m => Boolean(m.sender)); diff --git a/ts/models/message.ts b/ts/models/message.ts index a7d78ca32..74bbfef42 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -72,13 +72,9 @@ export class MessageModel extends Backbone.Model { this.propsForMessage = this.getPropsForMessage(); } - console.time(`messageChanged ${this.id}`); - if (triggerEvent) { window.inboxStore?.dispatch(conversationActions.messageChanged(this)); } - - console.timeEnd(`messageChanged ${this.id}`); } public idForLogging() { @@ -117,7 +113,7 @@ export class MessageModel extends Backbone.Model { const { unread } = attributes; if (unread === undefined) { - this.set({ unread: false }); + this.set({ unread: 0 }); } this.set(attributes); @@ -432,10 +428,6 @@ export class MessageModel extends Backbone.Model { if (sent || sentTo.length > 0) { return 'sent'; } - const calculatingPoW = this.get('calculatingPoW'); - if (calculatingPoW) { - return 'pow'; - } return 'sending'; } @@ -1009,18 +1001,6 @@ export class MessageModel extends Backbone.Model { return null; } - public async setCalculatingPoW() { - if (this.get('calculatingPoW')) { - return; - } - - this.set({ - calculatingPoW: true, - }); - - await this.commit(); - } - public async sendSyncMessageOnly(dataMessage: DataMessage) { const now = Date.now(); this.set({ @@ -1124,7 +1104,7 @@ export class MessageModel extends Backbone.Model { } public markReadNoCommit(readAt: number) { - this.set({ unread: false }); + this.set({ unread: 0 }); if (this.get('expireTimer') && !this.get('expirationStartTimestamp')) { const expirationStartTimestamp = Math.min( diff --git a/ts/models/messageType.ts b/ts/models/messageType.ts index 7a7cbf589..53ea4b076 100644 --- a/ts/models/messageType.ts +++ b/ts/models/messageType.ts @@ -50,20 +50,57 @@ export interface MessageAttributes { fromSync?: boolean; fromGroupUpdate?: boolean; }; - unread: boolean; + /** + * 1 means unread, 0 or anything else is read. + */ + unread: number; group?: any; + /** + * timestamp is the sent_at timestamp, which is the envelope.timestamp + */ timestamp?: number; status: MessageDeliveryStatus; dataMessage: any; sent_to: any; sent: boolean; - calculatingPoW: boolean; + + /** + * The serverId is the id on the open group server itself. + * Each message sent to an open group gets a serverId. + * This is not the id for the server, but the id ON the server. + * + * This field is not set for a message not on an opengroup server. + */ serverId?: number; + /** + * This is the timestamp of that messages as it was saved by the Open group server. + * We rely on this one to order Open Group messages. + * This field is not set for a message not on an opengroup server. + */ serverTimestamp?: number; + /** + * This field is set to true if the message is for a public server. + * This is useful to make the Badge `Public` Appear on a sent message to a server, even if we did not get + * the response from the server yet that this message was successfully added. + */ isPublic: boolean; + + /** + * sentSync set to true means we just triggered the sync message for this Private Chat message. + * We did not yet get the message sent confirmation, it was just added to the Outgoing MessageQueue + */ sentSync: boolean; + + /** + * synced set to true means that this message was successfully sent by our current device to our other devices. + * It is set to true when the MessageQueue did effectively sent our sync message without errors. + */ synced: boolean; sync: boolean; + + /** + * This field is used for search only + */ snippet?: any; direction: any; } @@ -103,14 +140,13 @@ export interface MessageAttributesOptionals { fromSync?: boolean; fromGroupUpdate?: boolean; }; - unread?: boolean; + unread?: number; group?: any; timestamp?: number; status?: MessageDeliveryStatus; dataMessage?: any; sent_to?: Array; sent?: boolean; - calculatingPoW?: boolean; serverId?: number; serverTimestamp?: number; isPublic?: boolean; @@ -133,6 +169,7 @@ export const fillMessageAttributesWithDefaults = ( expireTimer: 0, // disabled id: uuidv4(), schemaVersion: window.Signal.Types.Message.CURRENT_SCHEMA_VERSION, + unread: 0, // if nothing is set, this message is considered read }); }; @@ -147,7 +184,7 @@ export interface MessageRegularProps { direction: 'incoming' | 'outgoing'; timestamp: number; serverTimestamp?: number; - status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error' | 'pow'; + status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error'; // What if changed this over to a single contact like quote, and put the events on it? contact?: Contact & { onSendMessage?: () => void; diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 3c4c2a8d9..276cdd00b 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -289,7 +289,7 @@ function updateReadStatus( } } if (readSync || message.isExpirationTimerUpdate()) { - message.set({ unread: false }); + message.set({ unread: 0 }); // This is primarily to allow the conversation to mark all older // messages as read, as is done when we receive a read sync for diff --git a/ts/session/group/index.ts b/ts/session/group/index.ts index 1a969890c..bfd102331 100644 --- a/ts/session/group/index.ts +++ b/ts/session/group/index.ts @@ -206,7 +206,7 @@ export async function addUpdateMessage( sent_at: sentAt, received_at: now, group_update: groupUpdate, - unread, + unread: unread ? 1 : 0, expireTimer: 0, }); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 151039676..a842c8333 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -536,7 +536,6 @@ function handleMessageChanged( action: MessageChangedActionType ) { const { payload } = action; - console.time('handleMessageChanged' + payload.id); const messageInStoreIndex = state?.messages?.findIndex( m => m.id === payload.id