MCPcopy Create free account
hub / github.com/claude-code-best/claude-code / AppStateProvider

Function AppStateProvider

src/state/AppState.tsx:59–102  ·  view source on GitHub ↗
({ children, initialState, onChangeAppState }: Props)

Source from the content-addressed store, hash-verified

57const HasAppStateContext = React.createContext<boolean>(false);
58
59export function AppStateProvider({ children, initialState, onChangeAppState }: Props): React.ReactNode {
60 // Don't allow nested AppStateProviders.
61 const hasAppStateContext = useContext(HasAppStateContext);
62 if (hasAppStateContext) {
63 throw new Error('AppStateProvider can not be nested within another AppStateProvider');
64 }
65
66 // Store is created once and never changes -- stable context value means
67 // the provider never triggers re-renders. Consumers subscribe to slices
68 // via useSyncExternalStore in useAppState(selector).
69 const [store] = useState(() => createStore<AppState>(initialState ?? getDefaultAppState(), onChangeAppState));
70
71 // Check on mount if bypass mode should be disabled
72 // This handles the race condition where remote settings load BEFORE this component mounts,
73 // meaning the settings change notification was sent when no listeners were subscribed.
74 // On subsequent sessions, the cached remote-settings.json is read during initial setup,
75 // but on the first session the remote fetch may complete before React mounts.
76 useEffect(() => {
77 const { toolPermissionContext } = store.getState();
78 if (toolPermissionContext.isBypassPermissionsModeAvailable && isBypassPermissionsModeDisabled()) {
79 logForDebugging('Disabling bypass permissions mode on mount (remote settings loaded before mount)');
80 store.setState(prev => ({
81 ...prev,
82 toolPermissionContext: createDisabledBypassPermissionsContext(prev.toolPermissionContext),
83 }));
84 }
85 }, []);
86
87 // Listen for external settings changes and sync to AppState.
88 // This ensures file watcher changes propagate through the app --
89 // shared with the headless/SDK path via applySettingsChange.
90 const onSettingsChange = useEffectEvent((source: SettingSource) => applySettingsChange(source, store.setState));
91 useSettingsChange(onSettingsChange);
92
93 return (
94 <HasAppStateContext.Provider value={true}>
95 <AppStoreContext.Provider value={store}>
96 <MailboxProvider>
97 <VoiceProvider>{children}</VoiceProvider>
98 </MailboxProvider>
99 </AppStoreContext.Provider>
100 </HasAppStateContext.Provider>
101 );
102}
103
104function useAppStore(): AppStateStore {
105 // eslint-disable-next-line react-hooks/rules-of-hooks

Callers

nothing calls this directly

Calls 9

getDefaultAppStateFunction · 0.85
applySettingsChangeFunction · 0.85
useSettingsChangeFunction · 0.85
getStateMethod · 0.80
setStateMethod · 0.80
createStoreFunction · 0.70
logForDebuggingFunction · 0.50

Tested by

no test coverage detected