mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	feat(react): port bookmark switch
This commit is contained in:
		| @@ -1,54 +0,0 @@ | ||||
| import SwitchWidget from "./switch.js"; | ||||
| import server from "../services/server.js"; | ||||
| import toastService from "../services/toast.js"; | ||||
| import { t } from "../services/i18n.js"; | ||||
| import type FNote from "../entities/fnote.js"; | ||||
| import type { EventData } from "../components/app_context.js"; | ||||
|  | ||||
| // TODO: Deduplicate | ||||
| type Response = { | ||||
|     success: true; | ||||
| } | { | ||||
|     success: false; | ||||
|     message: string; | ||||
| } | ||||
|  | ||||
| export default class BookmarkSwitchWidget extends SwitchWidget { | ||||
|     isEnabled() { | ||||
|         return ( | ||||
|             super.isEnabled() && | ||||
|             // it's not possible to bookmark root because that would clone it under bookmarks and thus create a cycle | ||||
|             !["root", "_hidden"].includes(this.noteId ?? "") | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     doRender() { | ||||
|         super.doRender(); | ||||
|  | ||||
|         this.switchOnName = t("bookmark_switch.bookmark"); | ||||
|         this.switchOnTooltip = t("bookmark_switch.bookmark_this_note"); | ||||
|  | ||||
|         this.switchOffName = t("bookmark_switch.bookmark"); | ||||
|         this.switchOffTooltip = t("bookmark_switch.remove_bookmark"); | ||||
|     } | ||||
|  | ||||
|     async toggle(state: boolean | null | undefined) { | ||||
|         const resp = await server.put<Response>(`notes/${this.noteId}/toggle-in-parent/_lbBookmarks/${!!state}`); | ||||
|  | ||||
|         if (!resp.success && "message" in resp) { | ||||
|             toastService.showError(resp.message); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note: FNote) { | ||||
|         const isBookmarked = !!note.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); | ||||
|  | ||||
|         this.isToggled = isBookmarked; | ||||
|     } | ||||
|  | ||||
|     entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { | ||||
|         if (loadResults.getBranchRows().find((b) => b.noteId === this.noteId)) { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -10,16 +10,17 @@ interface FormToggleProps { | ||||
|     switchOffName: string; | ||||
|     switchOffTooltip: string; | ||||
|     helpPage?: string; | ||||
|     disabled?: boolean; | ||||
| } | ||||
|  | ||||
| export default function FormToggle({ currentValue, helpPage, switchOnName, switchOnTooltip, switchOffName, switchOffTooltip, onChange }: FormToggleProps) { | ||||
| export default function FormToggle({ currentValue, helpPage, switchOnName, switchOnTooltip, switchOffName, switchOffTooltip, onChange, disabled }: FormToggleProps) { | ||||
|     return ( | ||||
|         <div className="switch-widget"> | ||||
|             <span className="switch-name">{ currentValue ? switchOffName : switchOnName }</span> | ||||
|  | ||||
|             <label> | ||||
|                 <div | ||||
|                     className={`switch-button ${currentValue ? "on" : ""}`} | ||||
|                     className={`switch-button ${currentValue ? "on" : ""} ${disabled ? "disabled" : ""}`} | ||||
|                     title={currentValue ? switchOffTooltip : switchOnTooltip } | ||||
|                 > | ||||
|                     <input | ||||
| @@ -30,6 +31,7 @@ export default function FormToggle({ currentValue, helpPage, switchOnName, switc | ||||
|                             onChange(!currentValue); | ||||
|                             e.preventDefault(); | ||||
|                         }} | ||||
|                         disabled={disabled} | ||||
|                     /> | ||||
|                 </div> | ||||
|             </label> | ||||
|   | ||||
| @@ -1,17 +1,18 @@ | ||||
| import { useCallback, useMemo } from "preact/hooks"; | ||||
| import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; | ||||
| import Dropdown from "../react/Dropdown"; | ||||
| import { NOTE_TYPES } from "../../services/note_types"; | ||||
| import { FormDivider, FormListBadge, FormListItem } from "../react/FormList"; | ||||
| import { t } from "../../services/i18n"; | ||||
| import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumOption } from "../react/hooks"; | ||||
| import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption } from "../react/hooks"; | ||||
| import mime_types from "../../services/mime_types"; | ||||
| import { NoteType } from "@triliumnext/commons"; | ||||
| import { NoteType, ToggleInParentResponse } from "@triliumnext/commons"; | ||||
| import server from "../../services/server"; | ||||
| import dialog from "../../services/dialog"; | ||||
| import FormToggle from "../react/FormToggle"; | ||||
| import FNote from "../../entities/fnote"; | ||||
| import protected_session from "../../services/protected_session"; | ||||
| import FormDropdownList from "../react/FormDropdownList"; | ||||
| import toast from "../../services/toast"; | ||||
|  | ||||
| export default function BasicPropertiesTab() { | ||||
|     const { note } = useNoteContext(); | ||||
| @@ -21,6 +22,7 @@ export default function BasicPropertiesTab() { | ||||
|             <NoteTypeWidget note={note} /> | ||||
|             <ProtectedNoteSwitch note={note} /> | ||||
|             <EditabilitySelect note={note} /> | ||||
|             <BookmarkSwitch note={note} /> | ||||
|         </div> | ||||
|     ); | ||||
| } | ||||
| @@ -114,10 +116,10 @@ function ProtectedNoteSwitch({ note }: { note?: FNote | null }) { | ||||
|     return ( | ||||
|         <div className="protected-note-switch-container"> | ||||
|             <FormToggle | ||||
|                 currentValue={isProtected} | ||||
|                 onChange={(shouldProtect) => note && protected_session.protectNote(note.noteId, shouldProtect, false)} | ||||
|                 switchOnName={t("protect_note.toggle-on")} switchOnTooltip={t("protect_note.toggle-on-hint")} | ||||
|                 switchOffName={t("protect_note.toggle-off")} switchOffTooltip={t("protect_note.toggle-off-hint")} | ||||
|                 currentValue={isProtected} | ||||
|                 onChange={(shouldProtect) => note && protected_session.protectNote(note.noteId, shouldProtect, false)} | ||||
|             /> | ||||
|         </div> | ||||
|     ) | ||||
| @@ -163,6 +165,40 @@ function EditabilitySelect({ note }: { note?: FNote | null }) { | ||||
|     ) | ||||
| } | ||||
|  | ||||
| function BookmarkSwitch({ note }: { note?: FNote | null }) { | ||||
|     const [ isBookmarked, setIsBookmarked ] = useState<boolean>(false); | ||||
|     const refreshState = useCallback(() => { | ||||
|         const isBookmarked = note && !!note.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); | ||||
|         setIsBookmarked(!!isBookmarked); | ||||
|     }, [ note ]); | ||||
|  | ||||
|     useEffect(() => refreshState(), [ note ]); | ||||
|     useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => { | ||||
|         if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) { | ||||
|             refreshState(); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     return ( | ||||
|         <div className="bookmark-switch-container"> | ||||
|             <FormToggle | ||||
|                 switchOnName={t("bookmark_switch.bookmark")} switchOnTooltip={t("bookmark_switch.bookmark_this_note")} | ||||
|                 switchOffName={t("bookmark_switch.bookmark")} switchOffTooltip={t("bookmark_switch.remove_bookmark")} | ||||
|                 currentValue={isBookmarked}                 | ||||
|                 onChange={async (shouldBookmark) => { | ||||
|                     if (!note) return; | ||||
|                     const resp = await server.put<ToggleInParentResponse>(`notes/${note.noteId}/toggle-in-parent/_lbBookmarks/${shouldBookmark}`); | ||||
|  | ||||
|                     if (!resp.success && "message" in resp) { | ||||
|                         toast.showError(resp.message); | ||||
|                     } | ||||
|                 }} | ||||
|                 disabled={["root", "_hidden"].includes(note?.noteId ?? "")} | ||||
|             /> | ||||
|         </div> | ||||
|     ) | ||||
| } | ||||
|  | ||||
| function findTypeTitle(type?: NoteType, mime?: string | null) { | ||||
|     if (type === "code") { | ||||
|         const mimeTypes = mime_types.getMimeTypes(); | ||||
|   | ||||
| @@ -10,8 +10,6 @@ import type FNote from "../../entities/fnote.js"; | ||||
| import NoteLanguageWidget from "../note_language.js"; | ||||
|  | ||||
| const TPL = /*html*/` | ||||
|     <div class="bookmark-switch-container"></div> | ||||
|  | ||||
|     <div class="shared-switch-container"></div> | ||||
|  | ||||
|     <div class="template-switch-container"></div> | ||||
| @@ -23,8 +21,6 @@ const TPL = /*html*/` | ||||
|  | ||||
| export default class BasicPropertiesWidget extends NoteContextAwareWidget { | ||||
|  | ||||
|     private editabilitySelectWidget: EditabilitySelectWidget; | ||||
|     private bookmarkSwitchWidget: BookmarkSwitchWidget; | ||||
|     private sharedSwitchWidget: SharedSwitchWidget; | ||||
|     private templateSwitchWidget: TemplateSwitchWidget; | ||||
|     private noteLanguageWidget: NoteLanguageWidget; | ||||
| @@ -32,15 +28,11 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget { | ||||
|     constructor() { | ||||
|         super(); | ||||
|  | ||||
|         this.editabilitySelectWidget = new EditabilitySelectWidget().contentSized(); | ||||
|         this.bookmarkSwitchWidget = new BookmarkSwitchWidget().contentSized(); | ||||
|         this.sharedSwitchWidget = new SharedSwitchWidget().contentSized(); | ||||
|         this.templateSwitchWidget = new TemplateSwitchWidget().contentSized(); | ||||
|         this.noteLanguageWidget = new NoteLanguageWidget().contentSized(); | ||||
|  | ||||
|         this.child( | ||||
|             this.editabilitySelectWidget, | ||||
|             this.bookmarkSwitchWidget, | ||||
|             this.sharedSwitchWidget, | ||||
|             this.templateSwitchWidget, | ||||
|             this.noteLanguageWidget); | ||||
|   | ||||
| @@ -40,9 +40,6 @@ export default class SwitchWidget extends NoteContextAwareWidget { | ||||
|     } | ||||
|  | ||||
|     set canToggle(isEnabled) { | ||||
|         this.$switchButton.toggleClass("disabled", !isEnabled); | ||||
|         this.$switchToggle.attr("disabled", !isEnabled ? "disabled" : null); | ||||
|  | ||||
|         if (isEnabled) { | ||||
|             this.isToggled = this.currentState; // Reapply the correct tooltip | ||||
|         } else { | ||||
|   | ||||
| @@ -155,3 +155,10 @@ export interface OpenAiOrAnthropicModelResponse { | ||||
|         type: string; | ||||
|     }>; | ||||
| } | ||||
|  | ||||
| export type ToggleInParentResponse = { | ||||
|     success: true; | ||||
| } | { | ||||
|     success: false; | ||||
|     message: string; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user