mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 23:59:45 +08:00
* 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>
137 lines
3.9 KiB
TypeScript
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
|