2025-12-12 00:13:25 +02:00
|
|
|
import "./StatusBar.css";
|
|
|
|
|
|
2025-12-12 00:34:47 +02:00
|
|
|
import FNote from "../../entities/fnote";
|
|
|
|
|
import { t } from "../../services/i18n";
|
|
|
|
|
import { openInAppHelpFromUrl } from "../../services/utils";
|
2025-12-12 18:29:40 +02:00
|
|
|
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
2025-12-12 00:34:47 +02:00
|
|
|
import { useNoteContext } from "../react/hooks";
|
2025-12-12 18:29:40 +02:00
|
|
|
import { ContentLanguagesModal, NoteLanguageSelector, useLanguageSwitcher } from "../ribbon/BasicPropertiesTab";
|
2025-12-12 00:34:47 +02:00
|
|
|
import Breadcrumb from "./Breadcrumb";
|
2025-12-12 18:29:40 +02:00
|
|
|
import { useState } from "preact/hooks";
|
|
|
|
|
import { createPortal } from "preact/compat";
|
|
|
|
|
import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector";
|
2025-12-12 18:46:34 +02:00
|
|
|
import Dropdown, { DropdownProps } from "../react/Dropdown";
|
2025-12-12 18:29:40 +02:00
|
|
|
import { Locale } from "@triliumnext/commons";
|
2025-12-12 18:46:34 +02:00
|
|
|
import clsx from "clsx";
|
|
|
|
|
import Icon from "../react/Icon";
|
2025-12-12 00:34:47 +02:00
|
|
|
|
|
|
|
|
interface StatusBarContext {
|
|
|
|
|
note: FNote;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 00:13:25 +02:00
|
|
|
export default function StatusBar() {
|
2025-12-12 00:34:47 +02:00
|
|
|
const { note } = useNoteContext();
|
|
|
|
|
const context = note && { note } satisfies StatusBarContext;
|
|
|
|
|
|
2025-12-12 00:13:25 +02:00
|
|
|
return (
|
|
|
|
|
<div className="status-bar">
|
2025-12-12 00:34:47 +02:00
|
|
|
{context && <>
|
|
|
|
|
<div className="breadcrumb-row">
|
|
|
|
|
<Breadcrumb />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="actions-row">
|
|
|
|
|
<LanguageSwitcher {...context} />
|
|
|
|
|
</div>
|
|
|
|
|
</>}
|
2025-12-12 00:13:25 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-12-12 00:34:47 +02:00
|
|
|
|
2025-12-12 18:46:34 +02:00
|
|
|
function StatusBarDropdown({ children, icon, text, buttonClassName, ...dropdownProps }: Omit<DropdownProps, "hideToggleArrow"> & {
|
|
|
|
|
icon?: string;
|
|
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<Dropdown
|
|
|
|
|
buttonClassName={clsx("status-bar-dropdown-button", buttonClassName)}
|
|
|
|
|
text={<>
|
|
|
|
|
{icon && (<><Icon icon={icon} /> </>)}
|
|
|
|
|
{text}
|
|
|
|
|
</>}
|
|
|
|
|
{...dropdownProps}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</Dropdown>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-12 00:34:47 +02:00
|
|
|
function LanguageSwitcher({ note }: StatusBarContext) {
|
2025-12-12 18:29:40 +02:00
|
|
|
const [ modalShown, setModalShown ] = useState(false);
|
|
|
|
|
const { locales, DEFAULT_LOCALE, currentNoteLanguage, setCurrentNoteLanguage } = useLanguageSwitcher(note);
|
|
|
|
|
const { activeLocale, processedLocales } = useProcessedLocales(locales, DEFAULT_LOCALE, currentNoteLanguage ?? DEFAULT_LOCALE.id);
|
|
|
|
|
|
2025-12-12 00:34:47 +02:00
|
|
|
return (
|
2025-12-12 18:29:40 +02:00
|
|
|
<>
|
2025-12-12 18:53:54 +02:00
|
|
|
<StatusBarDropdown icon="bx bx-globe" text={<span dir={activeLocale?.rtl ? "rtl" : "ltr"}>{getLocaleName(activeLocale)}</span>}>
|
2025-12-12 18:29:40 +02:00
|
|
|
{processedLocales.map(locale => {
|
|
|
|
|
if (typeof locale === "object") {
|
|
|
|
|
return <FormListItem
|
|
|
|
|
rtl={locale.rtl}
|
|
|
|
|
checked={locale.id === currentNoteLanguage}
|
|
|
|
|
onClick={() => setCurrentNoteLanguage(locale.id)}
|
|
|
|
|
>{locale.name}</FormListItem>
|
|
|
|
|
} else {
|
|
|
|
|
return <FormDropdownDivider />
|
|
|
|
|
}
|
|
|
|
|
})}
|
|
|
|
|
<FormDropdownDivider />
|
2025-12-12 00:34:47 +02:00
|
|
|
<FormListItem
|
|
|
|
|
onClick={() => openInAppHelpFromUrl("veGu4faJErEM")}
|
|
|
|
|
icon="bx bx-help-circle"
|
|
|
|
|
>{t("note_language.help-on-languages")}</FormListItem>
|
2025-12-12 18:29:40 +02:00
|
|
|
<FormListItem
|
|
|
|
|
onClick={() => setModalShown(true)}
|
|
|
|
|
icon="bx bx-cog"
|
|
|
|
|
>{t("note_language.configure-languages")}</FormListItem>
|
2025-12-12 18:46:34 +02:00
|
|
|
</StatusBarDropdown>
|
2025-12-12 18:29:40 +02:00
|
|
|
{createPortal(
|
|
|
|
|
<ContentLanguagesModal modalShown={modalShown} setModalShown={setModalShown} />,
|
|
|
|
|
document.body
|
2025-12-12 00:34:47 +02:00
|
|
|
)}
|
2025-12-12 18:29:40 +02:00
|
|
|
</>
|
2025-12-12 00:34:47 +02:00
|
|
|
);
|
|
|
|
|
}
|
2025-12-12 18:29:40 +02:00
|
|
|
|
|
|
|
|
export function getLocaleName(locale: Locale | null | undefined) {
|
|
|
|
|
if (!locale) return "";
|
|
|
|
|
if (!locale.id) return "-";
|
2025-12-12 18:53:54 +02:00
|
|
|
if (locale.name.length <= 4 || locale.rtl) return locale.name; // Some locales like Japanese and Chinese look better than their ID.
|
|
|
|
|
return locale.id
|
|
|
|
|
.replace("_", "-")
|
|
|
|
|
.toLocaleUpperCase();
|
2025-12-12 18:29:40 +02:00
|
|
|
}
|