obsidian#Platform TypeScript Examples

The following examples show how to use obsidian#Platform. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: InternalModuleFile.ts    From Templater with GNU Affero General Public License v3.0 6 votes vote down vote up
generate_path(): (relative: boolean) => string {
        return (relative = false) => {
            // TODO: Add mobile support
            if (Platform.isMobileApp) {
                return UNSUPPORTED_MOBILE_TEMPLATE;
            }
            if (!(this.app.vault.adapter instanceof FileSystemAdapter)) {
                throw new TemplaterError(
                    "app.vault is not a FileSystemAdapter instance"
                );
            }
            const vault_path = this.app.vault.adapter.getBasePath();

            if (relative) {
                return this.config.target_file.path;
            } else {
                return `${vault_path}/${this.config.target_file.path}`;
            }
        };
    }
Example #2
Source File: settings.tsx    From obsidian-spaced-repetition with MIT License 6 votes vote down vote up
DEFAULT_SETTINGS: SRSettings = {
    // flashcards
    flashcardTags: ["#flashcards"],
    convertFoldersToDecks: false,
    cardCommentOnSameLine: false,
    burySiblingCards: false,
    showContextInCards: true,
    flashcardHeightPercentage: Platform.isMobile ? 100 : 80,
    flashcardWidthPercentage: Platform.isMobile ? 100 : 40,
    showFileNameInFileLink: false,
    randomizeCardOrder: true,
    convertHighlightsToClozes: true,
    convertBoldTextToClozes: false,
    singlelineCardSeparator: "::",
    singlelineReversedCardSeparator: ":::",
    multilineCardSeparator: "?",
    multilineReversedCardSeparator: "??",
    // notes
    tagsToReview: ["#review"],
    noteFoldersToIgnore: [],
    openRandomNote: false,
    autoNextNote: false,
    disableFileMenuReviewOptions: false,
    maxNDaysNotesReviewQueue: 365,
    // algorithm
    baseEase: 250,
    lapsesIntervalChange: 0.5,
    easyBonus: 1.3,
    maximumInterval: 36525,
    maxLinkFactor: 1.0,
    // logging
    showDebugMessages: false,
}
Example #3
Source File: main.ts    From obsidian-plantuml with MIT License 6 votes vote down vote up
getProcessor(): Processor {
        if (Platform.isMobileApp) {
            return this.serverProcessor;
        }
        if (this.settings.localJar.length > 0) {
            return this.localProcessor;
        }
        return this.serverProcessor;
    }
Example #4
Source File: handler.ts    From obsidian-switcher-plus with GNU General Public License v3.0 6 votes vote down vote up
/**
   * Determines whether or not a new leaf should be created
   * @param  {boolean} isModDown Set to true if the user holding cmd/ctrl
   * @param  {} isAlreadyOpen=false Set to true if there is a pane showing the file already
   * @param  {Mode} mode? Only Symbol mode has special handling.
   * @returns boolean
   */
  shouldCreateNewLeaf(isModDown: boolean, isAlreadyOpen = false, mode?: Mode): boolean {
    const {
      onOpenPreferNewPane,
      alwaysNewPaneForSymbols,
      useActivePaneForSymbolsOnMobile,
    } = this.settings;

    const isNewPaneRequested = !isAlreadyOpen && onOpenPreferNewPane;
    let shouldCreateNew = isModDown || isNewPaneRequested;

    if (mode === Mode.SymbolList && !onOpenPreferNewPane) {
      const { isMobile } = Platform;
      shouldCreateNew = alwaysNewPaneForSymbols || isModDown;

      if (isMobile) {
        shouldCreateNew = isModDown || !useActivePaneForSymbolsOnMobile;
      }
    }

    return shouldCreateNew;
  }
Example #5
Source File: stats-modal.tsx    From obsidian-spaced-repetition with MIT License 6 votes vote down vote up
constructor(app: App, plugin: SRPlugin) {
        super(app);

        this.plugin = plugin;

        this.titleEl.setText(`${t("STATS_TITLE")} `);
        this.titleEl.innerHTML += (
            <select id="chartPeriod">
                <option value="month" selected>
                    {t("MONTH")}
                </option>
                <option value="quarter">{t("QUARTER")}</option>
                <option value="year">{t("YEAR")}</option>
                <option value="lifetime">{t("LIFETIME")}</option>
            </select>
        );

        this.modalEl.style.height = "100%";
        this.modalEl.style.width = "100%";

        if (Platform.isMobile) {
            this.contentEl.style.display = "block";
        }
    }
Example #6
Source File: index.ts    From obsidian-admonition with MIT License 6 votes vote down vote up
useSelectedItem(event: MouseEvent | KeyboardEvent) {
        if (!this.items || !this.items.length) return;
        const currentValue = this.items[this.selectedItem];
        if (currentValue) {
            this.owner.selectSuggestion(currentValue, event);
        }
        if (Platform.isMobile) {
            this.chooseSuggestion(event);
        }
    }
