feat: fixed closed groups

improved setExpirationStartTimestamp logic
pull/2660/head
William Grant 2 years ago
parent b4fc33c8fa
commit d358ab2fb1

@ -187,7 +187,6 @@ message DataMessage {
repeated bytes members = 5; repeated bytes members = 5;
repeated bytes admins = 6; repeated bytes admins = 6;
repeated KeyPairWrapper wrappers = 7; repeated KeyPairWrapper wrappers = 7;
// TODO Make sure rename doesn't break anything
optional uint32 expirationTimer = 8; optional uint32 expirationTimer = 8;
} }

@ -653,6 +653,8 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const closedGroupVisibleMessage = new ClosedGroupVisibleMessage({ const closedGroupVisibleMessage = new ClosedGroupVisibleMessage({
chatMessage: chatMessageMediumGroup, chatMessage: chatMessageMediumGroup,
groupId: destination, groupId: destination,
expirationType,
expireTimer,
}); });
// we need the return await so that errors are caught in the catch {} // we need the return await so that errors are caught in the catch {}

@ -1182,8 +1182,8 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
this.get('expireTimer') && this.get('expireTimer') &&
!this.get('expirationStartTimestamp') !this.get('expirationStartTimestamp')
) { ) {
const expirationStartTimestamp = setExpirationStartTimestamp(this, 'deleteAfterRead', readAt); const message = setExpirationStartTimestamp(this, 'deleteAfterRead', readAt);
this.set({ expirationStartTimestamp }); this.set({ expirationStartTimestamp: message?.get('expirationStartTimestamp') });
} }
Notifications.clearByMessageId(this.id); Notifications.clearByMessageId(this.id);

