From ff19c95a9241e626d02ba61de9b4c21ae3ff483e Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 24 Aug 2023 14:19:42 +1000 Subject: [PATCH] fix: remove using legacy as a string for disappearing messages except in the UI created new isLegacyDisappearingModeEnabled check, default use UNKNOWN expiration type in message classes if not defined --- .../conversation/TimerNotification.tsx | 12 ++--- ts/models/conversation.ts | 3 -- ts/models/message.ts | 7 ++- ts/node/migration/sessionMigrations.ts | 8 ++-- ts/receiver/contentMessage.ts | 4 +- ts/receiver/queuedJob.ts | 17 ++++--- ts/session/group/closed-group.ts | 7 ++- .../messages/outgoing/ExpirableMessage.ts | 7 +-- .../group/ClosedGroupMessage.ts | 2 +- ts/session/sending/MessageSentHandler.ts | 12 ++--- ts/session/utils/calling/CallManager.ts | 13 ++++-- ts/state/selectors/selectedConversation.ts | 45 ++++++++++--------- ts/util/expiringMessages.ts | 10 +++++ ts/util/releaseFeature.ts | 2 +- 14 files changed, 92 insertions(+), 57 deletions(-) diff --git a/ts/components/conversation/TimerNotification.tsx b/ts/components/conversation/TimerNotification.tsx index 2f5032ada..b88e4c20b 100644 --- a/ts/components/conversation/TimerNotification.tsx +++ b/ts/components/conversation/TimerNotification.tsx @@ -8,6 +8,7 @@ import { ExpirableReadableMessage } from './message/message-item/ExpirableReadab import { SessionIcon } from '../icon'; import { SpacerSM, Text } from '../basic/Text'; import { Flex } from '../basic/Flex'; +import { isLegacyDisappearingModeEnabled } from '../../util/expiringMessages'; const StyledTimerNotification = styled(Flex)` text-align: center; @@ -18,12 +19,11 @@ export const TimerNotification = (props: PropsForExpirationTimer) => { const contact = profileName || pubkey; // TODO legacy messages support will be removed in a future release - const mode = - expirationType === 'legacy' - ? null - : expirationType === 'deleteAfterRead' - ? window.i18n('timerModeRead') - : window.i18n('timerModeSent'); + const mode = isLegacyDisappearingModeEnabled(expirationType) + ? null + : expirationType === 'deleteAfterRead' + ? window.i18n('timerModeRead') + : window.i18n('timerModeSent'); let textToRender: string | undefined; switch (type) { diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 5ea6e6b84..9a26d4818 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -2310,14 +2310,11 @@ export class ConversationModel extends Backbone.Model { } private isDisappearingMode(mode: DisappearingMessageConversationType) { - // TODO legacy messages support will be removed in a future release const success = mode === 'deleteAfterRead' ? this.get('expirationType') === 'deleteAfterRead' : mode === 'deleteAfterSend' ? this.get('expirationType') === 'deleteAfterSend' - : mode === 'legacy' - ? this.get('expirationType') === 'legacy' : mode === 'off' ? this.get('expirationType') === 'off' : false; diff --git a/ts/models/message.ts b/ts/models/message.ts index 7764fc626..573129b88 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -94,6 +94,7 @@ import { DisappearingMessageConversationType, DisappearingMessageUpdate, ExpirationTimerOptions, + isLegacyDisappearingModeEnabled, setExpirationStartTimestamp, } from '../util/expiringMessages'; import { LinkPreviews } from '../util/linkPreviews'; @@ -1113,7 +1114,11 @@ export class MessageModel extends Backbone.Model { const expirationType = this.get('expirationType'); // TODO legacy messages support will be removed in a future release const convo = this.getConversation(); - const isLegacyMode = convo && !convo.isMe() && convo.isPrivate() && expirationType === 'legacy'; + const isLegacyMode = + convo && + !convo.isMe() && + convo.isPrivate() && + isLegacyDisappearingModeEnabled(expirationType); if ((isLegacyMode || expirationType === 'deleteAfterRead') && this.get('expireTimer')) { this.set({ expirationStartTimestamp: setExpirationStartTimestamp( diff --git a/ts/node/migration/sessionMigrations.ts b/ts/node/migration/sessionMigrations.ts index 4f9bb5e0c..238f0886c 100644 --- a/ts/node/migration/sessionMigrations.ts +++ b/ts/node/migration/sessionMigrations.ts @@ -1688,7 +1688,7 @@ function updateToSessionSchemaVersion34(currentVersion: number, db: BetterSqlite db.prepare(`ALTER TABLE ${CONVERSATIONS_TABLE} ADD COLUMN hasOutdatedClient TEXT;`).run(); - // region Disappearing Messages Note to Self + // region v34 Disappearing Messages Note to Self const noteToSelfInfo = db .prepare( `UPDATE ${CONVERSATIONS_TABLE} SET @@ -1739,7 +1739,7 @@ function updateToSessionSchemaVersion34(currentVersion: number, db: BetterSqlite // endregion - // region Disappearing Messages Private Conversations + // region v34 Disappearing Messages Private Conversations const privateConversationsInfo = db .prepare( `UPDATE ${CONVERSATIONS_TABLE} SET @@ -1815,12 +1815,12 @@ function updateToSessionSchemaVersion34(currentVersion: number, db: BetterSqlite // endregion - // region Disappearing Messages Groups + // region v34 Disappearing Messages Groups const groupConversationsInfo = db .prepare( `UPDATE ${CONVERSATIONS_TABLE} SET expirationType = $expirationType - WHERE type = 'group' AND id LIKE '05%' AND expireTimer > 0;` + WHERE type = 'group' AND id LIKE '05%' AND expirationType = 'off' AND expireTimer > 0;` ) .run({ expirationType: 'deleteAfterSend' }); diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index b7c043720..015a49edb 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -38,6 +38,7 @@ import { ContactsWrapperActions } from '../webworker/workers/browser/libsession_ import { checkForExpireUpdate, checkHasOutdatedClient, + isLegacyDisappearingModeEnabled, setExpirationStartTimestamp, } from '../util/expiringMessages'; @@ -826,7 +827,8 @@ export async function handleDataExtractionNotification( const referencedAttachmentTimestamp = toNumber(referencedAttachment); const expirationType = convo.get('expirationType'); // TODO legacy messages support will be removed in a future release - const isLegacyMode = convo && convo.isPrivate() && expirationType === 'legacy'; + const isLegacyMode = + convo && convo.isPrivate() && isLegacyDisappearingModeEnabled(expirationType); await convo.addSingleIncomingMessage({ source, diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 775e6fa64..1fa75186e 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -15,7 +15,10 @@ import { ProfileManager } from '../session/profile_manager/ProfileManager'; import { showMessageRequestBannerOutsideRedux } from '../state/ducks/userConfig'; import { getHideMessageRequestBannerOutsideRedux } from '../state/selectors/userConfig'; import { GoogleChrome } from '../util'; -import { setExpirationStartTimestamp } from '../util/expiringMessages'; +import { + isLegacyDisappearingModeEnabled, + setExpirationStartTimestamp, +} from '../util/expiringMessages'; import { LinkPreviews } from '../util/linkPreviews'; import { ReleasedFeatures } from '../util/releaseFeature'; import { PropsForMessageWithoutConvoProps, lookupQuote } from '../state/ducks/conversations'; @@ -180,7 +183,11 @@ function updateReadStatus(message: MessageModel) { const expirationType = message.get('expirationType'); // TODO legacy messages support will be removed in a future release const convo = message.getConversation(); - const isLegacyMode = convo && !convo.isMe() && convo.isPrivate() && expirationType === 'legacy'; + const isLegacyMode = + convo && + !convo.isMe() && + convo.isPrivate() && + isLegacyDisappearingModeEnabled(expirationType); if ((isLegacyMode || expirationType === 'deleteAfterRead') && message.get('expireTimer')) { message.set({ expirationStartTimestamp: setExpirationStartTimestamp( @@ -384,18 +391,18 @@ export async function handleMessageJob( messageModel.set({ flags: regularDataMessage.flags }); // TODO legacy messages support will be removed in a future release + const isLegacyMode = isLegacyDisappearingModeEnabled(messageModel.get('expirationType')); if ( messageModel.isIncoming() && Boolean(messageModel.get('expirationStartTimestamp')) === false && - ((messageModel.get('expirationType') === 'legacy' && - (conversation.isMe() || conversation.isClosedGroup())) || + ((isLegacyMode && (conversation.isMe() || conversation.isClosedGroup())) || messageModel.get('expirationType') === 'deleteAfterSend') ) { messageModel.set({ expirationStartTimestamp: setExpirationStartTimestamp( 'deleteAfterSend', messageModel.get('sent_at'), - messageModel.get('expirationType') === 'legacy' + isLegacyMode ), }); } diff --git a/ts/session/group/closed-group.ts b/ts/session/group/closed-group.ts index c70be25dc..080065ab1 100644 --- a/ts/session/group/closed-group.ts +++ b/ts/session/group/closed-group.ts @@ -27,6 +27,7 @@ import { UserUtils } from '../utils'; import { fromHexToArray, toHex } from '../utils/String'; import { DisappearingMessageConversationType, + isLegacyDisappearingModeEnabled, setExpirationStartTimestamp, } from '../../util/expiringMessages'; @@ -172,7 +173,11 @@ export async function addUpdateMessage( expireTimer: expireTimer || 0, // closed groups are always deleteAfterSend expirationStartTimestamp: expirationType - ? setExpirationStartTimestamp('deleteAfterSend', sentAt, expirationType === 'legacy') + ? setExpirationStartTimestamp( + 'deleteAfterSend', + sentAt, + isLegacyDisappearingModeEnabled(expirationType) + ) : undefined, }; diff --git a/ts/session/messages/outgoing/ExpirableMessage.ts b/ts/session/messages/outgoing/ExpirableMessage.ts index ce11e1aa2..6357f71b6 100644 --- a/ts/session/messages/outgoing/ExpirableMessage.ts +++ b/ts/session/messages/outgoing/ExpirableMessage.ts @@ -30,7 +30,7 @@ export class ExpirableMessage extends ContentMessage { ? SignalService.Content.ExpirationType.DELETE_AFTER_SEND : this.expirationType === 'deleteAfterRead' ? SignalService.Content.ExpirationType.DELETE_AFTER_READ - : this.expirationType === 'legacy' + : this.expirationType ? SignalService.Content.ExpirationType.UNKNOWN : undefined, expirationTimer: this.expireTimer && this.expireTimer > -1 ? this.expireTimer : undefined, @@ -40,10 +40,7 @@ export class ExpirableMessage extends ContentMessage { public dataProto(): SignalService.DataMessage { return new SignalService.DataMessage({ // TODO legacy messages support will be removed in a future release - expireTimer: - (!this.expirationType || this.expirationType === 'legacy') && this.expireTimer - ? this.expireTimer - : undefined, + expireTimer: !this.expirationType ? this.expireTimer : undefined, }); } diff --git a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts index c20a18229..a021b8063 100644 --- a/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts +++ b/ts/session/messages/outgoing/controlMessage/group/ClosedGroupMessage.ts @@ -36,7 +36,7 @@ export abstract class ClosedGroupMessage extends ExpirableMessage { expirationType: this.expirationType === 'deleteAfterSend' ? SignalService.Content.ExpirationType.DELETE_AFTER_SEND - : !this.expirationType || this.expirationType === 'legacy' + : this.expirationType ? SignalService.Content.ExpirationType.UNKNOWN : undefined, }); diff --git a/ts/session/sending/MessageSentHandler.ts b/ts/session/sending/MessageSentHandler.ts index b9b181aae..9144fdb88 100644 --- a/ts/session/sending/MessageSentHandler.ts +++ b/ts/session/sending/MessageSentHandler.ts @@ -1,7 +1,10 @@ import _ from 'lodash'; import { Data } from '../../data/data'; import { SignalService } from '../../protobuf'; -import { setExpirationStartTimestamp } from '../../util/expiringMessages'; +import { + isLegacyDisappearingModeEnabled, + setExpirationStartTimestamp, +} from '../../util/expiringMessages'; import { PnServer } from '../apis/push_notification_api'; import { OpenGroupVisibleMessage } from '../messages/outgoing/visibleMessage/OpenGroupVisibleMessage'; import { RawMessage } from '../types'; @@ -124,10 +127,9 @@ async function handleMessageSentSuccess( const expirationType = fetchedMessage.get('expirationType'); // TODO legacy messages support will be removed in a future release const convo = fetchedMessage.getConversation(); - const isLegacyReadMode = - convo && !convo.isMe() && convo.isPrivate() && expirationType === 'legacy'; - const isLegacySentMode = - convo && (convo.isMe() || convo.isClosedGroup()) && expirationType === 'legacy'; + const isLegacyMode = isLegacyDisappearingModeEnabled(expirationType); + const isLegacyReadMode = convo && !convo.isMe() && convo.isPrivate() && isLegacyMode; + const isLegacySentMode = convo && (convo.isMe() || convo.isClosedGroup()) && isLegacyMode; fetchedMessage.set({ sent_to: sentTo, diff --git a/ts/session/utils/calling/CallManager.ts b/ts/session/utils/calling/CallManager.ts index a435889d5..08bdbfd6b 100644 --- a/ts/session/utils/calling/CallManager.ts +++ b/ts/session/utils/calling/CallManager.ts @@ -33,7 +33,10 @@ import { approveConvoAndSendResponse } from '../../../interactions/conversationI import { GetNetworkTime } from '../../apis/snode_api/getNetworkTime'; import { SnodeNamespaces } from '../../apis/snode_api/namespaces'; import { READ_MESSAGE_STATE } from '../../../models/conversationAttributes'; -import { setExpirationStartTimestamp } from '../../../util/expiringMessages'; +import { + isLegacyDisappearingModeEnabled, + setExpirationStartTimestamp, +} from '../../../util/expiringMessages'; // tslint:disable: function-name @@ -514,7 +517,7 @@ export async function USER_callRecipient(recipient: string) { weAreCallerOnCurrentCall = true; // TODO legacy messages support will be removed in a future release - const isLegacyMode = calledConvo.get('expirationType') === 'legacy'; + const isLegacyMode = isLegacyDisappearingModeEnabled(calledConvo.get('expirationType')); const expirationType = !isLegacyMode ? calledConvo.get('expirationType') : 'deleteAfterSend'; await calledConvo?.addSingleOutgoingMessage({ callNotificationType: 'started-call', @@ -888,7 +891,7 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) { await callerConvo.unhideIfNeeded(false); // TODO legacy messages support will be removed in a future release - const isLegacyMode = callerConvo.get('expirationType') === 'legacy'; + const isLegacyMode = isLegacyDisappearingModeEnabled(callerConvo.get('expirationType')); const expirationType = !isLegacyMode ? callerConvo.get('expirationType') : 'deleteAfterSend'; await callerConvo?.addSingleIncomingMessage({ callNotificationType: 'answered-a-call', @@ -1234,7 +1237,9 @@ async function addMissedCallMessage(callerPubkey: string, sentAt: number) { } // TODO legacy messages support will be removed in a future release - const isLegacyMode = incomingCallConversation.get('expirationType') === 'legacy'; + const isLegacyMode = isLegacyDisappearingModeEnabled( + incomingCallConversation.get('expirationType') + ); const expirationType = !isLegacyMode ? incomingCallConversation.get('expirationType') : 'deleteAfterSend'; diff --git a/ts/state/selectors/selectedConversation.ts b/ts/state/selectors/selectedConversation.ts index 88013dd23..538f8d847 100644 --- a/ts/state/selectors/selectedConversation.ts +++ b/ts/state/selectors/selectedConversation.ts @@ -7,6 +7,8 @@ import { StateType } from '../reducer'; import { getCanWrite, getModerators, getSubscriberCount } from './sogsRoomInfo'; import { getIsMessageSelectionMode, getSelectedConversation } from './conversations'; import { DisappearingMessageConversationSetting } from '../../util/expiringMessages'; +import { ReleasedFeatures } from '../../util/releaseFeature'; +import { ReduxConversationType } from '../ducks/conversations'; /** * Returns the formatted text for notification setting. @@ -155,59 +157,62 @@ const getSelectedSubscriberCount = (state: StateType): number | undefined => { return getSubscriberCount(state, convo.id); }; -export const getSelectedConversationExpirationModes = (state: StateType) => { - const convo = getSelectedConversation(state); +// TODO legacy messages support will be removed in a future release +const getSelectedConversationExpirationModesWithLegacy = (convo: ReduxConversationType) => { if (!convo) { return undefined; } let modes = DisappearingMessageConversationSetting; - // TODO legacy messages support will be removed in a future release - // TODO remove legacy mode - modes = modes.slice(0, -1); - // Note to Self and Closed Groups only support deleteAfterSend + // Note to Self and Closed Groups only support deleteAfterSend and legacy modes const isClosedGroup = !convo.isPrivate && !convo.isPublic; if (convo?.isMe || isClosedGroup) { - modes = [modes[0], modes[2]]; + modes = [modes[0], ...modes.slice(2)]; } + // Legacy mode is the 2nd option in the UI + modes = [modes[0], modes[modes.length - 1], ...modes.slice(1, modes.length - 1)]; + + // TODO it would be nice to type those with something else that string but it causes a lot of issues const modesWithDisabledState: Record = {}; + // The new modes are disabled by default if (modes && modes.length > 1) { modes.forEach(mode => { - modesWithDisabledState[mode] = isClosedGroup ? !convo.weAreAdmin : false; + modesWithDisabledState[mode] = Boolean( + (mode !== 'legacy' && mode !== 'off') || (isClosedGroup && !convo.weAreAdmin) + ); }); } return modesWithDisabledState; }; -// TODO legacy messages support will be removed in a future release -export const getSelectedConversationExpirationModesWithLegacy = (state: StateType) => { +export const getSelectedConversationExpirationModes = (state: StateType) => { const convo = getSelectedConversation(state); if (!convo) { return undefined; } + if (!ReleasedFeatures.isDisappearMessageV2FeatureReleasedCached()) { + return getSelectedConversationExpirationModesWithLegacy(convo); + } + let modes = DisappearingMessageConversationSetting; + // TODO legacy messages support will be removed in a future release + // TODO remove legacy mode + modes = modes.slice(0, -1); - // Note to Self and Closed Groups only support deleteAfterSend and legacy modes + // Note to Self and Closed Groups only support deleteAfterSend const isClosedGroup = !convo.isPrivate && !convo.isPublic; if (convo?.isMe || isClosedGroup) { - modes = [modes[0], ...modes.slice(2)]; + modes = [modes[0], modes[2]]; } - // Legacy mode is the 2nd option in the UI - modes = [modes[0], modes[modes.length - 1], ...modes.slice(1, modes.length - 1)]; - - // TODO it would be nice to type those with something else that string but it causes a lot of issues const modesWithDisabledState: Record = {}; - // The new modes are disabled by default if (modes && modes.length > 1) { modes.forEach(mode => { - modesWithDisabledState[mode] = Boolean( - (mode !== 'legacy' && mode !== 'off') || (isClosedGroup && !convo.weAreAdmin) - ); + modesWithDisabledState[mode] = isClosedGroup ? !convo.weAreAdmin : false; }); } diff --git a/ts/util/expiringMessages.ts b/ts/util/expiringMessages.ts index a2d055210..921b51074 100644 --- a/ts/util/expiringMessages.ts +++ b/ts/util/expiringMessages.ts @@ -437,3 +437,13 @@ export async function checkHasOutdatedClient( await convoToUpdate.commit(); } } + +export function isLegacyDisappearingModeEnabled( + expirationType: DisappearingMessageConversationType | DisappearingMessageType | undefined +): boolean { + return Boolean( + expirationType && + expirationType !== 'off' && + !ReleasedFeatures.isDisappearMessageV2FeatureReleasedCached() + ); +} diff --git a/ts/util/releaseFeature.ts b/ts/util/releaseFeature.ts index 206598549..ad257fdb4 100644 --- a/ts/util/releaseFeature.ts +++ b/ts/util/releaseFeature.ts @@ -106,7 +106,7 @@ function isUserConfigFeatureReleasedCached(): boolean { return !!isUserConfigLibsessionFeatureReleased; } -function isDisappearMessageV2FeatureReleasedCached() { +function isDisappearMessageV2FeatureReleasedCached(): boolean { return !!isDisappearingMessageFeatureReleased; }