Skip to content

Commit 374522c

Browse files
committed
refactor: encapsulate periodic notes logic
1 parent c0c5757 commit 374522c

29 files changed

+368
-329
lines changed

src/create-update-handler.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
import type { App, Notice } from "obsidian";
2-
import {
3-
createDailyNote,
4-
getDateFromPath,
5-
} from "obsidian-daily-notes-interface";
62
import { isNotVoid } from "typed-assert";
73

84
import { sortListsRecursivelyInMarkdown } from "./mdast/mdast";
@@ -20,6 +16,7 @@ import { EditMode } from "./ui/hooks/use-edit/types";
2016
import { SingleSuggestModal } from "./ui/SingleSuggestModal";
2117
import { createUndoNotice } from "./ui/undo-notice";
2218
import { applyScopedUpdates } from "./util/markdown";
19+
import type { PeriodicNotes } from "./service/periodic-notes";
2320

2421
async function getTextFromUser(app: App): Promise<string | undefined> {
2522
return new Promise((resolve) => {
@@ -44,10 +41,17 @@ export const createUpdateHandler = (props: {
4441
settings: () => DayPlannerSettings;
4542
transactionWriter: TransactionWriter;
4643
vaultFacade: VaultFacade;
44+
periodicNotes: PeriodicNotes;
4745
onEditCanceled: () => void;
4846
}): OnUpdateFn => {
49-
const { app, settings, transactionWriter, vaultFacade, onEditCanceled } =
50-
props;
47+
const {
48+
app,
49+
settings,
50+
transactionWriter,
51+
vaultFacade,
52+
onEditCanceled,
53+
periodicNotes,
54+
} = props;
5155

5256
let currentUndoNotice: Notice | undefined;
5357

@@ -78,7 +82,7 @@ export const createUpdateHandler = (props: {
7882
diff.added[0] = { ...created, text: modalOutput };
7983
}
8084

81-
const updates = mapTaskDiffToUpdates(diff, mode, settings());
85+
const updates = mapTaskDiffToUpdates(diff, mode, settings(), periodicNotes);
8286

8387
const afterEach = settings().sortTasksInPlanAfterEdit
8488
? (contents: string) =>
@@ -115,11 +119,11 @@ export const createUpdateHandler = (props: {
115119

116120
await Promise.all(
117121
needToCreate.map(async (path) => {
118-
const date = getDateFromPath(path, "day");
122+
const date = periodicNotes.getDateFromPath(path, "day");
119123

120124
isNotVoid(date);
121125

122-
await createDailyNote(date);
126+
await periodicNotes.createDailyNote(date);
123127
}),
124128
);
125129
}

src/main.ts

Lines changed: 68 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
Plugin,
66
WorkspaceLeaf,
77
type MarkdownFileInfo,
8-
type TFile,
98
} from "obsidian";
109
import { getAPI } from "obsidian-dataview";
1110
import { derived, fromStore, get, writable, type Writable } from "svelte/store";
@@ -17,7 +16,7 @@ import {
1716
viewTypeReleaseNotes,
1817
viewTypeTimeline,
1918
viewTypeMultiDay,
20-
icalRefreshIntervalMillis,
19+
reQueryAfterMillis,
2120
} from "./constants";
2221
import { createUpdateHandler } from "./create-update-handler";
2322
import { createDumpMetadataCommand } from "./dump-metadata";
@@ -33,24 +32,20 @@ import {
3332
toMdastPoint,
3433
} from "./mdast/mdast";
3534
import {
36-
dataviewChange as dataviewChangeAction,
3735
listPropsParsed,
3836
selectDataviewLoaded,
3937
selectListProps,
4038
} from "./redux/dataview/dataview-slice";
4139
import { editCanceled, visibleDaysUpdated } from "./redux/global-slice";
4240
import {
43-
initialIcalState,
44-
type IcalState,
4541
icalRefreshRequested,
4642
selectRemoteTasks,
4743
} from "./redux/ical/ical-slice";
48-
import { initListenerMiddleware } from "./redux/listener-middleware";
49-
import { settingsUpdated } from "./redux/settings-slice";
44+
import { selectDataviewSource, settingsUpdated } from "./redux/settings-slice";
5045
import {
5146
type AppListenerMiddlewareInstance,
5247
type AppStore,
53-
makeStore,
48+
initStoreForPlugin,
5449
} from "./redux/store";
5550
import { useActionDispatched } from "./redux/use-action-dispatched";
5651
import { createUseSelector } from "./redux/use-selector";
@@ -65,25 +60,30 @@ import {
6560
type PluginData,
6661
} from "./settings";
6762
import { createGetTasksApi } from "./tasks-plugin";
68-
import type { ObsidianContext, OnUpdateFn } from "./types";
63+
import type { ObsidianContext, OnUpdateFn, PointerDateTime } from "./types";
6964
import { createEditorMenuCallback } from "./ui/editor-menu";
7065
import { mountStatusBarWidget } from "./ui/hooks/use-status-bar-widget";
7166
import MultiDayView from "./ui/multi-day-view";
7267
import { DayPlannerReleaseNotesView } from "./ui/release-notes";
7368
import { DayPlannerSettingsTab } from "./ui/settings-tab";
7469
import TimelineView from "./ui/timeline-view";
75-
import { createHooks } from "./util/create-hooks.svelte";
7670
import { createRenderMarkdown } from "./util/create-render-markdown";
7771
import { createShowPreview } from "./util/create-show-preview";
78-
import { createDailyNoteIfNeeded } from "./util/daily-notes";
7972
import { notifyAboutStartedTasks } from "./util/notify-about-started-tasks";
8073
import { createEnvironmentHooks } from "./util/create-environment-hooks";
74+
import { getUpdateTrigger } from "./util/store";
75+
import { useDebounceWithDelay } from "./ui/hooks/use-debounce-with-delay";
76+
import { useDateRanges } from "./ui/hooks/use-date-ranges";
77+
import { useTasks } from "./ui/hooks/use-tasks";
78+
import { useVisibleDays } from "./ui/hooks/use-visible-days";
79+
import { PeriodicNotes } from "./service/periodic-notes";
8180

8281
export default class DayPlanner extends Plugin {
8382
settings!: () => DayPlannerSettings;
8483
private settingsStore!: Writable<DayPlannerSettings>;
8584
private workspaceFacade!: WorkspaceFacade;
8685
private dataviewFacade!: DataviewFacade;
86+
private periodicNotes!: PeriodicNotes;
8787
private sTaskEditor!: STaskEditor;
8888
private vaultFacade!: VaultFacade;
8989
private transationWriter!: TransactionWriter;
@@ -95,17 +95,15 @@ export default class DayPlanner extends Plugin {
9595
...(await this.loadData()),
9696
};
9797

98-
const { store, listenerMiddleware } =
99-
this.setUpReduxStore(initialPluginData);
100-
this.initSettingsStore({ initialSettings: initialPluginData, store });
101-
10298
const getTasksApi = createGetTasksApi(this.app);
10399

100+
this.periodicNotes = new PeriodicNotes();
104101
this.vaultFacade = new VaultFacade(this.app.vault, getTasksApi);
105102
this.transationWriter = new TransactionWriter(this.vaultFacade);
106103
this.workspaceFacade = new WorkspaceFacade(
107104
this.app.workspace,
108105
this.vaultFacade,
106+
this.periodicNotes,
109107
);
110108
this.dataviewFacade = new DataviewFacade(
111109
() => getAPI(this.app),
@@ -117,6 +115,15 @@ export default class DayPlanner extends Plugin {
117115
this.dataviewFacade,
118116
);
119117

118+
const { store, listenerMiddleware } = initStoreForPlugin({
119+
pluginData: initialPluginData,
120+
plugin: this,
121+
dataviewFacade: this.dataviewFacade,
122+
vault: this.app.vault,
123+
metadataCache: this.app.metadataCache,
124+
});
125+
126+
this.initSettingsStore({ initialSettings: initialPluginData, store });
120127
this.registerViews({ store, listenerMiddleware });
121128

122129
const handleEditorMenu = createEditorMenuCallback({
@@ -230,7 +237,9 @@ export default class DayPlanner extends Plugin {
230237
id: "show-day-planner-today-note",
231238
name: "Open today's Day Planner",
232239
callback: async () => {
233-
const dailyNote = await createDailyNoteIfNeeded(window.moment());
240+
const dailyNote = await this.periodicNotes.createDailyNoteIfNeeded(
241+
window.moment(),
242+
);
234243

235244
await this.app.workspace.getLeaf(false).openFile(dailyNote);
236245
},
@@ -359,6 +368,7 @@ export default class DayPlanner extends Plugin {
359368
settings: this.settings,
360369
transactionWriter: this.transationWriter,
361370
vaultFacade: this.vaultFacade,
371+
periodicNotes: this.periodicNotes,
362372
onEditCanceled: () => {
363373
new Notice("Edit canceled");
364374

@@ -379,6 +389,7 @@ export default class DayPlanner extends Plugin {
379389
const remoteTasks = useSelector(selectRemoteTasks);
380390
const listProps = useSelector(selectListProps);
381391
const dataviewLoaded = useSelector(selectDataviewLoaded);
392+
const dataviewSource = useSelector(selectDataviewSource);
382393

383394
const dataviewRefreshSignal = derived(
384395
actionDispatched,
@@ -392,29 +403,48 @@ export default class DayPlanner extends Plugin {
392403
const { isDarkMode, isOnline, keyDown, isModPressed, layoutReady } =
393404
createEnvironmentHooks({ workspace: this.app.workspace });
394405

406+
const taskUpdateTrigger = derived(
407+
[dataviewRefreshSignal, dataviewSource],
408+
getUpdateTrigger,
409+
);
410+
411+
const debouncedTaskUpdateTrigger = useDebounceWithDelay(
412+
taskUpdateTrigger,
413+
keyDown,
414+
reQueryAfterMillis,
415+
);
416+
417+
const pointerDateTime = writable<PointerDateTime>({
418+
dateTime: window.moment(),
419+
type: "dateTime",
420+
});
421+
422+
const dateRanges = useDateRanges();
423+
const visibleDays = useVisibleDays(dateRanges.ranges);
424+
395425
const {
396-
editContext,
397-
tasksWithTimeForToday,
398-
newlyStartedTasks,
399-
dateRanges,
400-
pointerDateTime,
401426
tasksWithActiveClockProps,
402427
getDisplayedTasksWithClocksForTimeline,
403-
visibleDays,
404-
} = createHooks({
405-
metadataCache: this.app.metadataCache,
428+
tasksWithTimeForToday,
429+
editContext,
430+
newlyStartedTasks,
431+
} = useTasks({
432+
onUpdate,
433+
onEditAborted,
434+
periodicNotes: this.periodicNotes,
406435
dataviewFacade: this.dataviewFacade,
436+
metadataCache: this.app.metadataCache,
407437
workspaceFacade: this.workspaceFacade,
438+
isOnline,
439+
visibleDays,
440+
layoutReady,
441+
debouncedTaskUpdateTrigger,
442+
dataviewChange: dataviewRefreshSignal,
408443
settingsStore: this.settingsStore,
409-
onUpdate,
410-
onEditAborted,
411444
currentTime,
412-
dataviewChange: dataviewRefreshSignal,
445+
pointerDateTime,
413446
remoteTasks,
414447
listProps,
415-
keyDown,
416-
isOnline,
417-
layoutReady,
418448
});
419449

420450
this.registerDomEvent(window, "blur", editContext.cancelEdit);
@@ -493,6 +523,7 @@ export default class DayPlanner extends Plugin {
493523
});
494524

495525
const defaultObsidianContext: ObsidianContext = {
526+
periodicNotes: this.periodicNotes,
496527
sTaskEditor: this.sTaskEditor,
497528
workspaceFacade: this.workspaceFacade,
498529
initWeeklyView: this.initWeeklyLeaf,
@@ -527,7 +558,13 @@ export default class DayPlanner extends Plugin {
527558
this.registerView(
528559
viewTypeTimeline,
529560
(leaf: WorkspaceLeaf) =>
530-
new TimelineView(leaf, this.settings, componentContext, dateRanges),
561+
new TimelineView(
562+
leaf,
563+
this.settings,
564+
componentContext,
565+
dateRanges,
566+
this.periodicNotes,
567+
),
531568
);
532569

533570
this.registerView(
@@ -546,52 +583,4 @@ export default class DayPlanner extends Plugin {
546583
(leaf: WorkspaceLeaf) => new DayPlannerReleaseNotesView(leaf),
547584
);
548585
}
549-
550-
private setUpReduxStore(pluginData: PluginData) {
551-
const listenerMiddleware = initListenerMiddleware({
552-
extra: {
553-
dataviewFacade: this.dataviewFacade,
554-
vault: this.app.vault,
555-
metadataCache: this.app.metadataCache,
556-
onIcalsFetched: async (rawIcals) => {
557-
await this.saveData({ ...this.settings(), rawIcals });
558-
},
559-
},
560-
});
561-
562-
const icalStateWithCachedRawIcals: IcalState = {
563-
...initialIcalState,
564-
plainTextIcals: pluginData.rawIcals || [],
565-
};
566-
567-
const store = makeStore({
568-
preloadedState: {
569-
ical: icalStateWithCachedRawIcals,
570-
},
571-
middleware: (getDefaultMiddleware) => {
572-
return getDefaultMiddleware().concat(listenerMiddleware.middleware);
573-
},
574-
});
575-
576-
this.register(() => {
577-
listenerMiddleware.clearListeners();
578-
});
579-
580-
this.registerInterval(
581-
window.setInterval(() => {
582-
store.dispatch(icalRefreshRequested());
583-
}, icalRefreshIntervalMillis),
584-
);
585-
586-
this.registerEvent(
587-
this.app.metadataCache.on(
588-
// @ts-expect-error
589-
"dataview:metadata-change",
590-
(eventType: unknown, file: TFile) =>
591-
store.dispatch(dataviewChangeAction(file.path)),
592-
),
593-
);
594-
595-
return { store, listenerMiddleware };
596-
}
597586
}

src/redux/global-slice.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
createAction,
3-
createSelector,
4-
type PayloadAction,
5-
} from "@reduxjs/toolkit";
1+
import { createSelector, type PayloadAction } from "@reduxjs/toolkit";
62

73
import { defaultDayFormat } from "../constants";
84

@@ -32,8 +28,6 @@ export const globalSlice = createAppSlice({
3228
},
3329
});
3430

35-
export const keyDown = createAction("obsidian/keyDown");
36-
3731
export const { visibleDaysUpdated, editCanceled } = globalSlice.actions;
3832

3933
export const { selectVisibleDays } = globalSlice.selectors;

src/redux/settings-slice.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,3 @@ export const { settingsUpdated, settingsLoaded } = settingsSlice.actions;
3939

4040
export const { selectDataviewSource, selectSettings, selectIcals } =
4141
settingsSlice.selectors;
42-
43-
export const checkDataviewSourceChanged =
44-
createSelectorChangePredicate(selectDataviewSource);

0 commit comments

Comments
 (0)