From dadc93bfda67db472f12aaab1266f2a991710ce9 Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 14:44:54 +1000 Subject: [PATCH 01/14] fix: remove unecessary useCallback for feature releaser --- ts/components/conversation/right-panel/RightPanel.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ts/components/conversation/right-panel/RightPanel.tsx b/ts/components/conversation/right-panel/RightPanel.tsx index c7fd5859f..b4eb18049 100644 --- a/ts/components/conversation/right-panel/RightPanel.tsx +++ b/ts/components/conversation/right-panel/RightPanel.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { getRightOverlayMode } from '../../../state/selectors/section'; @@ -10,14 +10,9 @@ const ClosableOverlay = () => { const rightOverlayMode = useSelector(getRightOverlayMode); const [showNewDisppearingMessageModes, setShowNewDisppearingMessageModes] = useState(false); - const checkForFeatureRelease = useCallback(async () => { - const isReleased = await checkIsFeatureReleased('Disappearing Messages V2'); - return isReleased; - }, []); - useEffect(() => { let isCancelled = false; - checkForFeatureRelease() + checkIsFeatureReleased('Disappearing Messages V2') .then(result => { if (isCancelled) { return; @@ -33,7 +28,7 @@ const ClosableOverlay = () => { return () => { isCancelled = true; }; - }, [checkForFeatureRelease]); + }, []); switch (rightOverlayMode) { case 'disappearing-messages': From c1c380ba9d3b47bf18d854fa58b45e1276e5961e Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 14:45:18 +1000 Subject: [PATCH 02/14] fix: remove unecessary any type from TimerOptions --- .../right-panel/overlay/disappearing-messages/TimeOptions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/components/conversation/right-panel/overlay/disappearing-messages/TimeOptions.tsx b/ts/components/conversation/right-panel/overlay/disappearing-messages/TimeOptions.tsx index 861779deb..cfd0bbf32 100644 --- a/ts/components/conversation/right-panel/overlay/disappearing-messages/TimeOptions.tsx +++ b/ts/components/conversation/right-panel/overlay/disappearing-messages/TimeOptions.tsx @@ -23,7 +23,7 @@ export const TimeOptions = (props: TimerOptionsProps) => { <> {!hasOnlyOneMode && {window.i18n('timer')}} - {options.map((option: any) => { + {options.map(option => { return ( Date: Wed, 26 Apr 2023 14:46:55 +1000 Subject: [PATCH 03/14] fix: log but continue if there are errors while clearing out sogs inboxes --- ts/components/dialog/DeleteAccountModal.tsx | 10 +++++++++- .../apis/open_group_api/sogsv3/sogsV3ClearInbox.ts | 14 +++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ts/components/dialog/DeleteAccountModal.tsx b/ts/components/dialog/DeleteAccountModal.tsx index 22145485b..f8ef34401 100644 --- a/ts/components/dialog/DeleteAccountModal.tsx +++ b/ts/components/dialog/DeleteAccountModal.tsx @@ -65,7 +65,15 @@ async function deleteEverythingAndNetworkData() { // clear each inbox per sogs for (const roomInfo of allRoomInfos.values()) { // TODO CONTINUE testing - use a dummy account with some message requests and then if we restore from seed there should be no message requests. - await clearInbox(roomInfo); + try { + const success = await clearInbox(roomInfo); + if (!success) { + throw Error(`Failed to clear inbox for ${roomInfo.conversationId}`); + } + } catch (error) { + window.log.info(`DeleteAccount =>`, error); + continue; + } } } diff --git a/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts b/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts index 14f46ecab..f88be9bc3 100644 --- a/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts +++ b/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts @@ -16,8 +16,8 @@ type OpenGroupClearInboxResponse = { export const clearInbox = async (roomInfos: OpenGroupRequestCommonType): Promise => { let success = false; - const converationId = getOpenGroupV2ConversationId(roomInfos.serverUrl, roomInfos.roomId); - const conversation = await Data.getConversationById(converationId); + const conversationId = getOpenGroupV2ConversationId(roomInfos.serverUrl, roomInfos.roomId); + const conversation = await Data.getConversationById(conversationId); if (!conversation) { window.log.warn('clearInbox Matching conversation not found in db'); @@ -40,27 +40,27 @@ export const clearInbox = async (roomInfos: OpenGroupRequestCommonType): Promise ); if (!result) { - throw new Error('Could not clearInbox, res is invalid'); + throw new Error(`Could not clearInbox, res is invalid for ${conversationId}`); } const rawMessage = (result.body && (result.body[0].body as OpenGroupClearInboxResponse)) || null; if (!rawMessage) { - throw new Error('clearInbox parsing failed'); + throw new Error(`clearInbox parsing failed for ${conversationId}`); } try { if (batchGlobalIsSuccess(result) && batchFirstSubIsSuccess(result)) { success = true; - window.log.info(`clearInbox ${rawMessage.deleted} messages deleted from ${converationId} `); + window.log.info(`clearInbox ${rawMessage.deleted} messages deleted for ${conversationId} `); } } catch (e) { - window?.log?.error("clearInbox Can't decode JSON body"); + window?.log?.error(`clearInbox Can't decode JSON body for ${conversationId}`); } } if (!success) { - window.log.info(`clearInbox message deletion failed for ${converationId} `); + window.log.info(`clearInbox message deletion failed for ${conversationId}`); } return success; }; From cfcf400ecf9be13ebb8957968ddead7dccc8ba1d Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 16:01:58 +1000 Subject: [PATCH 04/14] fix: cleaned up WIP logging and used the window log debug function where appropriate --- ts/hooks/useParamSelector.ts | 3 +- ts/models/conversation.ts | 17 ++++------ ts/models/message.ts | 2 +- ts/receiver/contentMessage.ts | 2 +- ts/receiver/dataMessage.ts | 2 +- ts/receiver/queuedJob.ts | 4 +-- ts/session/apis/snode_api/SNodeAPI.ts | 2 -- ts/session/apis/snode_api/expire.ts | 49 ++++++++++----------------- ts/session/utils/syncUtils.ts | 2 +- ts/util/expiringMessages.ts | 24 ++++++------- ts/util/releaseFeature.ts | 6 ++-- 11 files changed, 44 insertions(+), 69 deletions(-) diff --git a/ts/hooks/useParamSelector.ts b/ts/hooks/useParamSelector.ts index f6e2bab88..847daee10 100644 --- a/ts/hooks/useParamSelector.ts +++ b/ts/hooks/useParamSelector.ts @@ -184,7 +184,8 @@ export function useMessageReactsPropsById(messageId?: string) { }); } -// TODO remove 10 seconds timer +// TODO use env variable to toggle test values? +// https://github.com/oxen-io/session-desktop/pull/2660/files#r1174823750 export function useTimerOptionsByMode(disappearingMessageMode?: string, hasOnlyOneMode?: boolean) { return useSelector((state: StateType) => { const options = state.timerOptions.timerOptions; diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index eaf88607a..386142551 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -678,10 +678,7 @@ export class ConversationModel extends Backbone.Model { expireTimer: chatMessageParams.expireTimer, }); - window.log.info( - 'WIP: sendMessageJob() closedGroupVisibleMessage', - closedGroupVisibleMessage - ); + window.log.debug('sendMessageJob() closedGroupVisibleMessage', closedGroupVisibleMessage); // we need the return await so that errors are caught in the catch {} await getMessageQueue().sendToGroup(closedGroupVisibleMessage); @@ -1075,9 +1072,7 @@ export class ConversationModel extends Backbone.Model { existingMessage?: MessageModel; }): Promise { if (this.isPublic()) { - window.log.warning( - "WIP: updateExpireTimer() Disappearing messages aren't supported in communities" - ); + window.log.warn("updateExpireTimer() Disappearing messages aren't supported in communities"); return; } @@ -1094,7 +1089,7 @@ export class ConversationModel extends Backbone.Model { if ( this.get('lastDisappearingMessageChangeTimestamp') > lastDisappearingMessageChangeTimestamp ) { - window.log.info('WIP: updateExpireTimer() This is an outdated disappearing message setting'); + window.log.info('updateExpireTimer() This is an outdated disappearing message setting'); return; } @@ -1103,7 +1098,7 @@ export class ConversationModel extends Backbone.Model { isEqual(expireTimer, this.get('expireTimer')) ) { window.log.info( - 'WIP:updateExpireTimer() Dropping ExpireTimerUpdate message as we already have the same one set.' + 'updateExpireTimer() Dropping ExpireTimerUpdate message as we already have the same one set.' ); return; } @@ -1126,7 +1121,7 @@ export class ConversationModel extends Backbone.Model { lastDisappearingMessageChangeTimestamp, }); - window?.log?.info('WIP: Updating conversation disappearing messages setting', { + window?.log?.debug('Updating conversation disappearing messages setting', { id: this.idForLogging(), expirationType, expireTimer, @@ -1197,7 +1192,7 @@ export class ConversationModel extends Backbone.Model { // TODO Check that the args are correct // This might be happening too late in the message pipeline. Maybe should be moved to handleExpirationTimerUpdateNoCommit() if (expireUpdate.expirationType === 'deleteAfterRead') { - window.log.info('WIP: Note to Self messages cannot be delete after read!'); + window.log.info('Note to Self messages cannot be delete after read!'); return; } diff --git a/ts/models/message.ts b/ts/models/message.ts index 2e8e6002a..c260567e1 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -1280,7 +1280,7 @@ export class MessageModel extends Backbone.Model { await this.commit(); } - window?.log?.info('WIP: Set message expiration', { + window?.log?.debug('Set message expiration', { expiresAt, sentAt: this.get('sent_at'), }); diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index f158b6c81..82270a16d 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -417,7 +417,7 @@ export async function innerHandleSwarmContentMessage( expireUpdate ); if (expireUpdate.isLegacyConversationSettingMessage) { - window.log.info('WIP: The legacy message is an expiration timer update. Ignoring it.'); + window.log.info('The legacy message is an expiration timer update. Ignoring it.'); return; } } diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index da728dfd1..6a0e64870 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -246,7 +246,7 @@ export async function handleSwarmDataMessage( if (expireUpdate && !isEmpty(expireUpdate)) { if (isSyncedMessage) { // TODO handle sync messages expiring separately? - window.log.info('WIP: Sync Message dropping'); + window.log.debug('WIP: Sync Message dropping'); } else { msgModel = handleExpireUpdate(convoToAddMessageTo, msgModel, expireUpdate); } diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 2316c0e07..b25003066 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -361,7 +361,7 @@ export async function handleMessageJob( (!expirationTimerUpdate || isEmpty(expirationTimerUpdate)) ) { window.log.info( - 'WIP: There is a problem with the expiration timer update', + 'There is a problem with the expiration timer update', messageModel, expirationTimerUpdate ); @@ -380,7 +380,7 @@ export async function handleMessageJob( ) { confirm?.(); window?.log?.info( - 'WIP: Dropping ExpireTimerUpdate message as we already have the same one set.' + 'Dropping ExpireTimerUpdate message as we already have the same one set.' ); return; } diff --git a/ts/session/apis/snode_api/SNodeAPI.ts b/ts/session/apis/snode_api/SNodeAPI.ts index e597a743a..c2330a9c7 100644 --- a/ts/session/apis/snode_api/SNodeAPI.ts +++ b/ts/session/apis/snode_api/SNodeAPI.ts @@ -554,8 +554,6 @@ export async function retrieveNextMessages( handleTimestampOffset('retrieve', json.t); await handleHardforkResult(json); - // console.log(`WIP: retrieveNextMessages`, json.messages); - return json.messages || []; } catch (e) { window?.log?.warn('exception while parsing json of nextMessage:', e); diff --git a/ts/session/apis/snode_api/expire.ts b/ts/session/apis/snode_api/expire.ts index f239039ef..cf405700a 100644 --- a/ts/session/apis/snode_api/expire.ts +++ b/ts/session/apis/snode_api/expire.ts @@ -31,7 +31,7 @@ async function generateSignature({ // "expire" || ShortenOrExtend || expiry || messages[0] || ... || messages[N] const verificationString = `expire${shortenOrExtend}${timestamp}${messageHashes.join('')}`; const verificationData = StringUtils.encode(verificationString, 'utf8'); - // window.log.info(`WIP: generateSignature verificationString ${verificationString}`); + window.log.debug(`generateSignature verificationString ${verificationString}`); const message = new Uint8Array(verificationData); const sodium = await getSodiumRenderer(); @@ -44,7 +44,7 @@ async function generateSignature({ pubkey_ed25519: pubkey_ed25519.pubKey, }; } catch (e) { - window.log.warn('WIP: generateSignature failed with: ', e.message); + window.log.warn('generateSignature failed with: ', e.message); return null; } } @@ -68,7 +68,7 @@ async function verifySignature({ unchangedHashes?: Record; }): Promise { if (!expiryApplied || isEmpty(messageHashes) || isEmpty(signature)) { - // window.log.info('WIP: WIP: verifySignature missing argument'); + window.log.warn('verifySignature missing argument'); return false; } @@ -91,7 +91,7 @@ async function verifySignature({ const verificationString = `${pubkey.key}${expiryApplied}${hashes.join('')}`; const verificationData = StringUtils.encode(verificationString, 'utf8'); - // window.log.info(`WIP: verifySignature verificationString`, verificationString); + window.log.debug(`verifySignature verificationString`, verificationString); const sodium = await getSodiumRenderer(); try { @@ -103,7 +103,7 @@ async function verifySignature({ return isValid; } catch (e) { - window.log.warn('WIP: verifySignature failed with: ', e.message); + window.log.warn('verifySignature failed with: ', e.message); return false; } } @@ -115,20 +115,19 @@ async function processExpirationResults( messageHashes: Array ) { if (isEmpty(swarm)) { - throw Error(`WIP: expireOnNodes failed! ${messageHashes}`); + throw Error(`expireOnNodes failed! ${messageHashes}`); } // TODO need proper typing for swarm and results const results: Record; expiry: number }> = {}; - // window.log.info(`WIP: processExpirationResults start`, swarm, messageHashes); + // window.log.debug(`processExpirationResults start`, swarm, messageHashes); for (const nodeKey of Object.keys(swarm)) { - // window.log.info(`WIP: processExpirationResults processing nodeKey`, nodeKey, swarm[nodeKey]); if (!isEmpty(swarm[nodeKey].failed)) { const reason = 'Unknown'; const statusCode = '404'; window?.log?.warn( - `WIP: loki_message:::expireMessage - Couldn't delete data from: ${ + `loki_message:::expireMessage - Couldn't delete data from: ${ targetNode.pubkey_ed25519 }${reason && statusCode && ` due to an error ${reason} (${statusCode})`}` ); @@ -141,8 +140,6 @@ async function processExpirationResults( const expiryApplied = swarm[nodeKey].expiry; const signature = swarm[nodeKey].signature; - // window.log.info(`WIP: processExpirationResults swarm[nodeKey]`, swarm[nodeKey]); - const isValid = await verifySignature({ pubkey, snodePubkey: nodeKey, @@ -155,7 +152,7 @@ async function processExpirationResults( if (!isValid) { window.log.warn( - 'WIP: loki_message:::expireMessage - Signature verification failed!', + 'loki_message:::expireMessage - Signature verification failed!', messageHashes ); } @@ -189,27 +186,21 @@ async function expireOnNodes(targetNode: Snode, params: ExpireParams) { try { const parsed = JSON.parse(result.body); - await processExpirationResults(params.pubkey, targetNode, parsed.swarm, params.messages); - - // const expirationResults = await processExpirationResults( - // params.pubkey, - // targetNode, - // parsed.swarm, - // params.messages - // ); - // window.log.info(`WIP: expireOnNodes attempt complete. Here are the results`, expirationResults); + const expirationResults = await processExpirationResults( + params.pubkey, + targetNode, + parsed.swarm, + params.messages + ); + window.log.debug(`expireOnNodes attempt complete. Here are the results`, expirationResults); return true; } catch (e) { - window?.log?.warn('WIP: Failed to parse "swarm" result: ', e.msg); + window?.log?.warn('expireOnNodes Failed to parse "swarm" result: ', e.msg); } return false; } catch (e) { - window?.log?.warn( - 'WIP: expire - send error:', - e, - `destination ${targetNode.ip}:${targetNode.port}` - ); + window?.log?.warn('expire - send error:', e, `destination ${targetNode.ip}:${targetNode.port}`); throw e; } } @@ -223,7 +214,6 @@ type ExpireMessageOnSnodeProps = { export async function expireMessageOnSnode(props: ExpireMessageOnSnodeProps) { const { messageHash, expireTimer, extend, shorten } = props; - // window.log.info('WIP: expireMessageOnSnode running!'); if (extend && shorten) { window.log.error( @@ -270,8 +260,6 @@ export async function expireMessageOnSnode(props: ExpireMessageOnSnodeProps) { signature: signResult?.signature, }; - // window.log.info(`WIP: expireMessageOnSnode params`, params); - const usedNodes = slice(swarm, 0, DEFAULT_CONNECTIONS); if (!usedNodes || usedNodes.length === 0) { throw new EmptySwarmError(ourPubKey.key, 'Ran out of swarm nodes to query'); @@ -289,7 +277,6 @@ export async function expireMessageOnSnode(props: ExpireMessageOnSnodeProps) { try { const firstSuccessSnode = await firstTrue(promises); snode = firstSuccessSnode; - // window.log.info(`WIP: expireMessageOnSnode firstSuccessSnode`, firstSuccessSnode); } catch (e) { const snodeStr = snode ? `${snode.ip}:${snode.port}` : 'null'; window?.log?.warn( diff --git a/ts/session/utils/syncUtils.ts b/ts/session/utils/syncUtils.ts index fee9c2acc..b68160988 100644 --- a/ts/session/utils/syncUtils.ts +++ b/ts/session/utils/syncUtils.ts @@ -349,7 +349,7 @@ export const buildSyncMessage = ( if (expireUpdate && !isEmpty(expireUpdate)) { return buildSyncExpireTimerMessage(identifier, expireUpdate, timestamp, syncTarget); } else { - window.log.info('WIP: Building Sync Expire Timer Message failed', dataMessage, expireUpdate); + window.log.warn('Building Sync Expire Timer Message failed', dataMessage, expireUpdate); } } return buildSyncVisibleMessage(identifier, dataMessage, timestamp, syncTarget); diff --git a/ts/util/expiringMessages.ts b/ts/util/expiringMessages.ts index bdc6e7509..17141087f 100644 --- a/ts/util/expiringMessages.ts +++ b/ts/util/expiringMessages.ts @@ -235,8 +235,8 @@ export function setExpirationStartTimestamp( // TODO legacy messages support will be removed in a future release if (timestamp) { - window.log.info( - `WIP: We compare 2 timestamps for a disappear ${ + window.log.debug( + `We compare 2 timestamps for a disappear ${ isLegacyMode ? 'legacy' : mode === 'deleteAfterRead' ? 'after read' : 'after send' } message: \expirationStartTimestamp `, new Date(expirationStartTimestamp).toLocaleTimeString(), @@ -248,22 +248,22 @@ export function setExpirationStartTimestamp( // TODO legacy messages support will be removed in a future release if (mode === 'deleteAfterRead') { - window.log.info( - `WIP: We set the start timestamp for a ${ + window.log.debug( + `We set the start timestamp for a ${ isLegacyMode ? 'legacy ' : '' }delete after read message to ${new Date(expirationStartTimestamp).toLocaleTimeString()}` ); } else if (mode === 'deleteAfterSend') { - window.log.info( - `WIP: We set the start timestamp for a ${ + window.log.debug( + `We set the start timestamp for a ${ isLegacyMode ? 'legacy ' : '' }delete after send message to ${new Date(expirationStartTimestamp).toLocaleTimeString()}` ); } else if (mode === 'off') { - window.log.info(`WIP: Disappearing message mode "${mode}" set. We can safely ignore this.`); + window.log.debug(`Disappearing message mode "${mode}" set. We can safely ignore this.`); expirationStartTimestamp = undefined; } else { - window.log.info(`WIP: Invalid disappearing message mode "${mode}" set. Ignoring`); + window.log.debug(`Invalid disappearing message mode "${mode}" set. Ignoring`); expirationStartTimestamp = undefined; } @@ -332,7 +332,7 @@ export async function checkForExpireUpdate( isDisappearingMessagesV2Released && (isLegacyDataMessage || isLegacyConversationSettingMessage || shouldDisappearButIsntMessage) ) { - window.log.info('WIP: received a legacy disappearing message after v2 was released.'); + window.log.warn('Received a legacy disappearing message after v2 was released.', content); expirationType = convoToUpdate.get('expirationType'); expirationTimer = convoToUpdate.get('expireTimer'); } @@ -346,8 +346,6 @@ export async function checkForExpireUpdate( isDisappearingMessagesV2Released, }; - // window.log.info('WIP: checkForExpireUpdate', expireUpdate); - return expireUpdate; } @@ -358,9 +356,7 @@ export function handleExpireUpdate( expireUpdate: DisappearingMessageUpdate ) { if (converationModel.isPublic()) { - window.log.warning( - "WIP: updateExpireTimer() Disappearing messages aren't supported in communities" - ); + window.log.warn("updateExpireTimer() Disappearing messages aren't supported in communities"); return messageModel; } diff --git a/ts/util/releaseFeature.ts b/ts/util/releaseFeature.ts index 97c8d1422..e809c5283 100644 --- a/ts/util/releaseFeature.ts +++ b/ts/util/releaseFeature.ts @@ -36,9 +36,7 @@ export async function checkIsFeatureReleased(featureName: string): Promise Date: Wed, 26 Apr 2023 16:07:13 +1000 Subject: [PATCH 05/14] fix: updated comment for when to remove legacy code --- ts/receiver/queuedJob.ts | 2 +- ts/session/group/closed-group.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index b25003066..42f0c0601 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -198,7 +198,7 @@ export type RegularMessageType = Pick< | 'reaction' | 'profile' | 'profileKey' - // TODO Will be removed 2 weeks after release + // TODO legacy messages support will be removed in a future release | 'expireTimer' > & { isRegularMessage: true }; diff --git a/ts/session/group/closed-group.ts b/ts/session/group/closed-group.ts index 3b0fc9c62..105c86561 100644 --- a/ts/session/group/closed-group.ts +++ b/ts/session/group/closed-group.ts @@ -291,7 +291,7 @@ export async function updateOrCreateClosedGroup(details: GroupInfo) { } await conversation.updateExpireTimer({ - // TODO clean up 2 weeks after release? + // TODO legacy messages support will be removed in a future release // TODO What are we cleaning? providedExpirationType: expirationType || 'deleteAfterSend', providedExpireTimer: expireTimer, From c33e471bfc2d8b9ffb3e175fe7334923ef45d508 Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 16:21:37 +1000 Subject: [PATCH 06/14] fix: in clearinbox check in memory for conversation instead of db lookup this is more performent --- ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts b/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts index f88be9bc3..dc17e30a4 100644 --- a/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts +++ b/ts/session/apis/open_group_api/sogsv3/sogsV3ClearInbox.ts @@ -1,5 +1,4 @@ import AbortController from 'abort-controller'; -import { Data } from '../../../../data/data'; import { OpenGroupRequestCommonType } from '../opengroupV2/ApiUtil'; import { getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils'; import { @@ -8,6 +7,7 @@ import { OpenGroupBatchRow, sogsBatchSend, } from './sogsV3BatchPoll'; +import { getConversationController } from '../../../conversations'; type OpenGroupClearInboxResponse = { deleted: number; @@ -17,10 +17,10 @@ export const clearInbox = async (roomInfos: OpenGroupRequestCommonType): Promise let success = false; const conversationId = getOpenGroupV2ConversationId(roomInfos.serverUrl, roomInfos.roomId); - const conversation = await Data.getConversationById(conversationId); + const conversation = getConversationController().get(conversationId); if (!conversation) { - window.log.warn('clearInbox Matching conversation not found in db'); + throw new Error(`clearInbox Matching conversation not found in db ${conversationId}`); } else { const options: Array = [ { From dde244d7191b7fef35d9ee7b5e68843a7efc133f Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 16:27:42 +1000 Subject: [PATCH 07/14] fix: improved comment explaining how seen messages are expired --- ts/session/apis/snode_api/swarmPolling.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ts/session/apis/snode_api/swarmPolling.ts b/ts/session/apis/snode_api/swarmPolling.ts index 3784abdb6..f6778331a 100644 --- a/ts/session/apis/snode_api/swarmPolling.ts +++ b/ts/session/apis/snode_api/swarmPolling.ts @@ -360,8 +360,7 @@ export class SwarmPolling { const newMessages = messages.filter((m: Message) => !dupHashes.includes(m.hash)); if (newMessages.length) { - // TODO explain this better - // NOTE setting expiresAt here will trigger disappearing messages via the listener + // NOTE setting expiresAt will trigger the global function destroyExpiredMessages() on it's next interval const newHashes = newMessages.map((m: Message) => ({ expiresAt: m.expiration, hash: m.hash, From b3297ab8168eee7a2ff9be5fa1523bed08e7ba12 Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 16:33:46 +1000 Subject: [PATCH 08/14] fix: remove isFinite comment --- ts/session/messages/outgoing/ExpirableMessage.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ts/session/messages/outgoing/ExpirableMessage.ts b/ts/session/messages/outgoing/ExpirableMessage.ts index 2ae95b14b..ce11e1aa2 100644 --- a/ts/session/messages/outgoing/ExpirableMessage.ts +++ b/ts/session/messages/outgoing/ExpirableMessage.ts @@ -33,7 +33,6 @@ export class ExpirableMessage extends ContentMessage { : this.expirationType === 'legacy' ? SignalService.Content.ExpirationType.UNKNOWN : undefined, - // TODO could use isFinite? expirationTimer: this.expireTimer && this.expireTimer > -1 ? this.expireTimer : undefined, }); } From 90e29c7b74898e795729946606f881fb98e6a1c1 Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 16:56:02 +1000 Subject: [PATCH 09/14] fix: updated groupId comment for future work --- .../outgoing/visibleMessage/ClosedGroupVisibleMessage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts b/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts index 6016f08cb..844aafd89 100644 --- a/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/ClosedGroupVisibleMessage.ts @@ -8,8 +8,8 @@ import { } from '../controlMessage/group/ClosedGroupMessage'; interface ClosedGroupVisibleMessageParams extends ClosedGroupMessageParams { - // TODO Do we need strings? - // groupId: string | PubKey; + // TODO Refactor closed groups typings so groupId is PubKey only + // groupId: PubKey; chatMessage: VisibleMessage; } From f9c9702d122041bedf294f656769605e4ebb4eab Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 16:57:43 +1000 Subject: [PATCH 10/14] fix: clean disable-next-line on handleMessageSentSuccess --- ts/session/sending/MessageSentHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/session/sending/MessageSentHandler.ts b/ts/session/sending/MessageSentHandler.ts index 313673027..58c2bc580 100644 --- a/ts/session/sending/MessageSentHandler.ts +++ b/ts/session/sending/MessageSentHandler.ts @@ -41,7 +41,7 @@ async function handlePublicMessageSentSuccess( } } -// tslint:disable-next-line:// tslint:disable-next-line: cyclomatic-complexity +// tslint:disable-next-line: cyclomatic-complexity async function handleMessageSentSuccess( sentMessage: RawMessage, effectiveTimestamp: number, From ec3f62d12fab6df008f0fd694b8a65d9d36874da Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 17:02:14 +1000 Subject: [PATCH 11/14] fix: updated child types from PropsExpiringMessges use type and the ampersand operator instead of the interface with extends for better consistency with the rest of the code base --- ts/state/ducks/conversations.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 8205fc521..d0cc15300 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -23,11 +23,11 @@ import { export type CallNotificationType = 'missed-call' | 'started-call' | 'answered-a-call'; -export interface PropsForCallNotification extends PropsForExpiringMessage { +export type PropsForCallNotification = PropsForExpiringMessage & { notificationType: CallNotificationType; receivedAt: number; isUnread: boolean; -} +}; export type MessageModelPropsWithoutConvoProps = { propsForMessage: PropsForMessageWithoutConvoProps; @@ -84,7 +84,7 @@ export type PropsForExpiringMessage = { isExpired?: boolean; }; -export interface PropsForExpirationTimer extends PropsForExpiringMessage { +export type PropsForExpirationTimer = PropsForExpiringMessage & { expirationType: DisappearingMessageConversationType; timespan: string; disabled: boolean; @@ -97,7 +97,7 @@ export interface PropsForExpirationTimer extends PropsForExpiringMessage { messageId: string; isUnread: boolean; receivedAt: number | undefined; -} +}; export type PropsForGroupUpdateGeneral = { type: 'general'; @@ -130,21 +130,21 @@ export type PropsForGroupUpdateType = | PropsForGroupUpdateName | PropsForGroupUpdateLeft; -export interface PropsForGroupUpdate extends PropsForExpiringMessage { +export type PropsForGroupUpdate = PropsForExpiringMessage & { change: PropsForGroupUpdateType; messageId: string; receivedAt: number | undefined; isUnread: boolean; -} +}; -export interface PropsForGroupInvitation extends PropsForExpiringMessage { +export type PropsForGroupInvitation = PropsForExpiringMessage & { serverName: string; url: string; acceptUrl: string; messageId: string; receivedAt?: number; isUnread: boolean; -} +}; export type PropsForAttachment = { id: number; From 42924b0c5441c7c13325421bf021c37f2d7024f6 Mon Sep 17 00:00:00 2001 From: William Grant Date: Wed, 26 Apr 2023 17:58:40 +1000 Subject: [PATCH 12/14] fix: use storage put instead of data methods so that we can track in redux added a fix in OverlayDisappearingMessages so when v2 turns on an and the app is running a migration occurs --- .../OverlayDisappearingMessages.tsx | 21 ++++++++++++++++++- ts/util/releaseFeature.ts | 16 +++++--------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ts/components/conversation/right-panel/overlay/disappearing-messages/OverlayDisappearingMessages.tsx b/ts/components/conversation/right-panel/overlay/disappearing-messages/OverlayDisappearingMessages.tsx index ea2aa25d8..9dd428c61 100644 --- a/ts/components/conversation/right-panel/overlay/disappearing-messages/OverlayDisappearingMessages.tsx +++ b/ts/components/conversation/right-panel/overlay/disappearing-messages/OverlayDisappearingMessages.tsx @@ -13,11 +13,15 @@ import { getSelectedConversationExpirationSettings, getSelectedConversationKey, } from '../../../../../state/selectors/conversations'; -import { DEFAULT_TIMER_OPTION } from '../../../../../util/expiringMessages'; +import { + DEFAULT_TIMER_OPTION, + DisappearingMessageConversationType, +} from '../../../../../util/expiringMessages'; import { useTimerOptionsByMode } from '../../../../../hooks/useParamSelector'; import { Header } from './Header'; import { DisappearingModes } from './DisappearingModes'; import { TimeOptions } from './TimeOptions'; +import { getConversationController } from '../../../../../session/conversations'; const StyledScrollContainer = styled.div` width: 100%; @@ -113,6 +117,21 @@ export const OverlayDisappearingMessages = (props: OverlayDisappearingMessagesPr } }, [convoProps.expirationType, convoProps.expireTimer]); + // TODO legacy messages support will be removed in a future + useEffect(() => { + if (unlockNewModes && modeSelected === 'legacy' && selectedConversationKey) { + const convo = getConversationController().get(selectedConversationKey); + if (convo) { + let defaultExpirationType: DisappearingMessageConversationType = 'deleteAfterRead'; + if (convo.isMe() || convo.isMediumGroup()) { + defaultExpirationType = 'deleteAfterSend'; + } + convo.set('expirationType', defaultExpirationType); + setModeSelected(defaultExpirationType); + } + } + }, [unlockNewModes, selectedConversationKey, modeSelected]); + return ( diff --git a/ts/util/releaseFeature.ts b/ts/util/releaseFeature.ts index e809c5283..1e111a797 100644 --- a/ts/util/releaseFeature.ts +++ b/ts/util/releaseFeature.ts @@ -1,4 +1,4 @@ -import { Data } from '../data/data'; +import { Storage } from './storage'; // TODO update to agreed value between platforms const featureReleaseTimestamp = 1706778000000; // unix 01/02/2024 09:00 @@ -15,10 +15,10 @@ export function resetFeatureReleasedCachedValue() { export async function getIsFeatureReleased(): Promise { if (isFeatureReleased === undefined) { // read values from db and cache them as it looks like we did not - const oldIsFeatureReleased = (await Data.getItemById('featureReleased'))?.value; + const oldIsFeatureReleased = Boolean(Storage.get('featureReleased')); // values do not exist in the db yet. Let's store false for now in the db and update our cached value. if (oldIsFeatureReleased === undefined) { - await Data.createOrUpdateItem({ id: 'featureReleased', value: false }); + await Storage.put('featureReleased', false); isFeatureReleased = false; } else { isFeatureReleased = oldIsFeatureReleased; @@ -37,20 +37,14 @@ export async function checkIsFeatureReleased(featureName: string): Promise Date: Wed, 26 Apr 2023 18:02:44 +1000 Subject: [PATCH 13/14] fix: pass yarn ready --- ts/components/dialog/DeleteAccountModal.tsx | 2 +- ts/session/apis/snode_api/expire.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ts/components/dialog/DeleteAccountModal.tsx b/ts/components/dialog/DeleteAccountModal.tsx index f8ef34401..053b8389c 100644 --- a/ts/components/dialog/DeleteAccountModal.tsx +++ b/ts/components/dialog/DeleteAccountModal.tsx @@ -71,7 +71,7 @@ async function deleteEverythingAndNetworkData() { throw Error(`Failed to clear inbox for ${roomInfo.conversationId}`); } } catch (error) { - window.log.info(`DeleteAccount =>`, error); + window.log.info('DeleteAccount =>', error); continue; } } diff --git a/ts/session/apis/snode_api/expire.ts b/ts/session/apis/snode_api/expire.ts index cf405700a..0cf22e37b 100644 --- a/ts/session/apis/snode_api/expire.ts +++ b/ts/session/apis/snode_api/expire.ts @@ -91,7 +91,7 @@ async function verifySignature({ const verificationString = `${pubkey.key}${expiryApplied}${hashes.join('')}`; const verificationData = StringUtils.encode(verificationString, 'utf8'); - window.log.debug(`verifySignature verificationString`, verificationString); + window.log.debug('verifySignature verificationString', verificationString); const sodium = await getSodiumRenderer(); try { @@ -192,7 +192,7 @@ async function expireOnNodes(targetNode: Snode, params: ExpireParams) { parsed.swarm, params.messages ); - window.log.debug(`expireOnNodes attempt complete. Here are the results`, expirationResults); + window.log.debug('expireOnNodes attempt complete. Here are the results', expirationResults); return true; } catch (e) { From c759eed0d86eb5556c6a4d555fad2413b71e3c3f Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 27 Apr 2023 11:57:16 +1000 Subject: [PATCH 14/14] fix: check if path exists for deleted attachment instead of trying to read that data this is more performant since it should be deleted --- ts/types/MessageAttachment.ts | 15 ++++++++------- ts/types/attachments/migrations.ts | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/ts/types/MessageAttachment.ts b/ts/types/MessageAttachment.ts index 199d33908..683efd24f 100644 --- a/ts/types/MessageAttachment.ts +++ b/ts/types/MessageAttachment.ts @@ -10,6 +10,7 @@ import { autoOrientJPEGAttachment, captureDimensionsAndScreenshot, deleteData, + deleteDataSuccessful, loadData, replaceUnicodeV2, } from './attachments/migrations'; @@ -30,14 +31,14 @@ export const deleteExternalMessageFiles = async (message: { await Promise.all(attachments.map(deleteData)); // test that the files were deleted successfully try { - await Promise.all( - attachments.map(async (attachment: { path: string; thumbnail: any; screenshot: any }) => { - await readAttachmentData(attachment.path); - }) - ); - window.log.info('[deleteExternalMessageFiles]: Failed to delete attachments for', message); + let results = await Promise.allSettled(attachments.map(deleteDataSuccessful)); + results = results.filter(result => result.status === 'rejected'); + + if (results.length) { + throw Error; + } } catch (err) { - // If we fail to read the path then we know we deleted successfully + window.log.warn('[deleteExternalMessageFiles]: Failed to delete attachments for', message); } } diff --git a/ts/types/attachments/migrations.ts b/ts/types/attachments/migrations.ts index 44221d420..0624b10e9 100644 --- a/ts/types/attachments/migrations.ts +++ b/ts/types/attachments/migrations.ts @@ -2,6 +2,7 @@ import * as GoogleChrome from '../../../ts/util/GoogleChrome'; import * as MIME from '../../../ts/types/MIME'; import { toLogFormat } from './Errors'; import { arrayBufferToBlob, blobToArrayBuffer } from 'blob-util'; +import fse from 'fs-extra'; import { isString } from 'lodash'; import { @@ -170,6 +171,27 @@ export const deleteData = async (attachment: { path: string; thumbnail: any; scr return attachment; }; +export const deleteDataSuccessful = async (attachment: { + path: string; + thumbnail: any; + screenshot: any; +}) => { + const errorMessage = `deleteDataSuccessful: Deletion failed for attachment ${attachment.path}`; + return fse.pathExists(attachment.path, (err, exists) => { + if (err) { + return Promise.reject(`${errorMessage} ${err}`); + } + + // Note we want to confirm the path no longer exists + if (exists) { + return Promise.reject(errorMessage); + } + + window.log.debug(`deleteDataSuccessful: Deletion succeeded for attachment ${attachment.path}`); + return true; + }); +}; + type CaptureDimensionType = { contentType: string; path: string }; export const captureDimensionsAndScreenshot = async (