Example #7
Source File: settings.ts    From alx-folder-note with MIT License 6 votes vote down vote up
setModifier = () => {
    new Setting(this.containerEl)
      .setName("Modifier for New Note")
      .setDesc("Choose a modifier to click folders with to create folder notes")
      .addDropdown((dropDown) => {
        type NoShift = Exclude<Modifier, "Shift">;
        const windowsOpts: Record<NoShift, string> = {
          Mod: "Ctrl (Cmd in macOS)",
          Ctrl: "Ctrl (Ctrl in macOS)",
          Meta: "⊞ Win",
          // Shift: "Shift",
          Alt: "Alt",
        };
        const macOSOpts: Record<NoShift, string> = {
          Mod: "⌘ Cmd (Ctrl in Windows)",
          Ctrl: "⌃ Control",
          Meta: "⌘ Cmd (Win in Windows)",
          // Shift: "⇧ Shift",
          Alt: "⌥ Option",
        };

        const options = Platform.isMacOS ? macOSOpts : windowsOpts;

        dropDown
          .addOptions(options)
          .setValue(this.plugin.settings.modifierForNewNote)
          .onChange(async (value: string) => {
            this.plugin.settings.modifierForNewNote = value as NoShift;
            await this.plugin.saveSettings();
          });
      });
  };
Example #8
Source File: settings.ts    From alx-folder-note with MIT License 6 votes vote down vote up
setFocus() {
    new Setting(this.containerEl)
      .setHeading()
      .setName("Focus")
      .setDesc(
        `You can use "Toggle Focus" option in folder context menu${
          Platform.isMobile ? "" : " or long press on folder title"
        } to focus on a specific folder`,
      );
    if (!Platform.isMobile)
      this.addToggle(this.containerEl, "longPressFocus")
        .setName("Long Press on Folder to Focus")
        .setDesc(
          "Long press with mouse on folder name inside file explorer to focus the folder. " +
            "Only work on Desktop, reload obsidian to take effects",
        );
    new Setting(this.containerEl)
      .addText((text) => {
        Object.assign(text.inputEl, {
          type: "number",
          min: "0.2",
          step: "0.1",
          required: true,
        });
        text.inputEl.addClass("input-short");
        text.inputEl.insertAdjacentElement(
          "afterend",
          createSpan({ cls: ["validity", "unit"], text: "second(s)" }),
        );
        text
          .setValue(`${this.plugin.longPressDelay / 1e3}`)
          .onChange(async (val) => {
            const delay = +val * 1e3;
            this.plugin.longPressDelay = delay;
            await this.plugin.saveSettings();
          });
      })
      .setName("Long Press Delay");
  }
Example #9
Source File: settings.ts    From alx-folder-note with MIT License 6 votes vote down vote up
setMobile() {
    if (!Platform.isMobile) return;
    this.addToggle(this.containerEl, "mobileClickToOpen", (value) =>
      document.body.toggleClass(MobileNoClickMark, !value),
    )
      .setName("Click folder title to open folder note on mobile")
      .setDesc(
        "Disable this if you want to the default action. You can still use context menu to open folder note",
      );
  }
Example #10
Source File: long-press.ts    From alx-folder-note with MIT License 6 votes vote down vote up
AddLongPressEvt = (plugin: ALxFolderNote, el: HTMLElement) => {
  // disable on mobile (conflict with file-menu)
  if (!plugin.settings.longPressFocus || Platform.isMobile) return;
  if (moniterIn) {
    removeEvtListener(moniterIn);
  }
  moniterIn = el;
  // hook events that clear a pending long press event
  el.addEventListener("pointerup", clearLongPressTimer, true);
  el.addEventListener("drag", mouseMoveHandler, true);
  el.addEventListener("wheel", clearLongPressTimer, true);
  el.addEventListener("scroll", clearLongPressTimer, true);

  // hook events that can trigger a long press event
  el.addEventListener("pointerdown", mouseDownHandler, true); // <- start

  plugin.register(() => removeEvtListener(el));
}
Example #11
Source File: misc.ts    From alx-folder-note with MIT License 6 votes vote down vote up
isModifier = (evt: MouseEvent, pref: Modifier): boolean => {
  const { altKey, metaKey, ctrlKey, shiftKey } = evt;
  switch (pref) {
    case "Mod":
      return Platform.isMacOS ? metaKey : ctrlKey;
    case "Ctrl":
      return ctrlKey;
    case "Meta":
      return metaKey;
    case "Shift":
      return shiftKey;
    case "Alt":
      return altKey;
    default:
      assertNever(pref);
  }
}
Example #12
Source File: WebsiteParser.ts    From obsidian-ReadItLater with MIT License 6 votes vote down vote up
private async parsableArticle(app: App, article: Article, url: string) {
        const title = article.title || 'No title';
        let content = await parseHtmlContent(article.content);

        if (this.settings.downloadImages && Platform.isDesktop) {
            content = await replaceImages(app, content, this.settings.assetsDir);
        }

        const processedContent = this.settings.parsableArticleNote
            .replace(/%articleTitle%/g, title)
            .replace(/%articleURL%/g, url)
            .replace(/%articleContent%/g, content);

        const fileNameTemplate = this.settings.parseableArticleNoteTitle.replace(/%title%/g, title);

        const fileName = `${fileNameTemplate}.md`;
        return new Note(fileName, processedContent);
    }
Example #13
Source File: UserSystemFunctions.ts    From Templater with GNU Affero General Public License v3.0 6 votes vote down vote up
constructor(app: App, private plugin: TemplaterPlugin) {
        if (
            Platform.isMobileApp ||
            !(app.vault.adapter instanceof FileSystemAdapter)
        ) {
            this.cwd = "";
        } else {
            this.cwd = app.vault.adapter.getBasePath();
            this.exec_promise = promisify(exec);
        }
    }
