feat(react/ribbon): port note language

This commit is contained in:
Elian Doran 2025-08-22 12:34:21 +03:00
parent c91748da15
commit 8e29b5eed6
No known key found for this signature in database
4 changed files with 77 additions and 73 deletions

View File

@ -38,11 +38,6 @@ const TPL = /*html*/`\
</div>
`;
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 = $("<span>").text(locale.name);
const $link = $('<a class="dropdown-item">')
.attr("data-language", locale.id)
.append('<span class="check">&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">')
.append(`<span>${t("note_language.configure-languages")}</span>`)
.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;
}
}

View File

@ -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}
>
<Icon icon={icon} />&nbsp;
<div>
@ -120,6 +122,6 @@ export function FormListHeader({ text }: FormListHeaderOpts) {
)
}
export function FormDivider() {
export function FormDropdownDivider() {
return <div className="dropdown-divider" />;
}

View File

@ -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() {
<BookmarkSwitch note={note} />
<SharedSwitch note={note} />
<TemplateSwitch note={note} />
<NoteLanguageSwitch note={note} />
</div>
);
}
@ -93,7 +94,7 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
} else {
return (
<>
<FormDivider />
<FormDropdownDivider />
<FormListItem
checked={checked}
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) {
if (type === "code") {
const mimeTypes = mime_types.getMimeTypes();

View File

@ -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) {