From 8dc7dac55efdb65ff37122f5ddb61521f7e82200 Mon Sep 17 00:00:00 2001 From: William Grant Date: Mon, 3 Apr 2023 14:09:05 +0200 Subject: [PATCH] feat: control available modes depending on the conversation --- .../overlay/OverlayDisappearingMessages.tsx | 10 +++---- ts/models/conversation.ts | 27 ++++++++++++------- ts/receiver/contentMessage.ts | 9 ++++--- ts/receiver/queuedJob.ts | 12 ++++++--- ts/state/selectors/conversations.ts | 16 +++++++++++ 5 files changed, 53 insertions(+), 21 deletions(-) diff --git a/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx b/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx index b6cae9310..d24ba8f98 100644 --- a/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx +++ b/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx @@ -12,11 +12,11 @@ import { PanelButtonGroup } from '../../../buttons'; import { PanelLabel } from '../../../buttons/PanelButton'; import { PanelRadioButton } from '../../../buttons/PanelRadioButton'; import { SessionIconButton } from '../../../icon'; -import { getSelectedConversationExpirationSettings } from '../../../../state/selectors/conversations'; import { - DisappearingMessageConversationSetting, - DisappearingMessageConversationType, -} from '../../../../util/expiringMessages'; + getSelectedConversationExpirationModes, + getSelectedConversationExpirationSettings, +} from '../../../../state/selectors/conversations'; +import { DisappearingMessageConversationType } from '../../../../util/expiringMessages'; import { TimerOptionsArray } from '../../../../state/ducks/timerOptions'; import { useTimerOptionsByMode } from '../../../../hooks/useParamSelector'; import { isEmpty } from 'lodash'; @@ -177,7 +177,7 @@ const TimeOptions = (props: TimerOptionsProps) => { export const OverlayDisappearingMessages = () => { const dispatch = useDispatch(); const selectedConversationKey = useSelector(getSelectedConversationKey); - const disappearingModeOptions = DisappearingMessageConversationSetting; + const disappearingModeOptions = useSelector(getSelectedConversationExpirationModes); const convoProps = useSelector(getSelectedConversationExpirationSettings); diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 15a173cf3..12408f67b 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -1045,18 +1045,16 @@ export class ConversationModel extends Backbone.Model { } if (this.get('expireTimer') === expireTimer || (!expireTimer && !this.get('expireTimer'))) { + window.log.info(`WIP: This disappearing message setting is invalid`, { + id: this.idForLogging(), + expirationType, + expireTimer, + source, + }); return; } - window?.log?.info('WIP: Updated conversation disappearing messages setting', { - id: this.idForLogging(), - expirationType, - expireTimer, - source, - }); - const isOutgoing = Boolean(!receivedAt); - source = source || UserUtils.getOurPubKeyStrFromCache(); // When we add a disappearing messages notification to the conversation, we want it @@ -1069,8 +1067,14 @@ export class ConversationModel extends Backbone.Model { lastDisappearingMessageChangeTimestamp: providedChangeTimestamp || undefined, }); - const lastDisappearingMessageChangeTimestamp = providedChangeTimestamp || 0; + window?.log?.info('WIP: Updated conversation disappearing messages setting', { + id: this.idForLogging(), + expirationType, + expireTimer, + source, + }); + const lastDisappearingMessageChangeTimestamp = providedChangeTimestamp || 0; const commonAttributes = { flags: SignalService.DataMessage.Flags.EXPIRATION_TIMER_UPDATE, expirationTimerUpdate: { @@ -1125,6 +1129,11 @@ export class ConversationModel extends Backbone.Model { if (this.isMe()) { // TODO Check that the args are correct + if (expireUpdate.expirationType === 'deleteAfterRead') { + window.log.info(`WIP: Note to Self messages cannot be delete after read!`); + return; + } + const expirationTimerMessage = new ExpirationTimerUpdateMessage(expireUpdate); return message.sendSyncMessageOnly(expirationTimerMessage); } diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index d2d6f9441..d7146368c 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -402,13 +402,14 @@ export async function innerHandleSwarmContentMessage( perfStart(`handleSwarmDataMessage-${envelope.id}`); - const expirationType = DisappearingMessageConversationSetting[content.expirationType] || null; - // NOTE In the protobuf this is a long - const lastDisappearingMessageChangeTimestamp = - Number(content.lastDisappearingMessageChangeTimestamp) || null; 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 diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 2e6b84aba..63fa522c4 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -1,7 +1,7 @@ import { queueAttachmentDownloads } from './attachments'; import { Quote } from './types'; -import _, { isEmpty } from 'lodash'; +import _, { isEmpty, isEqual } from 'lodash'; import { getConversationController } from '../session/conversations'; import { ConversationModel } from '../models/conversation'; import { MessageModel, sliceQuoteText } from '../models/message'; @@ -318,6 +318,12 @@ async function handleExpirationTimerUpdateNoCommit( ) { const providedChangeTimestamp = getNowWithNetworkOffset(); + // TODO Not entirely sure that this works + if (conversation.get('lastDisappearingMessageChangeTimestamp') > providedChangeTimestamp) { + window.log.info(`WIP: This is an outdated disappearing message setting`); + return; + } + message.set({ expirationTimerUpdate: { source, @@ -366,9 +372,9 @@ export async function handleMessageJob( const expireTimer = expireUpdate.expireTimer || oldExpireTimer; // TODO compare types and change timestamps - // const oldTypeValue = conversation.get('expirationType'); + const oldTypeValue = conversation.get('expirationType'); const oldTimerValue = conversation.get('expireTimer'); - if (expireTimer === oldTimerValue) { + if (isEqual(expirationType, oldTypeValue) && expireTimer === oldTimerValue) { confirm?.(); window?.log?.info( 'Dropping ExpireTimerUpdate message as we already have the same one set.' diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 388ff5417..0037a81b1 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -37,6 +37,7 @@ import { ConversationTypeEnum } from '../../models/conversationAttributes'; import { MessageReactsSelectorProps } from '../../components/conversation/message/message-content/MessageReactions'; import { filter, isEmpty, pick, sortBy } from 'lodash'; +import { DisappearingMessageConversationSetting } from '../../util/expiringMessages'; export const getConversations = (state: StateType): ConversationsStateType => state.conversations; @@ -1175,6 +1176,21 @@ export const getIsSelectedConvoInitialLoadingInProgress = createSelector( (convo: ReduxConversationType | undefined): boolean => Boolean(convo?.isInitialFetchingInProgress) ); +export const getSelectedConversationExpirationModes = createSelector( + getSelectedConversation, + (convo: ReduxConversationType | undefined) => { + let modes = DisappearingMessageConversationSetting; + + // Note to Self and Closed Groups only support deleteAfterSend + if (convo?.isMe || (convo?.isGroup && !convo.isPublic)) { + // only deleteAfterSend + modes = [modes[0], modes[2]]; + } + + return modes; + } +); + export const getSelectedConversationExpirationSettings = createSelector( getSelectedConversation, (convo: ReduxConversationType | undefined) => ({