diff --git a/manifest.json b/manifest.json index 34b0b92..31898c8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "float-search", "name": "Floating Search", - "version": "3.4.3", + "version": "3.4.4", "minAppVersion": "0.15.0", "description": "You can use search view in modal/leaf/popout window now.", "author": "Boninall", diff --git a/package.json b/package.json index 5f7e6b3..76f6e40 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,27 @@ { - "name": "float-search", - "version": "3.4.3", - "description": "You can use search view in modal/leaf/popout window now.", - "main": "main.js", - "scripts": { - "dev": "node esbuild.config.mjs", - "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", - "version": "node version-bump.mjs && git add manifest.json versions.json" - }, - "keywords": [], - "author": "Boninall", - "license": "GPL-3.0", - "devDependencies": { - "@types/node": "^16.11.6", - "@typescript-eslint/eslint-plugin": "5.29.0", - "@typescript-eslint/parser": "5.29.0", - "builtin-modules": "3.3.0", - "esbuild": "0.14.47", - "obsidian": "latest", - "tslib": "2.4.0", - "typescript": "4.7.4" - }, - "dependencies": { - "monkey-around": "^2.3.0" - } + "name": "float-search", + "version": "3.4.4", + "description": "You can use search view in modal/leaf/popout window now.", + "main": "main.js", + "scripts": { + "dev": "node esbuild.config.mjs", + "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", + "version": "node version-bump.mjs && git add manifest.json versions.json" + }, + "keywords": [], + "author": "Boninall", + "license": "GPL-3.0", + "devDependencies": { + "@types/node": "^16.18.50", + "@typescript-eslint/eslint-plugin": "5.29.0", + "@typescript-eslint/parser": "5.29.0", + "builtin-modules": "3.3.0", + "esbuild": "0.14.47", + "obsidian": "latest", + "tslib": "2.4.0", + "typescript": "4.7.4" + }, + "dependencies": { + "monkey-around": "^2.3.0" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74dc5a6..124ada3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,14 +11,14 @@ dependencies: devDependencies: '@types/node': - specifier: ^16.11.6 - version: 16.18.13 + specifier: ^16.18.50 + version: 16.18.50 '@typescript-eslint/eslint-plugin': specifier: 5.29.0 - version: 5.29.0(@typescript-eslint/parser@5.29.0)(eslint@8.48.0)(typescript@4.7.4) + version: 5.29.0(@typescript-eslint/parser@5.29.0)(eslint@8.49.0)(typescript@4.7.4) '@typescript-eslint/parser': specifier: 5.29.0 - version: 5.29.0(eslint@8.48.0)(typescript@4.7.4) + version: 5.29.0(eslint@8.49.0)(typescript@4.7.4) builtin-modules: specifier: 3.3.0 version: 3.3.0 @@ -27,7 +27,7 @@ devDependencies: version: 0.14.47 obsidian: specifier: latest - version: 1.4.4(@codemirror/state@6.2.1)(@codemirror/view@6.18.0) + version: 1.4.11(@codemirror/state@6.2.1)(@codemirror/view@6.18.1) tslib: specifier: 2.4.0 version: 2.4.0 @@ -46,26 +46,26 @@ packages: resolution: {integrity: sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==} dev: true - /@codemirror/view@6.18.0: - resolution: {integrity: sha512-T6q1yYAoU+gSWfJFR4ryvDQcyOqS+Mw5RCvh26y0KiNksOOLYhNvdB3BTyLz8vy4fKaYlzbAOyBU7OQPUGHzjQ==} + /@codemirror/view@6.18.1: + resolution: {integrity: sha512-xcsXcMkIMd7l3WZEWoc4ljteAiqzxb5gVerRxk5132p5cLix6rTydWTQjsj2oxORepfsrwy1fC4r20iMa9plrg==} dependencies: '@codemirror/state': 6.2.1 style-mod: 4.1.0 w3c-keyname: 2.2.8 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.48.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.49.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.48.0 + eslint: 8.49.0 eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/regexpp@4.8.0: - resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==} + /@eslint-community/regexpp@4.8.1: + resolution: {integrity: sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true @@ -86,8 +86,8 @@ packages: - supports-color dev: true - /@eslint/js@8.48.0: - resolution: {integrity: sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==} + /@eslint/js@8.49.0: + resolution: {integrity: sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true @@ -138,25 +138,25 @@ packages: '@types/tern': 0.23.4 dev: true - /@types/estree@1.0.0: - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} dev: true - /@types/json-schema@7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + /@types/json-schema@7.0.12: + resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} dev: true - /@types/node@16.18.13: - resolution: {integrity: sha512-l0/3XZ153UTlNOnZK8xSNoJlQda9/WnYgiTdcKKPJSZjdjI9MU+A9oMXOesAWLSnqAaaJhj3qfQsU07Dr8OUwg==} + /@types/node@16.18.50: + resolution: {integrity: sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw==} dev: true /@types/tern@0.23.4: resolution: {integrity: sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==} dependencies: - '@types/estree': 1.0.0 + '@types/estree': 1.0.1 dev: true - /@typescript-eslint/eslint-plugin@5.29.0(@typescript-eslint/parser@5.29.0)(eslint@8.48.0)(typescript@4.7.4): + /@typescript-eslint/eslint-plugin@5.29.0(@typescript-eslint/parser@5.29.0)(eslint@8.49.0)(typescript@4.7.4): resolution: {integrity: sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -167,23 +167,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.29.0(eslint@8.48.0)(typescript@4.7.4) + '@typescript-eslint/parser': 5.29.0(eslint@8.49.0)(typescript@4.7.4) '@typescript-eslint/scope-manager': 5.29.0 - '@typescript-eslint/type-utils': 5.29.0(eslint@8.48.0)(typescript@4.7.4) - '@typescript-eslint/utils': 5.29.0(eslint@8.48.0)(typescript@4.7.4) + '@typescript-eslint/type-utils': 5.29.0(eslint@8.49.0)(typescript@4.7.4) + '@typescript-eslint/utils': 5.29.0(eslint@8.49.0)(typescript@4.7.4) debug: 4.3.4 - eslint: 8.48.0 + eslint: 8.49.0 functional-red-black-tree: 1.0.1 ignore: 5.2.4 regexpp: 3.2.0 - semver: 7.3.8 + semver: 7.5.4 tsutils: 3.21.0(typescript@4.7.4) typescript: 4.7.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.29.0(eslint@8.48.0)(typescript@4.7.4): + /@typescript-eslint/parser@5.29.0(eslint@8.49.0)(typescript@4.7.4): resolution: {integrity: sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -197,7 +197,7 @@ packages: '@typescript-eslint/types': 5.29.0 '@typescript-eslint/typescript-estree': 5.29.0(typescript@4.7.4) debug: 4.3.4 - eslint: 8.48.0 + eslint: 8.49.0 typescript: 4.7.4 transitivePeerDependencies: - supports-color @@ -211,7 +211,7 @@ packages: '@typescript-eslint/visitor-keys': 5.29.0 dev: true - /@typescript-eslint/type-utils@5.29.0(eslint@8.48.0)(typescript@4.7.4): + /@typescript-eslint/type-utils@5.29.0(eslint@8.49.0)(typescript@4.7.4): resolution: {integrity: sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -221,9 +221,9 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/utils': 5.29.0(eslint@8.48.0)(typescript@4.7.4) + '@typescript-eslint/utils': 5.29.0(eslint@8.49.0)(typescript@4.7.4) debug: 4.3.4 - eslint: 8.48.0 + eslint: 8.49.0 tsutils: 3.21.0(typescript@4.7.4) typescript: 4.7.4 transitivePeerDependencies: @@ -249,26 +249,26 @@ packages: debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 + semver: 7.5.4 tsutils: 3.21.0(typescript@4.7.4) typescript: 4.7.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.29.0(eslint@8.48.0)(typescript@4.7.4): + /@typescript-eslint/utils@5.29.0(eslint@8.49.0)(typescript@4.7.4): resolution: {integrity: sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@types/json-schema': 7.0.11 + '@types/json-schema': 7.0.12 '@typescript-eslint/scope-manager': 5.29.0 '@typescript-eslint/types': 5.29.0 '@typescript-eslint/typescript-estree': 5.29.0(typescript@4.7.4) - eslint: 8.48.0 + eslint: 8.49.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0(eslint@8.48.0) + eslint-utils: 3.0.0(eslint@8.49.0) transitivePeerDependencies: - supports-color - typescript @@ -279,7 +279,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.29.0 - eslint-visitor-keys: 3.3.0 + eslint-visitor-keys: 3.4.3 dev: true /acorn-jsx@5.3.2(acorn@8.10.0): @@ -645,13 +645,13 @@ packages: estraverse: 5.3.0 dev: true - /eslint-utils@3.0.0(eslint@8.48.0): + /eslint-utils@3.0.0(eslint@8.49.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.48.0 + eslint: 8.49.0 eslint-visitor-keys: 2.1.0 dev: true @@ -660,25 +660,20 @@ packages: engines: {node: '>=10'} dev: true - /eslint-visitor-keys@3.3.0: - resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - /eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.48.0: - resolution: {integrity: sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==} + /eslint@8.49.0: + resolution: {integrity: sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.48.0) - '@eslint-community/regexpp': 4.8.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) + '@eslint-community/regexpp': 4.8.1 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.48.0 + '@eslint/js': 8.49.0 '@humanwhocodes/config-array': 0.11.11 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -758,8 +753,8 @@ packages: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true - /fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} dependencies: '@nodelib/fs.stat': 2.0.5 @@ -864,7 +859,7 @@ packages: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.1 ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 @@ -1020,14 +1015,14 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /obsidian@1.4.4(@codemirror/state@6.2.1)(@codemirror/view@6.18.0): - resolution: {integrity: sha512-q2V5GNT/M40uYOENdVw5kovPSoaO6vppiiyBCkIqWgKp4oN654jA/GQ0OaNBA7p5NdfS245QCeRgCFQ42wOZiw==} + /obsidian@1.4.11(@codemirror/state@6.2.1)(@codemirror/view@6.18.1): + resolution: {integrity: sha512-BCVYTvaXxElJMl6MMbDdY/CGK+aq18SdtDY/7vH8v6BxCBQ6KF4kKxL0vG9UZ0o5qh139KpUoJHNm+6O5dllKA==} peerDependencies: '@codemirror/state': ^6.0.0 '@codemirror/view': ^6.0.0 dependencies: '@codemirror/state': 6.2.1 - '@codemirror/view': 6.18.0 + '@codemirror/view': 6.18.1 '@types/codemirror': 5.60.8 moment: 2.29.4 dev: true @@ -1138,8 +1133,8 @@ packages: queue-microtask: 1.2.3 dev: true - /semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} hasBin: true dependencies: diff --git a/src/floatSearchIndex.ts b/src/floatSearchIndex.ts index c439798..069d369 100644 --- a/src/floatSearchIndex.ts +++ b/src/floatSearchIndex.ts @@ -1,891 +1,891 @@ import { - addIcon, - App, - Editor, ExtraButtonComponent, - Menu, MenuItem, - Modal, OpenViewState, PaneType, - Plugin, SearchView, setIcon, - TAbstractFile, - TFile, ViewStateResult, - Workspace, - WorkspaceContainer, WorkspaceItem, - WorkspaceLeaf + addIcon, + App, + Editor, ExtraButtonComponent, + Menu, MenuItem, + Modal, OpenViewState, PaneType, + Plugin, SearchView, setIcon, + TAbstractFile, + TFile, ViewStateResult, + Workspace, + WorkspaceContainer, WorkspaceItem, + WorkspaceLeaf } from 'obsidian'; import { EmbeddedView, isEmebeddedLeaf, spawnLeafView } from "./leafView"; import { around } from "monkey-around"; type sortOrder = - "alphabetical" - | "alphabeticalReverse" - | "byModifiedTime" - | "byModifiedTimeReverse" - | "byCreatedTime" - | "byCreatedTimeReverse"; + "alphabetical" + | "alphabeticalReverse" + | "byModifiedTime" + | "byModifiedTimeReverse" + | "byCreatedTime" + | "byCreatedTimeReverse"; type searchType = "modal" | "sidebar" | PaneType; interface viewType { - type: searchType; - icon: string; + type: searchType; + icon: string; } interface searchState { - collapseAll?: boolean; - explainSearch?: boolean; - extraContext?: boolean; - matchingCase?: boolean; - query: string; - sortOrder?: sortOrder; - current?: boolean; + collapseAll?: boolean; + explainSearch?: boolean; + extraContext?: boolean; + matchingCase?: boolean; + query: string; + sortOrder?: sortOrder; + current?: boolean; } interface FloatSearchSettings { - searchViewState: searchState; + searchViewState: searchState; } const DEFAULT_SETTINGS: FloatSearchSettings = { - searchViewState: { - collapseAll: false, - explainSearch: false, - extraContext: false, - matchingCase: false, - query: "", - sortOrder: "alphabetical", - } + searchViewState: { + collapseAll: false, + explainSearch: false, + extraContext: false, + matchingCase: false, + query: "", + sortOrder: "alphabetical", + } } const allViews: viewType[] = [{ - type: "modal", - icon: "square-equal" + type: "modal", + icon: "square-equal" }, { - type: "sidebar", - icon: "panel-left-inactive" + type: "sidebar", + icon: "panel-left-inactive" }, { - type: "split", - icon: "split-square-horizontal" + type: "split", + icon: "split-square-horizontal" }, { - type: "tab", - icon: "panel-top" + type: "tab", + icon: "panel-top" }, { - type: "window", - icon: "app-window" + type: "window", + icon: "app-window" }]; const initSearchViewWithLeaf = async (app: App, type: PaneType | 'sidebar', state?: searchState) => { - const leaf = type === 'sidebar' ? app.workspace.getLeftLeaf(false) : app.workspace.getLeaf(type); - leaf.setPinned(type !== 'sidebar'); - await leaf.setViewState({ - type: "search", - active: true, - state: state - }); - setTimeout(() => { - const inputEl = leaf.containerEl.getElementsByTagName("input")[0]; - inputEl.focus(); - }, 0); + const leaf = type === 'sidebar' ? app.workspace.getLeftLeaf(false) : app.workspace.getLeaf(type); + leaf.setPinned(type !== 'sidebar'); + await leaf.setViewState({ + type: "search", + active: true, + state: state + }); + setTimeout(() => { + const inputEl = leaf.containerEl.getElementsByTagName("input")[0]; + inputEl.focus(); + }, 0); } export default class FloatSearchPlugin extends Plugin { - settings: FloatSearchSettings; - private state: any; - private modal: FloatSearchModal; + settings: FloatSearchSettings; + private state: any; + private modal: FloatSearchModal; - private applyStateDebounceTimer = 0; - private applySettingsDebounceTimer = 0; + private applyStateDebounceTimer = 0; + private applySettingsDebounceTimer = 0; - public applySettingsUpdate() { - clearTimeout(this.applySettingsDebounceTimer); - this.applySettingsDebounceTimer = window.setTimeout(async () => { - await this.saveSettings(); - }, 1000); - } + public applySettingsUpdate() { + clearTimeout(this.applySettingsDebounceTimer); + this.applySettingsDebounceTimer = window.setTimeout(async () => { + await this.saveSettings(); + }, 1000); + } - private applyStateUpdate() { - this.applyStateDebounceTimer = window.setTimeout(() => { - clearTimeout(this.applyStateDebounceTimer); - this.state = { - ...this.state, - query: "", - }; - }, 30000); - } + private applyStateUpdate() { + this.applyStateDebounceTimer = window.setTimeout(() => { + clearTimeout(this.applyStateDebounceTimer); + this.state = { + ...this.state, + query: "", + }; + }, 30000); + } - async onload() { - await this.loadSettings(); - this.initState(); - this.registerIcons(); + async onload() { + await this.loadSettings(); + this.initState(); + this.registerIcons(); - this.patchWorkspace(); - this.patchWorkspaceLeaf(); - this.patchSearchView(); + this.patchWorkspace(); + this.patchWorkspaceLeaf(); + this.patchSearchView(); - this.registerObsidianURIHandler(); - this.registerObsidianCommands(); - this.registerEditorMenuHandler(); - this.registerContextMenuHandler(); + this.registerObsidianURIHandler(); + this.registerObsidianCommands(); + this.registerEditorMenuHandler(); + this.registerContextMenuHandler(); - this.addRibbonIcon('search', 'Search Obsidian In Modal', () => this.initModal(this.state, true, true)); - } + this.addRibbonIcon('search', 'Search Obsidian In Modal', () => this.initModal(this.state, true, true)); + } - onunload() { - this.state = undefined; - this.modal?.close(); - } + onunload() { + this.state = undefined; + this.modal?.close(); + } - registerIcons() { - addIcon('panel-left-inactive', ``) - addIcon('app-window', ``); - addIcon('panel-top', ``); - addIcon('square-equal', ``); - } + registerIcons() { + addIcon('panel-left-inactive', ``) + addIcon('app-window', ``); + addIcon('panel-top', ``); + addIcon('square-equal', ``); + } - initState() { - this.state = this.settings.searchViewState as searchState; - } + initState() { + this.state = this.settings.searchViewState as searchState; + } - initModal(state: searchState, stateSave: boolean = false, clearQuery: boolean = false) { - this.modal = new FloatSearchModal((state) => { - this.state = state; - if (stateSave) this.applyStateUpdate(); - this.settings.searchViewState = state as searchState; - this.applySettingsUpdate(); - }, this, {...state, query: clearQuery ? "" : state.query}); - this.modal.open(); - } + initModal(state: searchState, stateSave: boolean = false, clearQuery: boolean = false) { + this.modal = new FloatSearchModal((state) => { + this.state = state; + if (stateSave) this.applyStateUpdate(); + this.settings.searchViewState = state as searchState; + this.applySettingsUpdate(); + }, this, {...state, query: clearQuery ? "" : state.query}); + this.modal.open(); + } - patchWorkspace() { - let layoutChanging = false; - const uninstaller = around(Workspace.prototype, { - getLeaf: (next) => - function (...args) { - const activeLeaf = this.activeLeaf; - if (activeLeaf) { - const fsCtnEl = (activeLeaf.parent?.containerEl as HTMLElement).parentElement; - if (fsCtnEl?.hasClass("fs-content")) { - if (activeLeaf.view.getViewType() === "markdown") { - return activeLeaf; - } - const newLeaf = app.workspace.getUnpinnedLeaf(); - if (newLeaf) { - this.setActiveLeaf(newLeaf); - } - } - return next.call(this); - } - return next.call(this, ...args); - }, - changeLayout(old) { - return async function (workspace: unknown) { - layoutChanging = true; - try { - // Don't consider hover popovers part of the workspace while it's changing - await old.call(this, workspace); - } finally { - layoutChanging = false; - } - }; - }, - iterateLeaves(old) { - type leafIterator = (item: WorkspaceLeaf) => boolean | void; - return function (arg1, arg2) { - // Fast exit if desired leaf found - if (old.call(this, arg1, arg2)) return true; + patchWorkspace() { + let layoutChanging = false; + const uninstaller = around(Workspace.prototype, { + getLeaf: (next) => + function (...args) { + const activeLeaf = this.activeLeaf; + if (activeLeaf) { + const fsCtnEl = (activeLeaf.parent?.containerEl as HTMLElement).parentElement; + if (fsCtnEl?.hasClass("fs-content")) { + if (activeLeaf.view.getViewType() === "markdown") { + return activeLeaf; + } + const newLeaf = app.workspace.getUnpinnedLeaf(); + if (newLeaf) { + this.setActiveLeaf(newLeaf); + } + } + return next.call(this); + } + return next.call(this, ...args); + }, + changeLayout(old) { + return async function (workspace: unknown) { + layoutChanging = true; + try { + // Don't consider hover popovers part of the workspace while it's changing + await old.call(this, workspace); + } finally { + layoutChanging = false; + } + }; + }, + iterateLeaves(old) { + type leafIterator = (item: WorkspaceLeaf) => boolean | void; + return function (arg1, arg2) { + // Fast exit if desired leaf found + if (old.call(this, arg1, arg2)) return true; - // Handle old/new API parameter swap - const cb: leafIterator = (typeof arg1 === "function" ? arg1 : arg2) as leafIterator; - const parent: WorkspaceItem = (typeof arg1 === "function" ? arg2 : arg1) as WorkspaceItem; + // Handle old/new API parameter swap + const cb: leafIterator = (typeof arg1 === "function" ? arg1 : arg2) as leafIterator; + const parent: WorkspaceItem = (typeof arg1 === "function" ? arg2 : arg1) as WorkspaceItem; - if (!parent) return false; // <- during app startup, rootSplit can be null - if (layoutChanging) return false; // Don't let HEs close during workspace change + if (!parent) return false; // <- during app startup, rootSplit can be null + if (layoutChanging) return false; // Don't let HEs close during workspace change - // 0.14.x doesn't have WorkspaceContainer; this can just be an instanceof check once 15.x is mandatory: - if (parent === app.workspace.rootSplit || (WorkspaceContainer && parent instanceof WorkspaceContainer)) { - for (const popover of EmbeddedView.popoversForWindow((parent as WorkspaceContainer).win)) { - // Use old API here for compat w/0.14.x - if (old.call(this, cb, popover.rootSplit)) return true; - } - } - return false; - }; - }, - onDragLeaf(old) { - return function (event: MouseEvent, leaf: WorkspaceLeaf) { - return old.call(this, event, leaf); - }; - }, - pushUndoHistory(old: any) { - return function (leaf: WorkspaceLeaf, id: string, ...args: any[]) { - const viewState = leaf.getViewState(); - if (viewState.type === "search") { - return; - } - return old.call(this, leaf, id, ...args); - }; - } - }); - this.register(uninstaller); - } + // 0.14.x doesn't have WorkspaceContainer; this can just be an instanceof check once 15.x is mandatory: + if (parent === app.workspace.rootSplit || (WorkspaceContainer && parent instanceof WorkspaceContainer)) { + for (const popover of EmbeddedView.popoversForWindow((parent as WorkspaceContainer).win)) { + // Use old API here for compat w/0.14.x + if (old.call(this, cb, popover.rootSplit)) return true; + } + } + return false; + }; + }, + onDragLeaf(old) { + return function (event: MouseEvent, leaf: WorkspaceLeaf) { + return old.call(this, event, leaf); + }; + }, + pushUndoHistory(old: any) { + return function (leaf: WorkspaceLeaf, id: string, ...args: any[]) { + const viewState = leaf.getViewState(); + if (viewState.type === "search") { + return; + } + return old.call(this, leaf, id, ...args); + }; + } + }); + this.register(uninstaller); + } - // Used for patch workspaceleaf pinned behaviors - patchWorkspaceLeaf() { - this.register( - around(WorkspaceLeaf.prototype, { - getRoot(old) { - return function () { - const top = old.call(this); - return top?.getRoot === this.getRoot ? top : top?.getRoot(); - }; - }, - setPinned(old) { - return function (pinned: boolean) { - old.call(this, pinned); - if (isEmebeddedLeaf(this) && !pinned) this.setPinned(true); - } - }, - openFile(old) { - return function (file: TFile, openState?: OpenViewState) { - if (isEmebeddedLeaf(this)) { - setTimeout( - around(Workspace.prototype, { - recordMostRecentOpenedFile(old) { - return function (_file: TFile) { - // Don't update the quick switcher's recent list - if (_file !== file) { - return old.call(this, _file); - } - }; - }, - }), - 1, - ); - const recentFiles = this.app.plugins.plugins["recent-files-obsidian"]; - if (recentFiles) { - setTimeout( - around(recentFiles, { - shouldAddFile(old) { - return function (_file: TFile) { - // Don't update the Recent Files plugin - return _file !== file && old.call(this, _file); - }; - }, - }), - 1, - ); - } + // Used for patch workspaceleaf pinned behaviors + patchWorkspaceLeaf() { + this.register( + around(WorkspaceLeaf.prototype, { + getRoot(old) { + return function () { + const top = old.call(this); + return top?.getRoot === this.getRoot ? top : top?.getRoot(); + }; + }, + setPinned(old) { + return function (pinned: boolean) { + old.call(this, pinned); + if (isEmebeddedLeaf(this) && !pinned) this.setPinned(true); + } + }, + openFile(old) { + return function (file: TFile, openState?: OpenViewState) { + if (isEmebeddedLeaf(this)) { + setTimeout( + around(Workspace.prototype, { + recordMostRecentOpenedFile(old) { + return function (_file: TFile) { + // Don't update the quick switcher's recent list + if (_file !== file) { + return old.call(this, _file); + } + }; + }, + }), + 1, + ); + const recentFiles = this.app.plugins.plugins["recent-files-obsidian"]; + if (recentFiles) { + setTimeout( + around(recentFiles, { + shouldAddFile(old) { + return function (_file: TFile) { + // Don't update the Recent Files plugin + return _file !== file && old.call(this, _file); + }; + }, + }), + 1, + ); + } - } + } - const view = old.call(this, file, openState); - setTimeout(() => { - const fsCtnEl = (this.parent.containerEl as HTMLElement).parentElement; - if (!(fsCtnEl?.classList.contains("fs-content"))) return; - if (file.extension != "canvas") return; + const view = old.call(this, file, openState); + setTimeout(() => { + const fsCtnEl = (this.parent.containerEl as HTMLElement).parentElement; + if (!(fsCtnEl?.classList.contains("fs-content"))) return; + if (file.extension != "canvas") return; - const canvas = this.view.canvas; - setTimeout(() => { - if (canvas && openState?.eState?.match) { - let node = canvas.data.nodes?.find((e: any) => e.text === openState.eState.match.content); - node = canvas.nodes.get(node.id); + const canvas = this.view.canvas; + setTimeout(() => { + if (canvas && openState?.eState?.match) { + let node = canvas.data.nodes?.find((e: any) => e.text === openState.eState.match.content); + node = canvas.nodes.get(node.id); - canvas.selectOnly(node); - canvas.zoomToSelection(); - } - }, 20); - }, 1); + canvas.selectOnly(node); + canvas.zoomToSelection(); + } + }, 20); + }, 1); - return view; - } - }, - }), - ); - } + return view; + } + }, + }), + ); + } - patchSearchView() { - const updateCurrentState = (state: searchState) => { - this.state = state; - this.settings.searchViewState = state as searchState; - this.applySettingsUpdate(); - } + patchSearchView() { + const updateCurrentState = (state: searchState) => { + this.state = state; + this.settings.searchViewState = state as searchState; + this.applySettingsUpdate(); + } - const checkCurrentViewType = (leaf: WorkspaceLeaf) => { - const isModal = document.querySelector('.float-search-modal') !== null; - const currentLeafRoot = leaf.getRoot(); - if (currentLeafRoot?.side && (currentLeafRoot?.side === "left" || currentLeafRoot?.side === 'right')) return "sidebar"; - if (leaf.getContainer()?.type === "window") return "window"; - return isModal ? "modal" : "split"; - } + const checkCurrentViewType = (leaf: WorkspaceLeaf) => { + const isModal = document.querySelector('.float-search-modal') !== null; + const currentLeafRoot = leaf.getRoot(); + if (currentLeafRoot?.side && (currentLeafRoot?.side === "left" || currentLeafRoot?.side === 'right')) return "sidebar"; + if (leaf.getContainer()?.type === "window") return "window"; + return isModal ? "modal" : "split"; + } - const initViewMenu = (menu: Menu, current: searchType, originLeaf?: WorkspaceLeaf) => { - menu.dom.toggleClass("float-search-view-menu", true); - let availableViews = allViews.filter((view) => { - if (current === "split") { - return view.type !== "tab"; - } else { - return view.type !== current; - } - }); - for (const view of availableViews) { - menu.addItem((item: MenuItem) => { - item.setTitle(`${view.type} view`).setIcon(`${view.icon}`).onClick(async () => { - if (view.type === "modal") { - originLeaf?.detach(); - setTimeout(() => { - this.initModal(this.state, true, false); - }, 10); - } else if (view.type === "sidebar") { - await initSearchViewWithLeaf(this.app, view.type, this.state); - } else { - if (current === "window") { - originLeaf?.detach(); - setTimeout(async () => { - await initSearchViewWithLeaf(this.app, <"tab" | "split">view.type, this.state); - }, 10); - } else { - await initSearchViewWithLeaf(this.app, view.type, this.state); - } + const initViewMenu = (menu: Menu, current: searchType, originLeaf?: WorkspaceLeaf) => { + menu.dom.toggleClass("float-search-view-menu", true); + let availableViews = allViews.filter((view) => { + if (current === "split") { + return view.type !== "tab"; + } else { + return view.type !== current; + } + }); + for (const view of availableViews) { + menu.addItem((item: MenuItem) => { + item.setTitle(`${view.type} view`).setIcon(`${view.icon}`).onClick(async () => { + if (view.type === "modal") { + originLeaf?.detach(); + setTimeout(() => { + this.initModal(this.state, true, false); + }, 10); + } else if (view.type === "sidebar") { + await initSearchViewWithLeaf(this.app, view.type, this.state); + } else { + if (current === "window") { + originLeaf?.detach(); + setTimeout(async () => { + await initSearchViewWithLeaf(this.app, <"tab" | "split">view.type, this.state); + }, 10); + } else { + await initSearchViewWithLeaf(this.app, view.type, this.state); + } - } - if (current === "modal") { - this.modal.close(); - } else { - originLeaf?.detach(); - } - }); - }); - } - return menu; - } + } + if (current === "modal") { + this.modal.close(); + } else { + originLeaf?.detach(); + } + }); + }); + } + return menu; + } - const patchSearch = () => { - const searchView = this.app.workspace.getLeavesOfType("search")[0]?.view as any; + const patchSearch = () => { + const searchView = this.app.workspace.getLeavesOfType("search")[0]?.view as any; - if (!searchView) return false; + if (!searchView) return false; - const searchViewConstructor = searchView.constructor; + const searchViewConstructor = searchView.constructor; - this.register( - around(searchViewConstructor.prototype, { - onOpen(old) { - return function () { - old.call(this); - const viewSwitchEl = createDiv({cls: "float-search-view-switch"}); - const targetEl = this.filterSectionToggleEl; - const viewSwitchButton = new ExtraButtonComponent(viewSwitchEl); - viewSwitchButton.setIcon('layout-template').setTooltip("Switch to File View"); - viewSwitchButton.onClick(() => { - const currentType = checkCurrentViewType(this.leaf); - const layoutMenu = initViewMenu(new Menu(), currentType, this.leaf); - const viewSwitchButtonPos = viewSwitchEl.getBoundingClientRect(); - layoutMenu.showAtPosition({x: viewSwitchButtonPos.x, y: viewSwitchButtonPos.y + 30}); - }); - targetEl.parentElement.insertBefore(viewSwitchEl, targetEl); - } - }, - startSearch(old) { - return function () { - old.call(this); - const viewState = this.getState(); - updateCurrentState({ - ...viewState, - query: this.searchComponent.getValue(), - }); - } - } - }) - ); - searchView.leaf?.rebuildView(); - console.log("Metadata-Style: all property view get patched"); - return true; - }; - this.app.workspace.onLayoutReady(() => { - if (!patchSearch()) { - const evt = this.app.workspace.on("layout-change", () => { - patchSearch() && this.app.workspace.offref(evt); - }); - this.registerEvent(evt); - } - }); - } + this.register( + around(searchViewConstructor.prototype, { + onOpen(old) { + return function () { + old.call(this); + const viewSwitchEl = createDiv({cls: "float-search-view-switch"}); + const targetEl = this.filterSectionToggleEl; + const viewSwitchButton = new ExtraButtonComponent(viewSwitchEl); + viewSwitchButton.setIcon('layout-template').setTooltip("Switch to File View"); + viewSwitchButton.onClick(() => { + const currentType = checkCurrentViewType(this.leaf); + const layoutMenu = initViewMenu(new Menu(), currentType, this.leaf); + const viewSwitchButtonPos = viewSwitchEl.getBoundingClientRect(); + layoutMenu.showAtPosition({x: viewSwitchButtonPos.x, y: viewSwitchButtonPos.y + 30}); + }); + targetEl.parentElement.insertBefore(viewSwitchEl, targetEl); + } + }, + startSearch(old) { + return function () { + old.call(this); + const viewState = this.getState(); + updateCurrentState({ + ...viewState, + query: this.searchComponent.getValue(), + }); + } + } + }) + ); + searchView.leaf?.rebuildView(); + console.log("Metadata-Style: all property view get patched"); + return true; + }; + this.app.workspace.onLayoutReady(() => { + if (!patchSearch()) { + const evt = this.app.workspace.on("layout-change", () => { + patchSearch() && this.app.workspace.offref(evt); + }); + this.registerEvent(evt); + } + }); + } - registerObsidianURIHandler() { - this.registerObsidianProtocolHandler("fs", (path) => this.initModal({ - ...this.state, - query: path.query, - current: false - }, true, true)); - } + registerObsidianURIHandler() { + this.registerObsidianProtocolHandler("fs", (path) => this.initModal({ + ...this.state, + query: path.query, + current: false + }, true, true)); + } - private createCommand(options: { - id: string; - name: string; - queryBuilder: (file: any) => string; - }): void { - this.addCommand({ - id: options.id, - name: options.name, - checkCallback: (checking: boolean) => { - const activeLeaf = this.app.workspace.activeLeaf; - if (!activeLeaf) return; + private createCommand(options: { + id: string; + name: string; + queryBuilder: (file: any) => string; + }): void { + this.addCommand({ + id: options.id, + name: options.name, + checkCallback: (checking: boolean) => { + const activeLeaf = this.app.workspace.activeLeaf; + if (!activeLeaf) return; - const viewType = activeLeaf.view.getViewType(); - if (viewType === "markdown" || viewType === "canvas") { - if (!checking) { - const currentFile = activeLeaf.view.file; - const query = options.queryBuilder(currentFile); - this.initModal({...this.state, query, current: true}, true, false); - } - return true; - } - } - }); - } + const viewType = activeLeaf.view.getViewType(); + if (viewType === "markdown" || viewType === "canvas") { + if (!checking) { + const currentFile = activeLeaf.view.file; + const query = options.queryBuilder(currentFile); + this.initModal({...this.state, query, current: true}, true, false); + } + return true; + } + } + }); + } - registerObsidianCommands() { - this.addCommand({ - id: 'search-obsidian-globally', - name: 'Search Obsidian Globally', - callback: () => this.initModal({...this.state, query: "", current: false}, false, true) - }); + registerObsidianCommands() { + this.addCommand({ + id: 'search-obsidian-globally', + name: 'Search Obsidian Globally', + callback: () => this.initModal({...this.state, query: "", current: false}, false, true) + }); - this.addCommand({ - id: 'search-obsidian-globally-state', - name: 'Search Obsidian Globally (With Last State)', - callback: () => this.initModal({...this.state, query: "", current: false}, true, false) - }); + this.addCommand({ + id: 'search-obsidian-globally-state', + name: 'Search Obsidian Globally (With Last State)', + callback: () => this.initModal({...this.state, query: "", current: false}, true, false) + }); - this.createCommand({ - id: 'search-in-backlink', - name: 'Search In Backlink Of Current File', - queryBuilder: (file) => { - return " /\\[\\[" + (file.extension === "canvas" ? file.name : file.basename) + "(\\|[^\\]]*)?\\]\\]/"; - } - }); + this.createCommand({ + id: 'search-in-backlink', + name: 'Search In Backlink Of Current File', + queryBuilder: (file) => { + return " /\\[\\[" + (file.extension === "canvas" ? file.name : file.basename) + "(\\|[^\\]]*)?\\]\\]/"; + } + }); - this.createCommand({ - id: 'search-in-current-file', - name: 'Search In Current File', - queryBuilder: (file) => { - return " path:" + `"${file.path}"`; - } - }); + this.createCommand({ + id: 'search-in-current-file', + name: 'Search In Current File', + queryBuilder: (file) => { + return " path:" + `"${file.path}"`; + } + }); - for (const type of ['split', 'tab', 'window'] as PaneType[]) { - this.addCommand({ - id: `open-search-view-${type}`, - name: `Open Search View (${type})`, - callback: async () => initSearchViewWithLeaf(this.app, type) - }); - } - } + for (const type of ['split', 'tab', 'window'] as PaneType[]) { + this.addCommand({ + id: `open-search-view-${type}`, + name: `Open Search View (${type})`, + callback: async () => initSearchViewWithLeaf(this.app, type) + }); + } + } - registerEditorMenuHandler() { - this.registerEvent( - this.app.workspace.on('editor-menu', (menu: Menu, editor: Editor) => { - if (!editor) { - return; - } - if (editor.getSelection().length === 0) { - return; - } - const selection = editor.getSelection().trim(); - let searchWord = selection; + registerEditorMenuHandler() { + this.registerEvent( + this.app.workspace.on('editor-menu', (menu: Menu, editor: Editor) => { + if (!editor) { + return; + } + if (editor.getSelection().length === 0) { + return; + } + const selection = editor.getSelection().trim(); + let searchWord = selection; - if (selection.length > 8) { - searchWord = selection.substring(0, 3) + "..." + selection.substring(selection.length - 3, selection.length); - } else { - searchWord = selection; - } + if (selection.length > 8) { + searchWord = selection.substring(0, 3) + "..." + selection.substring(selection.length - 3, selection.length); + } else { + searchWord = selection; + } - menu.addItem((item) => { - // Add sub menu - item.setTitle('Search "' + searchWord + '"' + " in Float Search").setIcon("search") - .onClick(() => this.initModal({...this.state, query: selection, current: false}, true, false)) - }) - })) - } + menu.addItem((item) => { + // Add sub menu + item.setTitle('Search "' + searchWord + '"' + " in Float Search").setIcon("search") + .onClick(() => this.initModal({...this.state, query: selection, current: false}, true, false)) + }) + })) + } - registerContextMenuHandler() { - this.registerEvent( - this.app.workspace.on("file-menu", (menu: Menu, file: TAbstractFile, source: string, leaf?: WorkspaceLeaf) => { - const popover = leaf ? EmbeddedView.forLeaf(leaf) : undefined; - if (file instanceof TFile && !popover && !leaf) { - menu.addItem(item => { - item - .setIcon("popup-open") - .setTitle("Open in Float Preview") - .onClick(async () => { - if (this.modal) { - await this.modal.initFileView(file, undefined); + registerContextMenuHandler() { + this.registerEvent( + this.app.workspace.on("file-menu", (menu: Menu, file: TAbstractFile, source: string, leaf?: WorkspaceLeaf) => { + const popover = leaf ? EmbeddedView.forLeaf(leaf) : undefined; + if (file instanceof TFile && !popover && !leaf) { + menu.addItem(item => { + item + .setIcon("popup-open") + .setTitle("Open in Float Preview") + .onClick(async () => { + if (this.modal) { + await this.modal.initFileView(file, undefined); - return; - } + return; + } - this.initModal({...this.state, current: false}, true, true); - setTimeout(async () => { - await this.modal.initFileView(file, undefined); - }, 20); - }) - .setSection?.("open"); - }); - } - }), - ); - } + this.initModal({...this.state, current: false}, true, true); + setTimeout(async () => { + await this.modal.initFileView(file, undefined); + }, 20); + }) + .setSection?.("open"); + }); + } + }), + ); + } - async loadSettings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } + async loadSettings() { + this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); + } - async saveSettings() { - await this.saveData(this.settings); - } + async saveSettings() { + await this.saveData(this.settings); + } } class FloatSearchModal extends Modal { - private readonly plugin: FloatSearchPlugin; - private searchEmbeddedView: EmbeddedView; - private fileEmbeddedView: EmbeddedView; + private readonly plugin: FloatSearchPlugin; + private searchEmbeddedView: EmbeddedView; + private fileEmbeddedView: EmbeddedView; - searchLeaf: WorkspaceLeaf; - fileLeaf: WorkspaceLeaf | undefined; + searchLeaf: WorkspaceLeaf; + fileLeaf: WorkspaceLeaf | undefined; - private cb: (state: any) => void; - private state: any; + private cb: (state: any) => void; + private state: any; - private fileState: any; + private fileState: any; - private searchCtnEl: HTMLElement; - private instructionsEl: HTMLElement; - private fileEl: HTMLElement; - private viewType: string; + private searchCtnEl: HTMLElement; + private instructionsEl: HTMLElement; + private fileEl: HTMLElement; + private viewType: string; - constructor(cb: (state: any) => void, plugin: FloatSearchPlugin, state: any, viewType: string = "search") { - super(plugin.app); - this.plugin = plugin; - this.cb = cb; - this.state = state; - this.viewType = viewType; - } + constructor(cb: (state: any) => void, plugin: FloatSearchPlugin, state: any, viewType: string = "search") { + super(plugin.app); + this.plugin = plugin; + this.cb = cb; + this.state = state; + this.viewType = viewType; + } - async onOpen() { - const {contentEl, containerEl, modalEl} = this; + async onOpen() { + const {contentEl, containerEl, modalEl} = this; - this.searchCtnEl = contentEl.createDiv({cls: "float-search-modal-search-ctn"}); - this.instructionsEl = modalEl.createDiv({cls: "float-search-modal-instructions"}); + this.searchCtnEl = contentEl.createDiv({cls: "float-search-modal-search-ctn"}); + this.instructionsEl = modalEl.createDiv({cls: "float-search-modal-instructions"}); - this.initInstructions(this.instructionsEl); - this.initCss(contentEl, modalEl, containerEl); - await this.initSearchView(this.searchCtnEl); - this.initInput(); - this.initContent(); - } + this.initInstructions(this.instructionsEl); + this.initCss(contentEl, modalEl, containerEl); + await this.initSearchView(this.searchCtnEl); + this.initInput(); + this.initContent(); + } - onClose() { - const {contentEl} = this; + onClose() { + const {contentEl} = this; - this.cb(this.searchLeaf.view.getState()); + this.cb(this.searchLeaf.view.getState()); - this.searchLeaf.detach(); - this.fileLeaf?.detach(); - this.searchEmbeddedView.unload(); - this.fileEmbeddedView?.unload(); - contentEl.empty(); - } + this.searchLeaf.detach(); + this.fileLeaf?.detach(); + this.searchEmbeddedView.unload(); + this.fileEmbeddedView?.unload(); + contentEl.empty(); + } - initInstructions(instructionsEl: HTMLElement) { - const navigateInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-navigate"}); - const collapseInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-collapse"}); - const enterInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-enter"}); - const altEnterInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-alt-enter"}); + initInstructions(instructionsEl: HTMLElement) { + const navigateInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-navigate"}); + const collapseInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-collapse"}); + const enterInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-enter"}); + const altEnterInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-alt-enter"}); - const tabInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-tab"}); - const switchInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-switch"}); + const tabInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-tab"}); + const switchInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-switch"}); - const navigateIconEl = navigateInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const navigateTextEl = navigateInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - navigateIconEl.setText("↑↓"); - navigateTextEl.setText("Navigate"); + const navigateIconEl = navigateInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const navigateTextEl = navigateInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + navigateIconEl.setText("↑↓"); + navigateTextEl.setText("Navigate"); - const collapseIconEl = collapseInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const collapseTextEl = collapseInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - collapseIconEl.setText("Shift+↑↓"); - collapseTextEl.setText("Collapse/Expand"); + const collapseIconEl = collapseInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const collapseTextEl = collapseInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + collapseIconEl.setText("Shift+↑↓"); + collapseTextEl.setText("Collapse/Expand"); - const enterIconEl = enterInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const enterTextEl = enterInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - enterIconEl.setText("↵"); - enterTextEl.setText("Open in background"); + const enterIconEl = enterInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const enterTextEl = enterInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + enterIconEl.setText("↵"); + enterTextEl.setText("Open in background"); - const altEnterIconEl = altEnterInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const altEnterTextEl = altEnterInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - altEnterIconEl.setText("Alt+↵"); - altEnterTextEl.setText("Open File and Close"); + const altEnterIconEl = altEnterInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const altEnterTextEl = altEnterInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + altEnterIconEl.setText("Alt+↵"); + altEnterTextEl.setText("Open File and Close"); - const tabIconEl = tabInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const tabTextEl = tabInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - tabIconEl.setText("Tab/Shift+Tab"); - tabTextEl.setText("Preview/Close Preview"); + const tabIconEl = tabInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const tabTextEl = tabInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + tabIconEl.setText("Tab/Shift+Tab"); + tabTextEl.setText("Preview/Close Preview"); - const switchIconEl = switchInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const switchTextEl = switchInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - switchIconEl.setText("Ctrl+G"); - switchTextEl.setText("Switch Between Search and File View"); + const switchIconEl = switchInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const switchTextEl = switchInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + switchIconEl.setText("Ctrl+G"); + switchTextEl.setText("Switch Between Search and File View"); - const clickInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-click"}); - const clickIconEl = clickInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); - const clickTextEl = clickInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); - clickIconEl.setText("Alt+Click"); - clickTextEl.setText("Close Modal While In File View"); - } + const clickInstructionsEl = instructionsEl.createDiv({cls: "float-search-modal-instructions-click"}); + const clickIconEl = clickInstructionsEl.createSpan({cls: "float-search-modal-instructions-key"}); + const clickTextEl = clickInstructionsEl.createSpan({cls: "float-search-modal-instructions-text"}); + clickIconEl.setText("Alt+Click"); + clickTextEl.setText("Close Modal While In File View"); + } - initCss(contentEl: HTMLElement, modalEl: HTMLElement, containerEl: HTMLElement) { - contentEl.classList.add("float-search-modal-content"); - modalEl.classList.add("float-search-modal"); - containerEl.classList.add("float-search-modal-container"); - } + initCss(contentEl: HTMLElement, modalEl: HTMLElement, containerEl: HTMLElement) { + contentEl.classList.add("float-search-modal-content"); + modalEl.classList.add("float-search-modal"); + containerEl.classList.add("float-search-modal-container"); + } - async initSearchView(contentEl: HTMLElement) { - const [createdLeaf, embeddedView] = spawnLeafView(this.plugin, contentEl); - this.searchLeaf = createdLeaf; - this.searchEmbeddedView = embeddedView; + async initSearchView(contentEl: HTMLElement) { + const [createdLeaf, embeddedView] = spawnLeafView(this.plugin, contentEl); + this.searchLeaf = createdLeaf; + this.searchEmbeddedView = embeddedView; - this.searchLeaf.setPinned(true); - await this.searchLeaf.setViewState({ - type: "search", - }); + this.searchLeaf.setPinned(true); + await this.searchLeaf.setViewState({ + type: "search", + }); - setTimeout(async () => { - await this.searchLeaf.view.setState(this.state, { - focus: true, - } as ViewStateResult); - this.state?.current ? (this.searchLeaf.view as SearchView).searchComponent.inputEl.setSelectionRange(0, 0) : (this.searchLeaf.view as SearchView).searchComponent.inputEl.setSelectionRange(0, this.state?.query?.length); - }, 0); + setTimeout(async () => { + await this.searchLeaf.view.setState(this.state, { + history: false, + }); + this.state?.current ? (this.searchLeaf.view as SearchView).searchComponent.inputEl.setSelectionRange(0, 0) : (this.searchLeaf.view as SearchView).searchComponent.inputEl.setSelectionRange(0, this.state?.query?.length); + }, 0); - return; - } + return; + } - initInput() { - const inputEl = this.contentEl.getElementsByTagName("input")[0]; - inputEl.focus(); - inputEl.onkeydown = (e) => { - const currentView = this.searchLeaf.view as SearchView; - switch (e.key) { - case "ArrowDown": - if (e.shiftKey) { - currentView.onKeyShowMoreAfter(e); - if (currentView.dom.focusedItem) { - if (currentView.dom.focusedItem.collapsible) { - currentView.dom.focusedItem.setCollapse(false); - } - } - break; - } else { - currentView.onKeyArrowDownInFocus(e); - break; - } - case "ArrowUp": - if (e.shiftKey) { - currentView.onKeyShowMoreBefore(e); - if (currentView.dom.focusedItem) { - if (currentView.dom.focusedItem.collapseEl) { - currentView.dom.focusedItem.setCollapse(true); - } - } - break; - } else { - currentView.onKeyArrowUpInFocus(e); - break; - } - case "ArrowLeft": - currentView.onKeyArrowLeftInFocus(e); - break; - case "ArrowRight": - currentView.onKeyArrowRightInFocus(e); - break; - case "Enter": - currentView.onKeyEnterInFocus(e); - if (e.altKey && currentView.dom.focusedItem) { - this.close(); - } - break; - case "Tab": - e.preventDefault(); - if (e.shiftKey) { - if (this.fileLeaf) { - this.fileLeaf?.detach(); - this.fileLeaf = undefined; - this.fileEmbeddedView?.unload(); - this.modalEl.toggleClass("float-search-width", false); - this.fileEl.detach(); + initInput() { + const inputEl = this.contentEl.getElementsByTagName("input")[0]; + inputEl.focus(); + inputEl.onkeydown = (e) => { + const currentView = this.searchLeaf.view as SearchView; + switch (e.key) { + case "ArrowDown": + if (e.shiftKey) { + currentView.onKeyShowMoreAfter(e); + if (currentView.dom.focusedItem) { + if (currentView.dom.focusedItem.collapsible) { + currentView.dom.focusedItem.setCollapse(false); + } + } + break; + } else { + currentView.onKeyArrowDownInFocus(e); + break; + } + case "ArrowUp": + if (e.shiftKey) { + currentView.onKeyShowMoreBefore(e); + if (currentView.dom.focusedItem) { + if (currentView.dom.focusedItem.collapseEl) { + currentView.dom.focusedItem.setCollapse(true); + } + } + break; + } else { + currentView.onKeyArrowUpInFocus(e); + break; + } + case "ArrowLeft": + currentView.onKeyArrowLeftInFocus(e); + break; + case "ArrowRight": + currentView.onKeyArrowRightInFocus(e); + break; + case "Enter": + currentView.onKeyEnterInFocus(e); + if (e.altKey && currentView.dom.focusedItem) { + this.close(); + } + break; + case "Tab": + e.preventDefault(); + if (e.shiftKey) { + if (this.fileLeaf) { + this.fileLeaf?.detach(); + this.fileLeaf = undefined; + this.fileEmbeddedView?.unload(); + this.modalEl.toggleClass("float-search-width", false); + this.fileEl.detach(); - break; - } - } + break; + } + } - if (currentView.dom.focusedItem) { - const item = currentView.dom.focusedItem; - const file = item.parent.file instanceof TFile ? item.parent.file : item.file; + if (currentView.dom.focusedItem) { + const item = currentView.dom.focusedItem; + const file = item.parent.file instanceof TFile ? item.parent.file : item.file; - item.parent.file instanceof TFile ? this.initFileView(file, { - match: { - content: item.content, - matches: item.matches - } - }) : this.initFileView(file, undefined); - } - break; - case "e": - if (e.ctrlKey) { - e.preventDefault(); - if (this.fileLeaf) { - const estate = this.fileLeaf.getViewState(); - estate.state.mode = "preview" === estate.state.mode ? "source" : "preview"; - this.fileLeaf.setViewState(estate, { - focus: !0 - }); - setTimeout(() => { - (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); - }, 0); - } - } - break; - case "g": - if (this.fileLeaf && e.ctrlKey) { - e.preventDefault(); - this.plugin.app.workspace.setActiveLeaf(this.fileLeaf, { - focus: true, - }); - } - break; - case "C": - if (e.ctrlKey && e.shiftKey) { - e.preventDefault(); - const text = currentView.dom.focusedItem.el.innerText; - navigator.clipboard.writeText(text); - } - break; + item.parent.file instanceof TFile ? this.initFileView(file, { + match: { + content: item.content, + matches: item.matches + } + }) : this.initFileView(file, undefined); + } + break; + case "e": + if (e.ctrlKey) { + e.preventDefault(); + if (this.fileLeaf) { + const estate = this.fileLeaf.getViewState(); + estate.state.mode = "preview" === estate.state.mode ? "source" : "preview"; + this.fileLeaf.setViewState(estate, { + focus: !0 + }); + setTimeout(() => { + (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); + }, 0); + } + } + break; + case "g": + if (this.fileLeaf && e.ctrlKey) { + e.preventDefault(); + this.plugin.app.workspace.setActiveLeaf(this.fileLeaf, { + focus: true, + }); + } + break; + case "C": + if (e.ctrlKey && e.shiftKey) { + e.preventDefault(); + const text = currentView.dom.focusedItem.el.innerText; + navigator.clipboard.writeText(text); + } + break; - } - } - } + } + } + } - initContent() { - const {contentEl} = this; - contentEl.onclick = (e) => { - const resultElement = contentEl.getElementsByClassName('search-results-children')[0]; - if (resultElement.children.length < 2) { - return; - } + initContent() { + const {contentEl} = this; + contentEl.onclick = (e) => { + const resultElement = contentEl.getElementsByClassName('search-results-children')[0]; + if (resultElement.children.length < 2) { + return; + } - let targetElement = e.target as HTMLElement | null; + let targetElement = e.target as HTMLElement | null; - if (e.altKey || !this.fileLeaf) { - while (targetElement) { - if (targetElement.classList.contains('tree-item-icon')) { - break; - } - if (targetElement.classList.contains('tree-item')) { - this.close(); - break; - } - targetElement = targetElement.parentElement; - } - return; - } + if (e.altKey || !this.fileLeaf) { + while (targetElement) { + if (targetElement.classList.contains('tree-item-icon')) { + break; + } + if (targetElement.classList.contains('tree-item')) { + this.close(); + break; + } + targetElement = targetElement.parentElement; + } + return; + } - if (this.fileLeaf) { - const currentView = this.searchLeaf.view as SearchView; + if (this.fileLeaf) { + const currentView = this.searchLeaf.view as SearchView; - if ((this.searchCtnEl as Node).contains(targetElement as Node)) { - while (targetElement) { - if (targetElement.classList.contains('tree-item')) { - break; - } - targetElement = targetElement.parentElement; - } - if (!targetElement) return; + if ((this.searchCtnEl as Node).contains(targetElement as Node)) { + while (targetElement) { + if (targetElement.classList.contains('tree-item')) { + break; + } + targetElement = targetElement.parentElement; + } + if (!targetElement) return; - const fileInnerEl = targetElement?.getElementsByClassName("tree-item-inner")[0] as HTMLElement; - const innerText = fileInnerEl.innerText; - const file = this.plugin.app.metadataCache.getFirstLinkpathDest(innerText, ""); + const fileInnerEl = targetElement?.getElementsByClassName("tree-item-inner")[0] as HTMLElement; + const innerText = fileInnerEl.innerText; + const file = this.plugin.app.metadataCache.getFirstLinkpathDest(innerText, ""); - if (file) { - const item = currentView.dom.resultDomLookup.get(file); - currentView.dom.setFocusedItem(item); - this.initFileView(file, undefined); - (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); - } - } + if (file) { + const item = currentView.dom.resultDomLookup.get(file); + currentView.dom.setFocusedItem(item); + this.initFileView(file, undefined); + (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); + } + } - return; - } - } - } + return; + } + } + } - async initFileView(file: TFile, state: any) { - if (this.fileLeaf) { - await this.fileLeaf.openFile(file, { - active: false, - eState: state - }); + async initFileView(file: TFile, state: any) { + if (this.fileLeaf) { + await this.fileLeaf.openFile(file, { + active: false, + eState: state + }); - if (this.fileState?.match?.matches[0] === state?.match?.matches[0] && state && this.fileState) { - setTimeout(() => { - if (this.fileLeaf) { - this.plugin.app.workspace.setActiveLeaf(this.fileLeaf, { - focus: true, - }); - } - }, 0); - } else { - this.fileState = state; - setTimeout(() => { - (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); - }, 0); - } + if (this.fileState?.match?.matches[0] === state?.match?.matches[0] && state && this.fileState) { + setTimeout(() => { + if (this.fileLeaf) { + this.plugin.app.workspace.setActiveLeaf(this.fileLeaf, { + focus: true, + }); + } + }, 0); + } else { + this.fileState = state; + setTimeout(() => { + (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); + }, 0); + } - return; - } + return; + } - const {contentEl} = this; - this.fileEl = contentEl.createDiv({cls: "float-search-modal-file-ctn"}); - this.modalEl.toggleClass("float-search-width", true); - this.fileEl.onkeydown = (e) => { - if (e.ctrlKey && e.key === "g") { - e.preventDefault(); - e.stopPropagation(); + const {contentEl} = this; + this.fileEl = contentEl.createDiv({cls: "float-search-modal-file-ctn"}); + this.modalEl.toggleClass("float-search-width", true); + this.fileEl.onkeydown = (e) => { + if (e.ctrlKey && e.key === "g") { + e.preventDefault(); + e.stopPropagation(); - (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); - } + (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); + } - if (e.key === "Tab" && e.ctrlKey) { - e.preventDefault(); - e.stopPropagation(); + if (e.key === "Tab" && e.ctrlKey) { + e.preventDefault(); + e.stopPropagation(); - (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); - } - } + (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); + } + } - if (!this.fileEl) return; + if (!this.fileEl) return; - const [createdLeaf, embeddedView] = spawnLeafView(this.plugin, this.fileEl); - this.fileLeaf = createdLeaf; - this.fileEmbeddedView = embeddedView; + const [createdLeaf, embeddedView] = spawnLeafView(this.plugin, this.fileEl); + this.fileLeaf = createdLeaf; + this.fileEmbeddedView = embeddedView; - this.fileLeaf.setPinned(true); - await this.fileLeaf.openFile(file, { - active: false, - eState: state - }); - this.fileState = state; + this.fileLeaf.setPinned(true); + await this.fileLeaf.openFile(file, { + active: false, + eState: state + }); + this.fileState = state; - (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); + (this.searchLeaf.view as SearchView).searchComponent.inputEl.focus(); - } + } } diff --git a/versions.json b/versions.json index 9ae6b6f..f256f59 100644 --- a/versions.json +++ b/versions.json @@ -20,5 +20,6 @@ "3.3.4": "0.15.0", "3.4.0": "0.15.0", "3.4.2": "0.15.0", - "3.4.3": "0.15.0" + "3.4.3": "0.15.0", + "3.4.4": "0.15.0" } \ No newline at end of file