Example #14
Source File: UserFunctions.ts    From Templater with GNU Affero General Public License v3.0 6 votes vote down vote up
async generate_object(
        config: RunningConfig
    ): Promise<Record<string, unknown>> {
        let user_system_functions = {};
        let user_script_functions = {};

        if (this.plugin.settings.enable_system_commands) {
            user_system_functions =
                await this.user_system_functions.generate_object(config);
        }

        // TODO: Add mobile support
        // user_scripts_folder needs to be explicitly set to '/' to query from root
        if (Platform.isDesktopApp && this.plugin.settings.user_scripts_folder) {
            user_script_functions =
                await this.user_script_functions.generate_object(config);
        }

        return {
            ...user_system_functions,
            ...user_script_functions,
        };
    }
Example #15
Source File: InternalModuleSystem.ts    From Templater with GNU Affero General Public License v3.0 6 votes vote down vote up
generate_clipboard(): () => Promise<string> {
        return async () => {
            // TODO: Add mobile support
            if (Platform.isMobileApp) {
                return UNSUPPORTED_MOBILE_TEMPLATE;
            }
            return await navigator.clipboard.readText();
        };
    }
Example #16
Source File: drag-patch.ts    From alx-folder-note with MIT License 5 votes vote down vote up
PatchDragManager = (plugin: ALxFolderNote) => {
  const { getFolderNote } = plugin.CoreApi;

  const patchClipboardManager = (): boolean => {
    const view = getMarkdownView();
    if (!view) return false;
    const editMode = view.editMode ?? view.sourceMode;

    if (!editMode)
      throw new Error("Failed to patch clipboard manager: no edit view found");

    plugin.register(
      around(
        editMode.clipboardManager.constructor.prototype as ClipboardManager,
        {
          handleDragOver: (next) =>
            function (this: ClipboardManager, evt, ...args) {
              const { draggable } = this.app.dragManager;
              if (
                draggable &&
                !(Platform.isMacOS ? evt.shiftKey : evt.altKey) &&
                draggable.file instanceof TFolder &&
                getFolderNote(draggable.file)
              ) {
                // evt.preventDefault();
                VD(evt, "link");
                this.app.dragManager.setAction(
                  i18next.t("interface.drag-and-drop.insert-link-here"),
                );
              } else {
                next.call(this, evt, ...args);
              }
            },
          handleDrop: (next) =>
            function (this: ClipboardManager, evt, ...args) {
              const fallback = () => next.call(this, evt, ...args);
              const { draggable } = plugin.app.dragManager;
              let note;
              if (
                draggable?.type === "folder" &&
                draggable.file instanceof TFolder &&
                (note = getFolderNote(draggable.file))
              ) {
                draggable.file = note;
                draggable.type = "file";
              }
              return fallback();
            },
        },
      ),
    );
    console.log("alx-folder-note: clipboard manager patched");
    return true;
  };

  plugin.app.workspace.onLayoutReady(() => {
    if (!patchClipboardManager()) {
      const evt = app.workspace.on("layout-change", () => {
        patchClipboardManager() && app.workspace.offref(evt);
      });
      plugin.registerEvent(evt);
    }
  });

  plugin.register(
    around(app.dragManager.constructor.prototype as DragManager, {
      dragFolder: (next) =>
        function (this: DragManager, evt, folder, source, ...args) {
          let note;
          if ((note = getFolderNote(folder))) {
            const url = app.getObsidianUrl(note);
            evt.dataTransfer!.setData("text/plain", url);
            evt.dataTransfer!.setData("text/uri-list", url);
          }
          return next.call(this, evt, folder, source, ...args);
        },
    }),
  );
}
Example #17
Source File: click-handler.ts    From alx-folder-note with MIT License 5 votes vote down vote up
getClickHandler = (plugin: ALxFolderNote) => {
  const { getFolderNote, getFolderNotePath, getNewFolderNote } = plugin.CoreApi;
  return async (item: FolderItem, evt: MouseEvent): Promise<boolean> => {
    if (
      !item ||
      (Platform.isMobile && !plugin.settings.mobileClickToOpen) ||
      // allow folder shift selection to work
      evt.shiftKey ||
      // triggered only when click on title
      !(
        item.titleInnerEl === evt.target ||
        item.titleInnerEl.contains(evt.target as Node)
      ) ||
      // ignore file being renamed
      item.fileExplorer.fileBeingRenamed === item.file
    )
      return false;

    if (evt.type === "auxclick" && evt.button !== 1) return false;

    // get the folder path
    const folder = item.file;
    const createNew =
      (evt.type === "click" &&
        isModifier(evt, plugin.settings.modifierForNewNote)) ||
      (evt.type === "auxclick" && evt.button === 1);
    try {
      // check if folder note exists
      let folderNote = getFolderNote(folder),
        fnPath;
      if (createNew && !folderNote && (fnPath = getFolderNotePath(folder))) {
        folderNote = await plugin.app.vault.create(
          fnPath.path,
          getNewFolderNote(folder),
        );
      }

      if (!folderNote) return false;

      // show the note
      await plugin.app.workspace.openLinkText(
        folderNote.path,
        "",
        createNew || evt.type === "auxclick",
        { active: true },
      );
      if (plugin.settings.expandFolderOnClick && item.collapsed)
        await item.setCollapsed(false);
      return true;
    } catch (error) {
      console.error(error);
      return false;
    }
  };
}
Example #18
Source File: main.tsx    From obsidian-chartsview-plugin with MIT License 5 votes vote down vote up
async onload() {
		try {
			await this.loadSettings();
			this.addSettingTab(new ChartsViewSettingTab(this.app, this));
			this.registerMarkdownCodeBlockProcessor("chartsview", this.ChartsViewProcessor.bind(this));
			
			this.addCommand({
				id: 'insert-chartsview-template',
				name: 'Insert Template',
				editorCallback: (editor) => {
					new ChartTemplateSuggestModal(this.app, editor).open();
				}
			});

			if (Platform.isDesktopApp) {
				this.addCommand({
					id: `import-chartsview-data-csv`,
					name: `Import data from external CSV file`,
					editorCallback: async (editor) => {
						const file = await fileDialog({ accept: '.csv', strict: true });
						const content = await file.text();
						const records = parseCsv(content);

						insertEditor(
							editor,
							yaml.dump(records, { quotingType: '"', noRefs: true })
								.replace(/\n/g, "\n" + " ".repeat(editor.getCursor().ch))
						);
					}
				});
			}
		} catch (error) {
			console.log(`Load error. ${error}`);
		}

		try {
			this.registerExtensions([CSV_FILE_EXTENSION], VIEW_TYPE_CSV);
		} catch (error) {
			console.log(`Existing file extension ${CSV_FILE_EXTENSION}`);
		}
		console.log('Loaded Charts View plugin');
	}
