diff --git a/apps/client/src/widgets/floating_buttons/help_button.spec.ts b/apps/client/src/services/in_app_help.spec.ts similarity index 91% rename from apps/client/src/widgets/floating_buttons/help_button.spec.ts rename to apps/client/src/services/in_app_help.spec.ts index c168c6e13..e19d0a095 100644 --- a/apps/client/src/widgets/floating_buttons/help_button.spec.ts +++ b/apps/client/src/services/in_app_help.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { byBookType, byNoteType } from "./help_button.js"; +import { byBookType, byNoteType } from "./in_app_help.js"; import fs from "fs"; import type { HiddenSubtreeItem } from "@triliumnext/commons"; import path from "path"; @@ -25,7 +25,7 @@ describe("Help button", () => { ...Object.values(byBookType) ].filter((noteId) => noteId) as string[]; - const metaPath = path.resolve(path.join(__dirname, "../../../../server/src/assets/doc_notes/en/User Guide/!!!meta.json")); + const metaPath = path.resolve(path.join(__dirname, "../../../server/src/assets/doc_notes/en/User Guide/!!!meta.json")); const meta: HiddenSubtreeItem[] = JSON.parse(fs.readFileSync(metaPath, "utf-8")); const allNoteIds = new Set(getNoteIds(meta)); diff --git a/apps/client/src/services/in_app_help.ts b/apps/client/src/services/in_app_help.ts new file mode 100644 index 000000000..7a51e8ed7 --- /dev/null +++ b/apps/client/src/services/in_app_help.ts @@ -0,0 +1,43 @@ +import { NoteType } from "@triliumnext/commons"; +import { ViewTypeOptions } from "./note_list_renderer"; +import { FNote } from "./frontend_script_entrypoint"; + +export const byNoteType: Record, string | null> = { + canvas: null, + code: null, + contentWidget: null, + doc: null, + file: null, + image: null, + launcher: null, + mermaid: null, + mindMap: null, + noteMap: null, + relationMap: null, + render: null, + search: null, + text: null, + webView: null, + aiChat: null +}; + +export const byBookType: Record = { + list: "mULW0Q3VojwY", + grid: "8QqnMzx393bx", + calendar: "xWbu3jpNWapp", + table: "2FvYrpmOXm29", + geoMap: "81SGnPGMk7Xc", + board: "CtBQqbwXDx1w" +}; + +export function getHelpUrlForNote(note: FNote | null | undefined) { + if (note && note.type !== "book" && byNoteType[note.type]) { + return byNoteType[note.type]; + } else if (note?.hasLabel("calendarRoot")) { + return "l0tKav7yLHGF"; + } else if (note?.hasLabel("textSnippet")) { + return "pwc194wlRzcH"; + } else if (note && note.type === "book") { + return byBookType[note.getAttributeValue("label", "viewType") as ViewTypeOptions ?? ""] + } +} diff --git a/apps/client/src/widgets/FloatingButtons.tsx b/apps/client/src/widgets/FloatingButtons.tsx index 97db0ff3b..a846a5113 100644 --- a/apps/client/src/widgets/FloatingButtons.tsx +++ b/apps/client/src/widgets/FloatingButtons.tsx @@ -1,8 +1,8 @@ import { t } from "i18next"; import "./FloatingButtons.css"; import Button from "./react/Button"; -import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent, useTriliumEvents, useTriliumOption, useTriliumOptionBool } from "./react/hooks"; -import { useContext, useEffect, useMemo, useRef, useState } from "preact/hooks"; +import { useNoteContext, useNoteProperty, useTriliumEvent, useTriliumEvents } from "./react/hooks"; +import { useContext, useEffect, useMemo, useState } from "preact/hooks"; import { ParentComponent } from "./react/react_utils"; import attributes from "../services/attributes"; import { EventData, EventNames } from "../components/app_context"; diff --git a/apps/client/src/widgets/FloatingButtonsDefinitions.tsx b/apps/client/src/widgets/FloatingButtonsDefinitions.tsx index b817908c4..1c2726e64 100644 --- a/apps/client/src/widgets/FloatingButtonsDefinitions.tsx +++ b/apps/client/src/widgets/FloatingButtonsDefinitions.tsx @@ -5,7 +5,7 @@ import NoteContext from "../components/note_context"; import FNote from "../entities/fnote"; import ActionButton, { ActionButtonProps } from "./react/ActionButton"; import { useNoteLabelBoolean, useTriliumOption } from "./react/hooks"; -import { useEffect, useRef, useState } from "preact/hooks"; +import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import { createImageSrcUrl, openInAppHelpFromUrl } from "../services/utils"; import server from "../services/server"; import { SaveSqlConsoleResponse } from "@triliumnext/commons"; @@ -15,6 +15,7 @@ import { copyImageReferenceToClipboard } from "../services/image"; import tree from "../services/tree"; import protected_session_holder from "../services/protected_session_holder"; import options from "../services/options"; +import { getHelpUrlForNote } from "../services/in_app_help"; export interface FloatingButtonDefinition { component: (context: FloatingButtonContext) => VNode; @@ -104,6 +105,10 @@ export const FLOATING_BUTTON_DEFINITIONS: FloatingButtonDefinition[] = [ isEnabled: ({ note, noteContext }) => ["mermaid", "mindMap"].includes(note?.type ?? "") && note?.isContentAvailable() && noteContext?.viewScope?.viewMode === "default" + }, + { + component: InAppHelpButton, + isEnabled: ({ note }) => !!getHelpUrlForNote(note) } ]; @@ -303,4 +308,16 @@ function ExportImageButtons({ triggerEvent }: FloatingButtonContext) { /> ) +} + +function InAppHelpButton({ note }: FloatingButtonContext) { + const helpUrl = getHelpUrlForNote(note); + + return ( + helpUrl && openInAppHelpFromUrl(helpUrl)} + /> + ) } \ No newline at end of file diff --git a/apps/client/src/widgets/floating_buttons/help_button.ts b/apps/client/src/widgets/floating_buttons/help_button.ts deleted file mode 100644 index b7f6a8fd2..000000000 --- a/apps/client/src/widgets/floating_buttons/help_button.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { type EventData } from "../../components/app_context.js"; -import type FNote from "../../entities/fnote.js"; -import type { NoteType } from "../../entities/fnote.js"; -import { t } from "../../services/i18n.js"; -import type { ViewTypeOptions } from "../../services/note_list_renderer.js"; -import NoteContextAwareWidget from "../note_context_aware_widget.js"; - -const TPL = /*html*/` - -`; - -export const byNoteType: Record, string | null> = { - canvas: null, - code: null, - contentWidget: null, - doc: null, - file: null, - image: null, - launcher: null, - mermaid: null, - mindMap: null, - noteMap: null, - relationMap: null, - render: null, - search: null, - text: null, - webView: null, - aiChat: null -}; - -export const byBookType: Record = { - list: "mULW0Q3VojwY", - grid: "8QqnMzx393bx", - calendar: "xWbu3jpNWapp", - table: "2FvYrpmOXm29", - geoMap: "81SGnPGMk7Xc", - board: "CtBQqbwXDx1w" -}; - -export default class ContextualHelpButton extends NoteContextAwareWidget { - - isEnabled() { - if (!super.isEnabled()) { - return false; - } - - return !!ContextualHelpButton.#getUrlToOpen(this.note); - } - - doRender() { - this.$widget = $(TPL); - } - - static #getUrlToOpen(note: FNote | null | undefined) { - if (note && note.type !== "book" && byNoteType[note.type]) { - return byNoteType[note.type]; - } else if (note?.hasLabel("calendarRoot")) { - return "l0tKav7yLHGF"; - } else if (note?.hasLabel("textSnippet")) { - return "pwc194wlRzcH"; - } else if (note && note.type === "book") { - return byBookType[note.getAttributeValue("label", "viewType") as ViewTypeOptions ?? ""] - } - } - - async refreshWithNote(note: FNote | null | undefined): Promise { - this.$widget.attr("data-in-app-help", ContextualHelpButton.#getUrlToOpen(this.note) ?? ""); - } - - entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - if (this.note?.type === "book" && loadResults.getAttributeRows().find((attr) => attr.noteId === this.noteId && attr.name === "viewType")) { - this.refresh(); - } - } - -}