|
|
|
@ -25,6 +25,7 @@ import { SignalService } from '../protobuf';
|
|
|
|
|
import { MessageModel, sliceQuoteText } from './message';
|
|
|
|
|
import { MessageAttributesOptionals, MessageDirection } from './messageType';
|
|
|
|
|
import autoBind from 'auto-bind';
|
|
|
|
|
|
|
|
|
|
import { Data } from '../../ts/data/data';
|
|
|
|
|
import { toHex } from '../session/utils/String';
|
|
|
|
|
import {
|
|
|
|
@ -1223,15 +1224,49 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mark everything as read efficiently if possible.
|
|
|
|
|
*
|
|
|
|
|
* For convos with a expiration timer enable, start the timer as of now.
|
|
|
|
|
* Send read receipt if needed.
|
|
|
|
|
*/
|
|
|
|
|
public async markAllAsRead() {
|
|
|
|
|
if (this.isOpenGroupV2()) {
|
|
|
|
|
// for opengroups, we batch everything as there is no expiration timer to take care (and potentially a lot of messages)
|
|
|
|
|
|
|
|
|
|
await Data.markAllAsReadByConversationNoExpiration(this.id);
|
|
|
|
|
this.set({ mentionedUs: false, unreadCount: 0 });
|
|
|
|
|
|
|
|
|
|
await this.commit();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the conversation has no expiration timer, we can also batch everything, but we also need to send read receipts potentially
|
|
|
|
|
// so we grab them from the db
|
|
|
|
|
if (!this.get('expireTimer')) {
|
|
|
|
|
const allReadMessages = await Data.markAllAsReadByConversationNoExpiration(this.id);
|
|
|
|
|
this.set({ mentionedUs: false, unreadCount: 0 });
|
|
|
|
|
await this.commit();
|
|
|
|
|
if (allReadMessages.length) {
|
|
|
|
|
await this.sendReadReceiptsIfNeeded(uniq(allReadMessages));
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await this.markReadBouncy(Date.now());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity
|
|
|
|
|
public async markReadBouncy(newestUnreadDate: number, providedOptions: any = {}) {
|
|
|
|
|
public async markReadBouncy(
|
|
|
|
|
newestUnreadDate: number,
|
|
|
|
|
providedOptions: { sendReadReceipts?: boolean; readAt?: number } = {}
|
|
|
|
|
) {
|
|
|
|
|
const lastReadTimestamp = this.lastReadTimestamp;
|
|
|
|
|
if (newestUnreadDate < lastReadTimestamp) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const options = providedOptions || {};
|
|
|
|
|
defaults(options, { sendReadReceipts: true });
|
|
|
|
|
const readAt = providedOptions?.readAt || Date.now();
|
|
|
|
|
const sendReadReceipts = providedOptions?.sendReadReceipts || true;
|
|
|
|
|
|
|
|
|
|
const conversationId = this.id;
|
|
|
|
|
Notifications.clearByConversationID(conversationId);
|
|
|
|
@ -1245,7 +1280,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
|
nowRead.markReadNoCommit(options.readAt);
|
|
|
|
|
nowRead.markReadNoCommit(readAt);
|
|
|
|
|
|
|
|
|
|
const errors = nowRead.get('errors');
|
|
|
|
|
read.push({
|
|
|
|
@ -1307,7 +1342,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|
|
|
|
// conversation is viewed, another error message shows up for the contact
|
|
|
|
|
read = read.filter(item => !item.hasErrors);
|
|
|
|
|
|
|
|
|
|
if (read.length && options.sendReadReceipts) {
|
|
|
|
|
if (read.length && sendReadReceipts) {
|
|
|
|
|
const timestamps = map(read, 'timestamp').filter(t => !!t) as Array<number>;
|
|
|
|
|
await this.sendReadReceiptsIfNeeded(timestamps);
|
|
|
|
|
}
|
|
|
|
|