1- import { isAnyOf } from "@reduxjs/toolkit" ;
21import {
32 MarkdownView ,
43 Notice ,
54 Plugin ,
65 WorkspaceLeaf ,
76 type MarkdownFileInfo ,
7+ type TFile ,
88} from "obsidian" ;
99import { 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" ;
1117import { isInstanceOf , isNotVoid } from "typed-assert" ;
1218
1319import {
@@ -17,6 +23,7 @@ import {
1723 viewTypeTimeline ,
1824 viewTypeMultiDay ,
1925 reQueryAfterMillis ,
26+ icalRefreshIntervalMillis ,
2027} from "./constants" ;
2128import { createUpdateHandler , getTextFromUser } from "./create-update-handler" ;
2229import { createDumpMetadataCommand } from "./dump-metadata" ;
@@ -32,22 +39,17 @@ import {
3239 toMdastPoint ,
3340} from "./mdast/mdast" ;
3441import {
35- listPropsParsed ,
36- selectDataviewLoaded ,
37- selectListProps ,
42+ dataviewChange ,
43+ type PathToListProps ,
3844} from "./redux/dataview/dataview-slice" ;
3945import { editCanceled , visibleDaysUpdated } from "./redux/global-slice" ;
4046import {
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" ;
5153import { createUseSelector } from "./redux/use-selector" ;
5254import { DataviewFacade } from "./service/dataview-facade" ;
5355import { TransactionWriter } from "./service/diff-writer" ;
@@ -76,9 +78,9 @@ import { createEnvironmentHooks } from "./util/create-environment-hooks";
7678import { createRenderMarkdown } from "./util/create-render-markdown" ;
7779import { createShowPreview } from "./util/create-show-preview" ;
7880import { notifyAboutStartedTasks } from "./util/notify-about-started-tasks" ;
79- import { getUpdateTrigger } from "./util/store" ;
8081import { createUndoNotice } from "./ui/undo-notice" ;
8182import { askForConfirmation } from "./ui/confirmation-modal" ;
83+ import type { RemoteTask } from "./task-types" ;
8284
8385export 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