Mercurial > obsidian-remember-file-state
annotate src/main.ts @ 28:fbaf7c7126be
Don't restore file state if we're just switching to another pane
To do this we have to track the opened file path in the new editor view
and check if it matches the last file path we knew for that view.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 14 Jul 2022 14:36:44 -0700 |
parents | 3d0ac176118f |
children | 66cada11efb8 |
rev | line source |
---|---|
0 | 1 import { |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
2 App, |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
3 Editor, |
0 | 4 MarkdownView, |
27
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
5 Modal, |
0 | 6 OpenViewState, |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
7 Plugin, |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
8 TAbstractFile, |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
9 TFile, |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
10 View, |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
11 WorkspaceLeaf |
0 | 12 } from 'obsidian'; |
13 | |
14 import { | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
15 EditorView |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
16 } from '@codemirror/view'; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
17 |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
18 import { |
2 | 19 EditorState, |
0 | 20 EditorSelection |
21 } from '@codemirror/state'; | |
22 | |
23 import { | |
24 around | |
25 } from 'monkey-around'; | |
26 | |
27 import { | |
28 DEFAULT_SETTINGS, | |
29 RememberFileStatePluginSettings, | |
30 RememberFileStatePluginSettingTab | |
31 } from './settings'; | |
32 | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
33 declare var app: App; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
34 |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
35 // Interface for CM6 editor view |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
36 interface EditorWithCM6 extends Editor { |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
37 cm: EditorView |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
38 }; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
39 |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
40 // View with unique ID |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
41 interface ViewWithID extends View { |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
42 __uniqueId: number |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
43 }; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
44 |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
45 // Scroll info interface |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
46 interface ScrollInfo { |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
47 top: number, left: number |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
48 }; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
49 |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
50 interface StateData { |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
51 selection: EditorSelection, |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
52 scrollInfo: ScrollInfo |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
53 }; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
54 |
0 | 55 // Interface for a file state. |
56 interface RememberedFileState { | |
57 path: string; | |
58 lastSavedTime: number; | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
59 stateData: StateData; |
0 | 60 } |
61 | |
62 // Interface for all currently remembered file states. | |
63 interface RememberFileStatePluginData { | |
11
6f7f35af6335
Better type information for the plugin data
Ludovic Chabant <ludovic@chabant.com>
parents:
8
diff
changeset
|
64 rememberedFiles: Record<string, RememberedFileState>; |
0 | 65 } |
66 | |
67 // Default empty list of remembered file states. | |
68 const DEFAULT_DATA: RememberFileStatePluginData = { | |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
69 rememberedFiles: {} |
0 | 70 }; |
71 | |
27
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
72 // Simple warning message. |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
73 class WarningModal extends Modal { |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
74 constructor(app: App, title: string, message: string) { |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
75 super(app) |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
76 this.title = title; |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
77 this.message = message; |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
78 } |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
79 onOpen() { |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
80 this.contentEl.createEl('h2', {text: this.title}); |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
81 this.contentEl.createEl('p', {text: this.message}); |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
82 } |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
83 }; |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
84 |
0 | 85 export default class RememberFileStatePlugin extends Plugin { |
86 settings: RememberFileStatePluginSettings; | |
87 data: RememberFileStatePluginData; | |
88 | |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
89 // Don't restore state on the next file being opened. |
0 | 90 private _suppressNextFileOpen: boolean = false; |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
91 // Next unique ID to identify views without keeping references to them. |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
92 private _nextUniqueViewId: number = 0; |
0 | 93 |
28
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
94 // Remember last open file in each view. |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
95 private _lastOpenFiles: Record<string, string> = {}; |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
96 |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
97 // Functions to unregister any monkey-patched view hooks on plugin unload. |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
98 private _viewUninstallers: Record<string, Function> = {}; |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
99 // Functions to unregister any global callbacks on plugin unload. |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
100 private _globalUninstallers: Function[] = []; |
0 | 101 |
102 async onload() { | |
103 console.log("Loading RememberFileState plugin"); | |
104 | |
105 await this.loadSettings(); | |
106 | |
107 this.data = Object.assign({}, DEFAULT_DATA); | |
108 | |
109 this.registerEvent(this.app.workspace.on('file-open', this.onFileOpen)); | |
110 this.registerEvent(this.app.vault.on('rename', this.onFileRename)); | |
111 this.registerEvent(this.app.vault.on('delete', this.onFileDelete)); | |
112 | |
113 this.app.workspace.getLeavesOfType("markdown").forEach( | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
114 (leaf: WorkspaceLeaf) => { this.registerOnUnloadFile(leaf.view as MarkdownView); }); |
0 | 115 |
116 const _this = this; | |
117 var uninstall = around(this.app.workspace, { | |
118 openLinkText: function(next) { | |
119 return async function( | |
120 linktext: string, sourcePath: string, | |
121 newLeaf?: boolean, openViewState?: OpenViewState) { | |
122 // When opening a link, we don't want to restore the | |
123 // scroll position/selection/etc because there's a | |
124 // good chance we want to show the file back at the | |
125 // top, or we're going straight to a specific block. | |
126 _this._suppressNextFileOpen = true; | |
127 return await next.call( | |
128 this, linktext, sourcePath, newLeaf, openViewState); | |
129 }; | |
130 } | |
131 }); | |
132 this._globalUninstallers.push(uninstall); | |
133 | |
134 this.addSettingTab(new RememberFileStatePluginSettingTab(this.app, this)); | |
27
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
135 |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
136 if (this.app.vault.getConfig('legacyEditor') !== false) { |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
137 new WarningModal( |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
138 this.app, |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
139 "Legacy Editor Not Supported", |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
140 "The 'Remember File State' plugin works only with the new editor. Please turn off 'Legacy Editor' in the options." |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
141 ).open(); |
3d0ac176118f
Show warning message if using the plugin with the legacy editor
Ludovic Chabant <ludovic@chabant.com>
parents:
23
diff
changeset
|
142 } |
0 | 143 } |
144 | |
145 onunload() { | |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
146 // Run view uninstallers on all current views. |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
147 var numViews: number = 0; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
148 this.app.workspace.getLeavesOfType("markdown").forEach( |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
149 (leaf: WorkspaceLeaf) => { |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
150 const filePath = (leaf.view as MarkdownView).file.path; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
151 const viewId = this.getUniqueViewId(leaf.view as ViewWithID); |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
152 if (viewId != undefined) { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
153 var uninstaller = this._viewUninstallers[viewId]; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
154 if (uninstaller) { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
155 console.debug(`Uninstalling hooks for view ${viewId}`, filePath); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
156 uninstaller(leaf.view); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
157 ++numViews; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
158 } else { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
159 console.debug("Found markdown view without an uninstaller!", filePath); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
160 } |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
161 // Clear the ID so we don't get confused if the plugin |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
162 // is re-enabled later. |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
163 this.clearUniqueViewId(leaf.view as ViewWithID); |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
164 } else { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
165 console.debug("Found markdown view without an ID!", filePath); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
166 } |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
167 }); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
168 console.debug(`Unregistered ${numViews} view callbacks`); |
0 | 169 this._viewUninstallers = {}; |
28
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
170 this._lastOpenFiles = {}; |
0 | 171 |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
172 // Run global unhooks. |
0 | 173 this._globalUninstallers.forEach((cb) => cb()); |
174 } | |
175 | |
176 async loadSettings() { | |
177 this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); | |
178 } | |
179 | |
180 async saveSettings() { | |
181 await this.saveData(this.settings); | |
182 } | |
183 | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
184 private readonly registerOnUnloadFile = function(view: MarkdownView) { |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
185 var filePath = view.file.path; |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
186 var viewId = this.getUniqueViewId(view as unknown as ViewWithID, true); |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
187 if (viewId in this._viewUninstallers) { |
0 | 188 return; |
189 } | |
190 | |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
191 console.debug(`Registering callback on view ${viewId}`, filePath); |
0 | 192 const _this = this; |
193 var uninstall = around(view, { | |
194 onUnloadFile: function(next) { | |
195 return async function (unloaded: TFile) { | |
12
42396b88c64d
Don't unnecessarily capture the view reference in injected callbacks
Ludovic Chabant <ludovic@chabant.com>
parents:
11
diff
changeset
|
196 _this.rememberFileState(unloaded, this); |
0 | 197 return await next.call(this, unloaded); |
198 }; | |
199 } | |
200 }); | |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
201 this._viewUninstallers[viewId] = uninstall; |
0 | 202 |
203 view.register(() => { | |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
204 // Don't hold a reference to this plugin here because this callback |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
205 // will outlive it if it gets deactivated. So let's find it, and |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
206 // do nothing if we don't find it. |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
207 // @ts-ignore |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
208 var plugin: RememberFileStatePlugin = app.plugins.getPlugin("obsidian-remember-file-state"); |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
209 if (plugin) { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
210 console.debug(`Unregistering view ${viewId} callback`, filePath); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
211 delete plugin._viewUninstallers[viewId]; |
28
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
212 delete plugin._lastOpenFiles[viewId]; |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
213 uninstall(); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
214 } else { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
215 console.debug( |
16
a50ef39473b6
Fix plugin ID, bump version to 1.0.4
Ludovic Chabant <ludovic@chabant.com>
parents:
13
diff
changeset
|
216 "Plugin obsidian-remember-file-state has been unloaded, ignoring unregister"); |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
217 } |
0 | 218 }); |
219 } | |
220 | |
221 private readonly onFileOpen = async ( | |
222 openedFile: TFile | |
223 ): Promise<void> => { | |
224 // If `openedFile` is null, it's because the last pane was closed | |
225 // and there is now an empty pane. | |
226 if (openedFile) { | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
227 var activeView: MarkdownView = this.app.workspace.getActiveViewOfType(MarkdownView); |
7
b1cb0474bb18
Fix possible crash when an opened file isn't a markdown file
Ludovic Chabant <ludovic@chabant.com>
parents:
6
diff
changeset
|
228 if (activeView) { |
b1cb0474bb18
Fix possible crash when an opened file isn't a markdown file
Ludovic Chabant <ludovic@chabant.com>
parents:
6
diff
changeset
|
229 this.registerOnUnloadFile(activeView); |
0 | 230 |
28
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
231 var isRealFileOpen = true; |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
232 const viewId = this.getUniqueViewId(activeView as ViewWithID); |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
233 if (viewId != undefined) { |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
234 const lastOpenFileInView = this._lastOpenFiles[viewId]; |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
235 isRealFileOpen = (lastOpenFileInView != openedFile.path); |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
236 this._lastOpenFiles[viewId] = openedFile.path; |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
237 } |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
238 |
22
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
239 // Don't restore the file state if: |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
240 // - We are suppressing it explicitly (such as if the file was |
28
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
241 // opened via clicking a hyperlink) |
22
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
242 // - The file is already currently open in another pane |
28
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
243 // - The file was already opened in this pane, and we're just |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
244 // returning to it. |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
245 if (!this._suppressNextFileOpen && |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
246 !this.isFileMultiplyOpen(openedFile) && |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
247 isRealFileOpen |
fbaf7c7126be
Don't restore file state if we're just switching to another pane
Ludovic Chabant <ludovic@chabant.com>
parents:
27
diff
changeset
|
248 ) { |
23
ba74a7d3709c
Add try/catch around restoring file state
Ludovic Chabant <ludovic@chabant.com>
parents:
22
diff
changeset
|
249 try { |
ba74a7d3709c
Add try/catch around restoring file state
Ludovic Chabant <ludovic@chabant.com>
parents:
22
diff
changeset
|
250 this.restoreFileState(openedFile, activeView); |
ba74a7d3709c
Add try/catch around restoring file state
Ludovic Chabant <ludovic@chabant.com>
parents:
22
diff
changeset
|
251 } catch (err) { |
ba74a7d3709c
Add try/catch around restoring file state
Ludovic Chabant <ludovic@chabant.com>
parents:
22
diff
changeset
|
252 console.error("Couldn't restore file state: ", err); |
ba74a7d3709c
Add try/catch around restoring file state
Ludovic Chabant <ludovic@chabant.com>
parents:
22
diff
changeset
|
253 } |
7
b1cb0474bb18
Fix possible crash when an opened file isn't a markdown file
Ludovic Chabant <ludovic@chabant.com>
parents:
6
diff
changeset
|
254 } |
0 | 255 } |
7
b1cb0474bb18
Fix possible crash when an opened file isn't a markdown file
Ludovic Chabant <ludovic@chabant.com>
parents:
6
diff
changeset
|
256 // else: the file isn't handled by a markdown editor. |
b1cb0474bb18
Fix possible crash when an opened file isn't a markdown file
Ludovic Chabant <ludovic@chabant.com>
parents:
6
diff
changeset
|
257 |
b1cb0474bb18
Fix possible crash when an opened file isn't a markdown file
Ludovic Chabant <ludovic@chabant.com>
parents:
6
diff
changeset
|
258 this._suppressNextFileOpen = false; |
0 | 259 } |
260 } | |
261 | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
262 private readonly rememberFileState = async (file: TFile, view: MarkdownView): Promise<void> => { |
0 | 263 const scrollInfo = view.editor.getScrollInfo(); |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
264 const cm6editor = view.editor as EditorWithCM6; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
265 const stateSelection: EditorSelection = cm6editor.cm.state.selection; |
13
7da0dec2dc8d
Simple bail out when legacy editors are enabled
Ludovic Chabant <ludovic@chabant.com>
parents:
12
diff
changeset
|
266 if (stateSelection == undefined) { |
7da0dec2dc8d
Simple bail out when legacy editors are enabled
Ludovic Chabant <ludovic@chabant.com>
parents:
12
diff
changeset
|
267 // Legacy editor is in use, let's ignore |
7da0dec2dc8d
Simple bail out when legacy editors are enabled
Ludovic Chabant <ludovic@chabant.com>
parents:
12
diff
changeset
|
268 return; |
7da0dec2dc8d
Simple bail out when legacy editors are enabled
Ludovic Chabant <ludovic@chabant.com>
parents:
12
diff
changeset
|
269 } |
7da0dec2dc8d
Simple bail out when legacy editors are enabled
Ludovic Chabant <ludovic@chabant.com>
parents:
12
diff
changeset
|
270 const stateSelectionJSON = stateSelection.toJSON(); |
0 | 271 const stateData = {'scrollInfo': scrollInfo, 'selection': stateSelectionJSON}; |
272 | |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
273 var existingFile = this.data.rememberedFiles[file.path]; |
0 | 274 if (existingFile) { |
275 existingFile.lastSavedTime = Date.now(); | |
276 existingFile.stateData = stateData; | |
277 } else { | |
278 let newFileState = { | |
279 path: file.path, | |
280 lastSavedTime: Date.now(), | |
281 stateData: stateData | |
282 }; | |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
283 this.data.rememberedFiles[file.path] = newFileState; |
0 | 284 |
285 // If we need to keep the number remembered files under a maximum, | |
286 // do it now. | |
287 this.forgetExcessFiles(); | |
288 } | |
289 console.debug("Remember file state for:", file.path); | |
290 } | |
291 | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
292 private readonly restoreFileState = function(file: TFile, view: MarkdownView) { |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
293 const existingFile = this.data.rememberedFiles[file.path]; |
0 | 294 if (existingFile) { |
295 console.debug("Restoring file state for:", file.path); | |
296 const stateData = existingFile.stateData; | |
297 view.editor.scrollTo(stateData.scrollInfo.left, stateData.scrollInfo.top); | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
298 const cm6editor = view.editor as EditorWithCM6; |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
299 var transaction = cm6editor.cm.state.update({ |
2 | 300 selection: EditorSelection.fromJSON(stateData.selection)}) |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
301 |
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
302 cm6editor.cm.dispatch(transaction); |
0 | 303 } |
304 } | |
22
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
305 |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
306 private readonly isFileMultiplyOpen = function(file: TFile) { |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
307 var numFound: number = 0; |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
308 this.app.workspace.getLeavesOfType("markdown").forEach( |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
309 (leaf: WorkspaceLeaf) => { |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
310 const filePath = (leaf.view as MarkdownView).file.path; |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
311 if (filePath == file.path) { |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
312 ++numFound; |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
313 } |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
314 }); |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
315 return numFound >= 2; |
f7e0926c2500
Don't restore state on a file that's already open in another pane.
Ludovic Chabant <ludovic@chabant.com>
parents:
21
diff
changeset
|
316 } |
0 | 317 |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
318 private readonly forgetExcessFiles = function() { |
0 | 319 const keepMax = this.settings.rememberMaxFiles; |
320 if (keepMax <= 0) { | |
321 return; | |
322 } | |
323 | |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
324 // Sort newer files first, older files last. |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
325 var filesData: RememberedFileState[] = Object.values(this.data.rememberedFiles); |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
326 filesData.sort((a, b) => { |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
327 if (a.lastSavedTime > b.lastSavedTime) return -1; // a before b |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
328 if (a.lastSavedTime < b.lastSavedTime) return 1; // b before a |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
329 return 0; |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
330 }); |
0 | 331 |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
332 // Remove older files past the limit. |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
333 for (var i = keepMax; i < filesData.length; ++i) { |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
334 var fileData = filesData[i]; |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
335 delete this.data.rememberedFiles[fileData.path]; |
0 | 336 } |
337 } | |
338 | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
339 private readonly getUniqueViewId = function(view: ViewWithID, autocreateId: boolean = false) { |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
340 if (view.__uniqueId == undefined) { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
341 if (!autocreateId) { |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
342 return -1; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
343 } |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
344 view.__uniqueId = (this._nextUniqueViewId++); |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
345 return view.__uniqueId; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
346 } |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
347 return view.__uniqueId; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
348 } |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
349 |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
350 private readonly clearUniqueViewId = function(view: ViewWithID) { |
6
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
351 delete view["__uniqueId"]; |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
352 } |
114d7e6d2633
Fix various issues around keeping references to editor objects
Ludovic Chabant <ludovic@chabant.com>
parents:
2
diff
changeset
|
353 |
0 | 354 private readonly onFileRename = async ( |
355 file: TAbstractFile, | |
356 oldPath: string, | |
357 ): Promise<void> => { | |
21
815b93d13e0f
Improve typescript compliance
Ludovic Chabant <ludovic@chabant.com>
parents:
16
diff
changeset
|
358 const existingFile: RememberedFileState = this.data.rememberedFiles[oldPath]; |
0 | 359 if (existingFile) { |
360 existingFile.path = file.path; | |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
361 delete this.data.rememberedFiles[oldPath]; |
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
362 this.data.rememberedFiles[file.path] = existingFile; |
0 | 363 } |
364 }; | |
365 | |
366 private readonly onFileDelete = async ( | |
367 file: TAbstractFile, | |
368 ): Promise<void> => { | |
8
ec6c48a07b03
Make the plugin data into a dictionary
Ludovic Chabant <ludovic@chabant.com>
parents:
7
diff
changeset
|
369 delete this.data.rememberedFiles[file.path]; |
0 | 370 }; |
371 } | |
372 |