From 28e1d9fe44fa5eccdfcaef9503cb182c5dc92330 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 10 Feb 2025 13:54:02 +1100 Subject: [PATCH] fix: cleanup releasedFeature slice --- preload.js | 2 +- .../useRefreshReleasedFeaturesTimestamp.ts | 4 +-- ts/session/apis/snode_api/swarmPolling.ts | 4 +-- ts/state/ducks/metaGroups.ts | 13 +++++----- ts/state/ducks/releasedFeatures.tsx | 16 +++++++++--- ts/state/selectors/releasedFeatures.ts | 26 +++++++++---------- .../browser/libsession_worker_interface.ts | 4 +++ 7 files changed, 41 insertions(+), 28 deletions(-) diff --git a/preload.js b/preload.js index c1d294df8..052724b38 100644 --- a/preload.js +++ b/preload.js @@ -40,7 +40,7 @@ window.saveLog = additionalText => ipc.send('save-debug-log', additionalText); window.sessionFeatureFlags = { useOnionRequests: true, useTestNet: isTestNet() || isTestIntegration(), - useClosedGroupV2: true, // TODO DO NOT MERGE Remove after QA + useClosedGroupV2: false, // TODO DO NOT MERGE Remove after QA forceLegacyGroupsDeprecated: false, // TODO DO NOT MERGE Remove after QA useClosedGroupV2QAButtons: true, // TODO DO NOT MERGE Remove after QA replaceLocalizedStringsWithKeys: false, diff --git a/ts/hooks/useRefreshReleasedFeaturesTimestamp.ts b/ts/hooks/useRefreshReleasedFeaturesTimestamp.ts index 8ffc21135..6c516be7a 100644 --- a/ts/hooks/useRefreshReleasedFeaturesTimestamp.ts +++ b/ts/hooks/useRefreshReleasedFeaturesTimestamp.ts @@ -4,7 +4,7 @@ import { DURATION } from '../session/constants'; import { updateLegacyGroupDeprecationTimestampUpdatedAt } from '../state/ducks/releasedFeatures'; import { NetworkTime } from '../util/NetworkTime'; import { PubKey } from '../session/types'; -import { areLegacyGroupsDeprecatedYet } from '../state/selectors/releasedFeatures'; +import { areLegacyGroupsReadOnly } from '../state/selectors/releasedFeatures'; import { useSelectedConversationKey } from '../state/selectors/selectedConversation'; import type { StateType } from '../state/reducer'; import { ConversationTypeEnum } from '../models/types'; @@ -27,7 +27,7 @@ export function getDisableLegacyGroupDeprecatedActions(state: StateType, convoId if (!selectedConvoIsGroup) { return false; } - const legacyGroupDeprecated = areLegacyGroupsDeprecatedYet(); + const legacyGroupDeprecated = areLegacyGroupsReadOnly(); // here we have // - a valid convoId // - that starts with 05 diff --git a/ts/session/apis/snode_api/swarmPolling.ts b/ts/session/apis/snode_api/swarmPolling.ts index b483ba9c6..45c1ced91 100644 --- a/ts/session/apis/snode_api/swarmPolling.ts +++ b/ts/session/apis/snode_api/swarmPolling.ts @@ -58,7 +58,7 @@ import { } from './types'; import { ConversationTypeEnum } from '../../../models/types'; import { Snode } from '../../../data/types'; -import { areLegacyGroupsDeprecatedYetOutsideRedux } from '../../../state/selectors/releasedFeatures'; +import { areLegacyGroupsReadOnlyOutsideRedux } from '../../../state/selectors/releasedFeatures'; const minMsgCountShouldRetry = 95; /** @@ -297,7 +297,7 @@ export class SwarmPolling { .filter(m => !allGroupsInWrapper.some(w => w.pubkeyHex === m.pubkey.key)) .map(entryToKey); - const legacyGroupDeprecatedDisabled = areLegacyGroupsDeprecatedYetOutsideRedux(); + const legacyGroupDeprecatedDisabled = areLegacyGroupsReadOnlyOutsideRedux(); const allLegacyGroupsTracked = legacyGroupDeprecatedDisabled ? [] diff --git a/ts/state/ducks/metaGroups.ts b/ts/state/ducks/metaGroups.ts index ff8d3a482..bf6fcc97c 100644 --- a/ts/state/ducks/metaGroups.ts +++ b/ts/state/ducks/metaGroups.ts @@ -59,8 +59,6 @@ export type GroupState = { members: Record>; memberChangesFromUIPending: boolean; nameChangesFromUIPending: boolean; - membersInviteSending: Record>; - membersPromoteSending: Record>; // those are group creation-related fields creationFromUIPending: boolean; @@ -74,8 +72,6 @@ export const initialGroupState: GroupState = { creationFromUIPending: false, memberChangesFromUIPending: false, nameChangesFromUIPending: false, - membersInviteSending: {}, - membersPromoteSending: {}, creationMembersSelected: [], creationGroupName: '', }; @@ -406,6 +402,10 @@ const loadMetaDumpsFromDB = createAsyncThunk( metaDumped: data, }); + // If we were sending to that member an invite/promote, we won't auto retry. + // We need to reset the sending state (on load from disk) so that the user can resend manually if needed + await MetaGroupWrapperActions.memberResetAllSendingState(groupPk); + const infos = await MetaGroupWrapperActions.infoGet(groupPk); const members = await MetaGroupWrapperActions.memberGetAll(groupPk); @@ -680,6 +680,9 @@ async function handleMemberAddedFromUI({ updateMessagesToPush.push(groupChange); } } + await LibSessionUtil.saveDumpsToDb(groupPk); + refreshConvosModelProps([groupPk]); + window.inboxStore?.dispatch(refreshGroupDetailsFromWrapper({ groupPk }) as any); const extraStoreRequests = await StoreGroupRequestFactory.makeGroupMessageSubRequest( updateMessagesToPush, @@ -1281,8 +1284,6 @@ const metaGroupSlice = createSlice({ ) { delete state.infos[payload.groupPk]; delete state.members[payload.groupPk]; - delete state.membersInviteSending[payload.groupPk]; - delete state.membersPromoteSending[payload.groupPk]; }, addSelectedGroupMember( state: GroupState, diff --git a/ts/state/ducks/releasedFeatures.tsx b/ts/state/ducks/releasedFeatures.tsx index 540afd694..666d58b37 100644 --- a/ts/state/ducks/releasedFeatures.tsx +++ b/ts/state/ducks/releasedFeatures.tsx @@ -1,26 +1,31 @@ import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; import { DURATION } from '../../session/constants'; +import { NetworkTime } from '../../util/NetworkTime'; // update this to be when we ship desktop groups REMOVE AFTER QA -const GROUP_DESKTOP_RELEASE = 1767225600 * 1000; // currently Thursday, January 1, 2026 12:00:00 AM +const GROUP_DESKTOP_RELEASE = 1767225600 * 1000; // currently 1st Jan 2026 /** - * 1 week after the release of groups (more or less), we force new groups to be created as new groups + * 3+7 days after the release of groups (more or less), we force new groups to be created as new groups */ -export const START_CREATE_NEW_GROUP_TIMESTAMP_MS = GROUP_DESKTOP_RELEASE + DURATION.WEEKS * 1; +const START_CREATE_NEW_GROUP_TIMESTAMP_MS = GROUP_DESKTOP_RELEASE + DURATION.DAYS * 10; /** * 2 weeks after `START_CREATE_NEW_GROUP_TIMESTAMP_MS`, we mark legacy groups readonly */ -export const LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS = +const LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS = START_CREATE_NEW_GROUP_TIMESTAMP_MS + DURATION.WEEKS * 2; export interface ReleasedFeaturesState { legacyGroupDeprecationTimestampRefreshAtMs: number; + canCreateGroupV2: boolean; + legacyGroupsReadOnly: boolean; } export const initialReleasedFeaturesState = { legacyGroupDeprecationTimestampRefreshAtMs: Date.now(), + canCreateGroupV2: Date.now() >= START_CREATE_NEW_GROUP_TIMESTAMP_MS, + legacyGroupsReadOnly: Date.now() >= LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS, }; const releasedFeaturesSlice = createSlice({ @@ -29,6 +34,9 @@ const releasedFeaturesSlice = createSlice({ reducers: { updateLegacyGroupDeprecationTimestampUpdatedAt: (state, action: PayloadAction) => { state.legacyGroupDeprecationTimestampRefreshAtMs = action.payload; + state.canCreateGroupV2 = NetworkTime.now() >= START_CREATE_NEW_GROUP_TIMESTAMP_MS; + state.legacyGroupsReadOnly = NetworkTime.now() >= LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS; + return state; }, }, }); diff --git a/ts/state/selectors/releasedFeatures.ts b/ts/state/selectors/releasedFeatures.ts index ddee21c73..3d5ccf243 100644 --- a/ts/state/selectors/releasedFeatures.ts +++ b/ts/state/selectors/releasedFeatures.ts @@ -1,29 +1,29 @@ import { useSelector } from 'react-redux'; -import { NetworkTime } from '../../util/NetworkTime'; -import { - LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS, - START_CREATE_NEW_GROUP_TIMESTAMP_MS, -} from '../ducks/releasedFeatures'; +import type { StateType } from '../reducer'; -export const areLegacyGroupsDeprecatedYet = (): boolean => { - const theyAreDeprecated = NetworkTime.now() >= LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS; +const areGroupsCreatedAsNewGroupsYet = (): boolean => { + const shouldCreateNewGroups = !!window.inboxStore?.getState()?.releasedFeatures.canCreateGroupV2; - return window.sessionFeatureFlags.forceLegacyGroupsDeprecated || theyAreDeprecated; + return window.sessionFeatureFlags.useClosedGroupV2 || shouldCreateNewGroups; }; -const areGroupsCreatedAsNewGroupsYet = (): boolean => { - const shouldCreateNewGroups = NetworkTime.now() >= START_CREATE_NEW_GROUP_TIMESTAMP_MS; +export const areLegacyGroupsReadOnly = (): boolean => { + const theyAre = !!window.inboxStore?.getState()?.releasedFeatures.legacyGroupsReadOnly; - return window.sessionFeatureFlags.useClosedGroupV2 || shouldCreateNewGroups; + return window.sessionFeatureFlags.forceLegacyGroupsDeprecated || theyAre; }; export function useAreGroupsCreatedAsNewGroupsYet() { + useSelector((state: StateType) => state.releasedFeatures.canCreateGroupV2); return useSelector(areGroupsCreatedAsNewGroupsYet); } -export function areLegacyGroupsDeprecatedYetOutsideRedux() { +/** + * @returns true if legacy groups should not be polled anymore + */ +export function areLegacyGroupsReadOnlyOutsideRedux() { if (!window.inboxStore) { return false; } - return areLegacyGroupsDeprecatedYet(); + return areLegacyGroupsReadOnly(); } diff --git a/ts/webworker/workers/browser/libsession_worker_interface.ts b/ts/webworker/workers/browser/libsession_worker_interface.ts index b178ffc5c..1e74e350f 100644 --- a/ts/webworker/workers/browser/libsession_worker_interface.ts +++ b/ts/webworker/workers/browser/libsession_worker_interface.ts @@ -674,6 +674,10 @@ export const MetaGroupWrapperActions: MetaGroupWrapperActionsCalls = { pubkeyHex, profilePicture, ]) as Promise>, + memberResetAllSendingState: async (groupPk: GroupPubkeyType) => + callLibSessionWorker([`MetaGroupConfig-${groupPk}`, 'memberResetAllSendingState']) as Promise< + ReturnType + >, /** GroupKeys wrapper specific actions */ keyRekey: async (groupPk: GroupPubkeyType) =>