Example #19
Source File: UserSystemFunctions.ts    From Templater with GNU Affero General Public License v3.0 5 votes vote down vote up
// TODO: Add mobile support
    async generate_system_functions(
        config: RunningConfig
    ): Promise<
        Map<string, (user_args?: Record<string, unknown>) => Promise<string>>
    > {
        const user_system_functions: Map<
            string,
            (user_args?: Record<string, unknown>) => Promise<string>
        > = new Map();
        const internal_functions_object =
            await this.plugin.templater.functions_generator.generate_object(
                config,
                FunctionsMode.INTERNAL
            );

        for (const template_pair of this.plugin.settings.templates_pairs) {
            const template = template_pair[0];
            let cmd = template_pair[1];
            if (!template || !cmd) {
                continue;
            }

            if (Platform.isMobileApp) {
                user_system_functions.set(template, (): Promise<string> => {
                    return new Promise((resolve) =>
                        resolve(UNSUPPORTED_MOBILE_TEMPLATE)
                    );
                });
            } else {
                cmd = await this.plugin.templater.parser.parse_commands(
                    cmd,
                    internal_functions_object
                );

                user_system_functions.set(
                    template,
                    async (
                        user_args?: Record<string, unknown>
                    ): Promise<string> => {
                        const process_env = {
                            ...process.env,
                            ...user_args,
                        };

                        const cmd_options = {
                            timeout:
                                this.plugin.settings.command_timeout * 1000,
                            cwd: this.cwd,
                            env: process_env,
                            ...(this.plugin.settings.shell_path && {
                                shell: this.plugin.settings.shell_path,
                            }),
                        };

                        try {
                            const { stdout } = await this.exec_promise(
                                cmd,
                                cmd_options
                            );
                            return stdout.trimRight();
                        } catch (error) {
                            throw new TemplaterError(
                                `Error with User Template ${template}`,
                                error
                            );
                        }
                    }
                );
            }
        }
        return user_system_functions;
    }
Example #20
Source File: index.ts    From obsidian-switcher-plus with GNU General Public License v3.0 5 votes vote down vote up
mockPlatform = mock<typeof Platform>({
  isDesktop: true,
  isMobile: false,
})
Example #21
Source File: main.ts    From obsidian-fantasy-calendar with MIT License 5 votes vote down vote up
MODIFIER_KEY = Platform.isMacOS ? "Meta" : "Control"
Example #22
Source File: settings.ts    From obsidian-fantasy-calendar with MIT License 5 votes vote down vote up
launchCalendarCreator(
        calendar: Calendar = DEFAULT_CALENDAR
    ): Promise<Calendar | void> {
        /* this.containerEl.empty(); */
        const clone = copy(calendar);

        if (Platform.isMobile) {
            const modal = new MobileCreatorModal(this.plugin, clone);
            return new Promise((resolve, reject) => {
                try {
                    modal.onClose = () => {
                        if (modal.saved) {
                            calendar = copy(modal.calendar);
                            resolve(calendar);
                        }
                        resolve();
                    };

                    modal.open();
                } catch (e) {
                    reject();
                }
            });
        } else {
            this.containerEl.addClass("fantasy-calendar-creator-open");
            return new Promise((resolve) => {
                const color = getComputedStyle(
                    this.containerEl.closest(".modal")
                ).backgroundColor;
                const $app = new CalendarCreator({
                    target: this.containerEl,
                    props: {
                        calendar: clone,
                        plugin: this.plugin,
                        width: this.contentEl.clientWidth,
                        color,
                        top: this.containerEl.scrollTop
                    }
                });
                const observer = new ResizeObserver(() => {
                    $app.$set({ width: this.contentEl.clientWidth });
                });
                observer.observe(this.contentEl);
                $app.$on(
                    "exit",
                    (
                        evt: CustomEvent<{ saved: boolean; calendar: Calendar }>
                    ) => {
                        this.containerEl.removeClass(
                            "fantasy-calendar-creator-open"
                        );
                        $app.$destroy();
                        if (evt.detail.saved) {
                            //saved
                            calendar = copy(evt.detail.calendar);
                            observer.disconnect();
                            resolve(calendar);
                        }
                        resolve();
                    }
                );
            });
        }
    }
