mirror of
https://github.com/quorafind/Obsidian-Float-Search.git
synced 2026-07-22 07:30:25 +00:00
feat: support save current settings
This commit is contained in:
parent
63d6e2ff3f
commit
6a322e9217
3 changed files with 936 additions and 304 deletions
|
|
@ -12,4 +12,4 @@
|
|||
"支付宝": "https://cdn.jsdelivr.net/gh/Quorafind/.github@main/IMAGE/%E6%94%AF%E4%BB%98%E5%AE%9D%E4%BB%98%E6%AC%BE%E7%A0%81.jpg"
|
||||
},
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
}
|
||||
836
pnpm-lock.yaml
836
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +1,8 @@
|
|||
import {
|
||||
apiVersion,
|
||||
App,
|
||||
Editor,
|
||||
MarkdownView,
|
||||
Menu,
|
||||
Modal, Notice, OpenViewState,
|
||||
Plugin, requireApiVersion, SearchView,
|
||||
Modal, OpenViewState,
|
||||
Plugin, SearchView,
|
||||
TAbstractFile,
|
||||
TFile,
|
||||
Workspace,
|
||||
|
|
@ -15,14 +12,59 @@ import {
|
|||
import { EmbeddedView, isEmebeddedLeaf, spawnLeafView } from "./leafView";
|
||||
import { around } from "monkey-around";
|
||||
|
||||
type sortOrder =
|
||||
"alphabetical"
|
||||
| "alphabeticalReverse"
|
||||
| "byModifiedTime"
|
||||
| "byModifiedTimeReverse"
|
||||
| "byCreatedTime"
|
||||
| "byCreatedTimeReverse";
|
||||
|
||||
interface searchState {
|
||||
collapseAll?: boolean;
|
||||
explainSearch?: boolean;
|
||||
extraContext?: boolean;
|
||||
matchingCase?: boolean;
|
||||
query: string;
|
||||
sortOrder?: sortOrder;
|
||||
current?: boolean;
|
||||
}
|
||||
|
||||
interface FloatSearchSettings {
|
||||
searchViewState: searchState;
|
||||
}
|
||||
|
||||
|
||||
const DEFAULT_SETTINGS: FloatSearchSettings = {
|
||||
searchViewState: {
|
||||
collapseAll: false,
|
||||
explainSearch: false,
|
||||
extraContext: false,
|
||||
matchingCase: false,
|
||||
query: "",
|
||||
sortOrder: "alphabetical",
|
||||
}
|
||||
}
|
||||
|
||||
export default class FloatSearchPlugin extends Plugin {
|
||||
settings: FloatSearchSettings;
|
||||
private state: any;
|
||||
private applyDebounceTimer = 0;
|
||||
private modal: FloatSearchModal;
|
||||
|
||||
private applyStateDebounceTimer = 0;
|
||||
private applySettingsDebounceTimer = 0;
|
||||
|
||||
|
||||
public applySettingsUpdate() {
|
||||
clearTimeout(this.applyDebounceTimer);
|
||||
this.applyDebounceTimer = window.setTimeout(() => {
|
||||
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: "",
|
||||
|
|
@ -31,6 +73,9 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
}
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
this.initState();
|
||||
|
||||
this.patchWorkspace();
|
||||
this.patchWorkspaceLeaf();
|
||||
|
||||
|
|
@ -39,40 +84,48 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
this.registerEditorMenuHandler();
|
||||
this.registerContextMenuHandler();
|
||||
|
||||
this.addRibbonIcon('search', 'Search Obsidian In Modal', () => {
|
||||
this.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
this.applySettingsUpdate();
|
||||
},this.app, this, this.state);
|
||||
this.modal.open();
|
||||
});
|
||||
this.addRibbonIcon('search', 'Search Obsidian In Modal', () => this.initModal(this.state, true, true));
|
||||
}
|
||||
|
||||
onunload() {
|
||||
this.state = undefined;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
patchWorkspace() {
|
||||
let layoutChanging = false;
|
||||
const uninstaller = around(Workspace.prototype, {
|
||||
getLeaf: (next) =>
|
||||
function (...args) {
|
||||
const activeLeaf = this.activeLeaf;
|
||||
if(activeLeaf) {
|
||||
if (activeLeaf) {
|
||||
const fsCtnEl = (activeLeaf.parent.containerEl as HTMLElement).parentElement;
|
||||
if(fsCtnEl?.classList.contains("fs-content")) {
|
||||
if(activeLeaf.view.getViewType() === "markdown") {
|
||||
if (fsCtnEl?.classList.contains("fs-content")) {
|
||||
if (activeLeaf.view.getViewType() === "markdown") {
|
||||
return activeLeaf;
|
||||
}
|
||||
const newLeaf = app.workspace.getUnpinnedLeaf();
|
||||
if(newLeaf) {
|
||||
if (newLeaf) {
|
||||
this.setActiveLeaf(newLeaf);
|
||||
}
|
||||
}
|
||||
return next.call(this, ...args);
|
||||
}
|
||||
return next.call(this, ...args);
|
||||
},
|
||||
},
|
||||
changeLayout(old) {
|
||||
return async function (workspace: unknown) {
|
||||
layoutChanging = true;
|
||||
|
|
@ -91,7 +144,7 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
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 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
|
||||
|
|
@ -99,7 +152,7 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
|
||||
// 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)) {
|
||||
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;
|
||||
}
|
||||
|
|
@ -129,7 +182,7 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
setPinned(old) {
|
||||
return function (pinned: boolean) {
|
||||
old.call(this, pinned);
|
||||
if(isEmebeddedLeaf(this) && !pinned) this.setPinned(true);
|
||||
if (isEmebeddedLeaf(this) && !pinned) this.setPinned(true);
|
||||
}
|
||||
},
|
||||
openFile(old) {
|
||||
|
|
@ -166,21 +219,21 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
}
|
||||
|
||||
const view = old.call(this, file, openState);
|
||||
setTimeout(()=>{
|
||||
setTimeout(() => {
|
||||
const fsCtnEl = (this.parent.containerEl as HTMLElement).parentElement;
|
||||
if(!(fsCtnEl?.classList.contains("fs-content"))) return;
|
||||
if(file.extension != "canvas" ) return;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}, 20);
|
||||
}, 1);
|
||||
|
||||
return view;
|
||||
|
|
@ -191,94 +244,78 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
}
|
||||
|
||||
registerObsidianURIHandler() {
|
||||
this.registerObsidianProtocolHandler("fs", (path)=>{
|
||||
this.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
this.applySettingsUpdate();
|
||||
},this.app, this, { query: path.query, current: false });
|
||||
this.modal.open();
|
||||
});
|
||||
this.registerObsidianProtocolHandler("fs", (path) => this.initModal({
|
||||
...this.state,
|
||||
query: path.query,
|
||||
current: false
|
||||
}, true, true));
|
||||
}
|
||||
|
||||
registerObsidianCommands() {
|
||||
this.addCommand({
|
||||
id: 'search-obsidian-globally',
|
||||
name: 'Search Obsidian Globally',
|
||||
callback: () => {
|
||||
this.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
},this.app, this, {...this.state, query: "", current: false});
|
||||
this.modal.open();
|
||||
}
|
||||
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.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
},this.app, this, {...this.state, current: false});
|
||||
this.modal.open();
|
||||
}
|
||||
callback: () => this.initModal({...this.state, query: "", current: false}, true, false)
|
||||
});
|
||||
|
||||
|
||||
this.addCommand({
|
||||
id: 'search-in-backlink',
|
||||
name: 'Search In Backlink Of Current File',
|
||||
checkCallback: (checking: boolean) => {
|
||||
// Conditions to check
|
||||
id: 'search-in-backlink',
|
||||
name: 'Search In Backlink Of Current File',
|
||||
checkCallback: (checking: boolean) => {
|
||||
// Conditions to check
|
||||
const activeLeaf = this.app.workspace.activeLeaf;
|
||||
if(!activeLeaf) return;
|
||||
if (!activeLeaf) return;
|
||||
|
||||
const viewType = activeLeaf.view.getViewType();
|
||||
if (viewType === "markdown" || viewType === "canvas") {
|
||||
if (!checking) {
|
||||
const currentFile = activeLeaf.view.file;
|
||||
|
||||
this.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
this.applySettingsUpdate();
|
||||
},this.app, this, {...this.state, query: " /\\[\\[" + (currentFile.extension === "canvas" ? currentFile.name : currentFile.basename) + "(\\|[^\\]]*)?\\]\\]/", current: true });
|
||||
this.modal.open();
|
||||
this.initModal({
|
||||
...this.state,
|
||||
query: " /\\[\\[" + (currentFile.extension === "canvas" ? currentFile.name : currentFile.basename) + "(\\|[^\\]]*)?\\]\\]/",
|
||||
current: true
|
||||
}, true, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: 'search-in-current-file',
|
||||
name: 'Search In Current File',
|
||||
checkCallback: (checking: boolean) => {
|
||||
// Conditions to check
|
||||
id: 'search-in-current-file',
|
||||
name: 'Search In Current File',
|
||||
checkCallback: (checking: boolean) => {
|
||||
// Conditions to check
|
||||
const activeLeaf = this.app.workspace.activeLeaf;
|
||||
if(!activeLeaf) return;
|
||||
if (!activeLeaf) return;
|
||||
|
||||
const viewType = activeLeaf.view.getViewType();
|
||||
if (viewType === "markdown" || viewType === "canvas") {
|
||||
if (!checking) {
|
||||
if (viewType === "markdown" || viewType === "canvas") {
|
||||
if (!checking) {
|
||||
const currentFile = activeLeaf.view.file;
|
||||
|
||||
this.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
this.applySettingsUpdate();
|
||||
},this.app, this, {...this.state, query: " path:" + currentFile.path, current: true });
|
||||
this.modal.open();
|
||||
}
|
||||
this.initModal({...this.state, query: " path:" + currentFile.path, current: true}, true, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: 'open-search-view',
|
||||
name: 'Open Search View',
|
||||
callback: async () => {
|
||||
id: 'open-search-view',
|
||||
name: 'Open Search View',
|
||||
callback: async () => {
|
||||
const leaf = app.workspace.getLeaf();
|
||||
leaf.setPinned(true);
|
||||
await leaf.setViewState({
|
||||
|
|
@ -302,7 +339,7 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
|
||||
registerEditorMenuHandler() {
|
||||
this.registerEvent(
|
||||
this.app.workspace.on('editor-menu', (menu: Menu, editor: Editor, view: MarkdownView) => {
|
||||
this.app.workspace.on('editor-menu', (menu: Menu, editor: Editor) => {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -312,7 +349,7 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
const selection = editor.getSelection().trim();
|
||||
let searchWord = selection;
|
||||
|
||||
if(selection.length > 8) {
|
||||
if (selection.length > 8) {
|
||||
searchWord = selection.substring(0, 3) + "..." + selection.substring(selection.length - 3, selection.length);
|
||||
} else {
|
||||
searchWord = selection;
|
||||
|
|
@ -321,48 +358,46 @@ export default class FloatSearchPlugin extends Plugin {
|
|||
menu.addItem((item) => {
|
||||
// Add sub menu
|
||||
item.setTitle('Search "' + searchWord + '"' + " in Float Search").setIcon("search")
|
||||
.onClick(()=>{
|
||||
this.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
this.applySettingsUpdate();
|
||||
},this.app, this, { query: selection, current: false });
|
||||
this.modal.open();
|
||||
})
|
||||
.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);
|
||||
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.modal = new FloatSearchModal((state)=>{
|
||||
this.state = state;
|
||||
this.applySettingsUpdate();
|
||||
},this.app, this, { query: "", current: false });
|
||||
this.modal.open();
|
||||
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 saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -374,7 +409,7 @@ class FloatSearchModal extends Modal {
|
|||
searchLeaf: WorkspaceLeaf;
|
||||
fileLeaf: WorkspaceLeaf | undefined;
|
||||
|
||||
private cb: (state: any)=> void;
|
||||
private cb: (state: any) => void;
|
||||
private state: any;
|
||||
|
||||
private fileState: any;
|
||||
|
|
@ -384,8 +419,8 @@ class FloatSearchModal extends Modal {
|
|||
private fileEl: HTMLElement;
|
||||
private viewType: string;
|
||||
|
||||
constructor(cb: (state: any)=> void, app: App, plugin: FloatSearchPlugin, state: any, viewType: string = "search") {
|
||||
super(app);
|
||||
constructor(cb: (state: any) => void, plugin: FloatSearchPlugin, state: any, viewType: string = "search") {
|
||||
super(plugin.app);
|
||||
this.plugin = plugin;
|
||||
this.cb = cb;
|
||||
this.state = state;
|
||||
|
|
@ -393,20 +428,20 @@ class FloatSearchModal extends Modal {
|
|||
}
|
||||
|
||||
async onOpen() {
|
||||
const { contentEl, containerEl, modalEl } = this;
|
||||
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.viewType);
|
||||
await this.initSearchView(this.searchCtnEl);
|
||||
this.initInput();
|
||||
this.initContent();
|
||||
}
|
||||
|
||||
onClose() {
|
||||
const { contentEl } = this;
|
||||
const {contentEl} = this;
|
||||
|
||||
this.cb(this.searchLeaf.view.getState());
|
||||
|
||||
|
|
@ -418,47 +453,47 @@ class FloatSearchModal extends Modal {
|
|||
}
|
||||
|
||||
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 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" });
|
||||
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" });
|
||||
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" });
|
||||
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" });
|
||||
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" });
|
||||
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" });
|
||||
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" });
|
||||
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");
|
||||
}
|
||||
|
|
@ -469,7 +504,7 @@ class FloatSearchModal extends Modal {
|
|||
containerEl.classList.add("float-search-modal-container");
|
||||
}
|
||||
|
||||
async initSearchView(contentEl: HTMLElement, viewType: string) {
|
||||
async initSearchView(contentEl: HTMLElement) {
|
||||
const [createdLeaf, embeddedView] = spawnLeafView(this.plugin, contentEl);
|
||||
this.searchLeaf = createdLeaf;
|
||||
this.searchEmbeddedView = embeddedView;
|
||||
|
|
@ -479,7 +514,7 @@ class FloatSearchModal extends Modal {
|
|||
type: "search",
|
||||
});
|
||||
|
||||
setTimeout(async ()=>{
|
||||
setTimeout(async () => {
|
||||
await this.searchLeaf.view.setState(this.state, true);
|
||||
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);
|
||||
|
|
@ -496,8 +531,8 @@ class FloatSearchModal extends Modal {
|
|||
case "ArrowDown":
|
||||
if (e.shiftKey) {
|
||||
currentView.onKeyShowMoreAfter(e);
|
||||
if(currentView.dom.focusedItem) {
|
||||
if(currentView.dom.focusedItem.collapsible) {
|
||||
if (currentView.dom.focusedItem) {
|
||||
if (currentView.dom.focusedItem.collapsible) {
|
||||
currentView.dom.focusedItem.setCollapse(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -509,8 +544,8 @@ class FloatSearchModal extends Modal {
|
|||
case "ArrowUp":
|
||||
if (e.shiftKey) {
|
||||
currentView.onKeyShowMoreBefore(e);
|
||||
if(currentView.dom.focusedItem) {
|
||||
if(currentView.dom.focusedItem.collapseEl) {
|
||||
if (currentView.dom.focusedItem) {
|
||||
if (currentView.dom.focusedItem.collapseEl) {
|
||||
currentView.dom.focusedItem.setCollapse(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -527,14 +562,14 @@ class FloatSearchModal extends Modal {
|
|||
break;
|
||||
case "Enter":
|
||||
currentView.onKeyEnterInFocus(e);
|
||||
if(e.altKey && currentView.dom.focusedItem) {
|
||||
if (e.altKey && currentView.dom.focusedItem) {
|
||||
this.close();
|
||||
}
|
||||
break;
|
||||
case "Tab":
|
||||
e.preventDefault();
|
||||
if(e.shiftKey) {
|
||||
if(this.fileLeaf) {
|
||||
if (e.shiftKey) {
|
||||
if (this.fileLeaf) {
|
||||
this.fileLeaf?.detach();
|
||||
this.fileLeaf = undefined;
|
||||
this.fileEmbeddedView?.unload();
|
||||
|
|
@ -545,33 +580,35 @@ class FloatSearchModal extends Modal {
|
|||
}
|
||||
}
|
||||
|
||||
if(currentView.dom.focusedItem) {
|
||||
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);
|
||||
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) {
|
||||
if (e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
if(this.fileLeaf) {
|
||||
if (this.fileLeaf) {
|
||||
const estate = this.fileLeaf.getViewState();
|
||||
estate.state.mode = "preview" === estate.state.mode ? "source" : "preview";
|
||||
estate.state.mode = "preview" === estate.state.mode ? "source" : "preview";
|
||||
this.fileLeaf.setViewState(estate, {
|
||||
focus: !0
|
||||
});
|
||||
setTimeout(()=>{
|
||||
setTimeout(() => {
|
||||
(this.searchLeaf.view as SearchView).searchComponent.inputEl.focus();
|
||||
}, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "g":
|
||||
if(this.fileLeaf && e.ctrlKey) {
|
||||
if (this.fileLeaf && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
app.workspace.setActiveLeaf(this.fileLeaf, {
|
||||
focus: true,
|
||||
|
|
@ -579,27 +616,28 @@ class FloatSearchModal extends Modal {
|
|||
}
|
||||
break;
|
||||
case "C":
|
||||
if(e.ctrlKey && e.shiftKey) {
|
||||
if (e.ctrlKey && e.shiftKey) {
|
||||
e.preventDefault();
|
||||
const text = currentView.dom.focusedItem.el.innerText;
|
||||
navigator.clipboard.writeText(text);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initContent() {
|
||||
const { contentEl } = this;
|
||||
const {contentEl} = this;
|
||||
contentEl.onclick = (e) => {
|
||||
const resultElement = contentEl.getElementsByClassName('search-results-children')[0];
|
||||
if(resultElement.children.length < 2) {
|
||||
if (resultElement.children.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
let targetElement = e.target as HTMLElement | null;
|
||||
|
||||
if(e.altKey || !this.fileLeaf) {
|
||||
if (e.altKey || !this.fileLeaf) {
|
||||
while (targetElement) {
|
||||
if (targetElement.classList.contains('tree-item-icon')) {
|
||||
break;
|
||||
|
|
@ -613,23 +651,23 @@ class FloatSearchModal extends Modal {
|
|||
return;
|
||||
}
|
||||
|
||||
if(this.fileLeaf) {
|
||||
if (this.fileLeaf) {
|
||||
const currentView = this.searchLeaf.view as SearchView;
|
||||
|
||||
if((this.searchCtnEl as Node).contains(targetElement as Node)) {
|
||||
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 (!targetElement) return;
|
||||
|
||||
const fileInnerEl = targetElement?.getElementsByClassName("tree-item-inner")[0] as HTMLElement;
|
||||
const innerText = fileInnerEl.innerText;
|
||||
const file = app.metadataCache.getFirstLinkpathDest(innerText, "");
|
||||
|
||||
if(file) {
|
||||
if (file) {
|
||||
const item = currentView.dom.resultDomLookup.get(file);
|
||||
currentView.dom.setFocusedItem(item);
|
||||
this.initFileView(file, undefined);
|
||||
|
|
@ -644,16 +682,16 @@ class FloatSearchModal extends Modal {
|
|||
}
|
||||
|
||||
async initFileView(file: TFile, state: any) {
|
||||
if(this.fileLeaf) {
|
||||
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) {
|
||||
app.workspace.setActiveLeaf(this.fileLeaf, {
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
|
@ -668,18 +706,18 @@ class FloatSearchModal extends Modal {
|
|||
return;
|
||||
}
|
||||
|
||||
const { contentEl } = this;
|
||||
this.fileEl = contentEl.createDiv({ cls: "float-search-modal-file-ctn" });
|
||||
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") {
|
||||
if (e.ctrlKey && e.key === "g") {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
(this.searchLeaf.view as SearchView).searchComponent.inputEl.focus();
|
||||
}
|
||||
|
||||
if(e.key === "Tab" && e.ctrlKey) {
|
||||
if (e.key === "Tab" && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
|
@ -687,7 +725,7 @@ class FloatSearchModal extends Modal {
|
|||
}
|
||||
}
|
||||
|
||||
if(!this.fileEl) return;
|
||||
if (!this.fileEl) return;
|
||||
|
||||
const [createdLeaf, embeddedView] = spawnLeafView(this.plugin, this.fileEl);
|
||||
this.fileLeaf = createdLeaf;
|
||||
|
|
|
|||
Loading…
Reference in a new issue