mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	feat(react/ribbon): port note language
This commit is contained in:
		| @@ -38,11 +38,6 @@ const TPL = /*html*/`\ | |||||||
| </div> | </div> | ||||||
| `; | `; | ||||||
|  |  | ||||||
| const DEFAULT_LOCALE: Locale = { |  | ||||||
|     id: "", |  | ||||||
|     name: t("note_language.not_set") |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| export default class NoteLanguageWidget extends NoteContextAwareWidget { | export default class NoteLanguageWidget extends NoteContextAwareWidget { | ||||||
|  |  | ||||||
|     private dropdown!: Dropdown; |     private dropdown!: Dropdown; | ||||||
| @@ -59,7 +54,6 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { | |||||||
|     doRender() { |     doRender() { | ||||||
|         this.$widget = $(TPL); |         this.$widget = $(TPL); | ||||||
|         this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]); |         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.$noteLanguageDropdown = this.$widget.find(".note-language-dropdown") | ||||||
|         this.$noteLanguageDesc = this.$widget.find(".note-language-desc"); |         this.$noteLanguageDesc = this.$widget.find(".note-language-desc"); | ||||||
| @@ -72,36 +66,8 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (const locale of this.locales) { |  | ||||||
|             if (typeof locale === "object") { |  | ||||||
|                 const $title = $("<span>").text(locale.name); |  | ||||||
|  |  | ||||||
|                 const $link = $('<a class="dropdown-item">') |  | ||||||
|                     .attr("data-language", locale.id) |  | ||||||
|                     .append('<span class="check">✓</span> ') |  | ||||||
|                     .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('<div class="dropdown-divider"></div>'); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         const $configureLink = $('<a class="dropdown-item">') |         const $configureLink = $('<a class="dropdown-item">') | ||||||
|             .append(`<span>${t("note_language.configure-languages")}</span>`) |             .on("click", () => )); | ||||||
|             .on("click", () => appContext.tabManager.openContextWithNote("_optionsLocalization", { activate: true })); |  | ||||||
|         this.$noteLanguageDropdown.append($configureLink); |         this.$noteLanguageDropdown.append($configureLink); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -114,7 +80,6 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async refreshWithNote(note: FNote) { |     async refreshWithNote(note: FNote) { | ||||||
|         const currentLanguageId = note.getLabelValue("language") ?? ""; |  | ||||||
|         const language = getLocaleById(currentLanguageId) ?? DEFAULT_LOCALE; |         const language = getLocaleById(currentLanguageId) ?? DEFAULT_LOCALE; | ||||||
|         this.currentLanguageId = currentLanguageId; |         this.currentLanguageId = currentLanguageId; | ||||||
|         this.$noteLanguageDesc.text(language.name); |         this.$noteLanguageDesc.text(language.name); | ||||||
| @@ -132,35 +97,7 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     static #buildLocales() { |     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; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -82,9 +82,10 @@ interface FormListItemOpts { | |||||||
|     onClick?: () => void; |     onClick?: () => void; | ||||||
|     description?: string; |     description?: string; | ||||||
|     className?: 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) { |     if (checked) { | ||||||
|         icon = "bx bx-check"; |         icon = "bx bx-check"; | ||||||
|     } |     } | ||||||
| @@ -95,6 +96,7 @@ export function FormListItem({ children, icon, value, title, active, badges, dis | |||||||
|             data-value={value} title={title} |             data-value={value} title={title} | ||||||
|             tabIndex={0} |             tabIndex={0} | ||||||
|             onClick={onClick} |             onClick={onClick} | ||||||
|  |             dir={rtl ? "rtl" : undefined} | ||||||
|         > |         > | ||||||
|             <Icon icon={icon} />  |             <Icon icon={icon} />  | ||||||
|             <div> |             <div> | ||||||
| @@ -120,6 +122,6 @@ export function FormListHeader({ text }: FormListHeaderOpts) { | |||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
| export function FormDivider() { | export function FormDropdownDivider() { | ||||||
|     return <div className="dropdown-divider" />; |     return <div className="dropdown-divider" />; | ||||||
| } | } | ||||||
| @@ -1,11 +1,11 @@ | |||||||
| import { useCallback, useEffect, useMemo, useState } 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 { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList"; | ||||||
| import { t } from "../../services/i18n"; | import { getAvailableLocales, t } from "../../services/i18n"; | ||||||
| import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption } from "../react/hooks"; | import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption, useTriliumOptionJson } from "../react/hooks"; | ||||||
| import mime_types from "../../services/mime_types"; | 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 server from "../../services/server"; | ||||||
| import dialog from "../../services/dialog"; | import dialog from "../../services/dialog"; | ||||||
| import FormToggle from "../react/FormToggle"; | import FormToggle from "../react/FormToggle"; | ||||||
| @@ -15,7 +15,7 @@ import FormDropdownList from "../react/FormDropdownList"; | |||||||
| import toast from "../../services/toast"; | import toast from "../../services/toast"; | ||||||
| import branches from "../../services/branches"; | import branches from "../../services/branches"; | ||||||
| import sync from "../../services/sync"; | import sync from "../../services/sync"; | ||||||
| import TemplateSwitchWidget from "../template_switch"; | import appContext from "../../components/app_context"; | ||||||
|  |  | ||||||
| export default function BasicPropertiesTab() { | export default function BasicPropertiesTab() { | ||||||
|     const { note } = useNoteContext(); |     const { note } = useNoteContext(); | ||||||
| @@ -28,6 +28,7 @@ export default function BasicPropertiesTab() { | |||||||
|             <BookmarkSwitch note={note} /> |             <BookmarkSwitch note={note} /> | ||||||
|             <SharedSwitch note={note} /> |             <SharedSwitch note={note} /> | ||||||
|             <TemplateSwitch note={note} /> |             <TemplateSwitch note={note} /> | ||||||
|  |             <NoteLanguageSwitch note={note} /> | ||||||
|         </div> |         </div> | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| @@ -93,7 +94,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) { | |||||||
|                     } else { |                     } else { | ||||||
|                         return ( |                         return ( | ||||||
|                             <> |                             <> | ||||||
|                                 <FormDivider /> |                                 <FormDropdownDivider /> | ||||||
|                                 <FormListItem |                                 <FormListItem | ||||||
|                                     checked={checked} |                                     checked={checked} | ||||||
|                                     disabled                                     |                                     disabled                                     | ||||||
| @@ -265,6 +266,70 @@ function SharedSwitch({ note }: { note?: FNote | null }) { | |||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function NoteLanguageSwitch({ note }: { note?: FNote | null }) { | ||||||
|  |     const [ languages ] = useTriliumOption("languages"); | ||||||
|  |     const DEFAULT_LOCALE = { | ||||||
|  |         id: "", | ||||||
|  |         name: t("note_language.not_set") | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     const [ currentNoteLanguage, setCurrentNoteLanguage ] = useNoteLabel(note, "language") ?? ""; | ||||||
|  |  | ||||||
|  |     const locales = useMemo(() => { | ||||||
|  |         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 ( | ||||||
|  |         <div className="note-language-container"> | ||||||
|  |             <Dropdown> | ||||||
|  |                 {locales.map(locale => { | ||||||
|  |                     if (typeof locale === "object") { | ||||||
|  |                         return <FormListItem | ||||||
|  |                             rtl={locale.rtl} | ||||||
|  |                             selected={locale.id === currentNoteLanguage} | ||||||
|  |                             onClick={() => setCurrentNoteLanguage(locale.id)} | ||||||
|  |                         >{locale.name}</FormListItem> | ||||||
|  |                     } else { | ||||||
|  |                         return <FormDropdownDivider /> | ||||||
|  |                     } | ||||||
|  |                 })} | ||||||
|  |  | ||||||
|  |                 <FormListItem | ||||||
|  |                     onClick={() => appContext.tabManager.openContextWithNote("_optionsLocalization", { activate: true })} | ||||||
|  |                 >{t("note_language.configure-languages")}</FormListItem>            | ||||||
|  |             </Dropdown> | ||||||
|  |         </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(); | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget { | |||||||
|         this.$widget.find(".bookmark-switch-container").append(this.bookmarkSwitchWidget.render()); |         this.$widget.find(".bookmark-switch-container").append(this.bookmarkSwitchWidget.render()); | ||||||
|         this.$widget.find(".shared-switch-container").append(this.sharedSwitchWidget.render()); |         this.$widget.find(".shared-switch-container").append(this.sharedSwitchWidget.render()); | ||||||
|         this.$widget.find(".template-switch-container").append(this.templateSwitchWidget.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) { |     async refreshWithNote(note: FNote) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user