From 4ec716db336b5e961e72b09fd73d7b68b836b1de Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Tue, 6 Jan 2026 16:16:15 -0500 Subject: [PATCH 1/3] WIP --- shared/constants/config/index.tsx | 8 -- .../platform-specific/index.desktop.tsx | 126 +++++++++--------- 2 files changed, 65 insertions(+), 69 deletions(-) diff --git a/shared/constants/config/index.tsx b/shared/constants/config/index.tsx index 3896495377eb..6b27f3685550 100644 --- a/shared/constants/config/index.tsx +++ b/shared/constants/config/index.tsx @@ -15,7 +15,6 @@ import {invalidPasswordErrorString} from './util' import {navigateAppend} from '../router2/util' import {storeRegistry} from '../store-registry' import {useWhatsNewState} from '../whats-new' -import {getSelectedConversation} from '@/constants/chat2/common' type Store = T.Immutable<{ forceSmallNav: boolean @@ -299,13 +298,6 @@ export const useConfigState = Z.createZustand((set, get) => { set(s => { s.appFocused = f }) - - if (!isMobile || !f) { - return - } - const {dispatch} = storeRegistry.getConvoState(getSelectedConversation()) - dispatch.loadMoreMessages({reason: 'foregrounding'}) - dispatch.markThreadAsRead() }, checkForUpdate: () => { const f = async () => { diff --git a/shared/constants/platform-specific/index.desktop.tsx b/shared/constants/platform-specific/index.desktop.tsx index 692bdcc0c6f8..a28843adb9be 100644 --- a/shared/constants/platform-specific/index.desktop.tsx +++ b/shared/constants/platform-specific/index.desktop.tsx @@ -25,6 +25,7 @@ import {initSharedSubscriptions} from './shared' import {switchTab} from '../router2/util' import {storeRegistry} from '../store-registry' import {wrapErrors} from '@/util/debug' +import {getSelectedConversation} from '@/constants/chat2/common' const {showMainWindow, activeChanged, requestWindowsStartService, dumpNodeLogger} = KB2.functions const {quitApp, exitApp, setOpenAtLogin, ctlQuit, copyToClipboard} = KB2.functions @@ -157,39 +158,49 @@ export const initPlatformListener = () => { }) useConfigState.subscribe((s, old) => { - if (s.loggedIn === old.loggedIn) return - s.dispatch.osNetworkStatusChanged(navigator.onLine, 'notavailable', true) - }) + if (s.loggedIn !== old.loggedIn) { + s.dispatch.osNetworkStatusChanged(navigator.onLine, 'notavailable', true) + } - useConfigState.subscribe((s, prev) => { - if (s.appFocused !== prev.appFocused) { + if (s.appFocused !== old.appFocused) { maybePauseVideos() + if (old.appFocused === false && s.appFocused === true) { + const {dispatch} = storeRegistry.getConvoState(getSelectedConversation()) + dispatch.loadMoreMessages({reason: 'foregrounding'}) + dispatch.markThreadAsRead() + } } - }) - useDaemonState.subscribe((s, old) => { - if (s.handshakeVersion === old.handshakeVersion) return - if (!isWindows) return - - const f = async () => { - const waitKey = 'pipeCheckFail' - const version = s.handshakeVersion - const {wait} = s.dispatch - wait(waitKey, version, true) - try { - logger.info('Checking RPC ownership') - if (KB2.functions.winCheckRPCOwnership) { - await KB2.functions.winCheckRPCOwnership() + if (s.openAtLogin !== old.openAtLogin) { + const {openAtLogin} = s + const f = async () => { + if (__DEV__) { + console.log('onSetOpenAtLogin disabled for dev mode') + return + } else { + await T.RPCGen.configGuiSetValueRpcPromise({ + path: ConfigConstants.openAtLoginKey, + value: {b: openAtLogin, isNull: false}, + }) + } + if (isLinux || isWindows) { + const enabled = + (await T.RPCGen.ctlGetOnLoginStartupRpcPromise()) === T.RPCGen.OnLoginStartupStatus.enabled + if (enabled !== openAtLogin) { + try { + await T.RPCGen.ctlSetOnLoginStartupRpcPromise({enabled: openAtLogin}) + } catch (error_) { + const error = error_ as RPCError + logger.warn(`Error in sending ctlSetOnLoginStartup: ${error.message}`) + } + } + } else { + logger.info(`Login item settings changed! now ${openAtLogin ? 'on' : 'off'}`) + await setOpenAtLogin?.(openAtLogin) } - wait(waitKey, version, false) - } catch (error_) { - // error will be logged in bootstrap check - getEngine().reset() - const error = error_ as RPCError - wait(waitKey, version, false, error.message || 'windows pipe owner fail', true) } + ignorePromise(f()) } - ignorePromise(f()) }) const handleWindowFocusEvents = () => { @@ -215,46 +226,39 @@ export const initPlatformListener = () => { } setupReachabilityWatcher() - useConfigState.subscribe((s, old) => { - if (s.openAtLogin === old.openAtLogin) return - const {openAtLogin} = s - const f = async () => { - if (__DEV__) { - console.log('onSetOpenAtLogin disabled for dev mode') - return - } else { - await T.RPCGen.configGuiSetValueRpcPromise({ - path: ConfigConstants.openAtLoginKey, - value: {b: openAtLogin, isNull: false}, - }) - } - if (isLinux || isWindows) { - const enabled = - (await T.RPCGen.ctlGetOnLoginStartupRpcPromise()) === T.RPCGen.OnLoginStartupStatus.enabled - if (enabled !== openAtLogin) { - try { - await T.RPCGen.ctlSetOnLoginStartupRpcPromise({enabled: openAtLogin}) - } catch (error_) { - const error = error_ as RPCError - logger.warn(`Error in sending ctlSetOnLoginStartup: ${error.message}`) + useDaemonState.subscribe((s, old) => { + if (s.handshakeVersion !== old.handshakeVersion) { + if (!isWindows) return + + const f = async () => { + const waitKey = 'pipeCheckFail' + const version = s.handshakeVersion + const {wait} = s.dispatch + wait(waitKey, version, true) + try { + logger.info('Checking RPC ownership') + if (KB2.functions.winCheckRPCOwnership) { + await KB2.functions.winCheckRPCOwnership() } + wait(waitKey, version, false) + } catch (error_) { + // error will be logged in bootstrap check + getEngine().reset() + const error = error_ as RPCError + wait(waitKey, version, false, error.message || 'windows pipe owner fail', true) } - } else { - logger.info(`Login item settings changed! now ${openAtLogin ? 'on' : 'off'}`) - await setOpenAtLogin?.(openAtLogin) } + ignorePromise(f()) } - ignorePromise(f()) - }) - useDaemonState.subscribe((s, old) => { - if (s.handshakeState === old.handshakeState || s.handshakeState !== 'done') return - useConfigState.getState().dispatch.setStartupDetails({ - conversation: Chat.noConversationIDKey, - followUser: '', - link: '', - tab: undefined, - }) + if (s.handshakeState !== old.handshakeState && s.handshakeState === 'done') { + useConfigState.getState().dispatch.setStartupDetails({ + conversation: Chat.noConversationIDKey, + followUser: '', + link: '', + tab: undefined, + }) + } }) if (isLinux) { From b7f7b035d28c95ea51c3dc045732236cdaf54afe Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Tue, 6 Jan 2026 16:22:55 -0500 Subject: [PATCH 2/3] WIP --- shared/constants/platform-specific/index.desktop.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/constants/platform-specific/index.desktop.tsx b/shared/constants/platform-specific/index.desktop.tsx index a28843adb9be..50fca882c4ef 100644 --- a/shared/constants/platform-specific/index.desktop.tsx +++ b/shared/constants/platform-specific/index.desktop.tsx @@ -164,7 +164,7 @@ export const initPlatformListener = () => { if (s.appFocused !== old.appFocused) { maybePauseVideos() - if (old.appFocused === false && s.appFocused === true) { + if (!old.appFocused && s.appFocused) { const {dispatch} = storeRegistry.getConvoState(getSelectedConversation()) dispatch.loadMoreMessages({reason: 'foregrounding'}) dispatch.markThreadAsRead() From a24f959862e4fb13ad0ab3a461d74f729217bccd Mon Sep 17 00:00:00 2001 From: chrisnojima-zoom <83838430+chrisnojima-zoom@users.noreply.github.com> Date: Tue, 6 Jan 2026 17:20:43 -0500 Subject: [PATCH 3/3] WIP (#28767) --- shared/constants/config/index.tsx | 27 ----- shared/constants/platform-specific/shared.tsx | 112 +++++++++++------- 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/shared/constants/config/index.tsx b/shared/constants/config/index.tsx index 6b27f3685550..01a496551e42 100644 --- a/shared/constants/config/index.tsx +++ b/shared/constants/config/index.tsx @@ -243,15 +243,6 @@ export const useConfigState = Z.createZustand((set, get) => { set(s => { s.gregorReachable = r }) - // Re-get info about our account if you log in/we're done handshaking/became reachable - if (r === T.RPCGen.Reachable.yes) { - // not in waiting state - if (storeRegistry.getState('daemon').handshakeWaiters.size === 0) { - ignorePromise(storeRegistry.getState('daemon').dispatch.loadDaemonBootstrapStatus()) - } - } - - storeRegistry.getState('teams').dispatch.eagerLoadTeams() } const setGregorPushState = (state: T.RPCGen.Gregor1.State) => { @@ -394,8 +385,6 @@ export const useConfigState = Z.createZustand((set, get) => { set(s => { s.installerRanCount++ }) - - storeRegistry.getState('fs').dispatch.checkKbfsDaemonRpcStatus() }, loadIsOnline: () => { const f = async () => { @@ -756,11 +745,6 @@ export const useConfigState = Z.createZustand((set, get) => { if (!changed) return - if (loggedIn) { - ignorePromise(storeRegistry.getState('daemon').dispatch.loadDaemonBootstrapStatus()) - } - storeRegistry.getState('daemon').dispatch.loadDaemonAccounts() - const {loadOnStart} = get().dispatch if (loggedIn) { if (!causedByStartup) { @@ -776,14 +760,6 @@ export const useConfigState = Z.createZustand((set, get) => { } else { Z.resetAllStores() } - - if (loggedIn) { - storeRegistry.getState('fs').dispatch.checkKbfsDaemonRpcStatus() - } - - if (!causedByStartup) { - ignorePromise(storeRegistry.getState('daemon').dispatch.refreshAccounts()) - } }, setLoginError: error => { set(s => { @@ -798,9 +774,6 @@ export const useConfigState = Z.createZustand((set, get) => { set(s => { s.mobileAppState = nextAppState }) - if (nextAppState === 'background' && storeRegistry.getState('chat').inboxSearch) { - storeRegistry.getState('chat').dispatch.toggleInboxSearch(false) - } }, setNotifySound: n => { set(s => { diff --git a/shared/constants/platform-specific/shared.tsx b/shared/constants/platform-specific/shared.tsx index a7e2c2a7649f..ebf3c4317f29 100644 --- a/shared/constants/platform-specific/shared.tsx +++ b/shared/constants/platform-specific/shared.tsx @@ -31,59 +31,91 @@ import * as UsersUtil from '../users/util' export const initSharedSubscriptions = () => { useConfigState.subscribe((s, old) => { - if (s.loadOnStartPhase === old.loadOnStartPhase) return + if (s.loadOnStartPhase !== old.loadOnStartPhase) { + if (s.loadOnStartPhase === 'startupOrReloginButNotInARush') { + const getFollowerInfo = () => { + const {uid} = useCurrentUserState.getState() + logger.info(`getFollowerInfo: init; uid=${uid}`) + if (uid) { + // request follower info in the background + T.RPCGen.configRequestFollowingAndUnverifiedFollowersRpcPromise() + .then(() => {}) + .catch(() => {}) + } + } - if (s.loadOnStartPhase === 'startupOrReloginButNotInARush') { - const getFollowerInfo = () => { - const {uid} = useCurrentUserState.getState() - logger.info(`getFollowerInfo: init; uid=${uid}`) - if (uid) { - // request follower info in the background - T.RPCGen.configRequestFollowingAndUnverifiedFollowersRpcPromise() - .then(() => {}) - .catch(() => {}) + const updateServerConfig = async () => { + if (s.loggedIn) { + try { + await T.RPCGen.configUpdateLastLoggedInAndServerConfigRpcPromise({ + serverConfigPath: serverConfigFileName, + }) + } catch {} + } + } + + const updateTeams = () => { + useTeamsState.getState().dispatch.getTeams() + useTeamsState.getState().dispatch.refreshTeamRoleMap() + } + + const updateSettings = () => { + useSettingsContactsState.getState().dispatch.loadContactImportEnabled() } - } - const updateServerConfig = async () => { - if (s.loggedIn) { + const updateChat = async () => { + // On login lets load the untrusted inbox. This helps make some flows easier + if (useCurrentUserState.getState().username) { + const {inboxRefresh} = useChatState.getState().dispatch + inboxRefresh('bootstrap') + } try { - await T.RPCGen.configUpdateLastLoggedInAndServerConfigRpcPromise({ - serverConfigPath: serverConfigFileName, - }) + const rows = await T.RPCGen.configGuiGetValueRpcPromise({path: 'ui.inboxSmallRows'}) + const ri = rows.i ?? -1 + if (ri > 0) { + useChatState.getState().dispatch.setInboxNumSmallRows(ri, true) + } } catch {} } - } - const updateTeams = () => { - useTeamsState.getState().dispatch.getTeams() - useTeamsState.getState().dispatch.refreshTeamRoleMap() + getFollowerInfo() + ignorePromise(updateServerConfig()) + updateTeams() + updateSettings() + ignorePromise(updateChat()) } + } - const updateSettings = () => { - useSettingsContactsState.getState().dispatch.loadContactImportEnabled() + if (s.gregorReachable !== old.gregorReachable) { + // 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()) + } + storeRegistry.getState('teams').dispatch.eagerLoadTeams() } + } - const updateChat = async () => { - // On login lets load the untrusted inbox. This helps make some flows easier - if (useCurrentUserState.getState().username) { - const {inboxRefresh} = useChatState.getState().dispatch - inboxRefresh('bootstrap') - } - try { - const rows = await T.RPCGen.configGuiGetValueRpcPromise({path: 'ui.inboxSmallRows'}) - const ri = rows.i ?? -1 - if (ri > 0) { - useChatState.getState().dispatch.setInboxNumSmallRows(ri, true) - } - } catch {} + if (s.installerRanCount !== old.installerRanCount) { + storeRegistry.getState('fs').dispatch.checkKbfsDaemonRpcStatus() + } + + if (s.loggedIn !== old.loggedIn) { + if (s.loggedIn) { + ignorePromise(storeRegistry.getState('daemon').dispatch.loadDaemonBootstrapStatus()) + storeRegistry.getState('fs').dispatch.checkKbfsDaemonRpcStatus() + } + storeRegistry.getState('daemon').dispatch.loadDaemonAccounts() + if (!s.loggedInCausedbyStartup) { + ignorePromise(storeRegistry.getState('daemon').dispatch.refreshAccounts()) } + } - getFollowerInfo() - ignorePromise(updateServerConfig()) - updateTeams() - updateSettings() - ignorePromise(updateChat()) + if (s.mobileAppState !== old.mobileAppState) { + if (s.mobileAppState === 'background' && storeRegistry.getState('chat').inboxSearch) { + storeRegistry.getState('chat').dispatch.toggleInboxSearch(false) + } } }) }