From 878053bec7e51c3d9b18eea1ffaeae0fb3afc01e Mon Sep 17 00:00:00 2001 From: wangchengdu Date: Tue, 2 Sep 2025 22:02:22 +0800 Subject: [PATCH 1/2] feat: add backup and restore functionality for personal views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../view/store/usePersonalViewStore.ts | 28 +++++++++++++++++++ packages/sdk/src/hooks/use-personal-view.ts | 13 ++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/sdk/src/context/view/store/usePersonalViewStore.ts b/packages/sdk/src/context/view/store/usePersonalViewStore.ts index d9034ad086..2fa2e05fc5 100644 --- a/packages/sdk/src/context/view/store/usePersonalViewStore.ts +++ b/packages/sdk/src/context/view/store/usePersonalViewStore.ts @@ -4,18 +4,22 @@ import { LocalStorageKeys } from '../../../config'; interface IPersonalViewState { personalViewMap: Record>; + personalViewMapBackup: Record>; isPersonalView: (viewId: string) => boolean; setPersonalViewMap: ( viewId: string, updater: (prev: Record) => Record ) => void; removePersonalView: (viewId: string) => void; + backupPersonalView: (viewId: string) => void; + restorePersonalView: (viewId: string) => boolean; } export const usePersonalViewStore = create()( persist( (set, get) => ({ personalViewMap: {}, + personalViewMapBackup: {}, isPersonalView: (viewId) => { const state = get(); return Boolean(state.personalViewMap[viewId]); @@ -32,6 +36,30 @@ export const usePersonalViewStore = create()( const { [viewId]: _, ...rest } = state.personalViewMap; return { personalViewMap: rest }; }), + backupPersonalView: (viewId) => + set((state) => { + const currentView = state.personalViewMap[viewId]; + if (!currentView) return state; + return { + personalViewMapBackup: { + ...state.personalViewMapBackup, + [viewId]: { ...currentView }, + }, + }; + }), + restorePersonalView: (viewId) => { + const state = get(); + const backup = state.personalViewMapBackup[viewId]; + if (!backup) return false; + + set((state) => ({ + personalViewMap: { + ...state.personalViewMap, + [viewId]: { ...backup }, + }, + })); + return true; + }, }), { name: LocalStorageKeys.PersonalViewMap, diff --git a/packages/sdk/src/hooks/use-personal-view.ts b/packages/sdk/src/hooks/use-personal-view.ts index abee6c5740..c397d529a0 100644 --- a/packages/sdk/src/hooks/use-personal-view.ts +++ b/packages/sdk/src/hooks/use-personal-view.ts @@ -8,19 +8,24 @@ import { useView } from './use-view'; export const usePersonalView = () => { const { isPersonalView, personalViewMap, personalViewCommonQuery, personalViewAggregationQuery } = useContext(PersonalViewContext); - const { removePersonalView, setPersonalViewMap } = usePersonalViewStore(); + const { removePersonalView, setPersonalViewMap, backupPersonalView, restorePersonalView } = + usePersonalViewStore(); const view = useView(); const viewId = view?.id ?? ''; const closePersonalView = () => { + backupPersonalView(viewId); removePersonalView(viewId); }; const openPersonalView = () => { - setPersonalViewMap(viewId, (prev) => { - return { ...prev, ...generatePersonalViewProps(view) }; - }); + const restored = restorePersonalView(viewId); + if (!restored) { + setPersonalViewMap(viewId, (prev) => { + return { ...prev, ...generatePersonalViewProps(view) }; + }); + } }; const syncViewProperties = async () => { From 65d101fc019b400a84efc502d8094b41402184df Mon Sep 17 00:00:00 2001 From: zhaosonghan01 Date: Fri, 5 Sep 2025 09:54:31 +0800 Subject: [PATCH 2/2] fix: filter out invalid documents in instance reducer --- packages/sdk/src/context/use-instances/reducer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/src/context/use-instances/reducer.ts b/packages/sdk/src/context/use-instances/reducer.ts index 44b2347b20..6424ab71de 100644 --- a/packages/sdk/src/context/use-instances/reducer.ts +++ b/packages/sdk/src/context/use-instances/reducer.ts @@ -42,7 +42,7 @@ export function instanceReducer( ...state, instances: [ ...state.instances.slice(0, action.index), - ...action.docs.map((doc) => factory(doc.data, doc)), + ...action.docs.filter((doc) => doc.data).map((doc) => factory(doc.data, doc)), ...state.instances.slice(action.index), ], };