Skip to content

Commit 8216e9f

Browse files
committed
refactor: clean up store initialization
1 parent df64ac2 commit 8216e9f

File tree

6 files changed

+253
-232
lines changed

6 files changed

+253
-232
lines changed

src/main.ts

Lines changed: 95 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
import { isAnyOf } from "@reduxjs/toolkit";
21
import {
32
MarkdownView,
43
Notice,
54
Plugin,
65
WorkspaceLeaf,
76
type MarkdownFileInfo,
7+
type TFile,
88
} from "obsidian";
99
import { getAPI } from "obsidian-dataview";
10-
import { derived, fromStore, get, writable, type Writable } from "svelte/store";
10+
import {
11+
fromStore,
12+
get,
13+
writable,
14+
type Readable,
15+
type Writable,
16+
} from "svelte/store";
1117
import { isInstanceOf, isNotVoid } from "typed-assert";
1218

1319
import {
@@ -17,6 +23,7 @@ import {
1723
viewTypeTimeline,
1824
viewTypeMultiDay,
1925
reQueryAfterMillis,
26+
icalRefreshIntervalMillis,
2027
} from "./constants";
2128
import { createUpdateHandler, getTextFromUser } from "./create-update-handler";
2229
import { createDumpMetadataCommand } from "./dump-metadata";
@@ -32,22 +39,17 @@ import {
3239
toMdastPoint,
3340
} from "./mdast/mdast";
3441
import {
35-
listPropsParsed,
36-
selectDataviewLoaded,
37-
selectListProps,
42+
dataviewChange,
43+
type PathToListProps,
3844
} from "./redux/dataview/dataview-slice";
3945
import { editCanceled, visibleDaysUpdated } from "./redux/global-slice";
4046
import {
4147
icalRefreshRequested,
42-
selectRemoteTasks,
48+
type IcalState,
49+
initialIcalState,
4350
} from "./redux/ical/ical-slice";
44-
import { selectDataviewSource, settingsUpdated } from "./redux/settings-slice";
45-
import {
46-
type AppListenerMiddlewareInstance,
47-
type AppStore,
48-
initStoreForPlugin,
49-
} from "./redux/store";
50-
import { useActionDispatched } from "./redux/use-action-dispatched";
51+
import { settingsUpdated } from "./redux/settings-slice";
52+
import { type AppDispatch, createReactor } from "./redux/store";
5153
import { createUseSelector } from "./redux/use-selector";
5254
import { DataviewFacade } from "./service/dataview-facade";
5355
import { TransactionWriter } from "./service/diff-writer";
@@ -76,9 +78,9 @@ import { createEnvironmentHooks } from "./util/create-environment-hooks";
7678
import { createRenderMarkdown } from "./util/create-render-markdown";
7779
import { createShowPreview } from "./util/create-show-preview";
7880
import { notifyAboutStartedTasks } from "./util/notify-about-started-tasks";
79-
import { getUpdateTrigger } from "./util/store";
8081
import { createUndoNotice } from "./ui/undo-notice";
8182
import { askForConfirmation } from "./ui/confirmation-modal";
83+
import type { RemoteTask } from "./task-types";
8284

8385
export default class DayPlanner extends Plugin {
8486
settings!: () => DayPlannerSettings;
@@ -89,7 +91,6 @@ export default class DayPlanner extends Plugin {
8991
private sTaskEditor!: STaskEditor;
9092
private vaultFacade!: VaultFacade;
9193
private transactionWriter!: TransactionWriter;
92-
private currentUndoNotice?: Notice;
9394

9495
async onload() {
9596
const initialPluginData: PluginData = {
@@ -117,16 +118,48 @@ export default class DayPlanner extends Plugin {
117118
this.dataviewFacade,
118119
);
119120

120-
const { store, listenerMiddleware } = initStoreForPlugin({
121-
pluginData: initialPluginData,
122-
plugin: this,
121+
const icalStateWithCachedRawIcals: IcalState = {
122+
...initialIcalState,
123+
plainTextIcals: initialPluginData.rawIcals || [],
124+
};
125+
126+
const {
127+
dispatch,
128+
useSelector,
129+
listenerMiddleware,
130+
remoteTasks,
131+
taskUpdateTrigger,
132+
listProps,
133+
dataviewLoaded,
134+
pointerDateTime,
135+
dataviewRefreshSignal,
136+
} = createReactor({
137+
preloadedState: {
138+
ical: icalStateWithCachedRawIcals,
139+
},
123140
dataviewFacade: this.dataviewFacade,
124141
vault: this.app.vault,
125142
metadataCache: this.app.metadataCache,
143+
onIcalsFetched: async (rawIcals) => {
144+
await this.saveData({ ...this.settings(), rawIcals });
145+
},
126146
});
127147

128-
this.initSettingsStore({ initialSettings: initialPluginData, store });
129-
this.registerViews({ store, listenerMiddleware });
148+
this.register(() => {
149+
listenerMiddleware.clearListeners();
150+
});
151+
152+
this.initSettingsStore({ initialSettings: initialPluginData, dispatch });
153+
this.registerViews({
154+
dispatch,
155+
remoteTasks,
156+
taskUpdateTrigger,
157+
listProps,
158+
dataviewLoaded,
159+
pointerDateTime,
160+
dataviewRefreshSignal,
161+
useSelector,
162+
});
130163

131164
const handleEditorMenu = createEditorMenuCallback({
132165
sTaskEditor: this.sTaskEditor,
@@ -306,15 +339,15 @@ export default class DayPlanner extends Plugin {
306339

307340
private initSettingsStore(props: {
308341
initialSettings: DayPlannerSettings;
309-
store: AppStore;
342+
dispatch: AppDispatch;
310343
}) {
311-
const { initialSettings, store } = props;
344+
const { initialSettings, dispatch } = props;
312345

313346
settings.set(initialSettings);
314347

315348
this.register(
316349
settings.subscribe(async (newValue) => {
317-
store.dispatch(settingsUpdated(newValue));
350+
dispatch(settingsUpdated(newValue));
318351

319352
await this.saveData(newValue);
320353
}),
@@ -360,10 +393,26 @@ export default class DayPlanner extends Plugin {
360393
};
361394

362395
private registerViews(props: {
363-
store: AppStore;
364-
listenerMiddleware: AppListenerMiddlewareInstance;
396+
dispatch: AppDispatch;
397+
useSelector: ReturnType<typeof createUseSelector>;
398+
remoteTasks: Readable<RemoteTask[]>;
399+
taskUpdateTrigger: Readable<unknown>;
400+
listProps: Readable<PathToListProps>;
401+
dataviewLoaded: Readable<boolean>;
402+
pointerDateTime: Writable<PointerDateTime>;
403+
dataviewRefreshSignal: Readable<unknown>;
365404
}) {
366-
const { store, listenerMiddleware } = props;
405+
const {
406+
dispatch,
407+
useSelector,
408+
remoteTasks,
409+
taskUpdateTrigger,
410+
listProps,
411+
dataviewLoaded,
412+
pointerDateTime,
413+
dataviewRefreshSignal,
414+
} = props;
415+
367416
let currentUndoNotice: Notice | undefined;
368417

369418
const onUpdate: OnUpdateFn = createUpdateHandler({
@@ -378,7 +427,7 @@ export default class DayPlanner extends Plugin {
378427
onEditCanceled: () => {
379428
new Notice("Edit canceled");
380429

381-
store.dispatch(editCanceled());
430+
dispatch(editCanceled());
382431
},
383432
getTextInput: () => getTextFromUser(this.app),
384433
getConfirmationInput: (input) =>
@@ -392,37 +441,6 @@ export default class DayPlanner extends Plugin {
392441
new Notice("Tasks changed externally; edit canceled");
393442
};
394443

395-
/**
396-
* These are the points of interop from Redux to Svelte
397-
*/
398-
const useSelector = createUseSelector(store);
399-
const actionDispatched = useActionDispatched({ listenerMiddleware });
400-
401-
const remoteTasks = useSelector(selectRemoteTasks);
402-
const listProps = useSelector(selectListProps);
403-
const dataviewLoaded = useSelector(selectDataviewLoaded);
404-
const dataviewSource = useSelector(selectDataviewSource);
405-
406-
const isDataviewRefreshSignal = isAnyOf(listPropsParsed, editCanceled);
407-
const dataviewRefreshSignal = derived(
408-
actionDispatched,
409-
($actionDispatched, set) => {
410-
if (isDataviewRefreshSignal($actionDispatched)) {
411-
set($actionDispatched);
412-
}
413-
},
414-
);
415-
416-
const taskUpdateTrigger = derived(
417-
[dataviewRefreshSignal, dataviewSource],
418-
getUpdateTrigger,
419-
);
420-
421-
const pointerDateTime = writable<PointerDateTime>({
422-
dateTime: window.moment(),
423-
type: "dateTime",
424-
});
425-
426444
const { isDarkMode, isOnline, keyDown, isModPressed, layoutReady } =
427445
createEnvironmentHooks({ workspace: this.app.workspace });
428446

@@ -460,6 +478,21 @@ export default class DayPlanner extends Plugin {
460478
listProps,
461479
});
462480

481+
this.registerInterval(
482+
window.setInterval(() => {
483+
dispatch(icalRefreshRequested());
484+
}, icalRefreshIntervalMillis),
485+
);
486+
487+
this.registerEvent(
488+
this.app.metadataCache.on(
489+
// @ts-expect-error
490+
"dataview:metadata-change",
491+
(eventType: unknown, file: TFile) =>
492+
dispatch(dataviewChange(file.path)),
493+
),
494+
);
495+
463496
this.registerDomEvent(window, "blur", editContext.cancelEdit);
464497
this.registerDomEvent(document, "pointerup", editContext.cancelEdit);
465498

@@ -470,7 +503,7 @@ export default class DayPlanner extends Plugin {
470503
);
471504
this.register(
472505
visibleDays.subscribe((days) => {
473-
store.dispatch(
506+
dispatch(
474507
// without the offset, an event right of UTC is going to be displayed as the previous day
475508
// a visible day in my zone is 2025-04-15, but in UTC it's 2025-04-14T22:00:00, and getDayKey returns 2025-04-14
476509
visibleDaysUpdated(days.map((it) => it.toISOString(true))),
@@ -498,7 +531,7 @@ export default class DayPlanner extends Plugin {
498531
id: "re-sync",
499532
name: "Re-sync tasks",
500533
callback: async () => {
501-
store.dispatch(icalRefreshRequested());
534+
dispatch(icalRefreshRequested());
502535
},
503536
});
504537

@@ -547,16 +580,15 @@ export default class DayPlanner extends Plugin {
547580
editContext,
548581
showPreview: createShowPreview(this.app),
549582
isModPressed,
550-
reSync: () => store.dispatch(icalRefreshRequested()),
583+
reSync: () => dispatch(icalRefreshRequested()),
551584
isOnline,
552585
isDarkMode,
553586
settings,
554587
settingsSignal: fromStore(settings),
555588
pointerDateTime,
556589
tasksWithActiveClockProps,
557590
getDisplayedTasksWithClocksForTimeline,
558-
dispatch: store.dispatch,
559-
store: store,
591+
dispatch,
560592
useSelector,
561593
};
562594

0 commit comments

Comments
 (0)