Example #23
Source File: flashcard-modal.tsx    From obsidian-spaced-repetition with MIT License 5 votes vote down vote up
constructor(app: App, plugin: SRPlugin, ignoreStats = false) {
        super(app);

        this.plugin = plugin;
        this.ignoreStats = ignoreStats;

        this.titleEl.setText(t("DECKS"));

        if (Platform.isMobile) {
            this.contentEl.style.display = "block";
        }
        this.modalEl.style.height = this.plugin.data.settings.flashcardHeightPercentage + "%";
        this.modalEl.style.width = this.plugin.data.settings.flashcardWidthPercentage + "%";

        this.contentEl.style.position = "relative";
        this.contentEl.style.height = "92%";
        this.contentEl.addClass("sr-modal-content");

        document.body.onkeydown = (e) => {
            if (this.mode !== FlashcardModalMode.DecksList) {
                if (this.mode !== FlashcardModalMode.Closed && e.code === "KeyS") {
                    this.currentDeck.deleteFlashcardAtIndex(
                        this.currentCardIdx,
                        this.currentCard.isDue
                    );
                    this.burySiblingCards(false);
                    this.currentDeck.nextCard(this);
                } else if (
                    this.mode === FlashcardModalMode.Front &&
                    (e.code === "Space" || e.code === "Enter")
                ) {
                    this.showAnswer();
                } else if (this.mode === FlashcardModalMode.Back) {
                    if (e.code === "Numpad1" || e.code === "Digit1") {
                        this.processReview(ReviewResponse.Hard);
                    } else if (e.code === "Numpad2" || e.code === "Digit2" || e.code === "Space") {
                        this.processReview(ReviewResponse.Good);
                    } else if (e.code === "Numpad3" || e.code === "Digit3") {
                        this.processReview(ReviewResponse.Easy);
                    } else if (e.code === "Numpad0" || e.code === "Digit0") {
                        this.processReview(ReviewResponse.Reset);
                    }
                }
            }
        };
    }
Example #24
Source File: baseTypes.ts    From remotely-save with Apache License 2.0 5 votes vote down vote up
VALID_REQURL =
  (!Platform.isAndroidApp && requireApiVersion(API_VER_REQURL)) ||
  (Platform.isAndroidApp && requireApiVersion(API_VER_REQURL_ANDROID))
Example #25
Source File: settings.ts    From obsidian-admonition with MIT License 4 votes vote down vote up
async display(): Promise<void> {
        this.containerEl.empty();
        this.containerEl.addClass("admonition-settings");
        this.containerEl.createEl("h2", { text: t("Admonition Settings") });

        const admonitionEl = this.containerEl.createDiv(
            "admonitions-nested-settings"
        );
        if (!Platform.isMobile) {
            new Setting(admonitionEl)
                .setName("Export Custom Types as CSS")
                .setDesc("Export a CSS snippet for custom callout types.")
                .addButton((b) =>
                    b
                        .setIcon("download")
                        .onClick(() => {
                            const sheet = [
                                `/* This snippet was auto-generated by the Admonitions plugin */\n\n`
                            ];
                            const file = new Blob(
                                [
                                    this.plugin.calloutManager.generateCssString()
                                ],
                                {
                                    type: "text/css"
                                }
                            );
                            createEl("a", {
                                attr: {
                                    download: "custom_callouts.css",
                                    href: URL.createObjectURL(file)
                                }
                            }).click();
                        })
                        .setDisabled(
                            !Object.keys(this.plugin.data.userAdmonitions)
                                .length
                        )
                );
        }

        new Setting(admonitionEl)
            .setName("Use CSS Snippet for Custom Callouts")
            .setDesc(
                "Instead of managing it internally, Admonitions will maintain a CSS snippet to enable your custom types for callouts."
            )
            .addToggle((t) =>
                t.setValue(this.plugin.data.useSnippet).onChange((v) => {
                    this.plugin.data.useSnippet = v;
                    this.plugin.saveSettings();
                    this.plugin.calloutManager.setUseSnippet();
                })
            );

        new Setting(admonitionEl)
            .setName(t("Add New"))
            .setDesc(
                "Add a new Admonition type. All custom Admonitions will also be usable as callouts."
            )
            .addButton((button: ButtonComponent): ButtonComponent => {
                let b = button
                    .setTooltip(t("Add Additional"))
                    .setButtonText("+")
                    .onClick(async () => {
                        let modal = new SettingsModal(this.plugin);

                        modal.onClose = async () => {
                            if (modal.saved) {
                                const admonition = {
                                    type: modal.type,
                                    color: modal.color,
                                    icon: modal.icon,
                                    command: false,
                                    title: modal.title,
                                    injectColor: modal.injectColor,
                                    noTitle: modal.noTitle,
                                    copy: modal.copy
                                };
                                this.plugin.addAdmonition(admonition);

                                this.plugin.calloutManager.addAdmonition(
                                    admonition
                                );
                                this.display();
                            }
                        };

                        modal.open();
                    });

                return b;
            });

        this.additionalEl = admonitionEl.createDiv("additional");
        this.buildTypes();

        this.buildAdmonitions(
            this.containerEl.createEl("details", {
                cls: "admonitions-nested-settings",
                attr: {
                    ...(this.plugin.data.open.admonitions ? { open: true } : {})
                }
            })
        );
        this.buildIcons(
            this.containerEl.createEl("details", {
                cls: "admonitions-nested-settings",
                attr: {
                    ...(this.plugin.data.open.icons ? { open: true } : {})
                }
            })
        );
        this.buildOtherSyntaxes(
            this.containerEl.createEl("details", {
                cls: "admonitions-nested-settings",
                attr: {
                    ...(this.plugin.data.open.other ? { open: true } : {})
                }
            })
        );
        this.buildAdvanced(
            this.containerEl.createEl("details", {
                cls: "admonitions-nested-settings",
                attr: {
                    ...(this.plugin.data.open.advanced ? { open: true } : {})
                }
            })
        );

        const div = this.containerEl.createDiv("coffee");
        div.createEl("a", {
            href: "https://www.buymeacoffee.com/valentine195"
        }).createEl("img", {
            attr: {
                src: "https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=☕&slug=valentine195&button_colour=e3e7ef&font_colour=262626&font_family=Inter&outline_colour=262626&coffee_colour=ff0000"
            }
        });
    }
