cherry-studio/src/renderer/src/store/index.ts
Pleasure1234 bf23c5b209
fix: initialize notes path on app startup to resolve missing default directory (#9728)
* fix: initialize notes path on app startup to resolve missing default directory

- Add notes path initialization in store persistStore callback after rehydration
- Update NotesSettings to sync tempPath when notesPath changes from initialization
- Ensure notes directory is set even when user doesn't visit NotesPage first
- Fixes issue where notes path was empty after data reset until NotesPage visit

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update NotesSettings.tsx

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-31 21:46:39 +08:00

137 lines
3.9 KiB
TypeScript

import { loggerService } from '@logger'
import { combineReducers, configureStore } from '@reduxjs/toolkit'
import { useDispatch, useSelector, useStore } from 'react-redux'
import { FLUSH, PAUSE, PERSIST, persistReducer, persistStore, PURGE, REGISTER, REHYDRATE } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import storeSyncService from '../services/StoreSyncService'
import agents from './agents'
import assistants from './assistants'
import backup from './backup'
import codeTools from './codeTools'
import copilot from './copilot'
import inputToolsReducer from './inputTools'
import knowledge from './knowledge'
import llm from './llm'
import mcp from './mcp'
import memory from './memory'
import messageBlocksReducer from './messageBlock'
import migrate from './migrate'
import minapps from './minapps'
import newMessagesReducer from './newMessage'
import { setNotesPath } from './note'
import note from './note'
import nutstore from './nutstore'
import ocr from './ocr'
import paintings from './paintings'
import preprocess from './preprocess'
import runtime from './runtime'
import selectionStore from './selectionStore'
import settings from './settings'
import shortcuts from './shortcuts'
import tabs from './tabs'
import translate from './translate'
import websearch from './websearch'
const logger = loggerService.withContext('Store')
const rootReducer = combineReducers({
assistants,
agents,
backup,
codeTools,
nutstore,
paintings,
llm,
settings,
runtime,
shortcuts,
knowledge,
minapps,
websearch,
mcp,
memory,
copilot,
selectionStore,
tabs,
preprocess,
messages: newMessagesReducer,
messageBlocks: messageBlocksReducer,
inputTools: inputToolsReducer,
translate,
ocr,
note
})
const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 142,
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs'],
migrate
},
rootReducer
)
/**
* Configures the store sync service to synchronize specific state slices across all windows.
* For detailed implementation, see @renderer/services/StoreSyncService.ts
*
* Usage:
* - 'xxxx/' - Synchronizes the entire state slice
* - 'xxxx/sliceName' - Synchronizes a specific slice within the state
*
* To listen for store changes in a window:
* Call storeSyncService.subscribe() in the window's entryPoint.tsx
*/
storeSyncService.setOptions({
syncList: ['assistants/', 'settings/', 'llm/', 'selectionStore/', 'note/']
})
const store = configureStore({
// @ts-ignore store type is unknown
reducer: persistedReducer as typeof rootReducer,
middleware: (getDefaultMiddleware) => {
return getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
}
}).concat(storeSyncService.createMiddleware())
},
devTools: true
})
export type RootState = ReturnType<typeof rootReducer>
export type AppDispatch = typeof store.dispatch
export const persistor = persistStore(store, undefined, () => {
// Initialize notes path after rehydration if empty
const state = store.getState()
if (!state.note.notesPath) {
// Use setTimeout to ensure this runs after the store is fully initialized
setTimeout(async () => {
try {
const info = await window.api.getAppInfo()
store.dispatch(setNotesPath(info.notesPath))
logger.info('Initialized notes path on startup:', info.notesPath)
} catch (error) {
logger.error('Failed to initialize notes path on startup:', error as Error)
}
}, 0)
}
})
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppStore = useStore.withTypes<typeof store>()
window.store = store
export async function handleSaveData() {
logger.info('Flushing redux persistor data')
await persistor.flush()
logger.info('Flushed redux persistor data')
}
export default store