feat: fixed closed groups

improved setExpirationStartTimestamp logic
pull/2660/head
William Grant 1 year ago
parent b4fc33c8fa
commit d358ab2fb1

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

@ -653,6 +653,8 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const closedGroupVisibleMessage = new ClosedGroupVisibleMessage({
chatMessage: chatMessageMediumGroup,
groupId: destination,
expirationType,
expireTimer,
});
// 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('expirationStartTimestamp')
) {
const expirationStartTimestamp = setExpirationStartTimestamp(this, 'deleteAfterRead', readAt);
this.set({ expirationStartTimestamp });
const message = setExpirationStartTimestamp(this, 'deleteAfterRead', readAt);
this.set({ expirationStartTimestamp: message?.get('expirationStartTimestamp') });
}
Notifications.clearByMessageId(this.id);

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

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

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

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

@ -3,10 +3,13 @@ import { PubKey } from '../../../types';
import { StringUtils } from '../../../utils';
import { VisibleMessage } from './VisibleMessage';
import { ClosedGroupMessage } from '../controlMessage/group/ClosedGroupMessage';
import { DisappearingMessageType } from '../../../../util/expiringMessages';
interface ClosedGroupVisibleMessageParams {
identifier?: string;
groupId: string | PubKey;
expirationType?: DisappearingMessageType;
expireTimer?: number;
chatMessage: VisibleMessage;
}
@ -18,12 +21,15 @@ export class ClosedGroupVisibleMessage extends ClosedGroupMessage {
timestamp: params.chatMessage.timestamp,
identifier: params.identifier ?? params.chatMessage.identifier,
groupId: params.groupId,
expirationType: params.expirationType,
expireTimer: params.expireTimer,
});
this.chatMessage = params.chatMessage;
if (!params.groupId) {
throw new Error('ClosedGroupVisibleMessage: groupId must be set');
}
}
public dataProto(): SignalService.DataMessage {
//expireTimer is set in the dataProto in this call directly
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
if (shouldTriggerSyncMessage) {
if (dataMessage) {
@ -119,14 +128,6 @@ async function handleMessageSentSuccess(
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) {
fetchedMessage.set({ synced: true });
// TODO handle sync messages separately
@ -148,7 +149,7 @@ async function handleMessageSentFailure(
sentMessage: RawMessage | OpenGroupVisibleMessage,
error: any
) {
const fetchedMessage = await fetchHandleMessageSentData(sentMessage.identifier);
let fetchedMessage = await fetchHandleMessageSentData(sentMessage.identifier);
if (!fetchedMessage) {
return;
}
@ -168,11 +169,9 @@ async function handleMessageSentFailure(
}
if (fetchedMessage.get('expirationType')) {
const expirationStartTimestamp = setExpirationStartTimestamp(
fetchedMessage,
fetchedMessage.get('expirationType')!
);
fetchedMessage.set('expirationStartTimestamp', expirationStartTimestamp);
fetchedMessage =
setExpirationStartTimestamp(fetchedMessage, fetchedMessage.get('expirationType')!) ||
fetchedMessage;
}
// always mark the message as sent.

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

Loading…
Cancel
Save