From 3ac7f1c07d8253a54d4331e9d41cc98d1a7cc93d Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Thu, 16 Apr 2026 22:35:53 -0400 Subject: [PATCH] remove registry --- shared/common-adapters/wave-button.tsx | 3 +- shared/constants/chat/meta.tsx | 9 +- shared/constants/init/shared.tsx | 77 +++++----- shared/constants/router.tsx | 10 +- .../renderer/remote-event-handler.desktop.tsx | 22 +-- shared/login/reset/account-reset.test.ts | 4 +- shared/login/reset/account-reset.tsx | 4 +- shared/stores/store-registry.tsx | 133 ------------------ 8 files changed, 69 insertions(+), 193 deletions(-) delete mode 100644 shared/stores/store-registry.tsx diff --git a/shared/common-adapters/wave-button.tsx b/shared/common-adapters/wave-button.tsx index 19d5d5691f11..612b5925862b 100644 --- a/shared/common-adapters/wave-button.tsx +++ b/shared/common-adapters/wave-button.tsx @@ -9,7 +9,6 @@ import NativeEmoji from './emoji/native-emoji' import * as Styles from '@/styles' import * as T from '@/constants/types' import logger from '@/logger' -import {storeRegistry} from '@/stores/store-registry' import {useCurrentUserState} from '@/stores/current-user' const Kb = { @@ -86,7 +85,7 @@ const WaveButtonImpl = (props: Props) => { logger.warn("WaveButton: couldn't resolve wave conversation") return } - storeRegistry.getConvoState(conversationIDKey).dispatch.sendMessage(':wave:') + ConvoState.getConvoState(conversationIDKey).dispatch.sendMessage(':wave:') }, error => { logger.warn('Could not send in WaveButton', error.message) diff --git a/shared/constants/chat/meta.tsx b/shared/constants/chat/meta.tsx index 350f7e7f2719..75760e97a2a1 100644 --- a/shared/constants/chat/meta.tsx +++ b/shared/constants/chat/meta.tsx @@ -4,9 +4,14 @@ import * as T from '@/constants/types' import * as Teams from '@/constants/teams' import * as Message from './message' import {base64ToUint8Array, uint8ArrayToHex} from '@/util/uint8array' -import {storeRegistry} from '@/stores/store-registry' +import type * as ConvoStateType from '@/stores/convostate' import {useCurrentUserState} from '@/stores/current-user' +const getConvoState = (conversationIDKey: T.Chat.ConversationIDKey) => { + const {getConvoState} = require('@/stores/convostate') as typeof ConvoStateType + return getConvoState(conversationIDKey) +} + const conversationMemberStatusToMembershipType = (m: T.RPCChat.ConversationMemberStatus) => { switch (m) { case T.RPCChat.ConversationMemberStatus.active: @@ -267,7 +272,7 @@ export const inboxUIItemToConversationMeta = ( const username = useCurrentUserState.getState().username const devicename = useCurrentUserState.getState().deviceName const getLastOrdinal = () => - storeRegistry.getConvoState(conversationIDKey).messageOrdinals?.at(-1) ?? T.Chat.numberToOrdinal(0) + getConvoState(conversationIDKey).messageOrdinals?.at(-1) ?? T.Chat.numberToOrdinal(0) const message = Message.uiMessageToMessage( conversationIDKey, i.pinnedMsg.message, diff --git a/shared/constants/init/shared.tsx b/shared/constants/init/shared.tsx index 74a3eb7cc074..cc8c7c77a94f 100644 --- a/shared/constants/init/shared.tsx +++ b/shared/constants/init/shared.tsx @@ -33,7 +33,6 @@ import {getSelectedConversation} from '@/constants/chat/common' import {emitDeepLink} from '@/router-v2/linking' import {ignorePromise} from '../utils' import {isMobile, isPhone, serverConfigFileName} from '../platform' -import {storeRegistry} from '@/stores/store-registry' import {useAvatarState} from '@/common-adapters/avatar/store' import {useChatState} from '@/stores/chat' import {useConfigState} from '@/stores/config' @@ -41,14 +40,20 @@ import {useCurrentUserState} from '@/stores/current-user' import {useDaemonState} from '@/stores/daemon' import {useDarkModeState} from '@/stores/darkmode' import {useFollowerState} from '@/stores/followers' +import {useFSState} from '@/stores/fs' import {useModalHeaderState} from '@/stores/modal-header' +import {usePeopleState} from '@/stores/people' import {useProvisionState} from '@/stores/provision' +import {useSettingsEmailState} from '@/stores/settings-email' +import {useSettingsPhoneState} from '@/stores/settings-phone' import {useSettingsContactsState} from '@/stores/settings-contacts' import {useTeamsState} from '@/stores/teams' +import {useUsersState} from '@/stores/users' import {useWaitingState} from '@/stores/waiting' import {useRouterState} from '@/stores/router' import * as Util from '@/constants/router' import { + getConvoState, onChatInboxSynced, onGetInboxConvsUnboxed, onGetInboxUnverifiedConvs, @@ -88,7 +93,7 @@ export const onEngineConnected = () => { ignorePromise(registerUIs()) } useConfigState.getState().dispatch.onEngineConnected() - storeRegistry.getState('daemon').dispatch.startHandshake() + useDaemonState.getState().dispatch.startHandshake() { const notifyCtl = async () => { try { @@ -118,7 +123,7 @@ export const onEngineDisconnected = () => { await logger.dump() } ignorePromise(f()) - storeRegistry.getState('daemon').dispatch.setError(new Error('Disconnected')) + useDaemonState.getState().dispatch.setError(new Error('Disconnected')) } export const initSharedSubscriptions = () => { @@ -180,45 +185,41 @@ export const initSharedSubscriptions = () => { // Re-get info about our account if you log in/we're done handshaking/became reachable if (s.gregorReachable === T.RPCGen.Reachable.yes) { // not in waiting state - if (storeRegistry.getState('daemon').handshakeWaiters.size === 0) { - ignorePromise(storeRegistry.getState('daemon').dispatch.loadDaemonBootstrapStatus()) + if (useDaemonState.getState().handshakeWaiters.size === 0) { + ignorePromise(useDaemonState.getState().dispatch.loadDaemonBootstrapStatus()) } - storeRegistry.getState('teams').dispatch.eagerLoadTeams() + useTeamsState.getState().dispatch.eagerLoadTeams() } } if (s.installerRanCount !== old.installerRanCount) { - storeRegistry.getState('fs').dispatch.checkKbfsDaemonRpcStatus() + useFSState.getState().dispatch.checkKbfsDaemonRpcStatus() } if (s.loggedIn !== old.loggedIn) { if (s.loggedIn) { - ignorePromise(storeRegistry.getState('daemon').dispatch.loadDaemonBootstrapStatus()) - storeRegistry.getState('fs').dispatch.checkKbfsDaemonRpcStatus() + ignorePromise(useDaemonState.getState().dispatch.loadDaemonBootstrapStatus()) + useFSState.getState().dispatch.checkKbfsDaemonRpcStatus() } else { clearSignupEmail() clearSignupDeviceNameDraft() } - storeRegistry - .getState('daemon') - .dispatch.loadDaemonAccounts( - s.configuredAccounts.length, - s.loggedIn, - useConfigState.getState().dispatch.refreshAccounts - ) + useDaemonState.getState().dispatch.loadDaemonAccounts( + s.configuredAccounts.length, + s.loggedIn, + useConfigState.getState().dispatch.refreshAccounts + ) if (!s.loggedInCausedbyStartup) { ignorePromise(useConfigState.getState().dispatch.refreshAccounts()) } } if (s.revokedTrigger !== old.revokedTrigger) { - storeRegistry - .getState('daemon') - .dispatch.loadDaemonAccounts( - s.configuredAccounts.length, - s.loggedIn, - useConfigState.getState().dispatch.refreshAccounts - ) + useDaemonState.getState().dispatch.loadDaemonAccounts( + s.configuredAccounts.length, + s.loggedIn, + useConfigState.getState().dispatch.refreshAccounts + ) } if (s.configuredAccounts !== old.configuredAccounts) { @@ -227,12 +228,12 @@ export const initSharedSubscriptions = () => { name: account.username, })) if (updates.length > 0) { - storeRegistry.getState('users').dispatch.updates(updates) + useUsersState.getState().dispatch.updates(updates) } } if (s.active !== old.active) { - const cs = storeRegistry.getConvoState(getSelectedConversation()) + const cs = getConvoState(getSelectedConversation()) cs.dispatch.markThreadAsRead() } }) @@ -242,7 +243,7 @@ export const initSharedSubscriptions = () => { useDaemonState.subscribe((s, old) => { if (s.handshakeVersion !== old.handshakeVersion) { useDarkModeState.getState().dispatch.loadDarkPrefs() - storeRegistry.getState('chat').dispatch.loadStaticConfig() + useChatState.getState().dispatch.loadStaticConfig() const configState = useConfigState.getState() s.dispatch.loadDaemonAccounts( configState.configuredAccounts.length, @@ -270,7 +271,7 @@ export const initSharedSubscriptions = () => { configDispatch.setHTTPSrvInfo(bootstrap.httpSrvInfo.address, bootstrap.httpSrvInfo.token) } - storeRegistry.getState('chat').dispatch.updateUserReacjis(userReacjis) + useChatState.getState().dispatch.updateUserReacjis(userReacjis) } } @@ -332,16 +333,16 @@ export const initSharedSubscriptions = () => { Util.getTab(prev) === Tabs.fsTab && next && Util.getTab(next) !== Tabs.fsTab && - storeRegistry.getState('fs').criticalUpdate + useFSState.getState().criticalUpdate ) { - const {dispatch} = storeRegistry.getState('fs') + const {dispatch} = useFSState.getState() dispatch.setCriticalUpdate(false) } const fsRrouteNames = ['fsRoot', 'barePreview'] const wasScreen = fsRrouteNames.includes(Util.getVisibleScreen(prev)?.name ?? '') const isScreen = fsRrouteNames.includes(Util.getVisibleScreen(next)?.name ?? '') if (wasScreen !== isScreen) { - const {dispatch} = storeRegistry.getState('fs') + const {dispatch} = useFSState.getState() if (wasScreen) { dispatch.userOut() } else { @@ -355,11 +356,11 @@ export const initSharedSubscriptions = () => { } if (prev && Util.getTab(prev) === Tabs.peopleTab && next && Util.getTab(next) !== Tabs.peopleTab) { - storeRegistry.getState('people').dispatch.markViewed() + usePeopleState.getState().dispatch.markViewed() } if (prev && Util.getTab(prev) === Tabs.teamsTab && next && Util.getTab(next) !== Tabs.teamsTab) { - storeRegistry.getState('teams').dispatch.clearNavBadges() + useTeamsState.getState().dispatch.clearNavBadges() } // Clear "check your inbox" in settings when you leave the settings tab @@ -368,9 +369,9 @@ export const initSharedSubscriptions = () => { Util.getTab(prev) === Tabs.settingsTab && next && Util.getTab(next) !== Tabs.settingsTab && - storeRegistry.getState('settings-email').addedEmail + useSettingsEmailState.getState().addedEmail ) { - storeRegistry.getState('settings-email').dispatch.resetAddedEmail() + useSettingsEmailState.getState().dispatch.resetAddedEmail() } onConvoRouteChanged(prev, next) @@ -486,7 +487,7 @@ export const _onEngineIncoming = (action: EngineGen.Actions) => { { const emailAddress = action.payload.params.emailAddress if (emailAddress) { - storeRegistry.getState('settings-email').dispatch.notifyEmailVerified(emailAddress) + useSettingsEmailState.getState().dispatch.notifyEmailVerified(emailAddress) } clearSignupEmail() } @@ -506,14 +507,12 @@ export const _onEngineIncoming = (action: EngineGen.Actions) => { break case 'keybase.1.NotifyPhoneNumber.phoneNumbersChanged': { const {list} = action.payload.params - storeRegistry - .getState('settings-phone') - .dispatch.notifyPhoneNumberPhoneNumbersChanged(list ?? undefined) + useSettingsPhoneState.getState().dispatch.notifyPhoneNumberPhoneNumbersChanged(list ?? undefined) break } case 'keybase.1.NotifyEmailAddress.emailsChanged': { const list = action.payload.params.list ?? [] - storeRegistry.getState('settings-email').dispatch.notifyEmailAddressEmailsChanged(list) + useSettingsEmailState.getState().dispatch.notifyEmailAddressEmailsChanged(list) break } case 'chat.1.chatUi.chatInboxFailed': diff --git a/shared/constants/router.tsx b/shared/constants/router.tsx index 8f6bd41f608e..0c13e3cdd193 100644 --- a/shared/constants/router.tsx +++ b/shared/constants/router.tsx @@ -22,7 +22,6 @@ import {isMobile} from './platform' import {ignorePromise, shallowEqual} from './utils' import {registerDebugClear} from '@/util/debug' import {makeUUID} from '@/util/uuid' -import {storeRegistry} from '@/stores/store-registry' import * as Meta from './chat/meta' import * as Strings from './strings' import logger from '@/logger' @@ -86,6 +85,11 @@ const uiParticipantsToParticipantInfo = ( return participantInfo } +const getConvoState = (conversationIDKey: T.Chat.ConversationIDKey) => { + const {getConvoState} = require('@/stores/convostate') as typeof ConvoStateType + return getConvoState(conversationIDKey) +} + export const getRootState = (): NavState | undefined => { if (!navigationRef.isReady()) return return navigationRef.getRootState() @@ -435,7 +439,7 @@ export const createConversation = ( const participantInfo = uiParticipantsToParticipantInfo(uiConv.participants ?? []) if (participantInfo.all.length > 0) { - storeRegistry.getConvoState(conversationIDKey).dispatch.setParticipants(participantInfo) + getConvoState(conversationIDKey).dispatch.setParticipants(participantInfo) } navigateToThread(conversationIDKey, 'justCreated', highlightMessageID) @@ -711,7 +715,7 @@ export const navigateToThread = ( threadSearchQuery?: string, createConversationError?: T.Chat.CreateConversationError ) => { - storeRegistry.getConvoState(conversationIDKey).dispatch.prepareToNavigateToThread(highlightMessageID) + getConvoState(conversationIDKey).dispatch.prepareToNavigateToThread(highlightMessageID) if (reason === 'navChanged') { return diff --git a/shared/desktop/renderer/remote-event-handler.desktop.tsx b/shared/desktop/renderer/remote-event-handler.desktop.tsx index 538dc0da2f1e..06461158f6d4 100644 --- a/shared/desktop/renderer/remote-event-handler.desktop.tsx +++ b/shared/desktop/renderer/remote-event-handler.desktop.tsx @@ -5,13 +5,15 @@ import * as Tabs from '@/constants/tabs' import {RPCError} from '@/util/errors' import {ignorePromise} from '@/constants/utils' import {navigateAppend, navigateToThread, previewConversation, switchTab} from '@/constants/router' -import {storeRegistry} from '@/stores/store-registry' import {onEngineConnected, onEngineDisconnected} from '@/constants/init/index.desktop' import {emitDeepLink} from '@/router-v2/linking' import {isPathSaltpackEncrypted, isPathSaltpackSigned} from '@/util/path' import type HiddenString from '@/util/hidden-string' +import {useChatState} from '@/stores/chat' import {useConfigState} from '@/stores/config' +import {useFSState} from '@/stores/fs' import {usePinentryState} from '@/stores/pinentry' +import {useTrackerState} from '@/stores/tracker' import logger from '@/logger' import {makeUUID} from '@/util/uuid' @@ -73,7 +75,7 @@ export const eventFromRemoteWindows = (action: RemoteGen.Actions) => { break } case RemoteGen.inboxRefresh: { - ignorePromise(storeRegistry.getState('chat').dispatch.inboxRefresh('widgetRefresh')) + ignorePromise(useChatState.getState().dispatch.inboxRefresh('widgetRefresh')) break } case RemoteGen.engineConnection: { @@ -90,15 +92,15 @@ export const eventFromRemoteWindows = (action: RemoteGen.Actions) => { break } case RemoteGen.setCriticalUpdate: { - storeRegistry.getState('fs').dispatch.setCriticalUpdate(action.payload.critical) + useFSState.getState().dispatch.setCriticalUpdate(action.payload.critical) break } case RemoteGen.userFileEditsLoad: { - storeRegistry.getState('fs').dispatch.userFileEditsLoad() + useFSState.getState().dispatch.userFileEditsLoad() break } case RemoteGen.openFilesFromWidget: { - storeRegistry.getState('fs').dispatch.defer.openFilesFromWidgetDesktop?.(action.payload.path) + useFSState.getState().dispatch.defer.openFilesFromWidgetDesktop?.(action.payload.path) break } case RemoteGen.saltpackFileOpen: { @@ -114,7 +116,7 @@ export const eventFromRemoteWindows = (action: RemoteGen.Actions) => { break } case RemoteGen.openPathInSystemFileManager: { - storeRegistry.getState('fs').dispatch.defer.openPathInSystemFileManagerDesktop?.(action.payload.path) + useFSState.getState().dispatch.defer.openPathInSystemFileManagerDesktop?.(action.payload.path) break } case RemoteGen.unlockFoldersSubmitPaperKey: { @@ -142,19 +144,19 @@ export const eventFromRemoteWindows = (action: RemoteGen.Actions) => { break } case RemoteGen.trackerChangeFollow: { - storeRegistry.getState('tracker').dispatch.changeFollow(action.payload.guiID, action.payload.follow) + useTrackerState.getState().dispatch.changeFollow(action.payload.guiID, action.payload.follow) break } case RemoteGen.trackerIgnore: { - storeRegistry.getState('tracker').dispatch.ignore(action.payload.guiID) + useTrackerState.getState().dispatch.ignore(action.payload.guiID) break } case RemoteGen.trackerCloseTracker: { - storeRegistry.getState('tracker').dispatch.closeTracker(action.payload.guiID) + useTrackerState.getState().dispatch.closeTracker(action.payload.guiID) break } case RemoteGen.trackerLoad: { - storeRegistry.getState('tracker').dispatch.load(action.payload) + useTrackerState.getState().dispatch.load(action.payload) break } case RemoteGen.link: diff --git a/shared/login/reset/account-reset.test.ts b/shared/login/reset/account-reset.test.ts index 5d6831f479dd..ee8c2f489b7d 100644 --- a/shared/login/reset/account-reset.test.ts +++ b/shared/login/reset/account-reset.test.ts @@ -13,8 +13,8 @@ jest.mock('@/constants/router', () => { } }) -jest.mock('@/stores/store-registry', () => ({ - storeRegistry: { +jest.mock('@/stores/provision', () => ({ + useProvisionState: { getState: jest.fn(() => ({ dispatch: { startProvision: mockStartProvision, diff --git a/shared/login/reset/account-reset.tsx b/shared/login/reset/account-reset.tsx index a56402cc4cd0..64391b2cc4f0 100644 --- a/shared/login/reset/account-reset.tsx +++ b/shared/login/reset/account-reset.tsx @@ -4,7 +4,7 @@ import * as T from '@/constants/types' import {ignorePromise} from '@/constants/utils' import logger from '@/logger' import {consumeKeyed, registerKeyed} from '@/stores/flow-handles' -import {storeRegistry} from '@/stores/store-registry' +import {useProvisionState} from '@/stores/provision' import {RPCError} from '@/util/errors' type EnterResetPipelineParams = { @@ -38,7 +38,7 @@ export const enterResetPipeline = ({onError, password = '', username}: EnterRese const resetKey = registerResetPrompt((action: T.RPCGen.ResetPromptResponse) => { response.result(action) if (action === T.RPCGen.ResetPromptResponse.confirmReset) { - storeRegistry.getState('provision').dispatch.startProvision(username, true) + useProvisionState.getState().dispatch.startProvision(username, true) } else { navUpToScreen('login') } diff --git a/shared/stores/store-registry.tsx b/shared/stores/store-registry.tsx deleted file mode 100644 index 1636bdd86945..000000000000 --- a/shared/stores/store-registry.tsx +++ /dev/null @@ -1,133 +0,0 @@ -// used to allow non-circular cross-calls between stores -// ONLY for zustand stores -import type * as T from '@/constants/types' -import type * as ConvoStateType from '@/stores/convostate' -import type {ConvoState} from '@/stores/convostate' -import type {State as ChatState, useChatState} from '@/stores/chat' -import type {State as DaemonState, useDaemonState} from '@/stores/daemon' -import type {State as FSState, useFSState} from '@/stores/fs' -import type {State as PeopleState, usePeopleState} from '@/stores/people' -import type {State as ProvisionState, useProvisionState} from '@/stores/provision' -import type {State as PushState, usePushState} from '@/stores/push' -import type { - State as RecoverPasswordState, - useState as useRecoverPasswordState, -} from '@/stores/recover-password' -import type {State as SettingsEmailState, useSettingsEmailState} from '@/stores/settings-email' -import type {State as SettingsPhoneState, useSettingsPhoneState} from '@/stores/settings-phone' -import type {State as TeamsState, useTeamsState} from '@/stores/teams' -import type {State as TrackerState, useTrackerState} from '@/stores/tracker' -import type {State as UsersState, useUsersState} from '@/stores/users' - -type StoreName = - | 'chat' - | 'daemon' - | 'fs' - | 'people' - | 'provision' - | 'push' - | 'recover-password' - | 'settings-email' - | 'settings-phone' - | 'teams' - | 'tracker' - | 'users' - -type StoreStates = { - chat: ChatState - daemon: DaemonState - fs: FSState - people: PeopleState - provision: ProvisionState - push: PushState - 'recover-password': RecoverPasswordState - 'settings-email': SettingsEmailState - 'settings-phone': SettingsPhoneState - teams: TeamsState - tracker: TrackerState - users: UsersState -} - -type StoreHooks = { - chat: typeof useChatState - daemon: typeof useDaemonState - fs: typeof useFSState - people: typeof usePeopleState - provision: typeof useProvisionState - push: typeof usePushState - 'recover-password': typeof useRecoverPasswordState - 'settings-email': typeof useSettingsEmailState - 'settings-phone': typeof useSettingsPhoneState - teams: typeof useTeamsState - tracker: typeof useTrackerState - users: typeof useUsersState -} - -class StoreRegistry { - getStore(storeName: T): StoreHooks[T] { - /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return */ - switch (storeName) { - case 'chat': { - const {useChatState} = require('@/stores/chat') - return useChatState - } - case 'daemon': { - const {useDaemonState} = require('@/stores/daemon') - return useDaemonState - } - case 'fs': { - const {useFSState} = require('@/stores/fs') - return useFSState - } - case 'people': { - const {usePeopleState} = require('@/stores/people') - return usePeopleState - } - case 'provision': { - const {useProvisionState} = require('@/stores/provision') - return useProvisionState - } - case 'push': { - const {usePushState} = require('@/stores/push') - return usePushState - } - case 'recover-password': { - const {useState} = require('@/stores/recover-password') - return useState - } - case 'settings-email': { - const {useSettingsEmailState} = require('@/stores/settings-email') - return useSettingsEmailState - } - case 'settings-phone': { - const {useSettingsPhoneState} = require('@/stores/settings-phone') - return useSettingsPhoneState - } - case 'teams': { - const {useTeamsState} = require('@/stores/teams') - return useTeamsState - } - case 'tracker': { - const {useTrackerState} = require('@/stores/tracker') - return useTrackerState - } - case 'users': { - const {useUsersState} = require('@/stores/users') - return useUsersState - } - default: - throw new Error(`Unknown store: ${storeName}`) - } - } - - getState(storeName: T): StoreStates[T] { - return this.getStore(storeName).getState() as StoreStates[T] - } - - getConvoState(id: T.Chat.ConversationIDKey): ConvoState { - const {getConvoState} = require('@/stores/convostate') as typeof ConvoStateType - return getConvoState(id) - } -} - -export const storeRegistry = new StoreRegistry()