Example #26
Source File: flashcard-modal.tsx    From obsidian-spaced-repetition with MIT License 4 votes vote down vote up
nextCard(modal: FlashcardModal): void {
        if (this.newFlashcards.length + this.dueFlashcards.length === 0) {
            if (this.dueFlashcardsCount + this.newFlashcardsCount > 0) {
                for (const deck of this.subdecks) {
                    if (deck.dueFlashcardsCount + deck.newFlashcardsCount > 0) {
                        modal.currentDeck = deck;
                        deck.nextCard(modal);
                        return;
                    }
                }
            }

            if (this.parent == modal.checkDeck) {
                modal.decksList();
            } else {
                this.parent.nextCard(modal);
            }
            return;
        }

        modal.responseDiv.style.display = "none";
        modal.resetLinkView.style.display = "none";
        modal.titleEl.setText(
            `${this.deckName}: ${this.dueFlashcardsCount + this.newFlashcardsCount}`
        );

        modal.answerBtn.style.display = "initial";
        modal.flashcardView.innerHTML = "";
        modal.mode = FlashcardModalMode.Front;

        let interval = 1.0,
            ease: number = modal.plugin.data.settings.baseEase,
            delayBeforeReview = 0;
        if (this.dueFlashcards.length > 0) {
            if (modal.plugin.data.settings.randomizeCardOrder) {
                modal.currentCardIdx = Math.floor(Math.random() * this.dueFlashcards.length);
            } else {
                modal.currentCardIdx = 0;
            }
            modal.currentCard = this.dueFlashcards[modal.currentCardIdx];
            modal.renderMarkdownWrapper(modal.currentCard.front, modal.flashcardView);

            interval = modal.currentCard.interval;
            ease = modal.currentCard.ease;
            delayBeforeReview = modal.currentCard.delayBeforeReview;
        } else if (this.newFlashcards.length > 0) {
            if (modal.plugin.data.settings.randomizeCardOrder) {
                const pickedCardIdx = Math.floor(Math.random() * this.newFlashcards.length);
                modal.currentCardIdx = pickedCardIdx;

                // look for first unscheduled sibling
                const pickedCard: Card = this.newFlashcards[pickedCardIdx];
                let idx = pickedCardIdx;
                while (idx >= 0 && pickedCard.siblings.includes(this.newFlashcards[idx])) {
                    if (!this.newFlashcards[idx].isDue) {
                        modal.currentCardIdx = idx;
                    }
                    idx--;
                }
            } else {
                modal.currentCardIdx = 0;
            }

            modal.currentCard = this.newFlashcards[modal.currentCardIdx];
            modal.renderMarkdownWrapper(modal.currentCard.front, modal.flashcardView);

            if (
                Object.prototype.hasOwnProperty.call(
                    modal.plugin.easeByPath,
                    modal.currentCard.note.path
                )
            ) {
                ease = modal.plugin.easeByPath[modal.currentCard.note.path];
            }
        }

        const hardInterval: number = schedule(
            ReviewResponse.Hard,
            interval,
            ease,
            delayBeforeReview,
            modal.plugin.data.settings
        ).interval;
        const goodInterval: number = schedule(
            ReviewResponse.Good,
            interval,
            ease,
            delayBeforeReview,
            modal.plugin.data.settings
        ).interval;
        const easyInterval: number = schedule(
            ReviewResponse.Easy,
            interval,
            ease,
            delayBeforeReview,
            modal.plugin.data.settings
        ).interval;

        if (modal.ignoreStats) {
            // Same for mobile/desktop
            modal.hardBtn.setText(`${t("HARD")}`);
            modal.easyBtn.setText(`${t("EASY")}`);
        } else if (Platform.isMobile) {
            modal.hardBtn.setText(textInterval(hardInterval, true));
            modal.goodBtn.setText(textInterval(goodInterval, true));
            modal.easyBtn.setText(textInterval(easyInterval, true));
        } else {
            modal.hardBtn.setText(`${t("HARD")} - ${textInterval(hardInterval, false)}`);
            modal.goodBtn.setText(`${t("GOOD")} - ${textInterval(goodInterval, false)}`);
            modal.easyBtn.setText(`${t("EASY")} - ${textInterval(easyInterval, false)}`);
        }

        if (modal.plugin.data.settings.showContextInCards)
            modal.contextView.setText(modal.currentCard.context);
        if (modal.plugin.data.settings.showFileNameInFileLink)
            modal.fileLinkView.setText(modal.currentCard.note.basename);
    }
