mirror of
https://github.com/zadam/trilium.git
synced 2025-10-20 23:29:02 +02:00
feat(react): port bookmark switch
This commit is contained in:
parent
da4810672d
commit
f9b6fd6ac5
@ -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
|
||||||
@ -30,6 +31,7 @@ export default function FormToggle({ currentValue, helpPage, switchOnName, switc
|
|||||||
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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user