# HG changeset patch # User Ludovic Chabant # Date 1647656718 25200 # Node ID 815b93d13e0fabf5700970fa031da4c388362912 # Parent 18ff216ce0c467060e19b215250dbe254e263ed6 Improve typescript compliance diff -r 18ff216ce0c4 -r 815b93d13e0f src/main.ts --- a/src/main.ts Fri Mar 18 19:19:51 2022 -0700 +++ b/src/main.ts Fri Mar 18 19:25:18 2022 -0700 @@ -1,12 +1,20 @@ import { - Editor, + App, + Editor, MarkdownView, OpenViewState, - Plugin, - View + Plugin, + TAbstractFile, + TFile, + View, + WorkspaceLeaf } from 'obsidian'; import { + EditorView +} from '@codemirror/view'; + +import { EditorState, EditorSelection } from '@codemirror/state'; @@ -21,11 +29,33 @@ RememberFileStatePluginSettingTab } from './settings'; +declare var app: App; + +// Interface for CM6 editor view +interface EditorWithCM6 extends Editor { + cm: EditorView +}; + +// View with unique ID +interface ViewWithID extends View { + __uniqueId: number +}; + +// Scroll info interface +interface ScrollInfo { + top: number, left: number +}; + +interface StateData { + selection: EditorSelection, + scrollInfo: ScrollInfo +}; + // Interface for a file state. interface RememberedFileState { path: string; lastSavedTime: number; - stateData: Object; + stateData: StateData; } // Interface for all currently remembered file states. @@ -48,9 +78,9 @@ private _nextUniqueViewId: number = 0; // Functions to unregister any monkey-patched view hooks on plugin unload. - private _viewUninstallers = {}; + private _viewUninstallers: Record = {}; // Functions to unregister any global callbacks on plugin unload. - private _globalUninstallers = []; + private _globalUninstallers: Function[] = []; async onload() { console.log("Loading RememberFileState plugin"); @@ -64,7 +94,7 @@ this.registerEvent(this.app.vault.on('delete', this.onFileDelete)); this.app.workspace.getLeavesOfType("markdown").forEach( - (leaf) => { this.registerOnUnloadFile(leaf.view); }); + (leaf: WorkspaceLeaf) => { this.registerOnUnloadFile(leaf.view as MarkdownView); }); const _this = this; var uninstall = around(this.app.workspace, { @@ -91,9 +121,9 @@ // Run view uninstallers on all current views. var numViews: number = 0; this.app.workspace.getLeavesOfType("markdown").forEach( - (leaf) => { - const filePath = leaf.view.file.path; - const viewId = this.getUniqueViewId(leaf.view); + (leaf: WorkspaceLeaf) => { + const filePath = (leaf.view as MarkdownView).file.path; + const viewId = this.getUniqueViewId(leaf.view as ViewWithID); if (viewId != undefined) { var uninstaller = this._viewUninstallers[viewId]; if (uninstaller) { @@ -105,7 +135,7 @@ } // Clear the ID so we don't get confused if the plugin // is re-enabled later. - this.clearUniqueViewId(leaf.view); + this.clearUniqueViewId(leaf.view as ViewWithID); } else { console.debug("Found markdown view without an ID!", filePath); } @@ -125,9 +155,9 @@ await this.saveData(this.settings); } - private readonly registerOnUnloadFile = function(view) { + private readonly registerOnUnloadFile = function(view: MarkdownView) { var filePath = view.file.path; - var viewId = this.getUniqueViewId(view, true); + var viewId = this.getUniqueViewId(view as unknown as ViewWithID, true); if (viewId in this._viewUninstallers) { console.debug(`View ${viewId} is already registered`, filePath); return; @@ -149,7 +179,8 @@ // Don't hold a reference to this plugin here because this callback // will outlive it if it gets deactivated. So let's find it, and // do nothing if we don't find it. - var plugin = app.plugins.getPlugin("obsidian-remember-file-state"); + // @ts-ignore + var plugin: RememberFileStatePlugin = app.plugins.getPlugin("obsidian-remember-file-state"); if (plugin) { console.debug(`Unregistering view ${viewId} callback`, filePath); delete plugin._viewUninstallers[viewId]; @@ -167,7 +198,7 @@ // If `openedFile` is null, it's because the last pane was closed // and there is now an empty pane. if (openedFile) { - var activeView = this.app.workspace.getActiveViewOfType(MarkdownView); + var activeView: MarkdownView = this.app.workspace.getActiveViewOfType(MarkdownView); if (activeView) { this.registerOnUnloadFile(activeView); @@ -181,9 +212,10 @@ } } - private readonly rememberFileState = async (file: TFile, view: View): Promise => { + private readonly rememberFileState = async (file: TFile, view: MarkdownView): Promise => { const scrollInfo = view.editor.getScrollInfo(); - const stateSelection = view.editor.cm.state.selection; + const cm6editor = view.editor as EditorWithCM6; + const stateSelection: EditorSelection = cm6editor.cm.state.selection; if (stateSelection == undefined) { // Legacy editor is in use, let's ignore return; @@ -210,15 +242,17 @@ console.debug("Remember file state for:", file.path); } - private readonly restoreFileState = function(file: TFile, view: View) { + private readonly restoreFileState = function(file: TFile, view: MarkdownView) { const existingFile = this.data.rememberedFiles[file.path]; if (existingFile) { console.debug("Restoring file state for:", file.path); const stateData = existingFile.stateData; view.editor.scrollTo(stateData.scrollInfo.left, stateData.scrollInfo.top); - var transaction = view.editor.cm.state.update({ + const cm6editor = view.editor as EditorWithCM6; + var transaction = cm6editor.cm.state.update({ selection: EditorSelection.fromJSON(stateData.selection)}) - view.editor.cm.dispatch(transaction); + + cm6editor.cm.dispatch(transaction); } } @@ -229,7 +263,7 @@ } // Sort newer files first, older files last. - var filesData = Object.values(this.data.rememberedFiles); + var filesData: RememberedFileState[] = Object.values(this.data.rememberedFiles); filesData.sort((a, b) => { if (a.lastSavedTime > b.lastSavedTime) return -1; // a before b if (a.lastSavedTime < b.lastSavedTime) return 1; // b before a @@ -243,7 +277,7 @@ } } - private readonly getUniqueViewId = function(view: View, autocreateId: boolean = false) { + private readonly getUniqueViewId = function(view: ViewWithID, autocreateId: boolean = false) { if (view.__uniqueId == undefined) { if (!autocreateId) { return -1; @@ -254,7 +288,7 @@ return view.__uniqueId; } - private readonly clearUniqueViewId = function(view: View) { + private readonly clearUniqueViewId = function(view: ViewWithID) { delete view["__uniqueId"]; } @@ -262,7 +296,7 @@ file: TAbstractFile, oldPath: string, ): Promise => { - const existingFile = this.data.rememberedFiles[oldPath]; + const existingFile: RememberedFileState = this.data.rememberedFiles[oldPath]; if (existingFile) { existingFile.path = file.path; delete this.data.rememberedFiles[oldPath]; diff -r 18ff216ce0c4 -r 815b93d13e0f src/settings.ts --- a/src/settings.ts Fri Mar 18 19:19:51 2022 -0700 +++ b/src/settings.ts Fri Mar 18 19:25:18 2022 -0700 @@ -1,11 +1,10 @@ import { + App, PluginSettingTab, Setting } from 'obsidian'; -import { - RememberFileStatePlugin -} from './main' +import RememberFileStatePlugin from './main'; export interface RememberFileStatePluginSettings { rememberMaxFiles: number; @@ -34,13 +33,13 @@ .setName('Remember files') .setDesc('How many files to remember at most') .addText(text => text - .setValue(this.plugin.settings.rememberMaxFiles?.toString())) - .onChange(async (value) => { + .setValue(this.plugin.settings.rememberMaxFiles?.toString()) + .onChange(async (value: string) => { const intValue = parseInt(value); if (!isNaN(intValue)) { this.plugin.settings.rememberMaxFiles = intValue; await this.plugin.saveSettings(); } - }); + })); } }