Example #27
Source File: settings.ts    From remotely-save with Apache License 2.0 4 votes vote down vote up
async onOpen() {
    let { contentEl } = this;

    const t = (x: TransItemType, vars?: any) => {
      return this.plugin.i18n.t(x, vars);
    };

    let needManualPatse = false;
    const userAgent = window.navigator.userAgent.toLocaleLowerCase() || "";
    // some users report that,
    // the Linux would open another instance Obsidian if jumping back,
    // so fallback to manual paste on Linux
    if (
      Platform.isDesktopApp &&
      !Platform.isMacOS &&
      (/linux/.test(userAgent) ||
        /ubuntu/.test(userAgent) ||
        /debian/.test(userAgent) ||
        /fedora/.test(userAgent) ||
        /centos/.test(userAgent))
    ) {
      needManualPatse = true;
    }

    const { authUrl, verifier } = await getAuthUrlAndVerifierDropbox(
      this.plugin.settings.dropbox.clientID,
      needManualPatse
    );

    if (needManualPatse) {
      t("modal_dropboxauth_manualsteps")
        .split("\n")
        .forEach((val) => {
          contentEl.createEl("p", {
            text: val,
          });
        });
    } else {
      this.plugin.oauth2Info.verifier = verifier;

      t("modal_dropboxauth_autosteps")
        .split("\n")
        .forEach((val) => {
          contentEl.createEl("p", {
            text: val,
          });
        });
    }

    const div2 = contentEl.createDiv();
    div2.createEl(
      "button",
      {
        text: t("modal_dropboxauth_copybutton"),
      },
      (el) => {
        el.onclick = async () => {
          await navigator.clipboard.writeText(authUrl);
          new Notice(t("modal_dropboxauth_copynotice"));
        };
      }
    );

    contentEl.createEl("p").createEl("a", {
      href: authUrl,
      text: authUrl,
    });

    if (needManualPatse) {
      let authCode = "";
      new Setting(contentEl)
        .setName(t("modal_dropboxauth_maualinput"))
        .setDesc(t("modal_dropboxauth_maualinput_desc"))
        .addText((text) =>
          text
            .setPlaceholder("")
            .setValue("")
            .onChange((val) => {
              authCode = val.trim();
            })
        )
        .addButton(async (button) => {
          button.setButtonText(t("submit"));
          button.onClick(async () => {
            new Notice(t("modal_dropboxauth_maualinput_notice"));
            try {
              const authRes = await sendAuthReqDropbox(
                this.plugin.settings.dropbox.clientID,
                verifier,
                authCode
              );
              const self = this;
              setConfigBySuccessfullAuthInplace(
                this.plugin.settings.dropbox,
                authRes,
                () => self.plugin.saveSettings()
              );
              const client = new RemoteClient(
                "dropbox",
                undefined,
                undefined,
                this.plugin.settings.dropbox,
                undefined,
                this.app.vault.getName(),
                () => self.plugin.saveSettings()
              );
              const username = await client.getUser();
              this.plugin.settings.dropbox.username = username;
              await this.plugin.saveSettings();
              new Notice(
                t("modal_dropboxauth_maualinput_conn_succ", {
                  username: username,
                })
              );
              this.authDiv.toggleClass(
                "dropbox-auth-button-hide",
                this.plugin.settings.dropbox.username !== ""
              );
              this.revokeAuthDiv.toggleClass(
                "dropbox-revoke-auth-button-hide",
                this.plugin.settings.dropbox.username === ""
              );
              this.revokeAuthSetting.setDesc(
                t("modal_dropboxauth_maualinput_conn_succ_revoke", {
                  username: this.plugin.settings.dropbox.username,
                })
              );
              this.close();
            } catch (err) {
              console.error(err);
              new Notice(t("modal_dropboxauth_maualinput_conn_fail"));
            }
          });
        });
    }
  }
