From 68d861823d59cdb364316b0621c277abbcb1b688 Mon Sep 17 00:00:00 2001 From: Sujyot <70472979+SujyotRaut@users.noreply.github.com> Date: Sun, 23 Jul 2023 20:44:53 +0530 Subject: [PATCH 1/6] Add `multiselect` function to `system` module --- docs/documentation.toml | 33 +++ .../system/InternalModuleSystem.ts | 45 ++++ .../system/MultiSelectModal.ts | 229 ++++++++++++++++++ styles.css | 49 +++- 4 files changed, 354 insertions(+), 2 deletions(-) create mode 100644 src/core/functions/internal_functions/system/MultiSelectModal.ts diff --git a/docs/documentation.toml b/docs/documentation.toml index 9eebfdbd..e6e62bd8 100644 --- a/docs/documentation.toml +++ b/docs/documentation.toml @@ -287,6 +287,39 @@ description = "Throws an error if the prompt is canceled, instead of returning a name = "multiline" description = "If set to true, the input field will be a multiline textarea" +[tp.system.functions.multiselect] +name = "multiselect" +description = "Spawns a multiselect prompt and returns the user's chosen items." +definition = "tp.system.multiselect(text_items: string[] ⎮ ((item: T) => string), items: T[], unrestricted: boolean = false, throw_on_cancel: boolean = false, placeholder: string = \"\", title: string = \"Multiselect\", limit?: number = undefined)" + +[tp.system.functions.multiselect.args.text_items] +name = "text_items" +description = "Array of strings representing the text that will be displayed for each item in the multiselect prompt. This can also be a function that maps an item to its text representation." + +[tp.system.functions.multiselect.args.items] +name = "items" +description = "Array containing the values of each item in the correct order." + +[tp.system.functions.multiselect.args.unrestricted] +name = "unrestricted" +description = "A boolean which represents whether the values outside suggestions can be selected or not" + +[tp.system.functions.multiselect.args.throw_on_cancel] +name = "throw_on_cancel" +description = "Throws an error if the prompt is canceled, instead of returning a `null` value" + +[tp.system.functions.multiselect.args.placeholder] +name = "placeholder" +description = "Placeholder string of the prompt" + +[tp.system.functions.multiselect.args.title] +name = "title" +description = "Title of multiselect prompt" + +[tp.system.functions.multiselect.args.limit] +name = "limit" +description = "Limit the number of items rendered at once (useful to improve performance when displaying large lists)" + [tp.system.functions.suggester] name = "suggester" description = "Spawns a suggester prompt and returns the user's chosen item." diff --git a/src/core/functions/internal_functions/system/InternalModuleSystem.ts b/src/core/functions/internal_functions/system/InternalModuleSystem.ts index a0403616..45b26072 100644 --- a/src/core/functions/internal_functions/system/InternalModuleSystem.ts +++ b/src/core/functions/internal_functions/system/InternalModuleSystem.ts @@ -3,6 +3,7 @@ import { InternalModule } from "../InternalModule"; import { Platform } from "obsidian"; import { PromptModal } from "./PromptModal"; import { SuggesterModal } from "./SuggesterModal"; +import { MultiSelectModal } from "./MultiSelectModal"; import { TemplaterError } from "utils/Error"; import { ModuleName } from "editor/TpDocumentation"; @@ -12,6 +13,7 @@ export class InternalModuleSystem extends InternalModule { async create_static_templates(): Promise { this.static_functions.set("clipboard", this.generate_clipboard()); this.static_functions.set("prompt", this.generate_prompt()); + this.static_functions.set("multiselect", this.generate_multiselect()); this.static_functions.set("suggester", this.generate_suggester()); } @@ -61,6 +63,49 @@ export class InternalModuleSystem extends InternalModule { }; } + generate_multiselect(): ( + text_items: string[] | ((item: T) => string), + items: T[], + unrestricted: boolean, + throw_on_cancel: boolean, + placeholder: string, + title: string, + limit?: number + ) => Promise { + return async ( + text_items: string[] | ((item: T) => string), + items: T[], + unrestricted = false, + throw_on_cancel = false, + placeholder = "", + title = "Multiselect", + limit?: number + ): Promise => { + const multiselect = new MultiSelectModal( + text_items, + items, + unrestricted, + placeholder, + title, + limit + ); + const promise = new Promise( + ( + resolve: (values: T[]) => void, + reject: (reason?: TemplaterError) => void + ) => multiselect.openAndGetValues(resolve, reject) + ); + try { + return await promise; + } catch (error) { + if (throw_on_cancel) { + throw error; + } + return []; + } + }; + } + generate_suggester(): ( text_items: string[] | ((item: T) => string), items: T[], diff --git a/src/core/functions/internal_functions/system/MultiSelectModal.ts b/src/core/functions/internal_functions/system/MultiSelectModal.ts new file mode 100644 index 00000000..7978fa8a --- /dev/null +++ b/src/core/functions/internal_functions/system/MultiSelectModal.ts @@ -0,0 +1,229 @@ +import { Modal, TextComponent, fuzzySearch, prepareQuery } from "obsidian"; +import { TemplaterError } from "utils/Error"; + +export class MultiSelectModal extends Modal { + private resolve: (values: T[]) => void; + private reject: (reason?: TemplaterError) => void; + private selectedItems = new Set(); + private mappedItems = new Map(); + private submitted = false; + + private SELECTOR_SELECTED = ".is-selected"; + private CLASS_SELECTED = "is-selected"; + + private suggestionsContainer: HTMLDivElement; + private chipsContainer: HTMLDivElement; + private textInput: TextComponent; + + constructor( + private text_items: string[] | ((item: T) => string), + private items: T[], + private unrestricted: boolean, + placeholder: string, + title: string, + private limit?: number + ) { + super(app); + + // If `T` is of type `string`, then `unrestricted` is set to provided value + // else `unrestricted` is always false + if (items.length === 0 || typeof items[0] === "string") { + this.unrestricted = unrestricted; + } + + // Map each item to its text representation + items.forEach((item) => + this.mappedItems.set(this.getItemText(item), item) + ); + + // Create Elements + this.titleEl.setText(title); + this.chipsContainer = this.contentEl.createDiv(); + this.textInput = new TextComponent(this.contentEl); + this.textInput.setPlaceholder(placeholder); + this.suggestionsContainer = this.contentEl.createDiv(); + + // Add styles + this.modalEl.addClass("templater-multiselect-modal"); + this.contentEl.addClass("templater-multiselect-container"); + this.chipsContainer.addClass("templater-multiselect-chips"); + this.suggestionsContainer.addClass("templater-multiselect-suggestions"); + } + + onOpen(): void { + this.textInput.inputEl.addEventListener( + "keydown", + (evt: KeyboardEvent) => { + switch (evt.key) { + case "Tab": + this.addItemFromSuggestionsOrInputField(); + break; + + case "Backspace": + if (!this.textInput.getValue()) this.removeLastItem(); + break; + + case "ArrowDown": + this.navigateSelection("DOWN"); + break; + + case "ArrowUp": + this.navigateSelection("UP"); + break; + + case "Enter": + this.submitted = true; + this.close(); + break; + } + } + ); + + this.textInput.onChange(() => this.renderSuggestions()); + this.renderSuggestions(); + } + + addItemFromSuggestionsOrInputField() { + const inputText = this.textInput.getValue().trim(); + const selected = this.suggestionsContainer.querySelector( + this.SELECTOR_SELECTED + ); + if (selected) this.addItem(selected.textContent!); + else if (inputText && this.unrestricted) this.addItem(inputText); + } + + addItem(value: string) { + this.selectedItems.add(value); + this.addChip(value); + this.textInput.setValue(""); + this.renderSuggestions(); + } + + removeLastItem() { + const lastChipValue = this.chipsContainer.lastElementChild?.textContent; + if (!lastChipValue) return; + this.selectedItems.delete(lastChipValue); + this.removeLastChip(); + this.renderSuggestions(); + } + + addChip(value: string) { + const chip = this.chipsContainer.createSpan({ text: value }); + chip.addClass("templater-multiselect-chip"); + chip.onClickEvent(() => { + this.selectedItems.delete(chip.textContent!); + this.renderSuggestions(); + chip.remove(); + }); + } + + removeLastChip() { + const lastChip = this.chipsContainer.lastElementChild; + lastChip?.remove(); + } + + matchText(text: string): boolean { + const query = this.textInput.getValue(); + const preparedQuery = prepareQuery(query); + const match = fuzzySearch(preparedQuery, text); + const alreadySelected = this.selectedItems.has(text); + if (match && !alreadySelected) return true; + else return false; + } + + matchItem(item: T): boolean { + const text = this.getItemText(item); + return this.matchText(text); + } + + getItemText(item: T): string { + if (this.text_items instanceof Function) { + return this.text_items(item); + } + return ( + this.text_items[this.items.indexOf(item)] || "Undefined Text Item" + ); + } + + getSuggestions(): string[] { + return this.items + .map((item) => this.getItemText(item)) + .filter((value) => this.matchText(value)) + .slice(0, this.limit ? this.limit : this.items.length); + } + + renderSuggestion(value: string) { + const suggestion = this.suggestionsContainer.createDiv({ text: value }); + suggestion.addClass("suggestion-item"); + suggestion.onClickEvent(() => { + this.addChip(value); + this.selectedItems.add(value); + this.renderSuggestions(); + }); + + suggestion.addEventListener("mouseenter", () => { + const selectedSuggestions = + this.suggestionsContainer.querySelectorAll(".is-selected"); + selectedSuggestions.forEach((suggestion) => + suggestion.removeClass(this.CLASS_SELECTED) + ); + suggestion.addClass(this.CLASS_SELECTED); + }); + } + + renderSuggestions() { + this.suggestionsContainer.empty(); + const suggestions = this.getSuggestions(); + suggestions.forEach((text) => this.renderSuggestion(text)); + this.suggestionsContainer.firstElementChild?.addClass( + this.CLASS_SELECTED + ); + } + + navigateSelection(navigate: "UP" | "DOWN") { + if (this.suggestionsContainer.children.length <= 1) return; + const selected = this.suggestionsContainer.querySelector( + this.SELECTOR_SELECTED + ); + + const nextElement = selected?.nextElementSibling; + const previousElement = selected?.previousElementSibling; + + const firstSuggestion = this.suggestionsContainer.firstElementChild; + const lastSuggestion = this.suggestionsContainer.lastElementChild; + + let nextSuggestion = + navigate === "DOWN" ? nextElement : previousElement; + if (!nextSuggestion) { + nextSuggestion = + navigate === "DOWN" ? firstSuggestion : lastSuggestion; + } + + selected?.removeClass(this.CLASS_SELECTED); + nextSuggestion?.addClass(this.CLASS_SELECTED); + nextSuggestion?.scrollIntoView(); + } + + onClose(): void { + if (!this.submitted) { + this.reject(new TemplaterError("Cancelled prompt")); + } else { + const values: T[] = []; + this.selectedItems.forEach((value) => { + const item = this.mappedItems.get(value); + if (item) values.push(item); + else if (this.unrestricted) values.push(value as T); + }); + this.resolve(values); + } + } + + async openAndGetValues( + resolve: (values: T[]) => void, + reject: (reason?: TemplaterError) => void + ): Promise { + this.resolve = resolve; + this.reject = reject; + this.open(); + } +} diff --git a/styles.css b/styles.css index 54ecbccb..8f0d4b4d 100644 --- a/styles.css +++ b/styles.css @@ -54,6 +54,49 @@ justify-content: center; } +.templater-multiselect-modal { + position: absolute; + top: 80px; +} + +.templater-multiselect-container { + display: flex; + flex-direction: column; + gap: 16px; +} + +.templater-multiselect-chips { + display: flex; + flex-wrap: wrap; + overflow-y: auto; + max-height: 106px; + gap: 8px; +} + +.templater-multiselect-chip { + border: var(--border-width) solid var(--color-green); + border-radius: var(--radius-s); + text-overflow: ellipsis; + display: inline-block; + white-space: nowrap; + overflow: hidden; + padding: 4px 8px; + cursor: pointer; + height: 30px; +} + +.templater-multiselect-chip:hover { + border: var(--border-width) solid var(--color-red); +} + +.templater-multiselect-suggestions { + overflow-y: auto; + max-height: 324px; + box-sizing: border-box; + padding: 0; + margin: 0; +} + .templater-prompt-div { display: flex; } @@ -135,8 +178,10 @@ textarea.templater-prompt-input:focus { } .cm-s-obsidian .cm-templater-command.cm-property, -.cm-s-obsidian .cm-templater-command.cm-property.cm-def -.cm-s-obsidian .cm-templater-command.cm-attribute { +.cm-s-obsidian + .cm-templater-command.cm-property.cm-def + .cm-s-obsidian + .cm-templater-command.cm-attribute { color: var(--code-function, #98e342); } From cb3145a07c3b6f8203230c630097e96f6d8c9387 Mon Sep 17 00:00:00 2001 From: Sujyot <70472979+SujyotRaut@users.noreply.github.com> Date: Tue, 1 Aug 2023 17:03:50 +0530 Subject: [PATCH 2/6] Cleanup `MultiSelectModal` constructor --- .../internal_functions/system/MultiSelectModal.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/functions/internal_functions/system/MultiSelectModal.ts b/src/core/functions/internal_functions/system/MultiSelectModal.ts index 7978fa8a..ea14f621 100644 --- a/src/core/functions/internal_functions/system/MultiSelectModal.ts +++ b/src/core/functions/internal_functions/system/MultiSelectModal.ts @@ -24,11 +24,13 @@ export class MultiSelectModal extends Modal { private limit?: number ) { super(app); + this.initializeModal(items, title, placeholder); + } - // If `T` is of type `string`, then `unrestricted` is set to provided value - // else `unrestricted` is always false - if (items.length === 0 || typeof items[0] === "string") { - this.unrestricted = unrestricted; + initializeModal(items: T[], title: string, placeholder: string) { + // If item isn't of type string or items array is empty, then unrestricted is false + if (items.length === 0 || typeof items[0] !== "string") { + this.unrestricted = false; } // Map each item to its text representation From 091ccaa049a742b8834424e90ed20f24629a900b Mon Sep 17 00:00:00 2001 From: Sujyot <70472979+SujyotRaut@users.noreply.github.com> Date: Thu, 10 Aug 2023 18:05:56 +0530 Subject: [PATCH 3/6] Remove placeholder from multiselect function --- docs/documentation.toml | 6 +----- .../internal_functions/system/InternalModuleSystem.ts | 3 --- .../functions/internal_functions/system/MultiSelectModal.ts | 6 ++---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/docs/documentation.toml b/docs/documentation.toml index e6e62bd8..456bd07c 100644 --- a/docs/documentation.toml +++ b/docs/documentation.toml @@ -290,7 +290,7 @@ description = "If set to true, the input field will be a multiline textarea" [tp.system.functions.multiselect] name = "multiselect" description = "Spawns a multiselect prompt and returns the user's chosen items." -definition = "tp.system.multiselect(text_items: string[] ⎮ ((item: T) => string), items: T[], unrestricted: boolean = false, throw_on_cancel: boolean = false, placeholder: string = \"\", title: string = \"Multiselect\", limit?: number = undefined)" +definition = "tp.system.multiselect(text_items: string[] ⎮ ((item: T) => string), items: T[], unrestricted: boolean = false, throw_on_cancel: boolean = false, title: string = \"Multiselect\", limit?: number = undefined)" [tp.system.functions.multiselect.args.text_items] name = "text_items" @@ -308,10 +308,6 @@ description = "A boolean which represents whether the values outside suggestions name = "throw_on_cancel" description = "Throws an error if the prompt is canceled, instead of returning a `null` value" -[tp.system.functions.multiselect.args.placeholder] -name = "placeholder" -description = "Placeholder string of the prompt" - [tp.system.functions.multiselect.args.title] name = "title" description = "Title of multiselect prompt" diff --git a/src/core/functions/internal_functions/system/InternalModuleSystem.ts b/src/core/functions/internal_functions/system/InternalModuleSystem.ts index 45b26072..a7825c35 100644 --- a/src/core/functions/internal_functions/system/InternalModuleSystem.ts +++ b/src/core/functions/internal_functions/system/InternalModuleSystem.ts @@ -68,7 +68,6 @@ export class InternalModuleSystem extends InternalModule { items: T[], unrestricted: boolean, throw_on_cancel: boolean, - placeholder: string, title: string, limit?: number ) => Promise { @@ -77,7 +76,6 @@ export class InternalModuleSystem extends InternalModule { items: T[], unrestricted = false, throw_on_cancel = false, - placeholder = "", title = "Multiselect", limit?: number ): Promise => { @@ -85,7 +83,6 @@ export class InternalModuleSystem extends InternalModule { text_items, items, unrestricted, - placeholder, title, limit ); diff --git a/src/core/functions/internal_functions/system/MultiSelectModal.ts b/src/core/functions/internal_functions/system/MultiSelectModal.ts index ea14f621..8f02f455 100644 --- a/src/core/functions/internal_functions/system/MultiSelectModal.ts +++ b/src/core/functions/internal_functions/system/MultiSelectModal.ts @@ -19,15 +19,14 @@ export class MultiSelectModal extends Modal { private text_items: string[] | ((item: T) => string), private items: T[], private unrestricted: boolean, - placeholder: string, title: string, private limit?: number ) { super(app); - this.initializeModal(items, title, placeholder); + this.initializeModal(items, title); } - initializeModal(items: T[], title: string, placeholder: string) { + initializeModal(items: T[], title: string) { // If item isn't of type string or items array is empty, then unrestricted is false if (items.length === 0 || typeof items[0] !== "string") { this.unrestricted = false; @@ -42,7 +41,6 @@ export class MultiSelectModal extends Modal { this.titleEl.setText(title); this.chipsContainer = this.contentEl.createDiv(); this.textInput = new TextComponent(this.contentEl); - this.textInput.setPlaceholder(placeholder); this.suggestionsContainer = this.contentEl.createDiv(); // Add styles From 56d8bb125b8ac27b6e2b041ddad515b706f84ad3 Mon Sep 17 00:00:00 2001 From: Sujyot Raut <70472979+sujyotraut@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:06:40 +0530 Subject: [PATCH 4/6] Update styles.css --- styles.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/styles.css b/styles.css index 8f0d4b4d..c8e3b061 100644 --- a/styles.css +++ b/styles.css @@ -178,10 +178,8 @@ textarea.templater-prompt-input:focus { } .cm-s-obsidian .cm-templater-command.cm-property, -.cm-s-obsidian - .cm-templater-command.cm-property.cm-def - .cm-s-obsidian - .cm-templater-command.cm-attribute { +.cm-s-obsidian .cm-templater-command.cm-property.cm-def +.cm-s-obsidian .cm-templater-command.cm-attribute { color: var(--code-function, #98e342); } From c7b8f35af7ab40ee4d5ed51a114228882108f994 Mon Sep 17 00:00:00 2001 From: Sujyot <70472979+sujyotraut@users.noreply.github.com> Date: Sat, 2 Dec 2023 12:39:34 +0530 Subject: [PATCH 5/6] Rename to `multi_suggester` from `muliselect` --- docs/documentation.toml | 24 +++++++-------- .../system/InternalModuleSystem.ts | 29 ++++++++++--------- ...iSelectModal.ts => MultiSuggesterModal.ts} | 10 +++---- 3 files changed, 32 insertions(+), 31 deletions(-) rename src/core/functions/internal_functions/system/{MultiSelectModal.ts => MultiSuggesterModal.ts} (96%) diff --git a/docs/documentation.toml b/docs/documentation.toml index 456bd07c..801c9e4f 100644 --- a/docs/documentation.toml +++ b/docs/documentation.toml @@ -287,32 +287,32 @@ description = "Throws an error if the prompt is canceled, instead of returning a name = "multiline" description = "If set to true, the input field will be a multiline textarea" -[tp.system.functions.multiselect] -name = "multiselect" -description = "Spawns a multiselect prompt and returns the user's chosen items." -definition = "tp.system.multiselect(text_items: string[] ⎮ ((item: T) => string), items: T[], unrestricted: boolean = false, throw_on_cancel: boolean = false, title: string = \"Multiselect\", limit?: number = undefined)" +[tp.system.functions.multi_suggester] +name = "multi_suggester" +description = "Spawns a multi_suggester prompt and returns the user's chosen items." +definition = "tp.system.multi_suggester(text_items: string[] ⎮ ((item: T) => string), items: T[], unrestricted: boolean = false, throw_on_cancel: boolean = false, title: string = \"multi_suggester\", limit?: number = undefined)" -[tp.system.functions.multiselect.args.text_items] +[tp.system.functions.multi_suggester.args.text_items] name = "text_items" -description = "Array of strings representing the text that will be displayed for each item in the multiselect prompt. This can also be a function that maps an item to its text representation." +description = "Array of strings representing the text that will be displayed for each item in the multi_suggester prompt. This can also be a function that maps an item to its text representation." -[tp.system.functions.multiselect.args.items] +[tp.system.functions.multi_suggester.args.items] name = "items" description = "Array containing the values of each item in the correct order." -[tp.system.functions.multiselect.args.unrestricted] +[tp.system.functions.multi_suggester.args.unrestricted] name = "unrestricted" description = "A boolean which represents whether the values outside suggestions can be selected or not" -[tp.system.functions.multiselect.args.throw_on_cancel] +[tp.system.functions.multi_suggester.args.throw_on_cancel] name = "throw_on_cancel" description = "Throws an error if the prompt is canceled, instead of returning a `null` value" -[tp.system.functions.multiselect.args.title] +[tp.system.functions.multi_suggester.args.title] name = "title" -description = "Title of multiselect prompt" +description = "Title of multi_suggester prompt" -[tp.system.functions.multiselect.args.limit] +[tp.system.functions.multi_suggester.args.limit] name = "limit" description = "Limit the number of items rendered at once (useful to improve performance when displaying large lists)" diff --git a/src/core/functions/internal_functions/system/InternalModuleSystem.ts b/src/core/functions/internal_functions/system/InternalModuleSystem.ts index a7825c35..bf1a538f 100644 --- a/src/core/functions/internal_functions/system/InternalModuleSystem.ts +++ b/src/core/functions/internal_functions/system/InternalModuleSystem.ts @@ -1,11 +1,11 @@ -import { UNSUPPORTED_MOBILE_TEMPLATE } from "utils/Constants"; -import { InternalModule } from "../InternalModule"; -import { Platform } from "obsidian"; -import { PromptModal } from "./PromptModal"; -import { SuggesterModal } from "./SuggesterModal"; -import { MultiSelectModal } from "./MultiSelectModal"; -import { TemplaterError } from "utils/Error"; -import { ModuleName } from "editor/TpDocumentation"; +import {UNSUPPORTED_MOBILE_TEMPLATE} from "utils/Constants"; +import {InternalModule} from "../InternalModule"; +import {Platform} from "obsidian"; +import {PromptModal} from "./PromptModal"; +import {SuggesterModal} from "./SuggesterModal"; +import {MultiSuggesterModal} from "./MultiSuggesterModal"; +import {TemplaterError} from "utils/Error"; +import {ModuleName} from "editor/TpDocumentation"; export class InternalModuleSystem extends InternalModule { public name: ModuleName = "system"; @@ -13,11 +13,12 @@ export class InternalModuleSystem extends InternalModule { async create_static_templates(): Promise { this.static_functions.set("clipboard", this.generate_clipboard()); this.static_functions.set("prompt", this.generate_prompt()); - this.static_functions.set("multiselect", this.generate_multiselect()); this.static_functions.set("suggester", this.generate_suggester()); + this.static_functions.set("multi_suggester", this.generate_multi_suggester()); } - async create_dynamic_templates(): Promise {} + async create_dynamic_templates(): Promise { + } generate_clipboard(): () => Promise { return async () => { @@ -63,7 +64,7 @@ export class InternalModuleSystem extends InternalModule { }; } - generate_multiselect(): ( + generate_multi_suggester(): ( text_items: string[] | ((item: T) => string), items: T[], unrestricted: boolean, @@ -76,10 +77,10 @@ export class InternalModuleSystem extends InternalModule { items: T[], unrestricted = false, throw_on_cancel = false, - title = "Multiselect", + title = "Multi Suggester", limit?: number ): Promise => { - const multiselect = new MultiSelectModal( + const multi_suggester = new MultiSuggesterModal( text_items, items, unrestricted, @@ -90,7 +91,7 @@ export class InternalModuleSystem extends InternalModule { ( resolve: (values: T[]) => void, reject: (reason?: TemplaterError) => void - ) => multiselect.openAndGetValues(resolve, reject) + ) => multi_suggester.openAndGetValues(resolve, reject) ); try { return await promise; diff --git a/src/core/functions/internal_functions/system/MultiSelectModal.ts b/src/core/functions/internal_functions/system/MultiSuggesterModal.ts similarity index 96% rename from src/core/functions/internal_functions/system/MultiSelectModal.ts rename to src/core/functions/internal_functions/system/MultiSuggesterModal.ts index 8f02f455..6f03674a 100644 --- a/src/core/functions/internal_functions/system/MultiSelectModal.ts +++ b/src/core/functions/internal_functions/system/MultiSuggesterModal.ts @@ -1,7 +1,7 @@ -import { Modal, TextComponent, fuzzySearch, prepareQuery } from "obsidian"; -import { TemplaterError } from "utils/Error"; +import {Modal, TextComponent, fuzzySearch, prepareQuery} from "obsidian"; +import {TemplaterError} from "utils/Error"; -export class MultiSelectModal extends Modal { +export class MultiSuggesterModal extends Modal { private resolve: (values: T[]) => void; private reject: (reason?: TemplaterError) => void; private selectedItems = new Set(); @@ -108,7 +108,7 @@ export class MultiSelectModal extends Modal { } addChip(value: string) { - const chip = this.chipsContainer.createSpan({ text: value }); + const chip = this.chipsContainer.createSpan({text: value}); chip.addClass("templater-multiselect-chip"); chip.onClickEvent(() => { this.selectedItems.delete(chip.textContent!); @@ -153,7 +153,7 @@ export class MultiSelectModal extends Modal { } renderSuggestion(value: string) { - const suggestion = this.suggestionsContainer.createDiv({ text: value }); + const suggestion = this.suggestionsContainer.createDiv({text: value}); suggestion.addClass("suggestion-item"); suggestion.onClickEvent(() => { this.addChip(value); From aa68ce25706fab3c84a63881d863237857dd803e Mon Sep 17 00:00:00 2001 From: Sujyot Raut <70472979+sujyotraut@users.noreply.github.com> Date: Sat, 2 Dec 2023 13:03:19 +0530 Subject: [PATCH 6/6] Update InternalModuleSystem --- .../system/InternalModuleSystem.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/core/functions/internal_functions/system/InternalModuleSystem.ts b/src/core/functions/internal_functions/system/InternalModuleSystem.ts index bf1a538f..f57f6168 100644 --- a/src/core/functions/internal_functions/system/InternalModuleSystem.ts +++ b/src/core/functions/internal_functions/system/InternalModuleSystem.ts @@ -1,11 +1,9 @@ -import {UNSUPPORTED_MOBILE_TEMPLATE} from "utils/Constants"; -import {InternalModule} from "../InternalModule"; -import {Platform} from "obsidian"; -import {PromptModal} from "./PromptModal"; -import {SuggesterModal} from "./SuggesterModal"; -import {MultiSuggesterModal} from "./MultiSuggesterModal"; -import {TemplaterError} from "utils/Error"; -import {ModuleName} from "editor/TpDocumentation"; +import { InternalModule } from "../InternalModule"; +import { PromptModal } from "./PromptModal"; +import { SuggesterModal } from "./SuggesterModal"; +import { MultiSuggesterModal } from "./MultiSuggesterModal"; +import { TemplaterError } from "utils/Error"; +import { ModuleName } from "editor/TpDocumentation"; export class InternalModuleSystem extends InternalModule { public name: ModuleName = "system"; @@ -22,10 +20,6 @@ export class InternalModuleSystem extends InternalModule { generate_clipboard(): () => Promise { return async () => { - // TODO: Add mobile support - if (Platform.isMobileApp) { - return UNSUPPORTED_MOBILE_TEMPLATE; - } return await navigator.clipboard.readText(); }; }