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; |     switchOffName: string; | ||||||
|     switchOffTooltip: string; |     switchOffTooltip: string; | ||||||
|     helpPage?: 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 ( |     return ( | ||||||
|         <div className="switch-widget"> |         <div className="switch-widget"> | ||||||
|             <span className="switch-name">{ currentValue ? switchOffName : switchOnName }</span> |             <span className="switch-name">{ currentValue ? switchOffName : switchOnName }</span> | ||||||
|  |  | ||||||
|             <label> |             <label> | ||||||
|                 <div |                 <div | ||||||
|                     className={`switch-button ${currentValue ? "on" : ""}`} |                     className={`switch-button ${currentValue ? "on" : ""} ${disabled ? "disabled" : ""}`} | ||||||
|                     title={currentValue ? switchOffTooltip : switchOnTooltip } |                     title={currentValue ? switchOffTooltip : switchOnTooltip } | ||||||
|                 > |                 > | ||||||
|                     <input |                     <input | ||||||
| @@ -29,7 +30,8 @@ export default function FormToggle({ currentValue, helpPage, switchOnName, switc | |||||||
|                         onInput={(e) => { |                         onInput={(e) => { | ||||||
|                             onChange(!currentValue); |                             onChange(!currentValue); | ||||||
|                             e.preventDefault(); |                             e.preventDefault(); | ||||||
|                         }}       |                         }} | ||||||
|  |                         disabled={disabled} | ||||||
|                     /> |                     /> | ||||||
|                 </div> |                 </div> | ||||||
|             </label> |             </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 Dropdown from "../react/Dropdown"; | ||||||
| import { NOTE_TYPES } from "../../services/note_types"; | import { NOTE_TYPES } from "../../services/note_types"; | ||||||
| import { FormDivider, FormListBadge, FormListItem } from "../react/FormList"; | import { FormDivider, FormListBadge, FormListItem } from "../react/FormList"; | ||||||
| import { t } from "../../services/i18n"; | 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 mime_types from "../../services/mime_types"; | ||||||
| import { NoteType } from "@triliumnext/commons"; | import { NoteType, ToggleInParentResponse } from "@triliumnext/commons"; | ||||||
| import server from "../../services/server"; | import server from "../../services/server"; | ||||||
| import dialog from "../../services/dialog"; | import dialog from "../../services/dialog"; | ||||||
| import FormToggle from "../react/FormToggle"; | import FormToggle from "../react/FormToggle"; | ||||||
| import FNote from "../../entities/fnote"; | import FNote from "../../entities/fnote"; | ||||||
| import protected_session from "../../services/protected_session"; | import protected_session from "../../services/protected_session"; | ||||||
| import FormDropdownList from "../react/FormDropdownList"; | import FormDropdownList from "../react/FormDropdownList"; | ||||||
|  | import toast from "../../services/toast"; | ||||||
|  |  | ||||||
| export default function BasicPropertiesTab() { | export default function BasicPropertiesTab() { | ||||||
|     const { note } = useNoteContext(); |     const { note } = useNoteContext(); | ||||||
| @@ -21,6 +22,7 @@ export default function BasicPropertiesTab() { | |||||||
|             <NoteTypeWidget note={note} /> |             <NoteTypeWidget note={note} /> | ||||||
|             <ProtectedNoteSwitch note={note} /> |             <ProtectedNoteSwitch note={note} /> | ||||||
|             <EditabilitySelect note={note} /> |             <EditabilitySelect note={note} /> | ||||||
|  |             <BookmarkSwitch note={note} /> | ||||||
|         </div> |         </div> | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| @@ -114,10 +116,10 @@ function ProtectedNoteSwitch({ note }: { note?: FNote | null }) { | |||||||
|     return ( |     return ( | ||||||
|         <div className="protected-note-switch-container"> |         <div className="protected-note-switch-container"> | ||||||
|             <FormToggle |             <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")} |                 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")} |                 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> |         </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) { | function findTypeTitle(type?: NoteType, mime?: string | null) { | ||||||
|     if (type === "code") { |     if (type === "code") { | ||||||
|         const mimeTypes = mime_types.getMimeTypes(); |         const mimeTypes = mime_types.getMimeTypes(); | ||||||
|   | |||||||
| @@ -10,8 +10,6 @@ import type FNote from "../../entities/fnote.js"; | |||||||
| import NoteLanguageWidget from "../note_language.js"; | import NoteLanguageWidget from "../note_language.js"; | ||||||
|  |  | ||||||
| const TPL = /*html*/` | const TPL = /*html*/` | ||||||
|     <div class="bookmark-switch-container"></div> |  | ||||||
|  |  | ||||||
|     <div class="shared-switch-container"></div> |     <div class="shared-switch-container"></div> | ||||||
|  |  | ||||||
|     <div class="template-switch-container"></div> |     <div class="template-switch-container"></div> | ||||||
| @@ -23,8 +21,6 @@ const TPL = /*html*/` | |||||||
|  |  | ||||||
| export default class BasicPropertiesWidget extends NoteContextAwareWidget { | export default class BasicPropertiesWidget extends NoteContextAwareWidget { | ||||||
|  |  | ||||||
|     private editabilitySelectWidget: EditabilitySelectWidget; |  | ||||||
|     private bookmarkSwitchWidget: BookmarkSwitchWidget; |  | ||||||
|     private sharedSwitchWidget: SharedSwitchWidget; |     private sharedSwitchWidget: SharedSwitchWidget; | ||||||
|     private templateSwitchWidget: TemplateSwitchWidget; |     private templateSwitchWidget: TemplateSwitchWidget; | ||||||
|     private noteLanguageWidget: NoteLanguageWidget; |     private noteLanguageWidget: NoteLanguageWidget; | ||||||
| @@ -32,15 +28,11 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget { | |||||||
|     constructor() { |     constructor() { | ||||||
|         super(); |         super(); | ||||||
|  |  | ||||||
|         this.editabilitySelectWidget = new EditabilitySelectWidget().contentSized(); |  | ||||||
|         this.bookmarkSwitchWidget = new BookmarkSwitchWidget().contentSized(); |  | ||||||
|         this.sharedSwitchWidget = new SharedSwitchWidget().contentSized(); |         this.sharedSwitchWidget = new SharedSwitchWidget().contentSized(); | ||||||
|         this.templateSwitchWidget = new TemplateSwitchWidget().contentSized(); |         this.templateSwitchWidget = new TemplateSwitchWidget().contentSized(); | ||||||
|         this.noteLanguageWidget = new NoteLanguageWidget().contentSized(); |         this.noteLanguageWidget = new NoteLanguageWidget().contentSized(); | ||||||
|  |  | ||||||
|         this.child( |         this.child( | ||||||
|             this.editabilitySelectWidget, |  | ||||||
|             this.bookmarkSwitchWidget, |  | ||||||
|             this.sharedSwitchWidget, |             this.sharedSwitchWidget, | ||||||
|             this.templateSwitchWidget, |             this.templateSwitchWidget, | ||||||
|             this.noteLanguageWidget); |             this.noteLanguageWidget); | ||||||
|   | |||||||
| @@ -40,9 +40,6 @@ export default class SwitchWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     set canToggle(isEnabled) { |     set canToggle(isEnabled) { | ||||||
|         this.$switchButton.toggleClass("disabled", !isEnabled); |  | ||||||
|         this.$switchToggle.attr("disabled", !isEnabled ? "disabled" : null); |  | ||||||
|  |  | ||||||
|         if (isEnabled) { |         if (isEnabled) { | ||||||
|             this.isToggled = this.currentState; // Reapply the correct tooltip |             this.isToggled = this.currentState; // Reapply the correct tooltip | ||||||
|         } else { |         } else { | ||||||
|   | |||||||
| @@ -155,3 +155,10 @@ export interface OpenAiOrAnthropicModelResponse { | |||||||
|         type: string; |         type: string; | ||||||
|     }>; |     }>; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | export type ToggleInParentResponse = { | ||||||
|  |     success: true; | ||||||
|  | } | { | ||||||
|  |     success: false; | ||||||
|  |     message: string; | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user