From 010801b78ca30c597f861c887aab59c1f350528a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 Feb 2025 16:12:21 +1100 Subject: [PATCH 1/5] fix: allow to switch from create group/groupv2 based on a ts.flag --- .../leftpane/LeftPaneMessageSection.tsx | 9 ++++----- .../choose-action/OverlayChooseAction.tsx | 17 +++++++++++++++++ ts/state/ducks/releasedFeatures.tsx | 8 +++++++- ts/state/selectors/releasedFeatures.ts | 16 +++++++++++++++- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/ts/components/leftpane/LeftPaneMessageSection.tsx b/ts/components/leftpane/LeftPaneMessageSection.tsx index 249dcfb22..8381dd83f 100644 --- a/ts/components/leftpane/LeftPaneMessageSection.tsx +++ b/ts/components/leftpane/LeftPaneMessageSection.tsx @@ -20,6 +20,7 @@ import { OverlayInvite } from './overlay/OverlayInvite'; import { OverlayMessage } from './overlay/OverlayMessage'; import { OverlayMessageRequest } from './overlay/OverlayMessageRequest'; import { OverlayChooseAction } from './overlay/choose-action/OverlayChooseAction'; +import { useAreGroupsCreatedAsNewGroupsYet } from '../../state/selectors/releasedFeatures'; const StyledLeftPaneContent = styled.div` display: flex; @@ -40,17 +41,15 @@ const StyledConversationListContent = styled.div` const ClosableOverlay = () => { const leftOverlayMode = useSelector(getLeftOverlayMode); + const shouldCreateNewGroups = useAreGroupsCreatedAsNewGroupsYet(); + switch (leftOverlayMode) { case 'choose-action': return ; case 'open-group': return ; case 'closed-group': - return window.sessionFeatureFlags.useClosedGroupV2 ? ( - - ) : ( - - ); + return shouldCreateNewGroups ? : ; case 'message': return ; case 'message-requests': diff --git a/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx b/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx index 6b6badd30..b589c4b5a 100644 --- a/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx +++ b/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx @@ -3,15 +3,19 @@ import { useCallback, useEffect } from 'react'; import { isEmpty, isString } from 'lodash'; import { useDispatch } from 'react-redux'; import useKey from 'react-use/lib/useKey'; +import useUpdate from 'react-use/lib/useUpdate'; import { resetLeftOverlayMode, setLeftOverlayMode } from '../../../../state/ducks/section'; import { SpacerSM } from '../../../basic/Text'; import { StyledLeftPaneOverlay } from '../OverlayMessage'; import { ActionRow, StyledActionRowContainer } from './ActionRow'; import { ContactsListWithBreaks } from './ContactsListWithBreaks'; import { groupInfoActions } from '../../../../state/ducks/metaGroups'; +import { SessionToggle } from '../../../basic/SessionToggle'; export const OverlayChooseAction = () => { const dispatch = useDispatch(); + const forceRefresh = useUpdate(); + function closeOverlay() { dispatch(resetLeftOverlayMode()); } @@ -78,6 +82,19 @@ export const OverlayChooseAction = () => { onClick={openNewMessage} dataTestId="chooser-new-conversation-button" /> + {window.sessionFeatureFlags.useClosedGroupV2QAButtons ? ( + + Create group v2?{' '} + { + window.sessionFeatureFlags.useClosedGroupV2 = + !window.sessionFeatureFlags.useClosedGroupV2; + forceRefresh(); + }} + /> + + ) : null} { const theyAreDeprecated = NetworkTime.now() >= LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS; @@ -7,6 +11,16 @@ export const areLegacyGroupsDeprecatedYet = (): boolean => { return window.sessionFeatureFlags.forceLegacyGroupsDeprecated || theyAreDeprecated; }; +const areGroupsCreatedAsNewGroupsYet = (): boolean => { + const shouldCreateNewGroups = NetworkTime.now() >= START_CREATE_NEW_GROUP_TIMESTAMP_MS; + + return window.sessionFeatureFlags.useClosedGroupV2 || shouldCreateNewGroups; +}; + +export function useAreGroupsCreatedAsNewGroupsYet() { + return useSelector(areGroupsCreatedAsNewGroupsYet); +} + export function areLegacyGroupsDeprecatedYetOutsideRedux() { if (!window.inboxStore) { return false; From ccd41f6bdc72de909707a9d8770499ecde468ed7 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 Feb 2025 16:39:41 +1100 Subject: [PATCH 2/5] fix: hide banner until we can create new groups --- ts/components/conversation/SessionConversation.tsx | 5 ++++- .../conversation/header/ConversationHeader.tsx | 4 +++- ts/state/ducks/releasedFeatures.tsx | 11 ++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ts/components/conversation/SessionConversation.tsx b/ts/components/conversation/SessionConversation.tsx index e0623aba2..17d72465b 100644 --- a/ts/components/conversation/SessionConversation.tsx +++ b/ts/components/conversation/SessionConversation.tsx @@ -69,6 +69,7 @@ import { useSelectedWeAreAdmin, } from '../../state/selectors/selectedConversation'; import { useSelectedDisableLegacyGroupDeprecatedActions } from '../../hooks/useRefreshReleasedFeaturesTimestamp'; +import { useAreGroupsCreatedAsNewGroupsYet } from '../../state/selectors/releasedFeatures'; const DEFAULT_JPEG_QUALITY = 0.85; @@ -675,6 +676,8 @@ function OutdatedLegacyGroupBanner() { const isLegacyGroup = !isPrivate && !isPublic && selectedConversationKey && selectedConversationKey.startsWith('05'); + const newGroupsCanBeCreated = useAreGroupsCreatedAsNewGroupsYet(); + // FIXME change the date here. Remove after QA const text = deprecatedLegacyGroups ? localize( @@ -686,7 +689,7 @@ function OutdatedLegacyGroupBanner() { .withArgs({ date: '[Date]' }) .toString(); - return isLegacyGroup ? ( + return isLegacyGroup && newGroupsCanBeCreated ? ( { diff --git a/ts/components/conversation/header/ConversationHeader.tsx b/ts/components/conversation/header/ConversationHeader.tsx index fe4433d39..935c8fdce 100644 --- a/ts/components/conversation/header/ConversationHeader.tsx +++ b/ts/components/conversation/header/ConversationHeader.tsx @@ -25,6 +25,7 @@ import { groupInfoActions } from '../../../state/ducks/metaGroups'; import { updateConfirmModal } from '../../../state/ducks/modalDialog'; import { setLeftOverlayMode } from '../../../state/ducks/section'; import { SessionButtonColor, SessionButton } from '../../basic/SessionButton'; +import { useAreGroupsCreatedAsNewGroupsYet } from '../../../state/selectors/releasedFeatures'; export const ConversationHeaderWithDetails = () => { const isSelectionMode = useIsMessageSelectionMode(); @@ -121,8 +122,9 @@ function RecreateGroupButton() { const weAreAdmin = useSelectedWeAreAdmin(); const showRecreateGroupModal = useShowRecreateModal(); + const newGroupsCanBeCreated = useAreGroupsCreatedAsNewGroupsYet(); - if (!isLegacyGroup || !weAreAdmin) { + if (!isLegacyGroup || !weAreAdmin || !newGroupsCanBeCreated) { return null; } diff --git a/ts/state/ducks/releasedFeatures.tsx b/ts/state/ducks/releasedFeatures.tsx index ed83a1c7f..540afd694 100644 --- a/ts/state/ducks/releasedFeatures.tsx +++ b/ts/state/ducks/releasedFeatures.tsx @@ -4,11 +4,16 @@ import { DURATION } from '../../session/constants'; // 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 -// FIXME update this to the correct timestamp REMOVE AFTER QA +/** + * 1 week 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; -// FIXME update this to the correct timestamp REMOVE AFTER QA -export const LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS = GROUP_DESKTOP_RELEASE + DURATION.WEEKS * 3; +/** + * 2 weeks after `START_CREATE_NEW_GROUP_TIMESTAMP_MS`, we mark legacy groups readonly + */ +export const LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS = + START_CREATE_NEW_GROUP_TIMESTAMP_MS + DURATION.WEEKS * 2; export interface ReleasedFeaturesState { legacyGroupDeprecationTimestampRefreshAtMs: number; From 28e1d9fe44fa5eccdfcaef9503cb182c5dc92330 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 10 Feb 2025 13:54:02 +1100 Subject: [PATCH 3/5] 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) => From 634cd08109425a228fa633bb04c08f1dfd4a4385 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 10 Feb 2025 14:08:21 +1100 Subject: [PATCH 4/5] chore: bump libsession to 0.4.16 --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0a1e21efd..7035cc886 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "fs-extra": "9.0.0", "glob": "10.3.10", "image-type": "^4.1.0", - "libsession_util_nodejs": "https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.15/libsession_util_nodejs-v0.4.15.tar.gz", + "libsession_util_nodejs": "https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.16/libsession_util_nodejs-v0.4.16.tar.gz", "libsodium-wrappers-sumo": "^0.7.9", "linkify-it": "^4.0.1", "lodash": "^4.17.21", diff --git a/yarn.lock b/yarn.lock index 10e898954..e6b06008b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4944,9 +4944,9 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -"libsession_util_nodejs@https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.15/libsession_util_nodejs-v0.4.15.tar.gz": - version "0.4.15" - resolved "https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.15/libsession_util_nodejs-v0.4.15.tar.gz#de0e90e14327e60d81d2a6941bcd0af33fcfed82" +"libsession_util_nodejs@https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.16/libsession_util_nodejs-v0.4.16.tar.gz": + version "0.4.16" + resolved "https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.16/libsession_util_nodejs-v0.4.16.tar.gz#253d4d02388b5bfb41f24c88fae5061b137ca615" dependencies: cmake-js "7.2.1" node-addon-api "^6.1.0" From d6dce706ff8e66cdc006e0bd3088324f040a9add Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 10 Feb 2025 16:06:51 +1100 Subject: [PATCH 5/5] chore: move groups-related timestamps to constants.ts --- ts/session/constants.ts | 15 +++++++++++++++ ts/state/ducks/releasedFeatures.tsx | 26 +++++++------------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/ts/session/constants.ts b/ts/session/constants.ts index 0ef7e7486..b7a2066b0 100644 --- a/ts/session/constants.ts +++ b/ts/session/constants.ts @@ -99,9 +99,24 @@ export const REACT_LIMIT = 6; export const UPDATER_INTERVAL_MS = 10 * DURATION.MINUTES; +// update this to be when we ship desktop groups REMOVE AFTER QA +const GROUP_DESKTOP_RELEASE = 1767225600000; // currently 1st Jan 2026 + +/** + * 3+7 days after the release of groups (more or less), we force new groups to be created as new groups + */ +const START_CREATE_NEW_GROUP = GROUP_DESKTOP_RELEASE + DURATION.DAYS * 10; + +/** + * 2 weeks after `START_CREATE_NEW_GROUP`, we mark legacy groups readonly + */ +const LEGACY_GROUP_READONLY = START_CREATE_NEW_GROUP + DURATION.WEEKS * 2; + export const FEATURE_RELEASE_TIMESTAMPS = { DISAPPEARING_MESSAGES_V2: 1710284400000, // 13/03/2024 10:00 Melbourne time USER_CONFIG: 1690761600000, // Monday July 31st at 10am Melbourne time + START_CREATE_NEW_GROUP, + LEGACY_GROUP_READONLY, }; export const ONBOARDING_TIMES = { diff --git a/ts/state/ducks/releasedFeatures.tsx b/ts/state/ducks/releasedFeatures.tsx index 666d58b37..a6e1ea138 100644 --- a/ts/state/ducks/releasedFeatures.tsx +++ b/ts/state/ducks/releasedFeatures.tsx @@ -1,20 +1,6 @@ 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 1st Jan 2026 - -/** - * 3+7 days after the release of groups (more or less), we force new groups to be created as new groups - */ -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 - */ -const LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS = - START_CREATE_NEW_GROUP_TIMESTAMP_MS + DURATION.WEEKS * 2; +import { FEATURE_RELEASE_TIMESTAMPS } from '../../session/constants'; export interface ReleasedFeaturesState { legacyGroupDeprecationTimestampRefreshAtMs: number; @@ -24,8 +10,8 @@ export interface ReleasedFeaturesState { export const initialReleasedFeaturesState = { legacyGroupDeprecationTimestampRefreshAtMs: Date.now(), - canCreateGroupV2: Date.now() >= START_CREATE_NEW_GROUP_TIMESTAMP_MS, - legacyGroupsReadOnly: Date.now() >= LEGACY_GROUP_DEPRECATED_TIMESTAMP_MS, + canCreateGroupV2: Date.now() >= FEATURE_RELEASE_TIMESTAMPS.START_CREATE_NEW_GROUP, + legacyGroupsReadOnly: Date.now() >= FEATURE_RELEASE_TIMESTAMPS.LEGACY_GROUP_READONLY, }; const releasedFeaturesSlice = createSlice({ @@ -34,8 +20,10 @@ 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; + state.canCreateGroupV2 = + NetworkTime.now() >= FEATURE_RELEASE_TIMESTAMPS.START_CREATE_NEW_GROUP; + state.legacyGroupsReadOnly = + NetworkTime.now() >= FEATURE_RELEASE_TIMESTAMPS.LEGACY_GROUP_READONLY; return state; }, },