diff --git a/background.html b/background.html index a65bbc589..47c2897bd 100644 --- a/background.html +++ b/background.html @@ -36,7 +36,6 @@ - diff --git a/js/read_receipts.js b/js/read_receipts.js deleted file mode 100644 index 43e9cb371..000000000 --- a/js/read_receipts.js +++ /dev/null @@ -1,108 +0,0 @@ -/* global - Whisper, - Backbone, - _, - window -*/ - -/* eslint-disable more/no-then */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Whisper = window.Whisper || {}; - Whisper.ReadReceipts = new (Backbone.Collection.extend({ - forMessage(conversation, message) { - if (!message.isOutgoing()) { - return []; - } - let ids = []; - if (conversation.isPrivate()) { - ids = [conversation.id]; - } else { - ids = conversation.get('members'); - } - const receipts = this.filter( - receipt => - receipt.get('timestamp') === message.get('sent_at') && - _.contains(ids, receipt.get('reader')) - ); - if (receipts.length) { - window.log.info('Found early read receipts for message'); - this.remove(receipts); - } - return receipts; - }, - async getTargetMessage(reader, messages) { - if (messages.length === 0) { - return null; - } - const message = messages.find( - item => item.isOutgoing() && reader === item.get('conversationId') - ); - if (message) { - return message; - } - - const groups = await window.Signal.Data.getAllGroupsInvolvingId(reader); - const ids = groups.pluck('id'); - ids.push(reader); - - const target = messages.find( - item => item.isOutgoing() && _.contains(ids, item.get('conversationId')) - ); - if (!target) { - return null; - } - - return target; - }, - async onReceipt(receipt) { - try { - const messages = await window.Signal.Data.getMessagesBySentAt(receipt.get('timestamp')); - - const message = await this.getTargetMessage(receipt.get('reader'), messages); - - if (!message) { - window.log.info( - 'No message for read receipt', - receipt.get('reader'), - receipt.get('timestamp') - ); - return; - } - - const readBy = message.get('read_by') || []; - const expirationStartTimestamp = message.get('expirationStartTimestamp'); - - readBy.push(receipt.get('reader')); - message.set({ - read_by: readBy, - expirationStartTimestamp: expirationStartTimestamp || Date.now(), - sent: true, - }); - - if (message.isExpiring() && !expirationStartTimestamp) { - // This will save the message for us while starting the timer - await message.setToExpire(); - } else { - await message.commit(); - } - - // notify frontend listeners - const conversation = window.getConversationController().get(message.get('conversationId')); - if (conversation) { - conversation.updateLastMessage(); - } - - this.remove(receipt); - } catch (error) { - window.log.error( - 'ReadReceipts.onReceipt error:', - error && error.stack ? error.stack : error - ); - } - }, - }))(); -})(); diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index d23fc9fb1..90a8adb71 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -19,6 +19,7 @@ import { getAllCachedECKeyPair } from './closedGroups'; import { handleCallMessage } from './callMessage'; import { SettingsKey } from '../data/settings-key'; import { ConversationTypeEnum } from '../models/conversation'; +import { ReadReceipts } from '../util/readReceipts'; export async function handleSwarmContentMessage(envelope: EnvelopePlus, messageHash: string) { try { @@ -439,23 +440,21 @@ export async function innerHandleSwarmContentMessage( } } -function onReadReceipt(readAt: any, timestamp: any, reader: any) { - const { storage, Whisper } = window; +function onReadReceipt(readAt: number, timestamp: number, source: string) { + const { storage } = window; - window?.log?.info('read receipt', reader, timestamp); + window?.log?.info('read receipt', source, timestamp); if (!storage.get(SettingsKey.settingsReadReceipt)) { return; } - const receipt = Whisper.ReadReceipts.add({ - reader, + // Calling this directly so we can wait for completion + return ReadReceipts.onReadReceipt({ + source, timestamp, - read_at: readAt, + readAt, }); - - // Calling this directly so we can wait for completion - return Whisper.ReadReceipts.onReceipt(receipt); } async function handleReceiptMessage( diff --git a/ts/util/readReceipts.ts b/ts/util/readReceipts.ts new file mode 100644 index 000000000..c0510cb17 --- /dev/null +++ b/ts/util/readReceipts.ts @@ -0,0 +1,60 @@ +import _ from 'lodash'; +import { MessageCollection } from '../models/message'; + +import * as Data from '../data/data'; +import { getConversationController } from '../session/conversations'; + +async function getTargetMessage(reader: string, messages: MessageCollection) { + if (messages.length === 0) { + return null; + } + const message = messages.find(msg => msg.isOutgoing() && reader === msg.get('conversationId')); + if (message) { + return message; + } + + // we do not support read messages for groups + return null; +} + +async function onReadReceipt(receipt: { source: string; timestamp: number; readAt: number }) { + try { + const messages = await Data.getMessagesBySentAt(receipt.timestamp); + + const message = await getTargetMessage(receipt.source, messages); + + if (!message) { + window.log.info('No message for read receipt', receipt.source, receipt.timestamp); + return; + } + + const readBy = message.get('read_by') || []; + const expirationStartTimestamp = message.get('expirationStartTimestamp'); + + if (!readBy.includes(receipt.source)) { + readBy.push(receipt.source); + } + message.set({ + read_by: readBy, + expirationStartTimestamp: expirationStartTimestamp || Date.now(), + sent: true, + }); + + if (message.isExpiring() && !expirationStartTimestamp) { + // This will save the message for us while starting the timer + await message.setToExpire(); + } else { + await message.commit(); + } + + // notify frontend listeners + const conversation = getConversationController().get(message.get('conversationId')); + if (conversation) { + conversation.updateLastMessage(); + } + } catch (error) { + window.log.error('ReadReceipts.onReceipt error:', error && error.stack ? error.stack : error); + } +} + +export const ReadReceipts = { onReadReceipt };