Example #28
Source File: main.ts    From obsidian-customizable-sidebar with MIT License 4 votes vote down vote up
sidebarPins() {
		if ( Platform.isMobile) {
			// don't do any of this if we're on mobile
			return;
		}
		if (this.settings.pinSidebar === undefined && this.pinSidebarSupport) {
			// clean up any sidebar pins & related classes if present

			const leftParent = this.pinSidebarSupport.pinLeft.parentElement;
			leftParent.removeChild(this.pinSidebarSupport.pinLeft);
			delete this.pinSidebarSupport.pinLeft;

			const rightParent = this.pinSidebarSupport.pinRight.parentElement;
			rightParent.removeChild(this.pinSidebarSupport.pinRight);
			delete this.pinSidebarSupport.pinRight;

			this.getSidebarContainer(true).removeClass("is-pinned");
			this.getSidebarContainer(true).removeClass("is-floating");

			this.getSidebarContainer(false).removeClass("is-pinned");
			this.getSidebarContainer(false).removeClass("is-floating");

		} else if (this.settings.pinSidebar) {
			// create sidebar pin buttons & related classes

			if ( this.pinSidebarSupport === undefined ) {
				// Commands are added once (not removed?)
				this.addCommand({
					id: "pin-left-sidebar",
					name: "Toggle pin left Sidebar",
					icon: "pin",
					callback: async () => this.toggleLeftSidebar()
				});

				this.addCommand({
					id: "pin-right-sidebar",
					name: "Toggle pin right Sidebar",
					icon: "pin",
					callback: async () => this.toggleRightSidebar()
				});
			}

			//@ts-ignore
			const leftParent: HTMLElement = this.app.workspace.leftRibbon.containerEl;
			let pinLeft = leftParent.children.namedItem("left-pin-sidebar") as HTMLElement;
			if (pinLeft == null) {
				pinLeft = leftParent.createDiv({
					cls: "pin-sidebar pin-left-sidebar",
					attr: {
						name: "left-pin-sidebar"
					}});
				pinLeft.addEventListener("click", async (e) => {
					this.toggleLeftSidebar();
					return e.preventDefault();
				});
				leftParent.insertBefore(pinLeft, leftParent.firstChild);
			}

			//@ts-ignore
			const rightParent: HTMLElement = this.app.workspace.rightRibbon.containerEl;
			let pinRight = rightParent.children.namedItem("right-pin-sidebar") as HTMLElement;
			if ( pinRight == null ) {
				pinRight = rightParent.createDiv({
					cls: "pin-sidebar pin-right-sidebar",
					attr: {
						name: "right-pin-sidebar",
					}});
				pinRight.addEventListener("click", async (e) => {
					this.toggleRightSidebar();
					return e.preventDefault();
				});
				rightParent.insertBefore(pinRight, rightParent.firstChild);
			}

			// Save elements for reference/toggle
			this.pinSidebarSupport = {
				pinLeft,
				pinRight
			};

			this.setAttributes(pinLeft,
					this.getSidebarContainer(true),
					this.settings.pinSidebar.left === undefined ? true : this.settings.pinSidebar.left);

			this.setAttributes(pinRight,
					this.getSidebarContainer(false),
					this.settings.pinSidebar.right === undefined ? true : this.settings.pinSidebar.right);
		}
	}
Example #29
Source File: settings.ts    From obsidian-plantuml with MIT License 4 votes vote down vote up
display(): void {
        const {containerEl} = this;

        containerEl.empty();

        new Setting(containerEl).setName("Server URL")
            .setDesc("PlantUML Server URL")
            .addText(text => text.setPlaceholder(DEFAULT_SETTINGS.server_url)
                .setValue(this.plugin.settings.server_url)
                .onChange(async (value) => {
                        this.plugin.settings.server_url = value;
                        await this.plugin.saveSettings();
                    }
                )
            );

        if(Platform.isDesktopApp) {
            new Setting(containerEl)
                .setName("Local JAR")
                .setDesc("Path to local PlantUML Jar")
                .addText(text => text.setPlaceholder(DEFAULT_SETTINGS.localJar)
                    .setValue(this.plugin.settings.localJar)
                    .onChange(async (value) => {
                            this.plugin.settings.localJar = value;
                            await this.plugin.saveSettings();
                        }
                    )
                );

            new Setting(containerEl)
                .setName("Java Path")
                .setDesc("Path to Java executable")
                .addText(text => text.setPlaceholder(DEFAULT_SETTINGS.javaPath)
                    .setValue(this.plugin.settings.javaPath)
                    .onChange(async (value) => {
                            this.plugin.settings.javaPath = value;
                            await this.plugin.saveSettings();
                        }
                    )
                );
        }

        new Setting(containerEl)
            .setName("Default processor for includes")
            .setDesc("Any .pu/.puml files linked will use this processor")
            .addDropdown(dropdown => {
               dropdown
                   .addOption("png", "PNG")
                   .addOption("svg", "SVG")
                   .setValue(this.plugin.settings.defaultProcessor)
                   .onChange(async(value) => {
                      this.plugin.settings.defaultProcessor = value;
                      await this.plugin.saveSettings();
                   });
            });

        new Setting(containerEl).setName("Header")
            .setDesc("Included at the head in every diagram. Useful for specifying a common theme (.puml file)")
            .addTextArea(text => {
                    text.setPlaceholder("!include https://raw.githubusercontent.com/....puml\n")
                        .setValue(this.plugin.settings.header)
                        .onChange(async (value) => {
                                this.plugin.settings.header = value;
                                await this.plugin.saveSettings();
                            }
                        )
                    text.inputEl.setAttr("rows", 4);
                    text.inputEl.addClass("puml-settings-area")
                }
            );
        new Setting(containerEl).setName("Debounce")
            .setDesc("How often should the diagram refresh in seconds")
            .addText(text => text.setPlaceholder(String(DEFAULT_SETTINGS.debounce))
                .setValue(String(this.plugin.settings.debounce))
                .onChange(async (value) => {
                    //make sure that there is always some value defined, or reset to default
                    if (!isNaN(Number(value)) || value === undefined) {
                        this.plugin.settings.debounce = Number(value || DEFAULT_SETTINGS.debounce);
                        await this.plugin.saveSettings();
                    } else {
                        new Notice("Please specify a valid number");
                    }
                }));
    }