@ -403,20 +403,21 @@ export async function innerHandleSwarmContentMessage(
perfStart(`handleSwarmDataMessage-${envelope.id}`); perfStart(`handleSwarmDataMessage-${envelope.id}`);
let expireUpdate = null; let expireUpdate = null;
const expirationType = DisappearingMessageConversationSetting[content.expirationType] || null;
const expirationType =
if (expirationType && content.expirationTimer) { DisappearingMessageConversationSetting[content.expirationType] || 'off';
// NOTE In the protobuf this is a long const expireTimer = content.expirationTimer || 0;
const lastDisappearingMessageChangeTimestamp =
Number(content.lastDisappearingMessageChangeTimestamp) || null; // NOTE In the protobuf this is a long
const lastDisappearingMessageChangeTimestamp =
expireUpdate = { Number(content.lastDisappearingMessageChangeTimestamp) || null;
expirationType,
// TODO rename to expireTimer expireUpdate = {
expireTimer: content.expirationTimer, expirationType,
lastDisappearingMessageChangeTimestamp, // TODO rename to expireTimer
}; expireTimer,
} lastDisappearingMessageChangeTimestamp,
};
await handleSwarmDataMessage( await handleSwarmDataMessage(
envelope, envelope,

@ -228,7 +228,7 @@ export async function handleSwarmDataMessage(
return; return;
} }
const msgModel = let msgModel =
isSyncedMessage || (envelope.senderIdentity && isUsFromCache(envelope.senderIdentity)) isSyncedMessage || (envelope.senderIdentity && isUsFromCache(envelope.senderIdentity))
? createSwarmMessageSentFromUs({ ? createSwarmMessageSentFromUs({
conversationId: convoIdToAddTheMessageTo, conversationId: convoIdToAddTheMessageTo,
@ -246,13 +246,10 @@ export async function handleSwarmDataMessage(
// TODO handle sync messages separately // TODO handle sync messages separately
console.log(`WIP: Sync Message dropping`); console.log(`WIP: Sync Message dropping`);
} else { } else {
if (expireUpdate.expirationType === 'deleteAfterSend') { if (msgModel.isIncoming() && expireUpdate.expirationType === 'deleteAfterSend') {
const expirationStartTimestamp = setExpirationStartTimestamp( msgModel =
msgModel, setExpirationStartTimestamp(msgModel, 'deleteAfterSend', msgModel.get('sent_at')) ||
'deleteAfterSend', msgModel;
msgModel.get('sent_at')
);
msgModel.set('expirationStartTimestamp', expirationStartTimestamp);
} }
} }

@ -1,14 +1,19 @@
import { SignalService } from '../../../../../protobuf'; import { SignalService } from '../../../../../protobuf';
import { DisappearingMessageType } from '../../../../../util/expiringMessages';
import { PubKey } from '../../../../types'; import { PubKey } from '../../../../types';
import { DataMessage } from '../../DataMessage'; import { ContentMessage } from '../../ContentMessage';
import { MessageParams } from '../../Message'; import { MessageParams } from '../../Message';
export interface ClosedGroupMessageParams extends MessageParams { export interface ClosedGroupMessageParams extends MessageParams {
groupId: string | PubKey; groupId: string | PubKey;
expirationType?: DisappearingMessageType;
expireTimer?: number;
} }
export abstract class ClosedGroupMessage extends DataMessage { export abstract class ClosedGroupMessage extends ContentMessage {
public readonly groupId: PubKey; public readonly groupId: PubKey;
public readonly expirationType?: DisappearingMessageType;
public readonly expireTimer?: number;
constructor(params: ClosedGroupMessageParams) { constructor(params: ClosedGroupMessageParams) {
super({ super({
@ -20,12 +25,25 @@ export abstract class ClosedGroupMessage extends DataMessage {
if (!this.groupId || this.groupId.key.length === 0) { if (!this.groupId || this.groupId.key.length === 0) {
throw new Error('groupId must be set'); throw new Error('groupId must be set');
} }
this.expirationType = params.expirationType;
this.expireTimer = params.expireTimer;
} }
public static areAdminsMembers(admins: Array<string>, members: Array<string>) { public static areAdminsMembers(admins: Array<string>, members: Array<string>) {
return admins.every(a => members.includes(a)); return admins.every(a => members.includes(a));
} }
public contentProto(): SignalService.Content {
return new SignalService.Content({
dataMessage: this.dataProto(),
expirationType:
this.expirationType === 'deleteAfterSend'
? SignalService.Content.ExpirationType.DELETE_AFTER_SEND
: undefined,
expirationTimer: this.expireTimer,
});
}
public dataProto(): SignalService.DataMessage { public dataProto(): SignalService.DataMessage {
const dataMessage = new SignalService.DataMessage(); const dataMessage = new SignalService.DataMessage();

@ -16,19 +16,19 @@ export class ClosedGroupNewMessage extends ClosedGroupMessage {
private readonly members: Array<string>; private readonly members: Array<string>;
private readonly admins: Array<string>; private readonly admins: Array<string>;
private readonly keypair: ECKeyPair; private readonly keypair: ECKeyPair;
private readonly expireTimer: number;
constructor(params: ClosedGroupNewMessageParams) { constructor(params: ClosedGroupNewMessageParams) {
super({ super({
timestamp: params.timestamp, timestamp: params.timestamp,
identifier: params.identifier, identifier: params.identifier,
groupId: params.groupId, groupId: params.groupId,
expirationType: params.expirationType,
expireTimer: params.expireTimer,
}); });
this.name = params.name; this.name = params.name;
this.members = params.members; this.members = params.members;
this.admins = params.admins; this.admins = params.admins;
this.keypair = params.keypair; this.keypair = params.keypair;
this.expireTimer = params.expireTimer;
if (!params.admins || params.admins.length === 0) { if (!params.admins || params.admins.length === 0) {
throw new Error('Admins must be set'); throw new Error('Admins must be set');

@ -3,10 +3,13 @@ import { PubKey } from '../../../types';
import { StringUtils } from '../../../utils'; import { StringUtils } from '../../../utils';
import { VisibleMessage } from './VisibleMessage'; import { VisibleMessage } from './VisibleMessage';
import { ClosedGroupMessage } from '../controlMessage/group/ClosedGroupMessage'; import { ClosedGroupMessage } from '../controlMessage/group/ClosedGroupMessage';
import { DisappearingMessageType } from '../../../../util/expiringMessages';
interface ClosedGroupVisibleMessageParams { interface ClosedGroupVisibleMessageParams {
identifier?: string; identifier?: string;
groupId: string | PubKey; groupId: string | PubKey;
expirationType?: DisappearingMessageType;
expireTimer?: number;
chatMessage: VisibleMessage; chatMessage: VisibleMessage;
} }
@ -18,12 +21,15 @@ export class ClosedGroupVisibleMessage extends ClosedGroupMessage {
timestamp: params.chatMessage.timestamp, timestamp: params.chatMessage.timestamp,
identifier: params.identifier ?? params.chatMessage.identifier, identifier: params.identifier ?? params.chatMessage.identifier,
groupId: params.groupId, groupId: params.groupId,
expirationType: params.expirationType,
expireTimer: params.expireTimer,
}); });
this.chatMessage = params.chatMessage; this.chatMessage = params.chatMessage;
if (!params.groupId) { if (!params.groupId) {
throw new Error('ClosedGroupVisibleMessage: groupId must be set'); throw new Error('ClosedGroupVisibleMessage: groupId must be set');
} }
} }
public dataProto(): SignalService.DataMessage { public dataProto(): SignalService.DataMessage {
//expireTimer is set in the dataProto in this call directly //expireTimer is set in the dataProto in this call directly
const dataProto = this.chatMessage.dataProto(); const dataProto = this.chatMessage.dataProto();

@ -99,6 +99,15 @@ async function handleMessageSentSuccess(
} }
} }
if (!shouldMarkMessageAsSynced && fetchedMessage.get('expirationType')) {
fetchedMessage =
setExpirationStartTimestamp(
fetchedMessage,
fetchedMessage.get('expirationType')!,
effectiveTimestamp
) || fetchedMessage;
}
// Handle the sync logic here // Handle the sync logic here
if (shouldTriggerSyncMessage) { if (shouldTriggerSyncMessage) {
if (dataMessage) { if (dataMessage) {
@ -119,14 +128,6 @@ async function handleMessageSentSuccess(
window?.log?.warn('Got an error while trying to sendSyncMessage():', e); window?.log?.warn('Got an error while trying to sendSyncMessage():', e);
} }
} }
if (fetchedMessage.get('expirationType')) {
const expirationStartTimestamp = setExpirationStartTimestamp(
fetchedMessage,
fetchedMessage.get('expirationType')!,
effectiveTimestamp
);
fetchedMessage.set('expirationStartTimestamp', expirationStartTimestamp);
}
} else if (shouldMarkMessageAsSynced) { } else if (shouldMarkMessageAsSynced) {
fetchedMessage.set({ synced: true }); fetchedMessage.set({ synced: true });
// TODO handle sync messages separately // TODO handle sync messages separately
@ -148,7 +149,7 @@ async function handleMessageSentFailure(
sentMessage: RawMessage | OpenGroupVisibleMessage, sentMessage: RawMessage | OpenGroupVisibleMessage,
error: any error: any
) { ) {
const fetchedMessage = await fetchHandleMessageSentData(sentMessage.identifier); let fetchedMessage = await fetchHandleMessageSentData(sentMessage.identifier);
if (!fetchedMessage) { if (!fetchedMessage) {
return; return;
} }
@ -168,11 +169,9 @@ async function handleMessageSentFailure(
} }
if (fetchedMessage.get('expirationType')) { if (fetchedMessage.get('expirationType')) {
const expirationStartTimestamp = setExpirationStartTimestamp( fetchedMessage =
fetchedMessage, setExpirationStartTimestamp(fetchedMessage, fetchedMessage.get('expirationType')!) ||
fetchedMessage.get('expirationType')! fetchedMessage;
);
fetchedMessage.set('expirationStartTimestamp', expirationStartTimestamp);
} }
// always mark the message as sent. // always mark the message as sent.

@ -8,7 +8,6 @@ import { initWallClockListener } from './wallClockListener';
import { Data } from '../data/data'; import { Data } from '../data/data';
import { getConversationController } from '../session/conversations'; import { getConversationController } from '../session/conversations';
import { MessageModel } from '../models/message'; import { MessageModel } from '../models/message';
import { getNowWithNetworkOffset } from '../session/apis/snode_api/SNodeAPI';
// TODO Might need to be improved by using an enum // TODO Might need to be improved by using an enum
export const DisappearingMessageMode = ['deleteAfterRead', 'deleteAfterSend']; export const DisappearingMessageMode = ['deleteAfterRead', 'deleteAfterSend'];
@ -201,11 +200,16 @@ export function setExpirationStartTimestamp(
message: MessageModel, message: MessageModel,
mode: DisappearingMessageType, mode: DisappearingMessageType,
timestamp?: number timestamp?: number
) { ): MessageModel | null {
let expirationStartTimestamp = getNowWithNetworkOffset(); if (message.get('expirationStartTimestamp') > 0) {
window.log.info(`WIP: Expiration Timer already set. Ignoring.`);
return null;
}
let expirationStartTimestamp = Date.now();
if (timestamp) { if (timestamp) {
expirationStartTimestamp = Math.max(getNowWithNetworkOffset(), timestamp); expirationStartTimestamp = Math.max(Date.now(), timestamp);
message.set('expirationStartTimestamp', expirationStartTimestamp); message.set('expirationStartTimestamp', expirationStartTimestamp);
} }
@ -221,11 +225,11 @@ export function setExpirationStartTimestamp(
); );
} else { } else {
console.log( console.log(
`WIP: setExpirationStartTimestamp Invalid disappearing message mode set, ignoring this message`, `WIP: setExpirationStartTimestamp Invalid disappearing message mode set. Ignoring.`,
message message
); );
return; return null;
} }
return expirationStartTimestamp; return message;
} }

Loading…
Cancel
Save