From 8e29b5eed65b6f60b3883c69a29f6875f3ec4b11 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 22 Aug 2025 12:34:21 +0300 Subject: [PATCH] feat(react/ribbon): port note language --- apps/client/src/widgets/note_language.ts | 65 +--------------- apps/client/src/widgets/react/FormList.tsx | 6 +- .../src/widgets/ribbon/BasicPropertiesTab.tsx | 77 +++++++++++++++++-- .../ribbon_widgets/basic_properties.ts | 2 +- 4 files changed, 77 insertions(+), 73 deletions(-) diff --git a/apps/client/src/widgets/note_language.ts b/apps/client/src/widgets/note_language.ts index 398951e20..b6be77230 100644 --- a/apps/client/src/widgets/note_language.ts +++ b/apps/client/src/widgets/note_language.ts @@ -38,11 +38,6 @@ const TPL = /*html*/`\ `; -const DEFAULT_LOCALE: Locale = { - id: "", - name: t("note_language.not_set") -}; - export default class NoteLanguageWidget extends NoteContextAwareWidget { private dropdown!: Dropdown; @@ -59,7 +54,6 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { doRender() { this.$widget = $(TPL); this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]); - this.$widget.on("show.bs.dropdown", () => this.renderDropdown()); this.$noteLanguageDropdown = this.$widget.find(".note-language-dropdown") this.$noteLanguageDesc = this.$widget.find(".note-language-desc"); @@ -72,36 +66,8 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { return; } - for (const locale of this.locales) { - if (typeof locale === "object") { - const $title = $("").text(locale.name); - - const $link = $('') - .attr("data-language", locale.id) - .append(' ') - .append($title) - .on("click", () => { - const languageId = $link.attr("data-language") ?? ""; - this.save(languageId); - }); - - if (locale.rtl) { - $link.attr("dir", "rtl"); - } - - if (locale.id === this.currentLanguageId) { - $link.addClass("selected"); - } - - this.$noteLanguageDropdown.append($link); - } else { - this.$noteLanguageDropdown.append(''); - } - } - const $configureLink = $('') - .append(`${t("note_language.configure-languages")}`) - .on("click", () => appContext.tabManager.openContextWithNote("_optionsLocalization", { activate: true })); + .on("click", () => )); this.$noteLanguageDropdown.append($configureLink); } @@ -114,7 +80,6 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { } async refreshWithNote(note: FNote) { - const currentLanguageId = note.getLabelValue("language") ?? ""; const language = getLocaleById(currentLanguageId) ?? DEFAULT_LOCALE; this.currentLanguageId = currentLanguageId; this.$noteLanguageDesc.text(language.name); @@ -132,35 +97,7 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { } static #buildLocales() { - const enabledLanguages = JSON.parse(options.get("languages") ?? "[]") as string[]; - const filteredLanguages = getAvailableLocales().filter((l) => typeof l !== "object" || enabledLanguages.includes(l.id)); - const leftToRightLanguages = filteredLanguages.filter((l) => !l.rtl); - const rightToLeftLanguages = filteredLanguages.filter((l) => l.rtl); - let locales: ("---" | Locale)[] = [ - DEFAULT_LOCALE - ]; - - if (leftToRightLanguages.length > 0) { - locales = [ - ...locales, - "---", - ...leftToRightLanguages - ]; - } - - if (rightToLeftLanguages.length > 0) { - locales = [ - ...locales, - "---", - ...rightToLeftLanguages - ]; - } - - // This will separate the list of languages from the "Configure languages" button. - // If there is at least one language. - locales.push("---"); - return locales; } } diff --git a/apps/client/src/widgets/react/FormList.tsx b/apps/client/src/widgets/react/FormList.tsx index 42aeb93d5..6d16e9d0f 100644 --- a/apps/client/src/widgets/react/FormList.tsx +++ b/apps/client/src/widgets/react/FormList.tsx @@ -82,9 +82,10 @@ interface FormListItemOpts { onClick?: () => void; description?: string; className?: string; + rtl?: boolean; } -export function FormListItem({ children, icon, value, title, active, badges, disabled, checked, onClick, description, selected }: FormListItemOpts) { +export function FormListItem({ children, icon, value, title, active, badges, disabled, checked, onClick, description, selected, rtl }: FormListItemOpts) { if (checked) { icon = "bx bx-check"; } @@ -95,6 +96,7 @@ export function FormListItem({ children, icon, value, title, active, badges, dis data-value={value} title={title} tabIndex={0} onClick={onClick} + dir={rtl ? "rtl" : undefined} >  
@@ -120,6 +122,6 @@ export function FormListHeader({ text }: FormListHeaderOpts) { ) } -export function FormDivider() { +export function FormDropdownDivider() { return
; } \ No newline at end of file diff --git a/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx b/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx index 8ed0526b7..ab5c35011 100644 --- a/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx +++ b/apps/client/src/widgets/ribbon/BasicPropertiesTab.tsx @@ -1,11 +1,11 @@ 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, useTriliumEventBeta, useTriliumOption } from "../react/hooks"; +import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList"; +import { getAvailableLocales, t } from "../../services/i18n"; +import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption, useTriliumOptionJson } from "../react/hooks"; import mime_types from "../../services/mime_types"; -import { NoteType, ToggleInParentResponse } from "@triliumnext/commons"; +import { Locale, NoteType, ToggleInParentResponse } from "@triliumnext/commons"; import server from "../../services/server"; import dialog from "../../services/dialog"; import FormToggle from "../react/FormToggle"; @@ -15,7 +15,7 @@ import FormDropdownList from "../react/FormDropdownList"; import toast from "../../services/toast"; import branches from "../../services/branches"; import sync from "../../services/sync"; -import TemplateSwitchWidget from "../template_switch"; +import appContext from "../../components/app_context"; export default function BasicPropertiesTab() { const { note } = useNoteContext(); @@ -28,6 +28,7 @@ export default function BasicPropertiesTab() { +
); } @@ -93,7 +94,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) { } else { return ( <> - + { + const enabledLanguages = JSON.parse(languages ?? "[]") as string[]; + const filteredLanguages = getAvailableLocales().filter((l) => typeof l !== "object" || enabledLanguages.includes(l.id)); + const leftToRightLanguages = filteredLanguages.filter((l) => !l.rtl); + const rightToLeftLanguages = filteredLanguages.filter((l) => l.rtl); + + let locales: ("---" | Locale)[] = [ + DEFAULT_LOCALE + ]; + + if (leftToRightLanguages.length > 0) { + locales = [ + ...locales, + "---", + ...leftToRightLanguages + ]; + } + + if (rightToLeftLanguages.length > 0) { + locales = [ + ...locales, + "---", + ...rightToLeftLanguages + ]; + } + + // This will separate the list of languages from the "Configure languages" button. + // If there is at least one language. + locales.push("---"); + return locales; + }, [ languages ]); + + return ( +
+ + {locales.map(locale => { + if (typeof locale === "object") { + return setCurrentNoteLanguage(locale.id)} + >{locale.name} + } else { + return + } + })} + + appContext.tabManager.openContextWithNote("_optionsLocalization", { activate: true })} + >{t("note_language.configure-languages")} + +
+ ) +} + function findTypeTitle(type?: NoteType, mime?: string | null) { if (type === "code") { const mimeTypes = mime_types.getMimeTypes(); diff --git a/apps/client/src/widgets/ribbon_widgets/basic_properties.ts b/apps/client/src/widgets/ribbon_widgets/basic_properties.ts index a60b999e4..5f0fc9ffa 100644 --- a/apps/client/src/widgets/ribbon_widgets/basic_properties.ts +++ b/apps/client/src/widgets/ribbon_widgets/basic_properties.ts @@ -57,7 +57,7 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget { this.$widget.find(".bookmark-switch-container").append(this.bookmarkSwitchWidget.render()); this.$widget.find(".shared-switch-container").append(this.sharedSwitchWidget.render()); this.$widget.find(".template-switch-container").append(this.templateSwitchWidget.render()); - this.$widget.find(".note-language-container").append(this.noteLanguageWidget.render()); + this.$widget.find(".").append(this.noteLanguageWidget.render()); } async refreshWithNote(note: FNote) {