From 752448cb07db0f1c2cd9ac2fd88800156b5cbfac Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Tue, 27 Jan 2026 16:16:47 -0500 Subject: [PATCH 1/2] WIP --- shared/app/global-errors/hook.tsx | 2 +- shared/app/out-of-date.tsx | 2 +- .../attachment-fullscreen/hooks.tsx | 2 +- shared/chat/conversation/command-status.tsx | 2 +- .../conversation/info-panel/attachments.tsx | 2 +- .../input-area/location-popup.native.tsx | 2 +- .../conversation/list-area/index.desktop.tsx | 2 +- .../messages/attachment/audio.tsx | 2 +- .../conversation/messages/attachment/file.tsx | 2 +- .../messages/attachment/shared.tsx | 2 +- .../messages/message-popup/attachment.tsx | 2 +- .../messages/message-popup/hooks.tsx | 2 +- .../messages/message-popup/text.tsx | 2 +- shared/chat/pdf/index.desktop.tsx | 2 +- shared/chat/pdf/index.native.tsx | 2 +- shared/common-adapters/copy-text.tsx | 4 +- shared/constants/init/index.desktop.tsx | 54 +++++++++---------- shared/constants/init/index.native.tsx | 26 ++++----- shared/constants/init/shared.tsx | 40 +++++++------- shared/crypto/output.tsx | 6 +-- shared/fs/banner/conflict-banner.tsx | 2 +- .../container.tsx | 4 +- .../kext-permission-popup.tsx | 2 +- shared/fs/browser/index.tsx | 2 +- shared/fs/common/hooks.tsx | 4 +- .../fs/common/open-in-system-file-manager.tsx | 2 +- .../common/refresh-driver-status-on-mount.tsx | 2 +- shared/fs/common/upload-button.tsx | 4 +- shared/fs/filepreview/default-view.tsx | 2 +- shared/fs/footer/download.tsx | 2 +- shared/fs/footer/downloads.tsx | 2 +- shared/profile/post-proof.tsx | 2 +- .../code-page/qr-scan/not-authorized.tsx | 2 +- shared/router-v2/router.native.tsx | 2 +- shared/settings/archive/index.tsx | 4 +- shared/settings/files/index.desktop.tsx | 2 +- shared/settings/manage-contacts.tsx | 2 +- shared/stores/autoreset.tsx | 8 +-- shared/stores/chat2.tsx | 22 ++++---- shared/stores/config.tsx | 16 +++--- shared/stores/convostate.tsx | 2 +- shared/stores/fs.tsx | 22 ++++---- shared/stores/notifications.tsx | 6 +-- shared/stores/profile.tsx | 38 +++++++------ shared/stores/push.d.ts | 2 +- shared/stores/push.desktop.tsx | 2 +- shared/stores/push.native.tsx | 14 ++--- shared/stores/recover-password.tsx | 16 +++--- shared/stores/router2.tsx | 4 +- shared/stores/signup.tsx | 10 ++-- shared/stores/team-building.tsx | 20 +++---- shared/stores/teams.tsx | 16 +++--- shared/stores/tracker2.tsx | 12 ++--- shared/teams/common/enable-contacts.tsx | 2 +- shared/tracker2/assertion.tsx | 2 +- shared/util/zustand.tsx | 11 +++- shared/wallets/really-remove-account.tsx | 2 +- 57 files changed, 224 insertions(+), 205 deletions(-) diff --git a/shared/app/global-errors/hook.tsx b/shared/app/global-errors/hook.tsx index d8e9d9701d30..df6a580e4787 100644 --- a/shared/app/global-errors/hook.tsx +++ b/shared/app/global-errors/hook.tsx @@ -26,7 +26,7 @@ const useData = () => { navigateAppend('feedback') } }, [navigateAppend, clearModals, loggedIn, setGlobalError]) - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const onDismiss = React.useCallback(() => { setGlobalError() }, [setGlobalError]) diff --git a/shared/app/out-of-date.tsx b/shared/app/out-of-date.tsx index d77926f918bc..70b33bb01693 100644 --- a/shared/app/out-of-date.tsx +++ b/shared/app/out-of-date.tsx @@ -62,7 +62,7 @@ const OutOfDate = () => { C.ignorePromise(f()) }) - const onOpenAppStore = useConfigState(s => s.dispatch.dynamic.openAppStore) + const onOpenAppStore = useConfigState(s => s.dispatch.defer.openAppStore) return status !== 'critical' ? null : ( diff --git a/shared/chat/conversation/attachment-fullscreen/hooks.tsx b/shared/chat/conversation/attachment-fullscreen/hooks.tsx index cd16b218c638..3c6c21497450 100644 --- a/shared/chat/conversation/attachment-fullscreen/hooks.tsx +++ b/shared/chat/conversation/attachment-fullscreen/hooks.tsx @@ -37,7 +37,7 @@ export const useData = (initialOrdinal: T.Chat.Ordinal) => { }, [onSwitchAttachment]) const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const navigateUp = C.useRouterState(s => s.dispatch.navigateUp) const showInfoPanel = Chat.useChatContext(s => s.dispatch.showInfoPanel) diff --git a/shared/chat/conversation/command-status.tsx b/shared/chat/conversation/command-status.tsx index d27ab60a9bf3..dc67888d461c 100644 --- a/shared/chat/conversation/command-status.tsx +++ b/shared/chat/conversation/command-status.tsx @@ -13,7 +13,7 @@ const Container = () => { const info = Chat.useChatContext(s => s.commandStatus) const _info = info || empty - const onOpenAppSettings = useConfigState(s => s.dispatch.dynamic.openAppSettings) + const onOpenAppSettings = useConfigState(s => s.dispatch.defer.openAppSettings) const setCommandStatusInfo = Chat.useChatContext(s => s.dispatch.setCommandStatusInfo) const onCancel = () => { setCommandStatusInfo() diff --git a/shared/chat/conversation/info-panel/attachments.tsx b/shared/chat/conversation/info-panel/attachments.tsx index 1deea243bb7d..61b7fb7608a9 100644 --- a/shared/chat/conversation/info-panel/attachments.tsx +++ b/shared/chat/conversation/info-panel/attachments.tsx @@ -499,7 +499,7 @@ export const useAttachmentSections = ( } const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const onShowInFinder = (message: T.Chat.MessageAttachment) => message.downloadPath && openLocalPathInSystemFileManagerDesktop?.(message.downloadPath) diff --git a/shared/chat/conversation/input-area/location-popup.native.tsx b/shared/chat/conversation/input-area/location-popup.native.tsx index 2327f955a1f0..ec5fef04455f 100644 --- a/shared/chat/conversation/input-area/location-popup.native.tsx +++ b/shared/chat/conversation/input-area/location-popup.native.tsx @@ -62,7 +62,7 @@ const LocationPopup = () => { const onClose = () => { clearModals() } - const onSettings = useConfigState(s => s.dispatch.dynamic.openAppSettings) + const onSettings = useConfigState(s => s.dispatch.defer.openAppSettings) const sendMessage = Chat.useChatContext(s => s.dispatch.sendMessage) const onLocationShare = (duration: string) => { onClose() diff --git a/shared/chat/conversation/list-area/index.desktop.tsx b/shared/chat/conversation/list-area/index.desktop.tsx index 2dd8fc5f700a..f9375aeba2d0 100644 --- a/shared/chat/conversation/list-area/index.desktop.tsx +++ b/shared/chat/conversation/list-area/index.desktop.tsx @@ -493,7 +493,7 @@ const ThreadWrapper = React.memo(function ThreadWrapper() { ) const {conversationIDKey, editingOrdinal, centeredOrdinal} = data const {containsLatestMessage, messageOrdinals, loaded, messageTypeMap} = data - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const listRef = React.useRef(null) const _setListRef = React.useCallback((r: HTMLDivElement | null) => { listRef.current = r diff --git a/shared/chat/conversation/messages/attachment/audio.tsx b/shared/chat/conversation/messages/attachment/audio.tsx index 1de12a908a91..cd32586199c4 100644 --- a/shared/chat/conversation/messages/attachment/audio.tsx +++ b/shared/chat/conversation/messages/attachment/audio.tsx @@ -25,7 +25,7 @@ const AudioAttachment = () => { const progressLabel = Chat.messageAttachmentTransferStateToProgressLabel(message.transferState) const hasProgress = messageAttachmentHasProgress(message) const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const onShowInFinder = () => { message.downloadPath && openLocalPathInSystemFileManagerDesktop?.(message.downloadPath) diff --git a/shared/chat/conversation/messages/attachment/file.tsx b/shared/chat/conversation/messages/attachment/file.tsx index ce6d9e15c985..bfcbe3bbc11f 100644 --- a/shared/chat/conversation/messages/attachment/file.tsx +++ b/shared/chat/conversation/messages/attachment/file.tsx @@ -57,7 +57,7 @@ const FileContainer = React.memo(function FileContainer(p: OwnProps) { [switchTab, saltpackOpenFile] ) const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const _onShowInFinder = React.useCallback(() => { downloadPath && openLocalPathInSystemFileManagerDesktop?.(downloadPath) diff --git a/shared/chat/conversation/messages/attachment/shared.tsx b/shared/chat/conversation/messages/attachment/shared.tsx index d0937dde1167..3f0efebc0588 100644 --- a/shared/chat/conversation/messages/attachment/shared.tsx +++ b/shared/chat/conversation/messages/attachment/shared.tsx @@ -103,7 +103,7 @@ export const TransferIcon = (p: {style: Kb.Styles.StylesCrossPlatform}) => { download(ordinal) }, [ordinal, download]) - const openFinder = useFSState(s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop) + const openFinder = useFSState(s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop) const onFinder = React.useCallback(() => { downloadPath && openFinder?.(downloadPath) }, [openFinder, downloadPath]) diff --git a/shared/chat/conversation/messages/message-popup/attachment.tsx b/shared/chat/conversation/messages/message-popup/attachment.tsx index 19227db84c07..b6da989e6deb 100644 --- a/shared/chat/conversation/messages/message-popup/attachment.tsx +++ b/shared/chat/conversation/messages/message-popup/attachment.tsx @@ -84,7 +84,7 @@ const PopAttach = (ownProps: OwnProps) => { const onShareAttachment = C.isMobile ? _onShareAttachment : undefined const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const _onShowInFinder = React.useCallback(() => { downloadPath && openLocalPathInSystemFileManagerDesktop?.(downloadPath) diff --git a/shared/chat/conversation/messages/message-popup/hooks.tsx b/shared/chat/conversation/messages/message-popup/hooks.tsx index 5a55ddf164ab..48b40ada8b7f 100644 --- a/shared/chat/conversation/messages/message-popup/hooks.tsx +++ b/shared/chat/conversation/messages/message-popup/hooks.tsx @@ -104,7 +104,7 @@ export const useItems = (ordinal: T.Chat.Ordinal, onHidden: () => void) => { : [] const convLabel = getConversationLabel(participantInfo, meta, true) - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const onCopyLink = React.useCallback(() => { copyToClipboard(linkFromConvAndMessage(convLabel, id)) }, [copyToClipboard, id, convLabel]) diff --git a/shared/chat/conversation/messages/message-popup/text.tsx b/shared/chat/conversation/messages/message-popup/text.tsx index ac05c2730cce..66425418691d 100644 --- a/shared/chat/conversation/messages/message-popup/text.tsx +++ b/shared/chat/conversation/messages/message-popup/text.tsx @@ -75,7 +75,7 @@ const PopText = (ownProps: OwnProps) => { // you can reply privately *if* text message, someone else's message, and not in a 1-on-1 chat const canReplyPrivately = ['small', 'big'].includes(teamType) || numPart > 2 const navigateAppend = C.useRouterState(s => s.dispatch.navigateAppend) - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const onCopy = React.useCallback(() => { text && copyToClipboard(text) }, [copyToClipboard, text]) diff --git a/shared/chat/pdf/index.desktop.tsx b/shared/chat/pdf/index.desktop.tsx index 6fcee8301fc1..8866e8ec8316 100644 --- a/shared/chat/pdf/index.desktop.tsx +++ b/shared/chat/pdf/index.desktop.tsx @@ -11,7 +11,7 @@ const ChatPDF = (props: Props) => { const title = message?.title || message?.fileName || 'PDF' const url = message?.fileURL const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const attachmentDownload = Chat.useChatContext(s => s.dispatch.attachmentDownload) diff --git a/shared/chat/pdf/index.native.tsx b/shared/chat/pdf/index.native.tsx index 8f6253a027d2..d0900794f567 100644 --- a/shared/chat/pdf/index.native.tsx +++ b/shared/chat/pdf/index.native.tsx @@ -12,7 +12,7 @@ const ChatPDF = (props: Props) => { const [error, setError] = React.useState('') const navigateUp = C.useRouterState(s => s.dispatch.navigateUp) const onBack = () => navigateUp() - const showShareActionSheet = useConfigState(s => s.dispatch.dynamic.showShareActionSheet) + const showShareActionSheet = useConfigState(s => s.dispatch.defer.showShareActionSheet) const onShare = () => { showShareActionSheet?.(url ?? '', '', 'application/pdf') } diff --git a/shared/common-adapters/copy-text.tsx b/shared/common-adapters/copy-text.tsx index 505513bd6efd..43a797333631 100644 --- a/shared/common-adapters/copy-text.tsx +++ b/shared/common-adapters/copy-text.tsx @@ -61,8 +61,8 @@ const CopyText = (props: Props) => { const popupAnchor = React.useRef(null) const textRef = React.useRef(null) - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) - const showShareActionSheet = useConfigState(s => s.dispatch.dynamic.showShareActionSheet) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) + const showShareActionSheet = useConfigState(s => s.dispatch.defer.showShareActionSheet) const copy = React.useCallback(() => { if (!text) { if (!loadText) { diff --git a/shared/constants/init/index.desktop.tsx b/shared/constants/init/index.desktop.tsx index ea30f3e872ca..08d952d63514 100644 --- a/shared/constants/init/index.desktop.tsx +++ b/shared/constants/init/index.desktop.tsx @@ -179,7 +179,7 @@ const fuseStatusToActions = if (status.kextStarted && previousStatusType === T.FS.DriverStatusType.Disabled) { useFSState .getState() - .dispatch.dynamic.openPathInSystemFileManagerDesktop?.(T.FS.stringToPath('/keybase')) + .dispatch.defer.openPathInSystemFileManagerDesktop?.(T.FS.stringToPath('/keybase')) } } @@ -198,7 +198,7 @@ const driverEnableFuse = async (isRetry: boolean) => { } else { await T.RPCGen.installInstallKBFSRpcPromise() // restarts kbfsfuse await T.RPCGen.kbfsMountWaitForMountsRpcPromise() - useFSState.getState().dispatch.dynamic.refreshDriverStatusDesktop?.() + useFSState.getState().dispatch.defer.refreshDriverStatusDesktop?.() } } @@ -223,7 +223,7 @@ const uninstallDokanConfirm = async () => { } if (!driverStatus.dokanUninstallExecPath) { await uninstallDokanDialog?.() - useFSState.getState().dispatch.dynamic.refreshDriverStatusDesktop?.() + useFSState.getState().dispatch.defer.refreshDriverStatusDesktop?.() return } useFSState.getState().dispatch.driverDisabling() @@ -237,7 +237,7 @@ const onUninstallDokan = async () => { try { await uninstallDokan?.(execPath) } catch {} - useFSState.getState().dispatch.dynamic.refreshDriverStatusDesktop?.() + useFSState.getState().dispatch.defer.refreshDriverStatusDesktop?.() } // Invoking the cached installer package has to happen from the topmost process @@ -246,7 +246,7 @@ const onUninstallDokan = async () => { const onInstallCachedDokan = async () => { try { await installCachedDokan?.() - useFSState.getState().dispatch.dynamic.refreshDriverStatusDesktop?.() + useFSState.getState().dispatch.defer.refreshDriverStatusDesktop?.() } catch (e) { errorToActionOrThrow(e) } @@ -254,10 +254,10 @@ const onInstallCachedDokan = async () => { export const initPlatformListener = () => { useConfigState.setState(s => { - s.dispatch.dynamic.dumpLogsNative = dumpLogs - s.dispatch.dynamic.showMainNative = wrapErrors(() => showMainWindow?.()) - s.dispatch.dynamic.copyToClipboard = wrapErrors((s: string) => copyToClipboard?.(s)) - s.dispatch.dynamic.onEngineConnectedDesktop = wrapErrors(() => { + s.dispatch.defer.dumpLogsNative = dumpLogs + s.dispatch.defer.showMainNative = wrapErrors(() => showMainWindow?.()) + s.dispatch.defer.copyToClipboard = wrapErrors((s: string) => copyToClipboard?.(s)) + s.dispatch.defer.onEngineConnectedDesktop = wrapErrors(() => { // Introduce ourselves to the service const f = async () => { await T.RPCGen.configHelloIAmRpcPromise({details: KB2.constants.helloDetails}) @@ -410,7 +410,7 @@ export const initPlatformListener = () => { }) useFSState.setState(s => { - s.dispatch.dynamic.uploadFromDragAndDropDesktop = wrapErrors( + s.dispatch.defer.uploadFromDragAndDropDesktop = wrapErrors( (parentPath: T.FS.Path, localPaths: string[]) => { const {upload} = useFSState.getState().dispatch const f = async () => { @@ -428,7 +428,7 @@ export const initPlatformListener = () => { } ) - s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop = wrapErrors((localPath: string) => { + s.dispatch.defer.openLocalPathInSystemFileManagerDesktop = wrapErrors((localPath: string) => { const f = async () => { try { if (getPathType) { @@ -442,7 +442,7 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.openPathInSystemFileManagerDesktop = wrapErrors((path: T.FS.Path) => { + s.dispatch.defer.openPathInSystemFileManagerDesktop = wrapErrors((path: T.FS.Path) => { const f = async () => { const {sfmi, pathItems} = useFSState.getState() return sfmi.driverStatus.type === T.FS.DriverStatusType.Enabled && sfmi.directMountDir @@ -466,7 +466,7 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.refreshDriverStatusDesktop = wrapErrors(() => { + s.dispatch.defer.refreshDriverStatusDesktop = wrapErrors(() => { const f = async () => { let status = await T.RPCGen.installFuseStatusRpcPromise({ bundleVersion: '', @@ -480,7 +480,7 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.refreshMountDirsDesktop = wrapErrors(() => { + s.dispatch.defer.refreshMountDirsDesktop = wrapErrors(() => { const f = async () => { const {sfmi, dispatch} = useFSState.getState() const driverStatus = sfmi.driverStatus @@ -495,16 +495,16 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.setSfmiBannerDismissedDesktop = wrapErrors((dismissed: boolean) => { + s.dispatch.defer.setSfmiBannerDismissedDesktop = wrapErrors((dismissed: boolean) => { const f = async () => { await T.RPCGen.SimpleFSSimpleFSSetSfmiBannerDismissedRpcPromise({dismissed}) } ignorePromise(f()) }) - s.dispatch.dynamic.afterDriverEnabled = wrapErrors((isRetry: boolean) => { + s.dispatch.defer.afterDriverEnabled = wrapErrors((isRetry: boolean) => { const f = async () => { - useFSState.getState().dispatch.dynamic.setSfmiBannerDismissedDesktop?.(false) + useFSState.getState().dispatch.defer.setSfmiBannerDismissedDesktop?.(false) if (isWindows) { await onInstallCachedDokan() } else { @@ -514,9 +514,9 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.afterDriverDisable = wrapErrors(() => { + s.dispatch.defer.afterDriverDisable = wrapErrors(() => { const f = async () => { - useFSState.getState().dispatch.dynamic.setSfmiBannerDismissedDesktop?.(false) + useFSState.getState().dispatch.defer.setSfmiBannerDismissedDesktop?.(false) if (isWindows) { await uninstallDokanConfirm() } else { @@ -526,7 +526,7 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.afterDriverDisabling = wrapErrors(() => { + s.dispatch.defer.afterDriverDisabling = wrapErrors(() => { const f = async () => { if (isWindows) { await onUninstallDokan() @@ -537,14 +537,14 @@ export const initPlatformListener = () => { ignorePromise(f()) }) - s.dispatch.dynamic.openSecurityPreferencesDesktop = wrapErrors(() => { + s.dispatch.defer.openSecurityPreferencesDesktop = wrapErrors(() => { const f = async () => { await openURL?.('x-apple.systempreferences:com.apple.preference.security?General', {activate: true}) } ignorePromise(f()) }) - s.dispatch.dynamic.openFilesFromWidgetDesktop = wrapErrors((path: T.FS.Path) => { + s.dispatch.defer.openFilesFromWidgetDesktop = wrapErrors((path: T.FS.Path) => { useConfigState.getState().dispatch.showMain() if (path) { Constants.navToPath(path) @@ -553,7 +553,7 @@ export const initPlatformListener = () => { } }) - s.dispatch.dynamic.openAndUploadDesktop = wrapErrors( + s.dispatch.defer.openAndUploadDesktop = wrapErrors( (type: T.FS.OpenDialogType, parentPath: T.FS.Path) => { const f = async () => { const localPaths = await (selectFilesToUploadDialog?.(type, parentPath ?? undefined) ?? @@ -565,15 +565,15 @@ export const initPlatformListener = () => { ) if (!isLinux) { - s.dispatch.dynamic.afterKbfsDaemonRpcStatusChanged = wrapErrors(() => { + s.dispatch.defer.afterKbfsDaemonRpcStatusChanged = wrapErrors(() => { const {kbfsDaemonStatus, dispatch} = useFSState.getState() if (kbfsDaemonStatus.rpcStatus === T.FS.KbfsDaemonRpcStatus.Connected) { - dispatch.dynamic.refreshDriverStatusDesktop?.() + dispatch.defer.refreshDriverStatusDesktop?.() } - dispatch.dynamic.refreshMountDirsDesktop?.() + dispatch.defer.refreshMountDirsDesktop?.() }) // force call as it could have happened already - s.dispatch.dynamic.afterKbfsDaemonRpcStatusChanged() + s.dispatch.defer.afterKbfsDaemonRpcStatusChanged() } }) diff --git a/shared/constants/init/index.native.tsx b/shared/constants/init/index.native.tsx index 9504f03afe6c..73ac54d22fad 100644 --- a/shared/constants/init/index.native.tsx +++ b/shared/constants/init/index.native.tsx @@ -242,7 +242,7 @@ export const onEngineIncoming = (action: EngineGen.Actions) => { export const initPlatformListener = () => { let _lastPersist = '' useConfigState.setState(s => { - s.dispatch.dynamic.persistRoute = wrapErrors((path?: ReadonlyArray) => { + s.dispatch.defer.persistRoute = wrapErrors((path?: ReadonlyArray) => { const f = async () => { if (!useConfigState.getState().startup.loaded) { return @@ -313,7 +313,7 @@ export const initPlatformListener = () => { }) useConfigState.setState(s => { - s.dispatch.dynamic.copyToClipboard = wrapErrors((s: string) => { + s.dispatch.defer.copyToClipboard = wrapErrors((s: string) => { Clipboard.setStringAsync(s) .then(() => {}) .catch(() => {}) @@ -352,10 +352,10 @@ export const initPlatformListener = () => { }) useConfigState.setState(s => { - s.dispatch.dynamic.onFilePickerError = wrapErrors((error: Error) => { + s.dispatch.defer.onFilePickerError = wrapErrors((error: Error) => { Alert.alert('Error', String(error)) }) - s.dispatch.dynamic.openAppStore = wrapErrors(() => { + s.dispatch.defer.openAppStore = wrapErrors(() => { Linking.openURL( isAndroid ? 'http://play.google.com/store/apps/details?id=io.keybase.ossifrage' @@ -412,7 +412,7 @@ export const initPlatformListener = () => { }) useConfigState.setState(s => { - s.dispatch.dynamic.showShareActionSheet = wrapErrors( + s.dispatch.defer.showShareActionSheet = wrapErrors( (filePath: string, message: string, mimeType: string) => { const f = async () => { await showShareActionSheet({filePath, message, mimeType}) @@ -448,7 +448,7 @@ export const initPlatformListener = () => { const f = async () => { await timeoutPromise(1000) const path = getVisiblePath() - useConfigState.getState().dispatch.dynamic.persistRoute?.(path) + useConfigState.getState().dispatch.defer.persistRoute?.(path) } if (!calledShareListenersRegistered && logState().loggedIn) { @@ -479,7 +479,7 @@ export const initPlatformListener = () => { } useConfigState.setState(s => { - s.dispatch.dynamic.openAppSettings = wrapErrors(() => { + s.dispatch.defer.openAppSettings = wrapErrors(() => { const f = async () => { if (isAndroid) { androidOpenSettings() @@ -498,7 +498,7 @@ export const initPlatformListener = () => { }) useRouterState.setState(s => { - s.dispatch.dynamic.tabLongPress = wrapErrors((tab: string) => { + s.dispatch.defer.tabLongPress = wrapErrors((tab: string) => { if (tab !== Tabs.peopleTab) return const accountRows = useConfigState.getState().configuredAccounts const current = useCurrentUserState.getState().username @@ -511,7 +511,7 @@ export const initPlatformListener = () => { }) useFSState.setState(s => { - s.dispatch.dynamic.pickAndUploadMobile = wrapErrors( + s.dispatch.defer.pickAndUploadMobile = wrapErrors( (type: T.FS.MobilePickType, parentPath: T.FS.Path) => { const f = async () => { try { @@ -528,7 +528,7 @@ export const initPlatformListener = () => { } ) - s.dispatch.dynamic.finishedDownloadWithIntentMobile = wrapErrors( + s.dispatch.defer.finishedDownloadWithIntentMobile = wrapErrors( (downloadID: string, downloadIntent: T.FS.DownloadIntent, mimeType: string) => { const f = async () => { const {downloads, dispatch} = useFSState.getState() @@ -570,7 +570,7 @@ export const initPlatformListener = () => { if (isAndroid) { useFSState.setState(s => { - s.dispatch.dynamic.afterKbfsDaemonRpcStatusChanged = wrapErrors(() => { + s.dispatch.defer.afterKbfsDaemonRpcStatusChanged = wrapErrors(() => { const f = async () => { await T.RPCGen.SimpleFSSimpleFSConfigureDownloadRpcPromise({ // Android's cache dir is (when I tried) [app]/cache but Go side uses @@ -582,9 +582,9 @@ export const initPlatformListener = () => { ignorePromise(f()) }) // needs to be called, TODO could make this better - s.dispatch.dynamic.afterKbfsDaemonRpcStatusChanged() + s.dispatch.defer.afterKbfsDaemonRpcStatusChanged() - s.dispatch.dynamic.finishedRegularDownloadMobile = wrapErrors( + s.dispatch.defer.finishedRegularDownloadMobile = wrapErrors( (downloadID: string, mimeType: string) => { const f = async () => { // This is fired from a hook and can happen more than once per downloadID. diff --git a/shared/constants/init/shared.tsx b/shared/constants/init/shared.tsx index 747feabf1c07..8f7c99df08b7 100644 --- a/shared/constants/init/shared.tsx +++ b/shared/constants/init/shared.tsx @@ -140,8 +140,8 @@ export const initTeamBuildingCallbacks = () => { store.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, ...commonCallbacks, ...(namespace === 'chat2' ? { @@ -168,7 +168,7 @@ export const initAutoResetCallbacks = () => { useAutoResetState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { + defer: { onGetRecoverPasswordUsername: () => { return storeRegistry.getState('recover-password').username }, @@ -185,7 +185,7 @@ export const initChat2Callbacks = () => { useChatState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { + defer: { onGetDaemonState: () => { const daemonState = storeRegistry.getState('daemon') return {dispatch: daemonState.dispatch, handshakeVersion: daemonState.handshakeVersion} @@ -215,8 +215,8 @@ export const initTeamsCallbacks = () => { useTeamsState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onChatNavigateToInbox: (allowSwitchTab?: boolean) => { storeRegistry.getState('chat').dispatch.navigateToInbox(allowSwitchTab) }, @@ -238,8 +238,8 @@ export const initFSCallbacks = () => { useFSState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onBadgeApp: (key: 'kbfsUploading' | 'outOfSpace', on: boolean) => { useNotifState.getState().dispatch.badgeApp(key, on) }, @@ -256,8 +256,8 @@ export const initNotificationsCallbacks = () => { useNotifState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onFavoritesLoad: () => { useFSState.getState().dispatch.favoritesLoad() }, @@ -271,8 +271,8 @@ export const initProfileCallbacks = () => { useProfileState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onTracker2GetDetails: (username: string) => { return useTrackerState.getState().getDetails(username) }, @@ -297,8 +297,8 @@ export const initPushCallbacks = () => { usePushState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onGetDaemonHandshakeState: () => { return useDaemonState.getState().handshakeState }, @@ -324,8 +324,8 @@ export const initRecoverPasswordCallbacks = () => { useRecoverPasswordState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onProvisionCancel: (ignoreWarning?: boolean) => { useProvisionState.getState().dispatch.dynamic.cancel?.(ignoreWarning) }, @@ -342,8 +342,8 @@ export const initSignupCallbacks = () => { useSignupState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onEditEmail: (p: {email: string; makeSearchable: boolean}) => { useSettingsEmailState.getState().dispatch.editEmail(p) }, @@ -360,8 +360,8 @@ export const initTracker2Callbacks = () => { useTrackerState.setState({ dispatch: { ...currentState.dispatch, - dynamic: { - ...currentState.dispatch.dynamic, + defer: { + ...currentState.dispatch.defer, onShowUserProfile: (username: string) => { useProfileState.getState().dispatch.showUserProfile(username) }, diff --git a/shared/crypto/output.tsx b/shared/crypto/output.tsx index 435d0edd901c..6510f136f84b 100644 --- a/shared/crypto/output.tsx +++ b/shared/crypto/output.tsx @@ -181,7 +181,7 @@ export const OutputActionsBar = (props: OutputActionsBarProps) => { const actionsDisabled = waiting || !outputValid const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const onShowInFinder = () => { openLocalPathInSystemFileManagerDesktop?.(output.stringValue()) @@ -194,7 +194,7 @@ export const OutputActionsBar = (props: OutputActionsBarProps) => { previewConversation({participants: [username.stringValue()], reason: 'search'}) } - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const onCopyOutput = () => { copyToClipboard(output.stringValue()) } @@ -369,7 +369,7 @@ export const OperationOutput = (props: OutputProps) => { const output = _output.stringValue() const openLocalPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop + s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop ) const onShowInFinder = () => { if (!output) return diff --git a/shared/fs/banner/conflict-banner.tsx b/shared/fs/banner/conflict-banner.tsx index c39440d9d96c..c43e0333121f 100644 --- a/shared/fs/banner/conflict-banner.tsx +++ b/shared/fs/banner/conflict-banner.tsx @@ -33,7 +33,7 @@ const ConnectedBanner = (ownProps: OwnProps) => { }, [startManualConflictResolution, path]) const openPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openPathInSystemFileManagerDesktop + s => s.dispatch.defer.openPathInSystemFileManagerDesktop ) const openInSystemFileManager = React.useCallback( diff --git a/shared/fs/banner/system-file-manager-integration-banner/container.tsx b/shared/fs/banner/system-file-manager-integration-banner/container.tsx index 0114e131cbad..232e32b74c5d 100644 --- a/shared/fs/banner/system-file-manager-integration-banner/container.tsx +++ b/shared/fs/banner/system-file-manager-integration-banner/container.tsx @@ -14,7 +14,7 @@ const SFMIContainer = (op: OwnProps) => { driverDisable: s.dispatch.driverDisable, driverEnable: s.dispatch.driverEnable, driverStatus: s.sfmi.driverStatus, - setSfmiBannerDismissedDesktop: s.dispatch.dynamic.setSfmiBannerDismissedDesktop, + setSfmiBannerDismissedDesktop: s.dispatch.defer.setSfmiBannerDismissedDesktop, settings: s.settings, })) ) @@ -218,7 +218,7 @@ const JustEnabled = ({onDismiss}: JustEnabledProps) => { const {displayingMountDir, openLocalPathInSystemFileManagerDesktop} = useFSState( C.useShallow(s => ({ displayingMountDir: s.sfmi.preferredMountDirs[0] ?? '', - openLocalPathInSystemFileManagerDesktop: s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop, + openLocalPathInSystemFileManagerDesktop: s.dispatch.defer.openLocalPathInSystemFileManagerDesktop, })) ) const open = displayingMountDir diff --git a/shared/fs/banner/system-file-manager-integration-banner/kext-permission-popup.tsx b/shared/fs/banner/system-file-manager-integration-banner/kext-permission-popup.tsx index 7898cf2ca82c..c294c7b776ea 100644 --- a/shared/fs/banner/system-file-manager-integration-banner/kext-permission-popup.tsx +++ b/shared/fs/banner/system-file-manager-integration-banner/kext-permission-popup.tsx @@ -6,7 +6,7 @@ import {useFSState} from '@/stores/fs' const InstallSecurityPrefs = () => { const driverStatus = useFSState(s => s.sfmi.driverStatus) - const openSecurityPreferencesDesktop = useFSState(s => s.dispatch.dynamic.openSecurityPreferencesDesktop) + const openSecurityPreferencesDesktop = useFSState(s => s.dispatch.defer.openSecurityPreferencesDesktop) const onCancel = C.useRouterState(s => s.dispatch.navigateUp) const openSecurityPrefs = React.useCallback( () => openSecurityPreferencesDesktop?.(), diff --git a/shared/fs/browser/index.tsx b/shared/fs/browser/index.tsx index b8dff985b6d0..29410ae9c1bc 100644 --- a/shared/fs/browser/index.tsx +++ b/shared/fs/browser/index.tsx @@ -68,7 +68,7 @@ const DragAndDrop = React.memo(function DragAndDrop(p: { rejectReason?: string }) { const {children, path, rejectReason} = p - const uploadFromDragAndDrop = useFSState(s => s.dispatch.dynamic.uploadFromDragAndDropDesktop) + const uploadFromDragAndDrop = useFSState(s => s.dispatch.defer.uploadFromDragAndDropDesktop) const onAttach = React.useCallback( (localPaths: Array) => uploadFromDragAndDrop?.(path, localPaths), [path, uploadFromDragAndDrop] diff --git a/shared/fs/common/hooks.tsx b/shared/fs/common/hooks.tsx index 95edbb6d8778..bb30566beb4f 100644 --- a/shared/fs/common/hooks.tsx +++ b/shared/fs/common/hooks.tsx @@ -185,8 +185,8 @@ export const useFsWatchDownloadForMobile = C.isMobile const {dlState, finishedDownloadWithIntentMobile, finishedRegularDownloadMobile} = useFSState( C.useShallow(s => ({ dlState: s.downloads.state.get(downloadID) || FS.emptyDownloadState, - finishedDownloadWithIntentMobile: s.dispatch.dynamic.finishedDownloadWithIntentMobile, - finishedRegularDownloadMobile: s.dispatch.dynamic.finishedRegularDownloadMobile, + finishedDownloadWithIntentMobile: s.dispatch.defer.finishedDownloadWithIntentMobile, + finishedRegularDownloadMobile: s.dispatch.defer.finishedRegularDownloadMobile, })) ) const finished = dlState !== FS.emptyDownloadState && !FS.downloadIsOngoing(dlState) diff --git a/shared/fs/common/open-in-system-file-manager.tsx b/shared/fs/common/open-in-system-file-manager.tsx index c45d43352971..44daf606fd2e 100644 --- a/shared/fs/common/open-in-system-file-manager.tsx +++ b/shared/fs/common/open-in-system-file-manager.tsx @@ -9,7 +9,7 @@ type Props = {path: T.FS.Path} const OpenInSystemFileManager = React.memo(function OpenInSystemFileManager({path}: Props) { const openPathInSystemFileManagerDesktop = useFSState( - s => s.dispatch.dynamic.openPathInSystemFileManagerDesktop + s => s.dispatch.defer.openPathInSystemFileManagerDesktop ) const openInSystemFileManager = React.useCallback( () => openPathInSystemFileManagerDesktop?.(path), diff --git a/shared/fs/common/refresh-driver-status-on-mount.tsx b/shared/fs/common/refresh-driver-status-on-mount.tsx index c4739b49fa67..a710da6894c8 100644 --- a/shared/fs/common/refresh-driver-status-on-mount.tsx +++ b/shared/fs/common/refresh-driver-status-on-mount.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import {useFSState} from '@/stores/fs' const RefreshDriverStatusOnMount = () => { - const refreshDriverStatusDesktop = useFSState(s => s.dispatch.dynamic.refreshDriverStatusDesktop) + const refreshDriverStatusDesktop = useFSState(s => s.dispatch.defer.refreshDriverStatusDesktop) const refresh = React.useCallback(() => refreshDriverStatusDesktop?.(), [refreshDriverStatusDesktop]) React.useEffect(() => { diff --git a/shared/fs/common/upload-button.tsx b/shared/fs/common/upload-button.tsx index c335b8e84126..3021fbfbfa05 100644 --- a/shared/fs/common/upload-button.tsx +++ b/shared/fs/common/upload-button.tsx @@ -73,8 +73,8 @@ const UploadButton = (props: UploadButtonProps) => { const Container = (ownProps: OwnProps) => { const _pathItem = useFSState(s => FS.getPathItem(s.pathItems, ownProps.path)) - const openAndUploadDesktop = useFSState(s => s.dispatch.dynamic.openAndUploadDesktop) - const pickAndUploadMobile = useFSState(s => s.dispatch.dynamic.pickAndUploadMobile) + const openAndUploadDesktop = useFSState(s => s.dispatch.defer.openAndUploadDesktop) + const pickAndUploadMobile = useFSState(s => s.dispatch.defer.pickAndUploadMobile) const _openAndUploadBoth = () => { openAndUploadDesktop?.(T.FS.OpenDialogType.Both, ownProps.path) } diff --git a/shared/fs/filepreview/default-view.tsx b/shared/fs/filepreview/default-view.tsx index 70b01d0109ac..3fa036521c01 100644 --- a/shared/fs/filepreview/default-view.tsx +++ b/shared/fs/filepreview/default-view.tsx @@ -19,7 +19,7 @@ const Container = (ownProps: OwnProps) => { C.useShallow(s => ({ _download: s.dispatch.download, fileContext: s.fileContext.get(path) || FS.emptyFileContext, - openPathInSystemFileManagerDesktop: s.dispatch.dynamic.openPathInSystemFileManagerDesktop, + openPathInSystemFileManagerDesktop: s.dispatch.defer.openPathInSystemFileManagerDesktop, pathItem: FS.getPathItem(s.pathItems, path), sfmiEnabled: s.sfmi.driverStatus.type === T.FS.DriverStatusType.Enabled, })) diff --git a/shared/fs/footer/download.tsx b/shared/fs/footer/download.tsx index 062e69bc0a46..9cf91a45cefb 100644 --- a/shared/fs/footer/download.tsx +++ b/shared/fs/footer/download.tsx @@ -37,7 +37,7 @@ const Download = (props: Props) => { cancelDownload: s.dispatch.cancelDownload, dismissDownload: s.dispatch.dismissDownload, dlState: s.downloads.state.get(props.downloadID) || FS.emptyDownloadState, - openLocalPathInSystemFileManagerDesktop: s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop, + openLocalPathInSystemFileManagerDesktop: s.dispatch.defer.openLocalPathInSystemFileManagerDesktop, })) ) const open = dlState.localPath diff --git a/shared/fs/footer/downloads.tsx b/shared/fs/footer/downloads.tsx index bee401a9f534..f00942abd8b0 100644 --- a/shared/fs/footer/downloads.tsx +++ b/shared/fs/footer/downloads.tsx @@ -33,7 +33,7 @@ const Desktop = () => { const {downloadIDs, openLocalPathInSystemFileManagerDesktop} = useFSState( C.useShallow(s => ({ downloadIDs: s.downloads.regularDownloads, - openLocalPathInSystemFileManagerDesktop: s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop, + openLocalPathInSystemFileManagerDesktop: s.dispatch.defer.openLocalPathInSystemFileManagerDesktop, })) ) const openDownloadFolder = () => openLocalPathInSystemFileManagerDesktop?.(C.downloadFolder) diff --git a/shared/profile/post-proof.tsx b/shared/profile/post-proof.tsx index 7f52f1b555be..74f1cc9fd63c 100644 --- a/shared/profile/post-proof.tsx +++ b/shared/profile/post-proof.tsx @@ -49,7 +49,7 @@ const Container = () => { break } const platformUserName = username - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const clearModals = C.useRouterState(s => s.dispatch.clearModals) const onCancel = () => { clearModals() diff --git a/shared/provision/code-page/qr-scan/not-authorized.tsx b/shared/provision/code-page/qr-scan/not-authorized.tsx index 35f641e2827a..cdd21978b3b4 100644 --- a/shared/provision/code-page/qr-scan/not-authorized.tsx +++ b/shared/provision/code-page/qr-scan/not-authorized.tsx @@ -2,7 +2,7 @@ import * as Kb from '@/common-adapters' import {useConfigState} from '@/stores/config' const QRScanNotAuthorized = () => { - const onOpenSettings = useConfigState(s => s.dispatch.dynamic.openAppSettings) + const onOpenSettings = useConfigState(s => s.dispatch.defer.openAppSettings) return ( diff --git a/shared/router-v2/router.native.tsx b/shared/router-v2/router.native.tsx index b6b3cf21b97c..53099d8043d7 100644 --- a/shared/router-v2/router.native.tsx +++ b/shared/router-v2/router.native.tsx @@ -68,7 +68,7 @@ const tabStacks = tabs.map(tab => ( name={tab} listeners={{ tabLongPress: () => { - C.useRouterState.getState().dispatch.dynamic.tabLongPress?.(tab) + C.useRouterState.getState().dispatch.defer.tabLongPress?.(tab) }, }} component={TabStack} diff --git a/shared/settings/archive/index.tsx b/shared/settings/archive/index.tsx index b4953431cd93..ab07df9512c9 100644 --- a/shared/settings/archive/index.tsx +++ b/shared/settings/archive/index.tsx @@ -30,7 +30,7 @@ const ChatJob = React.memo(function ChatJob(p: {index: number; id: string}) { resume(id) }, [resume, id]) - const openFinder = useFSState(s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop) + const openFinder = useFSState(s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop) const onShowFinder = React.useCallback(() => { if (!job) return openFinder?.(job.outPath) @@ -153,7 +153,7 @@ const KBFSJob = React.memo(function KBFSJob(p: {index: number; id: string}) { loadKBFSJobFreshness(id) }) - const openFinder = useFSState(s => s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop) + const openFinder = useFSState(s => s.dispatch.defer.openLocalPathInSystemFileManagerDesktop) const onShowFinder = React.useCallback(() => { if (Kb.Styles.isMobile || !job) { return diff --git a/shared/settings/files/index.desktop.tsx b/shared/settings/files/index.desktop.tsx index 02c9475c612e..f62f7811fba2 100644 --- a/shared/settings/files/index.desktop.tsx +++ b/shared/settings/files/index.desktop.tsx @@ -58,7 +58,7 @@ const FinderIntegration = () => { C.useShallow(s => ({ driverDisable: s.dispatch.driverDisable, driverStatus: s.sfmi.driverStatus, - openLocalPathInSystemFileManagerDesktop: s.dispatch.dynamic.openLocalPathInSystemFileManagerDesktop, + openLocalPathInSystemFileManagerDesktop: s.dispatch.defer.openLocalPathInSystemFileManagerDesktop, preferredMountDirs: s.sfmi.preferredMountDirs, })) ) diff --git a/shared/settings/manage-contacts.tsx b/shared/settings/manage-contacts.tsx index aca33a0abc2f..47cd4f558a43 100644 --- a/shared/settings/manage-contacts.tsx +++ b/shared/settings/manage-contacts.tsx @@ -72,7 +72,7 @@ const ManageContactsBanner = () => { status: s.permissionStatus, })) ) - const onOpenAppSettings = useConfigState(s => s.dispatch.dynamic.openAppSettings) + const onOpenAppSettings = useConfigState(s => s.dispatch.defer.openAppSettings) const {appendNewChatBuilder, navigateAppend, switchTab} = C.useRouterState( C.useShallow(s => ({ appendNewChatBuilder: s.appendNewChatBuilder, diff --git a/shared/stores/autoreset.tsx b/shared/stores/autoreset.tsx index 1120b55e5b04..5c066b41a4e5 100644 --- a/shared/stores/autoreset.tsx +++ b/shared/stores/autoreset.tsx @@ -32,7 +32,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { cancelReset: () => void - dynamic: { + defer: { onGetRecoverPasswordUsername: () => string onStartProvision: (username: string, fromReset: boolean) => void } @@ -85,7 +85,7 @@ export const useAutoResetState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - dynamic: { + defer: { onGetRecoverPasswordUsername: () => { throw new Error('onGetRecoverPasswordUsername not properly initialized') }, @@ -129,7 +129,7 @@ export const useAutoResetState = Z.createZustand((set, get) => { set(s => { s.error = '' }) - get().dispatch.dynamic.onStartProvision(get().username, true) + get().dispatch.defer.onStartProvision(get().username, true) } else { navUpToScreen('login') } @@ -175,7 +175,7 @@ export const useAutoResetState = Z.createZustand((set, get) => { }, resetState: 'default', startAccountReset: (skipPassword, _username) => { - const username = _username || get().dispatch.dynamic.onGetRecoverPasswordUsername() || '' + const username = _username || get().dispatch.defer.onGetRecoverPasswordUsername() || '' set(s => { s.skipPassword = skipPassword s.error = '' diff --git a/shared/stores/chat2.tsx b/shared/stores/chat2.tsx index 6c83479ae0f7..24c548599ed0 100644 --- a/shared/stores/chat2.tsx +++ b/shared/stores/chat2.tsx @@ -113,7 +113,7 @@ export const getBotsAndParticipants = ( ) => { const isAdhocTeam = meta.teamType === 'adhoc' const teamMembers = - useChatState.getState().dispatch.dynamic.onGetTeamsTeamIDToMembers(meta.teamID) ?? + useChatState.getState().dispatch.defer.onGetTeamsTeamIDToMembers(meta.teamID) ?? new Map() let bots: Array = [] if (isAdhocTeam) { @@ -290,7 +290,7 @@ export interface State extends Store { dispatch: { badgesUpdated: (badgeState?: T.RPCGen.BadgeState) => void clearMetas: () => void - dynamic: { + defer: { onGetDaemonState: () => {handshakeVersion: number; dispatch: any} onGetTeamsTeamIDToMembers: ( teamID: T.Teams.TeamID @@ -492,7 +492,7 @@ export const useChatState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - dynamic: { + defer: { onGetDaemonState: () => { throw new Error('onGetDaemonState not properly initialized') }, @@ -845,7 +845,7 @@ export const useChatState = Z.createZustand((set, get) => { if (get().staticConfig) { return } - const {handshakeVersion, dispatch} = get().dispatch.dynamic.onGetDaemonState() + const {handshakeVersion, dispatch} = get().dispatch.defer.onGetDaemonState() const f = async () => { const name = 'chat.loadStatic' dispatch.wait(name, handshakeVersion, true) @@ -984,8 +984,8 @@ export const useChatState = Z.createZustand((set, get) => { const {isMetaGood, meta} = storeRegistry.getConvoState(selectedConversation) if (isMetaGood()) { const {teamID} = meta - if (!get().dispatch.dynamic.onGetTeamsTeamIDToMembers(teamID) && meta.teamname) { - get().dispatch.dynamic.onTeamsGetMembers(teamID) + if (!get().dispatch.defer.onGetTeamsTeamIDToMembers(teamID) && meta.teamname) { + get().dispatch.defer.onTeamsGetMembers(teamID) } } }, @@ -1158,7 +1158,7 @@ export const useChatState = Z.createZustand((set, get) => { const usernames = update.CanonicalName.split(',') const broken = (update.breaks.breaks || []).map(b => b.user.username) const updates = usernames.map(name => ({info: {broken: broken.includes(name)}, name})) - get().dispatch.dynamic.onUsersUpdates(updates) + get().dispatch.defer.onUsersUpdates(updates) break } case EngineGen.chat1ChatUiChatInboxUnverified: @@ -1345,7 +1345,7 @@ export const useChatState = Z.createZustand((set, get) => { cs.dispatch.setMeta(meta) } }) - get().dispatch.dynamic.onTeamsUpdateTeamRetentionPolicy(metas) + get().dispatch.defer.onTeamsUpdateTeamRetentionPolicy(metas) } // this is a more serious problem, but we don't need to bug the user about it logger.error( @@ -1379,7 +1379,7 @@ export const useChatState = Z.createZustand((set, get) => { }, onGetInboxConvsUnboxed: (action: EngineGen.Chat1ChatUiChatInboxConversationPayload) => { // TODO not reactive - const infoMap = get().dispatch.dynamic.onGetUsersInfoMap() + const infoMap = get().dispatch.defer.onGetUsersInfoMap() const {convs} = action.payload.params const inboxUIItems = JSON.parse(convs) as Array const metas: Array = [] @@ -1407,7 +1407,7 @@ export const useChatState = Z.createZustand((set, get) => { }) }) if (added) { - get().dispatch.dynamic.onUsersUpdates( + get().dispatch.defer.onUsersUpdates( Object.keys(usernameToFullname).map(name => ({ info: {fullname: usernameToFullname[name]}, name, @@ -1442,7 +1442,7 @@ export const useChatState = Z.createZustand((set, get) => { return map }, {}) - get().dispatch.dynamic.onUsersUpdates( + get().dispatch.defer.onUsersUpdates( Object.keys(usernameToFullname).map(name => ({ info: {fullname: usernameToFullname[name]}, name, diff --git a/shared/stores/config.tsx b/shared/stores/config.tsx index 1c4e6112c8ab..e9f2aec25ef6 100644 --- a/shared/stores/config.tsx +++ b/shared/stores/config.tsx @@ -147,7 +147,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { + defer: { copyToClipboard: (s: string) => void dumpLogsNative?: (reason: string) => Promise onFilePickerError?: (error: Error) => void @@ -295,10 +295,7 @@ export const useConfigState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - dumpLogs: async reason => { - await get().dispatch.dynamic.dumpLogsNative?.(reason) - }, - dynamic: { + defer: { copyToClipboard: () => { throw new Error('copyToClipboard not implemented?????') }, @@ -312,8 +309,11 @@ export const useConfigState = Z.createZustand((set, get) => { showMainNative: undefined, showShareActionSheet: undefined, }, + dumpLogs: async reason => { + await get().dispatch.defer.dumpLogsNative?.(reason) + }, filePickerError: error => { - get().dispatch.dynamic.onFilePickerError?.(error) + get().dispatch.defer.onFilePickerError?.(error) }, initAppUpdateLoop: () => { const f = async () => { @@ -509,7 +509,7 @@ export const useConfigState = Z.createZustand((set, get) => { } ignorePromise(registerForGregorNotifications()) - get().dispatch.dynamic.onEngineConnectedDesktop?.() + get().dispatch.defer.onEngineConnectedDesktop?.() get().dispatch.loadOnStart('initialStartupAsEarlyAsPossible') }, onEngineIncoming: action => { @@ -854,7 +854,7 @@ export const useConfigState = Z.createZustand((set, get) => { }) }, showMain: () => { - get().dispatch.dynamic.showMainNative?.() + get().dispatch.defer.showMainNative?.() }, toggleRuntimeStats: () => { const f = async () => { diff --git a/shared/stores/convostate.tsx b/shared/stores/convostate.tsx index 189056f6512f..a48c54a4cc79 100644 --- a/shared/stores/convostate.tsx +++ b/shared/stores/convostate.tsx @@ -1245,7 +1245,7 @@ const createSlice = ( blockConversation: reportUser => { const f = async () => { chatStateHook.getState().dispatch.navigateToInbox() - useConfigState.getState().dispatch.dynamic.persistRoute?.() + useConfigState.getState().dispatch.defer.persistRoute?.() await T.RPCChat.localSetConversationStatusLocalRpcPromise({ conversationID: get().getConvID(), identifyBehavior: T.RPCGen.TLFIdentifyBehavior.chatGui, diff --git a/shared/stores/fs.tsx b/shared/stores/fs.tsx index ca53bdd9fa85..8be0322acc7f 100644 --- a/shared/stores/fs.tsx +++ b/shared/stores/fs.tsx @@ -379,7 +379,7 @@ export interface State extends Store { driverDisabling: () => void driverEnable: (isRetry?: boolean) => void driverKextPermissionError: () => void - dynamic: { + defer: { afterDriverDisable?: () => void afterDriverDisabling?: () => void afterDriverEnabled?: (isRetry: boolean) => void @@ -743,7 +743,7 @@ export const useFSState = Z.createZustand((set, get) => { ignorePromise(f()) }, driverDisable: () => { - get().dispatch.dynamic.afterDriverDisable?.() + get().dispatch.defer.afterDriverDisable?.() }, driverDisabling: () => { set(s => { @@ -751,7 +751,7 @@ export const useFSState = Z.createZustand((set, get) => { s.sfmi.driverStatus.isDisabling = true } }) - get().dispatch.dynamic.afterDriverDisabling?.() + get().dispatch.defer.afterDriverDisabling?.() }, driverEnable: isRetry => { set(s => { @@ -759,7 +759,7 @@ export const useFSState = Z.createZustand((set, get) => { s.sfmi.driverStatus.isEnabling = true } }) - get().dispatch.dynamic.afterDriverEnabled?.(!!isRetry) + get().dispatch.defer.afterDriverEnabled?.(!!isRetry) }, driverKextPermissionError: () => { set(s => { @@ -769,7 +769,7 @@ export const useFSState = Z.createZustand((set, get) => { } }) }, - dynamic: { + defer: { afterDriverDisable: undefined, afterDriverDisabling: undefined, afterDriverEnabled: undefined, @@ -905,7 +905,7 @@ export const useFSState = Z.createZustand((set, get) => { }) const counts = new Map() counts.set(Tabs.fsTab, Constants.computeBadgeNumberForAll(get().tlfs)) - get().dispatch.dynamic.onSetBadgeCounts?.(counts) + get().dispatch.defer.onSetBadgeCounts?.(counts) } } catch (e) { errorToActionOrThrow(e) @@ -1148,7 +1148,7 @@ export const useFSState = Z.createZustand((set, get) => { } subscribeAndLoadJournalStatus() // how this works isn't great. This function gets called way early before we set this - get().dispatch.dynamic.afterKbfsDaemonRpcStatusChanged?.() + get().dispatch.defer.afterKbfsDaemonRpcStatusChanged?.() }, letResetUserBackIn: (id, username) => { const f = async () => { @@ -1645,12 +1645,12 @@ export const useFSState = Z.createZustand((set, get) => { if (totalSyncingBytes <= 0 && !syncingPaths?.length) { break } - get().dispatch.dynamic.onBadgeApp?.('kbfsUploading', true) + get().dispatch.defer.onBadgeApp?.('kbfsUploading', true) await timeoutPromise(getWaitDuration(endEstimate || undefined, 100, 4000)) // 0.1s to 4s } } finally { pollJournalStatusPolling = false - get().dispatch.dynamic.onBadgeApp?.('kbfsUploading', false) + get().dispatch.defer.onBadgeApp?.('kbfsUploading', false) get().dispatch.checkKbfsDaemonRpcStatus() } } @@ -1693,7 +1693,7 @@ export const useFSState = Z.createZustand((set, get) => { set(s => { s.sfmi.driverStatus = driverStatus }) - get().dispatch.dynamic.refreshMountDirsDesktop?.() + get().dispatch.defer.refreshMountDirsDesktop?.() }, setEditName: (editID, name) => { set(s => { @@ -1903,7 +1903,7 @@ export const useFSState = Z.createZustand((set, get) => { body: 'You are out of disk space. Some folders could not be synced.', sound: true, }) - get().dispatch.dynamic.onBadgeApp?.('outOfSpace', status.outOfSyncSpace) + get().dispatch.defer.onBadgeApp?.('outOfSpace', status.outOfSyncSpace) break } case T.FS.DiskSpaceStatus.Warning: diff --git a/shared/stores/notifications.tsx b/shared/stores/notifications.tsx index 1d472d36a83b..ba83285d4302 100644 --- a/shared/stores/notifications.tsx +++ b/shared/stores/notifications.tsx @@ -29,7 +29,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { + defer: { onFavoritesLoad?: () => void } onEngineIncomingImpl: (action: EngineGen.Actions) => void @@ -103,7 +103,7 @@ export const useNotifState = Z.createZustand((set, get) => { updateWidgetBadge(s) }) }, - dynamic: { + defer: { onFavoritesLoad: () => { throw new Error('onFavoritesLoad not implemented') }, @@ -133,7 +133,7 @@ export const useNotifState = Z.createZustand((set, get) => { const counts = badgeStateToBadgeCounts(badgeState) if (!isMobile && shouldTriggerTlfLoad(badgeState)) { - get().dispatch.dynamic.onFavoritesLoad?.() + get().dispatch.defer.onFavoritesLoad?.() } if (counts) { get().dispatch.setBadgeCounts(counts) diff --git a/shared/stores/profile.tsx b/shared/stores/profile.tsx index 40df3896e0c8..154178603e1c 100644 --- a/shared/stores/profile.tsx +++ b/shared/stores/profile.tsx @@ -98,12 +98,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { - afterCheckProof?: () => void - cancelAddProof?: () => void - cancelPgpGen?: () => void - finishedWithKeyGen?: (shouldStoreKeyOnServer: boolean) => void - submitUsername?: () => void + defer: { onTracker2GetDetails?: (username: string) => T.Tracker.Details | undefined onTracker2Load?: ( params: Parameters['dispatch']['load']>[0] @@ -111,6 +106,13 @@ export interface State extends Store { onTracker2ShowUser?: (username: string, asTracker: boolean, skipNav?: boolean) => void onTracker2UpdateResult?: (guiID: string, result: T.Tracker.DetailsState, reason?: string) => void } + dynamic: { + afterCheckProof?: () => void + cancelAddProof?: () => void + cancelPgpGen?: () => void + finishedWithKeyGen?: (shouldStoreKeyOnServer: boolean) => void + submitUsername?: () => void + } addProof: (platform: string, reason: 'appLink' | 'profile') => void backToProfile: () => void checkProof: () => void @@ -272,7 +274,7 @@ export const useProfileState = Z.createZustand((set, get) => { let canceled = false const loadAfter = () => - get().dispatch.dynamic.onTracker2Load?.({ + get().dispatch.defer.onTracker2Load?.({ assertion: useCurrentUserState.getState().username, guiID: generateGUIID(), inTracker: false, @@ -491,10 +493,7 @@ export const useProfileState = Z.createZustand((set, get) => { clearErrors(s) }) }, - dynamic: { - cancelAddProof: _cancelAddProof, - cancelPgpGen: undefined, - finishedWithKeyGen: undefined, + defer: { onTracker2GetDetails: () => { throw new Error('onTracker2GetDetails not implemented') }, @@ -508,6 +507,11 @@ export const useProfileState = Z.createZustand((set, get) => { throw new Error('onTracker2UpdateResult not implemented') }, }, + dynamic: { + cancelAddProof: _cancelAddProof, + cancelPgpGen: undefined, + finishedWithKeyGen: undefined, + }, editAvatar: () => { throw new Error('This is overloaded by platform specific') }, @@ -521,7 +525,7 @@ export const useProfileState = Z.createZustand((set, get) => { finishRevoking: () => { const username = useCurrentUserState.getState().username get().dispatch.showUserProfile(username) - get().dispatch.dynamic.onTracker2Load?.({ + get().dispatch.defer.onTracker2Load?.({ assertion: useCurrentUserState.getState().username, guiID: generateGUIID(), inTracker: false, @@ -617,7 +621,7 @@ export const useProfileState = Z.createZustand((set, get) => { }) const f = async () => { await T.RPCGen.proveCheckProofRpcPromise({sigID}, S.waitingKeyProfile) - get().dispatch.dynamic.onTracker2ShowUser?.(useCurrentUserState.getState().username, false) + get().dispatch.defer.onTracker2ShowUser?.(useCurrentUserState.getState().username, false) } ignorePromise(f()) }, @@ -644,7 +648,7 @@ export const useProfileState = Z.createZustand((set, get) => { set(s => { s.blockUserModal = undefined }) - get().dispatch.dynamic.onTracker2Load?.({ + get().dispatch.defer.onTracker2Load?.({ assertion: username, guiID: generateGUIID(), inTracker: false, @@ -665,7 +669,7 @@ export const useProfileState = Z.createZustand((set, get) => { }, submitRevokeProof: proofId => { const f = async () => { - const you = get().dispatch.dynamic.onTracker2GetDetails?.(useCurrentUserState.getState().username) + const you = get().dispatch.defer.onTracker2GetDetails?.(useCurrentUserState.getState().username) if (!you?.assertions) return const proof = [...you.assertions.values()].find(a => a.sigID === proofId) if (!proof) return @@ -697,7 +701,7 @@ export const useProfileState = Z.createZustand((set, get) => { const f = async () => { try { await T.RPCGen.userUnblockUserRpcPromise({username}) - get().dispatch.dynamic.onTracker2Load?.({ + get().dispatch.defer.onTracker2Load?.({ assertion: username, guiID: generateGUIID(), inTracker: false, @@ -709,7 +713,7 @@ export const useProfileState = Z.createZustand((set, get) => { } const error = _error logger.warn(`Error unblocking user ${username}`, error) - get().dispatch.dynamic.onTracker2UpdateResult?.( + get().dispatch.defer.onTracker2UpdateResult?.( guiID, 'error', `Failed to unblock ${username}: ${error.desc}` diff --git a/shared/stores/push.d.ts b/shared/stores/push.d.ts index 690c3ebfe63d..29e8b1ff366f 100644 --- a/shared/stores/push.d.ts +++ b/shared/stores/push.d.ts @@ -10,7 +10,7 @@ type Store = T.Immutable<{ export type State = Store & { dispatch: { - dynamic: { + defer: { onGetDaemonHandshakeState?: () => T.Config.DaemonHandshakeState onNavigateToThread?: ( conversationIDKey: T.Chat.ConversationIDKey, diff --git a/shared/stores/push.desktop.tsx b/shared/stores/push.desktop.tsx index 8596722c5f76..de5cbab96bff 100644 --- a/shared/stores/push.desktop.tsx +++ b/shared/stores/push.desktop.tsx @@ -16,7 +16,7 @@ export const usePushState = Z.createZustand(() => { return Promise.resolve(false) }, deleteToken: () => {}, - dynamic: { + defer: { onGetDaemonHandshakeState: () => { return 'done' }, diff --git a/shared/stores/push.native.tsx b/shared/stores/push.native.tsx index b1f131b7cde1..582f0a8603f9 100644 --- a/shared/stores/push.native.tsx +++ b/shared/stores/push.native.tsx @@ -71,7 +71,7 @@ export const usePushState = Z.createZustand((set, get) => { const {conversationIDKey, unboxPayload, membersType} = notification - get().dispatch.dynamic.onNavigateToThread?.(conversationIDKey, 'push', unboxPayload) + get().dispatch.defer.onNavigateToThread?.(conversationIDKey, 'push', unboxPayload) if (unboxPayload && membersType && !isIOS) { try { await T.RPCChat.localUnboxMobilePushNotificationRpcPromise({ @@ -135,7 +135,7 @@ export const usePushState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - dynamic: { + defer: { onGetDaemonHandshakeState: () => { throw new Error('onGetDaemonHandshakeState not implemented') }, @@ -164,13 +164,13 @@ export const usePushState = Z.createZustand((set, get) => { // We only care if the user clicked while in session if (notification.userInteraction) { const {username} = notification - get().dispatch.dynamic.onShowUserProfile?.(username) + get().dispatch.defer.onShowUserProfile?.(username) } break case 'chat.extension': { const {conversationIDKey} = notification - get().dispatch.dynamic.onNavigateToThread?.(conversationIDKey, 'extension') + get().dispatch.defer.onNavigateToThread?.(conversationIDKey, 'extension') } break case 'settings.contacts': @@ -233,13 +233,13 @@ export const usePushState = Z.createZustand((set, get) => { const shownPushPrompt = await askNativeIfSystemPushPromptHasBeenShown() if (shownPushPrompt) { // we've already shown the prompt, take them to settings - useConfigState.getState().dispatch.dynamic.openAppSettings?.() + useConfigState.getState().dispatch.defer.openAppSettings?.() get().dispatch.showPermissionsPrompt({persistSkip: true, show: false}) return } } try { - useConfigState.getState().dispatch.dynamic.openAppSettings?.() + useConfigState.getState().dispatch.defer.openAppSettings?.() const {increment} = useWaitingState.getState().dispatch increment(S.waitingKeyPushPermissionsRequesting) await requestPermissionsFromNative() @@ -307,7 +307,7 @@ export const usePushState = Z.createZustand((set, get) => { if ( p.show && useConfigState.getState().loggedIn && - get().dispatch.dynamic.onGetDaemonHandshakeState?.() === 'done' && + get().dispatch.defer.onGetDaemonHandshakeState?.() === 'done' && !get().justSignedUp && !get().hasPermissions ) { diff --git a/shared/stores/recover-password.tsx b/shared/stores/recover-password.tsx index 2888b3f79dcb..6136a01a06ec 100644 --- a/shared/stores/recover-password.tsx +++ b/shared/stores/recover-password.tsx @@ -34,10 +34,12 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { - cancel?: () => void + defer: { onProvisionCancel?: (ignoreWarning?: boolean) => void onStartAccountReset?: (skipPassword: boolean, username: string) => void + } + dynamic: { + cancel?: () => void submitDeviceSelect?: (name: string) => void submitPaperKey?: (key: string) => void submitPassword?: (pw: string) => void @@ -50,14 +52,16 @@ export interface State extends Store { export const useState = Z.createZustand((set, get) => { const dispatch: State['dispatch'] = { - dynamic: { - cancel: undefined, + defer: { onProvisionCancel: () => { throw new Error('onProvisionCancel not implemented') }, onStartAccountReset: () => { throw new Error('onStartAccountReset not implemented') }, + }, + dynamic: { + cancel: undefined, submitDeviceSelect: undefined, submitPaperKey: undefined, submitPassword: undefined, @@ -82,7 +86,7 @@ export const useState = Z.createZustand((set, get) => { const f = async () => { if (p.abortProvisioning) { - get().dispatch.dynamic.onProvisionCancel?.() + get().dispatch.defer.onProvisionCancel?.() } let hadError = false try { @@ -146,7 +150,7 @@ export const useState = Z.createZustand((set, get) => { }) }) } else { - get().dispatch.dynamic.onStartAccountReset?.(true, '') + get().dispatch.defer.onStartAccountReset?.(true, '') response.result(T.RPCGen.ResetPromptResponse.nothing) } }, diff --git a/shared/stores/router2.tsx b/shared/stores/router2.tsx index b2dc1cbac7d6..0a1cf4cc0804 100644 --- a/shared/stores/router2.tsx +++ b/shared/stores/router2.tsx @@ -34,7 +34,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { clearModals: () => void - dynamic: { + defer: { tabLongPress?: (tab: string) => void } navigateAppend: (path: Util.PathParam, replace?: boolean) => void @@ -54,7 +54,7 @@ export interface State extends Store { export const useRouterState = Z.createZustand((set, get) => { const dispatch: State['dispatch'] = { clearModals: Util.clearModals, - dynamic: { + defer: { tabLongPress: undefined, }, navUpToScreen: Util.navUpToScreen, diff --git a/shared/stores/signup.tsx b/shared/stores/signup.tsx index f42110c7072d..3d35852a6978 100644 --- a/shared/stores/signup.tsx +++ b/shared/stores/signup.tsx @@ -45,7 +45,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { + defer: { onEditEmail?: (p: {email: string; makeSearchable: boolean}) => void onShowPermissionsPrompt?: (p: {justSignedUp?: boolean}) => void } @@ -84,7 +84,7 @@ export const useSignupState = Z.createZustand((set, get) => { } try { - get().dispatch.dynamic.onShowPermissionsPrompt?.({justSignedUp: true}) + get().dispatch.defer.onShowPermissionsPrompt?.({justSignedUp: true}) await T.RPCGen.signupSignupRpcListener({ customResponseIncomingCallMap: { @@ -125,7 +125,7 @@ export const useSignupState = Z.createZustand((set, get) => { } // If the email was set to be visible during signup, we need to set that with a separate RPC. if (noErrors() && get().emailVisible) { - get().dispatch.dynamic.onEditEmail?.({email: get().email, makeSearchable: true}) + get().dispatch.defer.onEditEmail?.({email: get().email, makeSearchable: true}) } } catch (_error) { if (_error instanceof RPCError) { @@ -134,7 +134,7 @@ export const useSignupState = Z.createZustand((set, get) => { s.signupError = error }) navigateAppend('signupError') - get().dispatch.dynamic.onShowPermissionsPrompt?.({justSignedUp: false}) + get().dispatch.defer.onShowPermissionsPrompt?.({justSignedUp: false}) } } } @@ -232,7 +232,7 @@ export const useSignupState = Z.createZustand((set, get) => { s.justSignedUpEmail = '' }) }, - dynamic: { + defer: { onEditEmail: () => { throw new Error('onEditEmail not implemented') }, diff --git a/shared/stores/team-building.tsx b/shared/stores/team-building.tsx index d76b23e45847..549bedfb5e95 100644 --- a/shared/stores/team-building.tsx +++ b/shared/stores/team-building.tsx @@ -53,7 +53,7 @@ export interface State extends Store { cancelTeamBuilding: () => void changeSendNotification: (sendNotification: boolean) => void closeTeamBuilding: () => void - dynamic: { + defer: { onAddMembersWizardPushMembers: (members: Array) => void onFinishedTeamBuildingChat: (users: ReadonlySet) => void onFinishedTeamBuildingCrypto: (users: ReadonlySet) => void @@ -280,7 +280,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { // we want the first item for (const user of teamSoFar) { const username = user.serviceMap.keybase || user.id - get().dispatch.dynamic.onShowUserProfile(username) + get().dispatch.defer.onShowUserProfile(username) break } }, 100) @@ -307,7 +307,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { navigateUp() } }, - dynamic: { + defer: { onAddMembersWizardPushMembers: (_members: Array) => { throw new Error('onAddMembersWizardPushMembers not properly initialized') }, @@ -348,7 +348,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { const contacts = contactRes.map(contactToUser) let suggestions = suggestionRes.map(interestingPersonToUser) const expectingContacts = - get().dispatch.dynamic.onGetSettingsContactsImportEnabled() && includeContacts + get().dispatch.defer.onGetSettingsContactsImportEnabled() && includeContacts if (expectingContacts) { suggestions = suggestions.slice(0, 10) } @@ -371,7 +371,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { get().dispatch.closeTeamBuilding() const {teamSoFar} = get() if (get().namespace === 'teams') { - get().dispatch.dynamic.onAddMembersWizardPushMembers( + get().dispatch.defer.onAddMembersWizardPushMembers( [...teamSoFar].map(user => ({assertion: user.id, role: 'writer'})) ) get().dispatch.finishedTeamBuilding() @@ -393,11 +393,11 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { const {finishedTeam, namespace} = get() switch (namespace) { case 'crypto': { - get().dispatch.dynamic.onFinishedTeamBuildingCrypto(finishedTeam) + get().dispatch.defer.onFinishedTeamBuildingCrypto(finishedTeam) break } case 'chat2': { - get().dispatch.dynamic.onFinishedTeamBuildingChat(finishedTeam) + get().dispatch.defer.onFinishedTeamBuildingChat(finishedTeam) break } default: @@ -448,7 +448,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { let users: typeof _users if (selectedService === 'keybase') { // If we are on Keybase tab, do additional search if query is phone/email. - const userRegion = get().dispatch.dynamic.onGetSettingsContactsUserCountryCode() + const userRegion = get().dispatch.defer.onGetSettingsContactsUserCountryCode() users = await specialContactSearch(_users, searchQuery, userRegion) } else { users = _users @@ -465,7 +465,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { } return arr }, new Array<{info: {fullname: string}; name: string}>()) - get().dispatch.dynamic.onUsersUpdates(updates) + get().dispatch.defer.onUsersUpdates(updates) const blocks = users.reduce((arr, {serviceMap}) => { const {keybase} = serviceMap if (keybase) { @@ -474,7 +474,7 @@ const createSlice: Z.ImmerStateCreator = (set, get) => { return arr }, new Array()) if (blocks.length) { - get().dispatch.dynamic.onUsersGetBlockState(blocks) + get().dispatch.defer.onUsersGetBlockState(blocks) } } ignorePromise(f()) diff --git a/shared/stores/teams.tsx b/shared/stores/teams.tsx index b240ef5a7dad..1ed37904cabe 100644 --- a/shared/stores/teams.tsx +++ b/shared/stores/teams.tsx @@ -865,12 +865,14 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { + defer: { onChatNavigateToInbox?: (allowSwitchTab?: boolean) => void onChatPreviewConversation?: ( p: Parameters['dispatch']['previewConversation']>[0] ) => void onUsersUpdates?: (updates: ReadonlyArray<{name: string; info: Partial}>) => void + } + dynamic: { respondToInviteLink?: (accept: boolean) => void } addMembersWizardPushMembers: (members: Array) => void @@ -1431,7 +1433,7 @@ export const useTeamsState = Z.createZustand((set, get) => { get().dispatch.loadTeamChannelList(teamID) // Select the new channel, and switch to the chat tab. if (navToChatOnSuccess) { - get().dispatch.dynamic.onChatPreviewConversation?.({ + get().dispatch.defer.onChatPreviewConversation?.({ channelname, conversationIDKey: newConversationIDKey, reason: 'newChannel', @@ -1501,8 +1503,8 @@ export const useTeamsState = Z.createZustand((set, get) => { if (fromChat) { clearModals() - get().dispatch.dynamic.onChatNavigateToInbox?.() - get().dispatch.dynamic.onChatPreviewConversation?.({ + get().dispatch.defer.onChatNavigateToInbox?.() + get().dispatch.defer.onChatPreviewConversation?.({ channelname: 'general', reason: 'convertAdHoc', teamname, @@ -1593,7 +1595,7 @@ export const useTeamsState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - dynamic: { + defer: { onChatNavigateToInbox: (_allowSwitchTab?: boolean) => { throw new Error('onChatNavigateToInbox not implemented') }, @@ -1608,6 +1610,8 @@ export const useTeamsState = Z.createZustand((set, get) => { onUsersUpdates: (_updates: ReadonlyArray<{name: string; info: Partial}>) => { throw new Error('onUsersUpdates not implemented') }, + }, + dynamic: { respondToInviteLink: undefined, }, eagerLoadTeams: () => { @@ -1748,7 +1752,7 @@ export const useTeamsState = Z.createZustand((set, get) => { set(s => { s.teamIDToMembers.set(teamID, members) }) - get().dispatch.dynamic.onUsersUpdates?.( + get().dispatch.defer.onUsersUpdates?.( [...members.values()].map(m => ({ info: {fullname: m.fullName}, name: m.username, diff --git a/shared/stores/tracker2.tsx b/shared/stores/tracker2.tsx index 506941d024ef..8b9475cb04a8 100644 --- a/shared/stores/tracker2.tsx +++ b/shared/stores/tracker2.tsx @@ -163,7 +163,7 @@ const initialStore: Store = { export interface State extends Store { dispatch: { - dynamic: { + defer: { onShowUserProfile?: (username: string) => void onUsersUpdates?: (updates: ReadonlyArray<{name: string; info: Partial}>) => void } @@ -231,7 +231,7 @@ export const useTrackerState = Z.createZustand((set, get) => { s.showTrackerSet.delete(username) }) }, - dynamic: { + defer: { onShowUserProfile: () => { throw new Error('onShowUserProfile not implemented') }, @@ -331,7 +331,7 @@ export const useTrackerState = Z.createZustand((set, get) => { d.followersCount = d.followers.size }) if (fs.users) { - get().dispatch.dynamic.onUsersUpdates?.( + get().dispatch.defer.onUsersUpdates?.( fs.users.map(u => ({info: {fullname: u.fullName}, name: u.username})) ) } @@ -357,7 +357,7 @@ export const useTrackerState = Z.createZustand((set, get) => { d.followingCount = d.following.size }) if (fs.users) { - get().dispatch.dynamic.onUsersUpdates?.( + get().dispatch.defer.onUsersUpdates?.( fs.users.map(u => ({info: {fullname: u.fullName}, name: u.username})) ) } @@ -447,7 +447,7 @@ export const useTrackerState = Z.createZustand((set, get) => { ) d.hidFromFollowers = hidFromFollowers }) - username && get().dispatch.dynamic.onUsersUpdates?.([{info: {fullname: card.fullName}, name: username}]) + username && get().dispatch.defer.onUsersUpdates?.([{info: {fullname: card.fullName}, name: username}]) }, notifyReset: guiID => { set(s => { @@ -606,7 +606,7 @@ export const useTrackerState = Z.createZustand((set, get) => { }) if (!skipNav) { // go to profile page - get().dispatch.dynamic.onShowUserProfile?.(username) + get().dispatch.defer.onShowUserProfile?.(username) } }, updateResult: (guiID, result, reason) => { diff --git a/shared/teams/common/enable-contacts.tsx b/shared/teams/common/enable-contacts.tsx index 829078c08933..477d3faf51dd 100644 --- a/shared/teams/common/enable-contacts.tsx +++ b/shared/teams/common/enable-contacts.tsx @@ -11,7 +11,7 @@ import {useConfigState} from '@/stores/config' * popup. */ const EnableContactsPopup = ({noAccess, onClose}: {noAccess: boolean; onClose: () => void}) => { - const onOpenSettings = useConfigState(s => s.dispatch.dynamic.openAppSettings) + const onOpenSettings = useConfigState(s => s.dispatch.defer.openAppSettings) const [showingPopup, setShowingPopup] = React.useState(noAccess) React.useEffect(() => { diff --git a/shared/tracker2/assertion.tsx b/shared/tracker2/assertion.tsx index 41a35459911b..1cf078bf5ece 100644 --- a/shared/tracker2/assertion.tsx +++ b/shared/tracker2/assertion.tsx @@ -424,7 +424,7 @@ const assertionColorToColor = (c: T.Tracker.AssertionColor) => { const StellarValue = (p: {value: string; color: T.Tracker.AssertionColor}) => { const {value, color} = p - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const onCopyAddress = React.useCallback(() => { copyToClipboard(value) }, [copyToClipboard, value]) diff --git a/shared/util/zustand.tsx b/shared/util/zustand.tsx index 340308eb6d95..b3d223636d5b 100644 --- a/shared/util/zustand.tsx +++ b/shared/util/zustand.tsx @@ -9,7 +9,13 @@ import {wrapErrors} from '@/util/debug' // needed for tsc export type {WritableDraft} from 'immer' -type HasReset = {dispatch: {resetDeleteMe?: boolean; resetState: 'default' | (() => void)}} +type HasReset = { + dispatch: { + defer?: Record + resetDeleteMe?: boolean + resetState: 'default' | (() => void) + } +} const resetters: ((isDebug?: boolean) => void)[] = [] const resettersAndDelete: ((isDebug?: boolean) => void)[] = [] @@ -39,8 +45,9 @@ export const createZustand = ( let resetFunc: () => void if (reset === 'default') { resetFunc = () => { + const currentDefer = store.getState().dispatch.defer // eslint-disable-next-line - store.setState(initialState as any, true) + store.setState({...initialState, dispatch: {...initialState.dispatch, defer: currentDefer}} as any, true) } } else { resetFunc = reset diff --git a/shared/wallets/really-remove-account.tsx b/shared/wallets/really-remove-account.tsx index 88c7ad3c6408..aa7b88fb2143 100644 --- a/shared/wallets/really-remove-account.tsx +++ b/shared/wallets/really-remove-account.tsx @@ -17,7 +17,7 @@ const ReallyRemoveAccountPopup = (props: OwnProps) => { const attachmentRef = React.useRef(null) const setShowToastFalseLater = Kb.useTimeout(() => setShowToast(false), 2000) - const copyToClipboard = useConfigState(s => s.dispatch.dynamic.copyToClipboard) + const copyToClipboard = useConfigState(s => s.dispatch.defer.copyToClipboard) const [sk, setSK] = React.useState('') const loading = !sk From a05ab05b5bc54117ffc8abc177a6a5fddea08f31 Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Tue, 27 Jan 2026 16:39:20 -0500 Subject: [PATCH 2/2] WIP --- shared/desktop/renderer/main2.desktop.tsx | 4 +- .../path-item-action/menu-container.tsx | 2 +- shared/stores/fs.tsx | 48 +++++++++---------- shared/stores/push.desktop.tsx | 2 +- shared/stores/push.native.tsx | 22 ++++----- shared/stores/teams.tsx | 32 ++++++------- 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/shared/desktop/renderer/main2.desktop.tsx b/shared/desktop/renderer/main2.desktop.tsx index 329d55bb0b53..e2d29cd73822 100644 --- a/shared/desktop/renderer/main2.desktop.tsx +++ b/shared/desktop/renderer/main2.desktop.tsx @@ -120,7 +120,7 @@ const eventFromRemoteWindows = (action: RemoteGen.Actions) => { break } case RemoteGen.openFilesFromWidget: { - storeRegistry.getState('fs').dispatch.dynamic.openFilesFromWidgetDesktop?.(action.payload.path) + storeRegistry.getState('fs').dispatch.defer.openFilesFromWidgetDesktop?.(action.payload.path) break } case RemoteGen.saltpackFileOpen: { @@ -136,7 +136,7 @@ const eventFromRemoteWindows = (action: RemoteGen.Actions) => { break } case RemoteGen.openPathInSystemFileManager: { - storeRegistry.getState('fs').dispatch.dynamic.openPathInSystemFileManagerDesktop?.(action.payload.path) + storeRegistry.getState('fs').dispatch.defer.openPathInSystemFileManagerDesktop?.(action.payload.path) break } case RemoteGen.unlockFoldersSubmitPaperKey: { diff --git a/shared/fs/common/path-item-action/menu-container.tsx b/shared/fs/common/path-item-action/menu-container.tsx index 9a7e2f751dd5..74d8f8c7180b 100644 --- a/shared/fs/common/path-item-action/menu-container.tsx +++ b/shared/fs/common/path-item-action/menu-container.tsx @@ -32,7 +32,7 @@ const Container = (op: OwnProps) => { const fileContext = s.fileContext.get(path) || FS.emptyFileContext const {cancelDownload, setPathItemActionMenuView, download, newFolderRow} = s.dispatch const {favoriteIgnore, startRename, dismissDownload} = s.dispatch - const {openPathInSystemFileManagerDesktop} = s.dispatch.dynamic + const {openPathInSystemFileManagerDesktop} = s.dispatch.defer const sfmiEnabled = s.sfmi.driverStatus.type === T.FS.DriverStatusType.Enabled return { cancelDownload, diff --git a/shared/stores/fs.tsx b/shared/stores/fs.tsx index 8be0322acc7f..f3bdde88ab18 100644 --- a/shared/stores/fs.tsx +++ b/shared/stores/fs.tsx @@ -686,6 +686,30 @@ export const useFSState = Z.createZustand((set, get) => { } ignorePromise(f()) }, + defer: { + afterDriverDisable: undefined, + afterDriverDisabling: undefined, + afterDriverEnabled: undefined, + afterKbfsDaemonRpcStatusChanged: undefined, + finishedDownloadWithIntentMobile: undefined, + finishedRegularDownloadMobile: undefined, + onBadgeApp: () => { + throw new Error('onBadgeApp not implemented') + }, + onSetBadgeCounts: () => { + throw new Error('onSetBadgeCounts not implemented') + }, + openAndUploadDesktop: undefined, + openFilesFromWidgetDesktop: undefined, + openLocalPathInSystemFileManagerDesktop: undefined, + openPathInSystemFileManagerDesktop: undefined, + openSecurityPreferencesDesktop: undefined, + pickAndUploadMobile: undefined, + refreshDriverStatusDesktop: undefined, + refreshMountDirsDesktop: undefined, + setSfmiBannerDismissedDesktop: undefined, + uploadFromDragAndDropDesktop: undefined, + }, deleteFile: path => { const f = async () => { const opID = makeUUID() @@ -769,30 +793,6 @@ export const useFSState = Z.createZustand((set, get) => { } }) }, - defer: { - afterDriverDisable: undefined, - afterDriverDisabling: undefined, - afterDriverEnabled: undefined, - afterKbfsDaemonRpcStatusChanged: undefined, - finishedDownloadWithIntentMobile: undefined, - finishedRegularDownloadMobile: undefined, - onBadgeApp: () => { - throw new Error('onBadgeApp not implemented') - }, - onSetBadgeCounts: () => { - throw new Error('onSetBadgeCounts not implemented') - }, - openAndUploadDesktop: undefined, - openFilesFromWidgetDesktop: undefined, - openLocalPathInSystemFileManagerDesktop: undefined, - openPathInSystemFileManagerDesktop: undefined, - openSecurityPreferencesDesktop: undefined, - pickAndUploadMobile: undefined, - refreshDriverStatusDesktop: undefined, - refreshMountDirsDesktop: undefined, - setSfmiBannerDismissedDesktop: undefined, - uploadFromDragAndDropDesktop: undefined, - }, editError: (editID, error) => { set(s => { const e = s.edits.get(editID) diff --git a/shared/stores/push.desktop.tsx b/shared/stores/push.desktop.tsx index de5cbab96bff..4a59a43a8a35 100644 --- a/shared/stores/push.desktop.tsx +++ b/shared/stores/push.desktop.tsx @@ -15,7 +15,6 @@ export const usePushState = Z.createZustand(() => { checkPermissions: async () => { return Promise.resolve(false) }, - deleteToken: () => {}, defer: { onGetDaemonHandshakeState: () => { return 'done' @@ -23,6 +22,7 @@ export const usePushState = Z.createZustand(() => { onNavigateToThread: () => {}, onShowUserProfile: () => {}, }, + deleteToken: () => {}, handlePush: () => {}, initialPermissionsCheck: () => {}, rejectPermissions: () => {}, diff --git a/shared/stores/push.native.tsx b/shared/stores/push.native.tsx index 582f0a8603f9..a2edcc1a8b48 100644 --- a/shared/stores/push.native.tsx +++ b/shared/stores/push.native.tsx @@ -109,6 +109,17 @@ export const usePushState = Z.createZustand((set, get) => { return false } }, + defer: { + onGetDaemonHandshakeState: () => { + throw new Error('onGetDaemonHandshakeState not implemented') + }, + onNavigateToThread: () => { + throw new Error('onNavigateToThread not implemented') + }, + onShowUserProfile: () => { + throw new Error('onShowUserProfile not implemented') + }, + }, deleteToken: version => { const f = async () => { const waitKey = 'push:deleteToken' @@ -135,17 +146,6 @@ export const usePushState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - defer: { - onGetDaemonHandshakeState: () => { - throw new Error('onGetDaemonHandshakeState not implemented') - }, - onNavigateToThread: () => { - throw new Error('onNavigateToThread not implemented') - }, - onShowUserProfile: () => { - throw new Error('onShowUserProfile not implemented') - }, - }, handlePush: notification => { const f = async () => { try { diff --git a/shared/stores/teams.tsx b/shared/stores/teams.tsx index 1ed37904cabe..608429c44cdc 100644 --- a/shared/stores/teams.tsx +++ b/shared/stores/teams.tsx @@ -1540,6 +1540,22 @@ export const useTeamsState = Z.createZustand((set, get) => { })) get().dispatch.createNewTeam(teamname, false, true, {sendChatNotification: true, users}) }, + defer: { + onChatNavigateToInbox: (_allowSwitchTab?: boolean) => { + throw new Error('onChatNavigateToInbox not implemented') + }, + onChatPreviewConversation: (_p: { + channelname?: string + conversationIDKey?: T.Chat.ConversationIDKey + reason?: string + teamname?: string + }) => { + throw new Error('onChatPreviewConversation not implemented') + }, + onUsersUpdates: (_updates: ReadonlyArray<{name: string; info: Partial}>) => { + throw new Error('onUsersUpdates not implemented') + }, + }, deleteChannelConfirmed: (teamID, conversationIDKey) => { const f = async () => { // channelName is only needed for confirmation, so since we handle @@ -1595,22 +1611,6 @@ export const useTeamsState = Z.createZustand((set, get) => { } ignorePromise(f()) }, - defer: { - onChatNavigateToInbox: (_allowSwitchTab?: boolean) => { - throw new Error('onChatNavigateToInbox not implemented') - }, - onChatPreviewConversation: (_p: { - channelname?: string - conversationIDKey?: T.Chat.ConversationIDKey - reason?: string - teamname?: string - }) => { - throw new Error('onChatPreviewConversation not implemented') - }, - onUsersUpdates: (_updates: ReadonlyArray<{name: string; info: Partial}>) => { - throw new Error('onUsersUpdates not implemented') - }, - }, dynamic: { respondToInviteLink: undefined, },