comparison src/main.ts @ 52:586f857a98dd

Move unregistering of all views into a reusable function.
author Ludovic Chabant <ludovic@chabant.com>
date Mon, 02 Oct 2023 10:05:02 -0700
parents e932f1b73133
children f2e066bbe343
comparison
equal deleted inserted replaced
51:e932f1b73133 52:586f857a98dd
161 ).open(); 161 ).open();
162 } 162 }
163 } 163 }
164 164
165 onunload() { 165 onunload() {
166 console.log("RememberFileState: unloading plugin");
167
168 // Unregister unload callbacks on all views.
169 this.unregisterAllViews();
170
171 // Forget which files are opened in which views.
172 this._lastOpenFiles = {};
173
174 // Run global unhooks.
175 this._globalUninstallers.forEach((cb) => cb());
176 }
177
178 async loadSettings() {
179 this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
180 }
181
182 async saveSettings() {
183 await this.saveData(this.settings);
184 }
185
186 private readonly onLayoutReady = function() {
187 this.app.workspace.getLeavesOfType("markdown").forEach(
188 (leaf: WorkspaceLeaf) => {
189 var view = leaf.view as MarkdownView;
190
191 // On startup, assign unique IDs to views and register the
192 // unload callback to remember their state.
193 this.registerOnUnloadFile(view);
194
195 // Also remember which file is opened in which view.
196 const viewId = this.getUniqueViewId(view as unknown as ViewWithID);
197 if (viewId != undefined) {
198 this._lastOpenFiles[viewId] = view.file.path;
199 }
200
201 // Restore state for each opened pane on startup.
202 const existingFile = this.data.rememberedFiles[view.file.path];
203 if (existingFile) {
204 const savedStateData = existingFile.stateData;
205 console.debug("RememberFileState: restoring saved state for:", view.file.path, savedStateData);
206 this.restoreState(savedStateData, view);
207 }
208 });
209 }
210
211 private readonly registerOnUnloadFile = function(view: MarkdownView) {
212 var filePath = view.file.path;
213 var viewId = this.getUniqueViewId(view as unknown as ViewWithID, true);
214 if (viewId in this._viewUninstallers) {
215 return;
216 }
217
218 console.debug(`RememberFileState: registering callback on view ${viewId}`, filePath);
219 const _this = this;
220 var uninstall = around(view, {
221 onUnloadFile: function(next) {
222 return async function (unloaded: TFile) {
223 _this.rememberFileState(this, unloaded);
224 return await next.call(this, unloaded);
225 };
226 }
227 });
228 this._viewUninstallers[viewId] = uninstall;
229
230 view.register(() => {
231 // Don't hold a reference to this plugin here because this callback
232 // will outlive it if it gets deactivated. So let's find it, and
233 // do nothing if we don't find it.
234 // @ts-ignore
235 var plugin: RememberFileStatePlugin = app.plugins.getPlugin("obsidian-remember-file-state");
236 if (plugin) {
237 console.debug(`RememberFileState: unregistering view ${viewId} callback`, filePath);
238 delete plugin._viewUninstallers[viewId];
239 delete plugin._lastOpenFiles[viewId];
240 uninstall();
241 } else {
242 console.debug(
243 "RememberFileState: plugin was unloaded, ignoring unregister");
244 }
245 });
246 }
247
248 private readonly unregisterAllViews = function() {
166 // Run view uninstallers on all current views. 249 // Run view uninstallers on all current views.
167 var numViews: number = 0; 250 var numViews: number = 0;
168 this.app.workspace.getLeavesOfType("markdown").forEach( 251 this.app.workspace.getLeavesOfType("markdown").forEach(
169 (leaf: WorkspaceLeaf) => { 252 (leaf: WorkspaceLeaf) => {
170 const filePath = (leaf.view as MarkdownView).file.path; 253 const filePath = (leaf.view as MarkdownView).file.path;
185 console.debug("RememberFileState: found markdown view without an ID!", filePath); 268 console.debug("RememberFileState: found markdown view without an ID!", filePath);
186 } 269 }
187 }); 270 });
188 console.debug(`RememberFileState: unregistered ${numViews} view callbacks`); 271 console.debug(`RememberFileState: unregistered ${numViews} view callbacks`);
189 this._viewUninstallers = {}; 272 this._viewUninstallers = {};
190 this._lastOpenFiles = {};
191
192 // Run global unhooks.
193 this._globalUninstallers.forEach((cb) => cb());
194 }
195
196 async loadSettings() {
197 this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
198 }
199
200 async saveSettings() {
201 await this.saveData(this.settings);
202 }
203
204 private readonly onLayoutReady = function() {
205 this.app.workspace.getLeavesOfType("markdown").forEach(
206 (leaf: WorkspaceLeaf) => {
207 var view = leaf.view as MarkdownView;
208
209 // On startup, assign unique IDs to views and register the
210 // unload callback to remember their state.
211 this.registerOnUnloadFile(view);
212
213 // Also remember which file is opened in which view.
214 const viewId = this.getUniqueViewId(view as unknown as ViewWithID);
215 if (viewId != undefined) {
216 this._lastOpenFiles[viewId] = view.file.path;
217 }
218
219 // Restore state for each opened pane on startup.
220 const existingFile = this.data.rememberedFiles[view.file.path];
221 if (existingFile) {
222 const savedStateData = existingFile.stateData;
223 console.debug("RememberFileState: restoring saved state for:", view.file.path, savedStateData);
224 this.restoreState(savedStateData, view);
225 }
226 });
227 }
228
229 private readonly registerOnUnloadFile = function(view: MarkdownView) {
230 var filePath = view.file.path;
231 var viewId = this.getUniqueViewId(view as unknown as ViewWithID, true);
232 if (viewId in this._viewUninstallers) {
233 return;
234 }
235
236 console.debug(`RememberFileState: registering callback on view ${viewId}`, filePath);
237 const _this = this;
238 var uninstall = around(view, {
239 onUnloadFile: function(next) {
240 return async function (unloaded: TFile) {
241 _this.rememberFileState(this, unloaded);
242 return await next.call(this, unloaded);
243 };
244 }
245 });
246 this._viewUninstallers[viewId] = uninstall;
247
248 view.register(() => {
249 // Don't hold a reference to this plugin here because this callback
250 // will outlive it if it gets deactivated. So let's find it, and
251 // do nothing if we don't find it.
252 // @ts-ignore
253 var plugin: RememberFileStatePlugin = app.plugins.getPlugin("obsidian-remember-file-state");
254 if (plugin) {
255 console.debug(`RememberFileState: unregistering view ${viewId} callback`, filePath);
256 delete plugin._viewUninstallers[viewId];
257 delete plugin._lastOpenFiles[viewId];
258 uninstall();
259 } else {
260 console.debug(
261 "RememberFileState: plugin was unloaded, ignoring unregister");
262 }
263 });
264 } 273 }
265 274
266 private readonly onFileOpen = async ( 275 private readonly onFileOpen = async (
267 openedFile: TFile 276 openedFile: TFile
268 ): Promise<void> => { 277 ): Promise<void> => {