sync expire timer updates

pull/1542/head
Audric Ackermann 4 years ago
parent 79193ee7be
commit ec6a5995db
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -841,12 +841,14 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
providedExpireTimer: any,
providedSource?: string,
receivedAt?: number, // is set if it comes from outside
options: any = {}
options: {
fromSync?: boolean;
} = {}
) {
let expireTimer = providedExpireTimer;
let source = providedSource;
_.defaults(options, { fromSync: false, fromGroupUpdate: false });
_.defaults(options, { fromSync: false });
if (!expireTimer) {
expireTimer = null;
@ -887,7 +889,6 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
expireTimer,
source,
fromSync: options.fromSync,
fromGroupUpdate: options.fromGroupUpdate,
},
expireTimer: 0,
type: isOutgoing ? 'outgoing' : ('incoming' as MessageModelType),

@ -7,6 +7,7 @@ import { getMessageQueue, Types, Utils } from '../../ts/session';
import { ConversationController } from '../../ts/session/conversations';
import { MessageController } from '../../ts/session/messages';
import {
ContentMessage,
DataMessage,
OpenGroupMessage,
} from '../../ts/session/messages/outgoing';
@ -24,6 +25,7 @@ import { saveMessage } from '../../ts/data/data';
import { ConversationModel } from './conversation';
import { actions as conversationActions } from '../state/ducks/conversations';
import { VisibleMessage } from '../session/messages/outgoing/visibleMessage/VisibleMessage';
import { buildSyncMessage } from '../session/utils/syncUtils';
export class MessageModel extends Backbone.Model<MessageAttributes> {
public propsForTimerNotification: any;
@ -1027,13 +1029,15 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
// if this message needs to be synced
if (
(dataMessage.body && dataMessage.body.length) ||
dataMessage.attachments.length
dataMessage.attachments.length ||
dataMessage.flags ===
SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE
) {
const conversation = this.getConversation();
if (!conversation) {
throw new Error('Cannot trigger syncMessage with unknown convo.');
}
const syncMessage = VisibleMessage.buildSyncMessage(
const syncMessage = buildSyncMessage(
this.id,
dataMessage,
conversation.id,

@ -48,7 +48,6 @@ export interface MessageAttributes {
expireTimer: number;
source: string;
fromSync?: boolean;
fromGroupUpdate?: boolean;
};
/**
* 1 means unread, 0 or anything else is read.
@ -138,7 +137,6 @@ export interface MessageAttributesOptionals {
expireTimer: number;
source: string;
fromSync?: boolean;
fromGroupUpdate?: boolean;
};
unread?: number;
group?: any;

@ -196,39 +196,6 @@ async function copyFromQuotedMessage(
}
}
// Handle expiration timer as part of a regular message
async function handleExpireTimer(
source: string,
message: MessageModel,
expireTimer: number,
conversation: ConversationModel
) {
const oldValue = conversation.get('expireTimer');
if (expireTimer) {
message.set({ expireTimer });
if (expireTimer !== oldValue) {
await conversation.updateExpirationTimer(
expireTimer,
source,
message.get('sent_at') || message.get('received_at'),
{
fromGroupUpdate: message.isGroupUpdate(), // WHAT DOES GROUP UPDATE HAVE TO DO WITH THIS???
}
);
}
} else if (oldValue && !message.isGroupUpdate()) {
// We only turn off timers if it's not a group update
await conversation.updateExpirationTimer(
null,
source,
message.get('received_at'),
{}
);
}
}
function handleLinkPreviews(
messageBody: string,
messagePreview: any,
@ -363,7 +330,7 @@ async function handleRegularMessage(
// `upgradeMessageSchema` only seems to add `schemaVersion: 10` to the message
const dataMessage = await upgradeMessageSchema(initialMessage);
const now = new Date().getTime();
const now = Date.now();
// Medium groups might have `group` set even if with group chat messages...
if (dataMessage.group && !conversation.isMediumGroup()) {
@ -383,6 +350,7 @@ async function handleRegularMessage(
}
handleLinkPreviews(dataMessage.body, dataMessage.preview, message);
const existingExpireTimer = conversation.get('expireTimer');
message.set({
flags: dataMessage.flags,
@ -399,15 +367,14 @@ async function handleRegularMessage(
errors: [],
});
conversation.set({ active_at: now });
if (existingExpireTimer) {
message.set({ expireTimer: existingExpireTimer });
message.set({ expirationStartTimestamp: now });
}
// Handle expireTimer found directly as part of a regular message
await handleExpireTimer(
source,
message,
dataMessage.expireTimer,
conversation
);
conversation.set({ active_at: now });
// Expire timer updates are now explicit.
// We don't handle an expire timer from a incoming message except if it is an ExpireTimerUpdate message.
const ourPubKey = PubKey.cast(ourNumber);
@ -478,10 +445,7 @@ async function handleExpirationTimerUpdate(
await conversation.updateExpirationTimer(
expireTimer,
source,
message.get('received_at'),
{
fromGroupUpdate: message.isGroupUpdate(), // WHAT DOES GROUP UPDATE HAVE TO DO WITH THIS???
}
message.get('received_at')
);
}

@ -449,17 +449,6 @@ async function sendAddedMembers(
expireTimer,
});
// if an expire timer is set, we have to send it to the joining members
// let expirationTimerMessage: ExpirationTimerUpdateMessage | undefined;
// if (expireTimer && expireTimer > 0) {
// const expireUpdate = {
// timestamp: Date.now(),
// expireTimer,
// groupId: groupId,
// };
// expirationTimerMessage = new ExpirationTimerUpdateMessage(expireUpdate);
// }
const promises = addedMembers.map(async m => {
await ConversationController.getInstance().getOrCreateAndWait(m, 'private');
const memberPubKey = PubKey.cast(m);

@ -13,7 +13,7 @@ interface ExpirationTimerUpdateMessageParams extends MessageParams {
export class ExpirationTimerUpdateMessage extends DataMessage {
public readonly groupId?: PubKey;
public readonly syncTarget?: PubKey;
public readonly syncTarget?: string;
public readonly expireTimer: number | null;
constructor(params: ExpirationTimerUpdateMessageParams) {
@ -22,7 +22,7 @@ export class ExpirationTimerUpdateMessage extends DataMessage {
const { groupId, syncTarget } = params;
this.groupId = groupId ? PubKey.cast(groupId) : undefined;
this.syncTarget = syncTarget ? PubKey.cast(syncTarget) : undefined;
this.syncTarget = syncTarget ? PubKey.cast(syncTarget).key : undefined;
}
public ttl(): number {
@ -50,7 +50,7 @@ export class ExpirationTimerUpdateMessage extends DataMessage {
}
if (this.syncTarget) {
data.syncTarget = this.syncTarget.key;
data.syncTarget = this.syncTarget;
}
if (this.expireTimer) {

@ -5,6 +5,7 @@ import { DataMessage } from '..';
import { Constants } from '../../..';
import { SignalService } from '../../../../protobuf';
import { LokiProfile } from '../../../../types/Message';
import { ExpirationTimerUpdateMessage } from '../controlMessage/ExpirationTimerUpdateMessage';
import { MessageParams } from '../Message';
export interface AttachmentPointer {
@ -91,62 +92,6 @@ export class VisibleMessage extends DataMessage {
this.syncTarget = params.syncTarget;
}
public static buildSyncMessage(
identifier: string,
dataMessage: SignalService.DataMessage,
syncTarget: string,
sentTimestamp: number
) {
if (
(dataMessage as any).constructor.name !== 'DataMessage' &&
!(dataMessage instanceof SignalService.DataMessage)
) {
window.log.warn(
'buildSyncMessage with something else than a DataMessage'
);
}
if (!sentTimestamp || !isNumber(sentTimestamp)) {
throw new Error('Tried to build a sync message without a sentTimestamp');
}
// don't include our profileKey on syncing message. This is to be done by a ConfigurationMessage now
const timestamp = toNumber(sentTimestamp);
const body = dataMessage.body || undefined;
const wrapToUInt8Array = (buffer: any) => {
if (!buffer) {
return undefined;
}
if (buffer instanceof Uint8Array) {
// Audio messages are already uint8Array
return buffer;
}
return new Uint8Array(buffer.toArrayBuffer());
};
const attachments = (dataMessage.attachments || []).map(attachment => {
const key = wrapToUInt8Array(attachment.key);
const digest = wrapToUInt8Array(attachment.digest);
return {
...attachment,
key,
digest,
};
}) as Array<AttachmentPointer>;
const quote = (dataMessage.quote as Quote) || undefined;
const preview = (dataMessage.preview as Array<Preview>) || [];
return new VisibleMessage({
identifier,
timestamp,
attachments,
body,
quote,
preview,
syncTarget,
});
}
public ttl(): number {
return Constants.TTL_DEFAULT.REGULAR_MESSAGE;
}

@ -16,6 +16,7 @@ import { ClosedGroupEncryptionPairRequestMessage } from '../messages/outgoing/co
import { ClosedGroupNewMessage } from '../messages/outgoing/controlMessage/group/ClosedGroupNewMessage';
import { ClosedGroupRemovedMembersMessage } from '../messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage';
import { ClosedGroupVisibleMessage } from '../messages/outgoing/visibleMessage/ClosedGroupVisibleMessage';
import { SyncMessageType } from '../utils/syncUtils';
type ClosedGroupMessageType =
| ClosedGroupVisibleMessage
@ -108,7 +109,7 @@ export class MessageQueue {
}
public async sendSyncMessage(
message?: ContentMessage,
message?: SyncMessageType,
sentCb?: (message: RawMessage) => Promise<void>
): Promise<void> {
if (!message) {

@ -21,6 +21,15 @@ import {
fromHexToArray,
} from './String';
import { fromBase64 } from 'bytebuffer';
import { SignalService } from '../../protobuf';
import _ from 'lodash';
import {
AttachmentPointer,
Preview,
Quote,
VisibleMessage,
} from '../messages/outgoing/visibleMessage/VisibleMessage';
import { ExpirationTimerUpdateMessage } from '../messages/outgoing/controlMessage/ExpirationTimerUpdateMessage';
const ITEM_ID_LAST_SYNC_TIMESTAMP = 'lastSyncedTimestamp';
@ -186,3 +195,105 @@ export const getCurrentConfigurationMessage = async (
contacts,
});
};
const buildSyncVisibleMessage = (
identifier: string,
dataMessage: SignalService.DataMessage,
timestamp: number,
syncTarget: string
) => {
const body = dataMessage.body || undefined;
const wrapToUInt8Array = (buffer: any) => {
if (!buffer) {
return undefined;
}
if (buffer instanceof Uint8Array) {
// Audio messages are already uint8Array
return buffer;
}
return new Uint8Array(buffer.toArrayBuffer());
};
const attachments = (dataMessage.attachments || []).map(attachment => {
const key = wrapToUInt8Array(attachment.key);
const digest = wrapToUInt8Array(attachment.digest);
return {
...attachment,
key,
digest,
};
}) as Array<AttachmentPointer>;
const quote = (dataMessage.quote as Quote) || undefined;
const preview = (dataMessage.preview as Array<Preview>) || [];
const expireTimer = dataMessage.expireTimer;
return new VisibleMessage({
identifier,
timestamp,
attachments,
body,
quote,
preview,
syncTarget,
expireTimer,
});
};
const buildSyncExpireTimerMessage = (
identifier: string,
dataMessage: SignalService.DataMessage,
timestamp: number,
syncTarget: string
) => {
const expireTimer = dataMessage.expireTimer;
return new ExpirationTimerUpdateMessage({
identifier,
timestamp,
expireTimer,
syncTarget,
});
};
export type SyncMessageType =
| VisibleMessage
| ExpirationTimerUpdateMessage
| ConfigurationMessage;
export const buildSyncMessage = (
identifier: string,
dataMessage: SignalService.DataMessage,
syncTarget: string,
sentTimestamp: number
): VisibleMessage | ExpirationTimerUpdateMessage => {
if (
(dataMessage as any).constructor.name !== 'DataMessage' &&
!(dataMessage instanceof SignalService.DataMessage)
) {
window.log.warn('buildSyncMessage with something else than a DataMessage');
}
if (!sentTimestamp || !_.isNumber(sentTimestamp)) {
throw new Error('Tried to build a sync message without a sentTimestamp');
}
// don't include our profileKey on syncing message. This is to be done by a ConfigurationMessage now
const timestamp = _.toNumber(sentTimestamp);
if (
dataMessage.flags ===
SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE
) {
return buildSyncExpireTimerMessage(
identifier,
dataMessage,
timestamp,
syncTarget
);
}
return buildSyncVisibleMessage(
identifier,
dataMessage,
timestamp,
syncTarget
);
};

Loading…
Cancel
Save