diff --git a/lib/types/thread-types-enum.js b/lib/types/thread-types-enum.js --- a/lib/types/thread-types-enum.js +++ b/lib/types/thread-types-enum.js @@ -78,7 +78,9 @@ threadTypes.COMMUNITY_SECRET_ANNOUNCEMENT_SUBTHREAD, ]); -export function threadTypeIsCommunityRoot(threadType: ThreadType): boolean { +export function threadTypeIsCommunityRoot( + threadType: ThreadType | number, +): boolean { return communityThreadTypes.includes(threadType); } diff --git a/native/redux/persist.js b/native/redux/persist.js --- a/native/redux/persist.js +++ b/native/redux/persist.js @@ -16,6 +16,11 @@ convertConnectionInfoToNewIDSchema, } from 'lib/_generated/migration-utils.js'; import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js'; +import { + communityStoreOpsHandlers, + type ClientDBCommunityStoreOperation, + type ReplaceCommunityOperation, +} from 'lib/ops/community-store-ops.js'; import { type ClientDBKeyserverStoreOperation, keyserverStoreOpsHandlers, @@ -53,6 +58,7 @@ DEPRECATED_unshimMessageStore, unshimFunc, } from 'lib/shared/unshim-utils.js'; +import type { CommunityInfo } from 'lib/types/community-types.js'; import { defaultEnabledApps } from 'lib/types/enabled-apps.js'; import { defaultCalendarQuery } from 'lib/types/entry-types.js'; import { defaultCalendarFilters } from 'lib/types/filter-types.js'; @@ -75,6 +81,7 @@ } from 'lib/types/report-types.js'; import { defaultConnectionInfo } from 'lib/types/socket-types.js'; import { defaultGlobalThemeInfo } from 'lib/types/theme-types.js'; +import { threadTypeIsCommunityRoot } from 'lib/types/thread-types-enum.js'; import type { ClientDBThreadInfo, LegacyRawThreadInfo, @@ -1126,6 +1133,42 @@ } return newState; }, + [64]: async (state: AppState) => { + const clientDBThreadInfos = commCoreModule.getAllThreadsSync(); + + const replaceOperations: $ReadOnlyArray = + clientDBThreadInfos + .filter(threadInfo => threadTypeIsCommunityRoot(threadInfo.type)) + .map(threadInfo => { + const communityInfo: CommunityInfo = { + enabledApps: defaultEnabledApps, + }; + return { + type: 'replace_community', + payload: { + id: threadInfo.id, + communityInfo, + }, + }; + }); + + const dbOperations: $ReadOnlyArray = + communityStoreOpsHandlers.convertOpsToClientDBOps([ + { type: 'remove_all_communities' }, + ...replaceOperations, + ]); + + try { + await commCoreModule.processCommunityStoreOperations(dbOperations); + } catch (exception) { + if (isTaskCancelledError(exception)) { + return state; + } + return handleReduxMigrationFailure(state); + } + + return state; + }, }; // After migration 31, we'll no longer want to persist `messageStore.messages` @@ -1193,7 +1236,7 @@ storage: AsyncStorage, blacklist: persistBlacklist, debug: __DEV__, - version: 63, + version: 64, transforms: [ messageStoreMessagesBlocklistTransform, reportStoreTransform, diff --git a/web/redux/persist.js b/web/redux/persist.js --- a/web/redux/persist.js +++ b/web/redux/persist.js @@ -5,6 +5,11 @@ import storage from 'redux-persist/es/storage/index.js'; import type { PersistConfig } from 'redux-persist/src/types.js'; +import { + communityStoreOpsHandlers, + type ClientDBCommunityStoreOperation, + type ReplaceCommunityOperation, +} from 'lib/ops/community-store-ops.js'; import { type ClientDBKeyserverStoreOperation, keyserverStoreOpsHandlers, @@ -15,10 +20,13 @@ type StorageMigrationFunction, } from 'lib/shared/create-async-migrate.js'; import { keyserverStoreTransform } from 'lib/shared/transforms/keyserver-store-transform.js'; +import type { CommunityInfo } from 'lib/types/community-types.js'; +import { defaultEnabledApps } from 'lib/types/enabled-apps.js'; import type { KeyserverInfo } from 'lib/types/keyserver-types.js'; import { cookieTypes } from 'lib/types/session-types.js'; import { defaultConnectionInfo } from 'lib/types/socket-types.js'; import { defaultGlobalThemeInfo } from 'lib/types/theme-types.js'; +import { threadTypeIsCommunityRoot } from 'lib/types/thread-types-enum.js'; import { parseCookies } from 'lib/utils/cookie-utils.js'; import { isDev } from 'lib/utils/dev-utils.js'; import { wipeKeyserverStore } from 'lib/utils/keyserver-store-utils.js'; @@ -48,6 +56,7 @@ 'keyserverStore', 'globalThemeInfo', 'customServer', + 'communityStore', ]; function handleReduxMigrationFailure(oldState: AppState): AppState { @@ -261,6 +270,56 @@ return handleReduxMigrationFailure(state); } }, + [12]: async (state: AppState) => { + const databaseModule = await getDatabaseModule(); + const isDatabaseSupported = await databaseModule.isDatabaseSupported(); + + if (!isDatabaseSupported) { + return state; + } + + const clientDBStores = await databaseModule.schedule({ + type: workerRequestMessageTypes.GET_CLIENT_STORE, + }); + invariant(clientDBStores?.store, 'Stores should exist'); + + const threadInfos = clientDBStores.store.threads; + + const replaceOperations: $ReadOnlyArray = + threadInfos + .filter(threadInfo => threadTypeIsCommunityRoot(threadInfo.type)) + .map(threadInfo => { + const communityInfo: CommunityInfo = { + enabledApps: defaultEnabledApps, + }; + return { + type: 'replace_community', + payload: { + id: threadInfo.id, + communityInfo, + }, + }; + }); + + const commmunityStoreOperations: $ReadOnlyArray = + communityStoreOpsHandlers.convertOpsToClientDBOps([ + { type: 'remove_all_communities' }, + ...replaceOperations, + ]); + + try { + await databaseModule.schedule({ + type: workerRequestMessageTypes.PROCESS_STORE_OPERATIONS, + storeOperations: { + communityStoreOperations: commmunityStoreOperations, + }, + }); + return state; + } catch (e) { + console.log(e); + return handleReduxMigrationFailure(state); + } + }, }; const rootKey = 'root'; @@ -307,7 +366,7 @@ { debug: isDev }, migrateStorageToSQLite, ): any), - version: 11, + version: 12, transforms: [keyserverStoreTransform], };