mirror of
https://github.com/zadam/trilium.git
synced 2025-12-13 03:39:54 +01:00
feat(status_bar): code mime switcher
This commit is contained in:
@@ -2163,6 +2163,7 @@
|
||||
"attributes_one": "{{count}} attribute",
|
||||
"attributes_other": "{{count}} attributes",
|
||||
"attributes_title": "Click to open a dedicated pane to edit this note's owned attributes, as well as to see the list of inherited attributes.",
|
||||
"note_paths_title": "Click to see the paths where this note is placed into the tree."
|
||||
"note_paths_title": "Click to see the paths where this note is placed into the tree.",
|
||||
"code_note_switcher": "Change language mode"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ import { formatDateTime } from "../../utils/formatters";
|
||||
import { BacklinksList, useBacklinkCount } from "../FloatingButtonsDefinitions";
|
||||
import Dropdown, { DropdownProps } from "../react/Dropdown";
|
||||
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
||||
import { useActiveNoteContext, useLegacyImperativeHandlers, useStaticTooltip, useTriliumEvent, useTriliumEvents } from "../react/hooks";
|
||||
import { useActiveNoteContext, useLegacyImperativeHandlers, useNoteProperty, useStaticTooltip, useTriliumEvent, useTriliumEvents } from "../react/hooks";
|
||||
import Icon from "../react/Icon";
|
||||
import { ParentComponent } from "../react/react_utils";
|
||||
import { ContentLanguagesModal, useLanguageSwitcher } from "../ribbon/BasicPropertiesTab";
|
||||
import { ContentLanguagesModal, NoteTypeCodeNoteList, useLanguageSwitcher, useMimeTypes } from "../ribbon/BasicPropertiesTab";
|
||||
import AttributeEditor, { AttributeEditorImperativeHandlers } from "../ribbon/components/AttributeEditor";
|
||||
import InheritedAttributesTab from "../ribbon/InheritedAttributesTab";
|
||||
import { NoteSizeWidget, useNoteMetadata } from "../ribbon/NoteInfoTab";
|
||||
@@ -28,6 +28,7 @@ import { NotePathsWidget, useSortedNotePaths } from "../ribbon/NotePathsTab";
|
||||
import { useAttachments } from "../type_widgets/Attachment";
|
||||
import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector";
|
||||
import Breadcrumb from "./Breadcrumb";
|
||||
import server from "../../services/server";
|
||||
|
||||
interface StatusBarContext {
|
||||
note: FNote;
|
||||
@@ -53,6 +54,7 @@ export default function StatusBar() {
|
||||
<Breadcrumb {...context} />
|
||||
|
||||
<div className="actions-row">
|
||||
<CodeNoteSwitcher {...context} />
|
||||
<LanguageSwitcher {...context} />
|
||||
{!isHiddenNote && <NotePaths {...context} />}
|
||||
<AttributesButton {...attributesContext} />
|
||||
@@ -75,15 +77,19 @@ function StatusBarDropdown({ children, icon, text, buttonClassName, titleOptions
|
||||
buttonClassName={clsx("status-bar-dropdown-button", buttonClassName)}
|
||||
titlePosition="top"
|
||||
titleOptions={{
|
||||
...titleOptions,
|
||||
popperConfig: {
|
||||
...titleOptions?.popperConfig,
|
||||
strategy: "fixed"
|
||||
}
|
||||
},
|
||||
...titleOptions
|
||||
}}
|
||||
dropdownOptions={{
|
||||
...dropdownOptions,
|
||||
autoClose: "outside"
|
||||
autoClose: "outside",
|
||||
popperConfig: {
|
||||
strategy: "fixed",
|
||||
placement: "top"
|
||||
},
|
||||
...dropdownOptions
|
||||
}}
|
||||
text={<>
|
||||
{icon && (<><Icon icon={icon} /> </>)}
|
||||
@@ -340,3 +346,28 @@ function NotePaths({ note, hoistedNoteId, notePath }: StatusBarContext) {
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Code note switcher
|
||||
function CodeNoteSwitcher({ note }: StatusBarContext) {
|
||||
const currentNoteMime = useNoteProperty(note, "mime");
|
||||
const mimeTypes = useMimeTypes();
|
||||
const correspondingMimeType = useMemo(() => (
|
||||
mimeTypes.find(m => m.mime === currentNoteMime)
|
||||
), [ mimeTypes, currentNoteMime ]);
|
||||
|
||||
return (
|
||||
<StatusBarDropdown
|
||||
icon="bx bx-code-curly"
|
||||
text={correspondingMimeType?.title}
|
||||
title={t("status_bar.code_note_switcher")}
|
||||
dropdownOptions={{ autoClose: true }}
|
||||
>
|
||||
<NoteTypeCodeNoteList
|
||||
mimeTypes={mimeTypes}
|
||||
changeNoteType={(type, mime) => server.put(`notes/${note.noteId}/type`, { type, mime })}
|
||||
setModalShown={() => {}}
|
||||
/>
|
||||
</StatusBarDropdown>
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NoteType, ToggleInParentResponse } from "@triliumnext/commons";
|
||||
import { MimeType, NoteType, ToggleInParentResponse } from "@triliumnext/commons";
|
||||
import { ComponentChildren } from "preact";
|
||||
import { createPortal } from "preact/compat";
|
||||
import { Dispatch, StateUpdater, useCallback, useEffect, useMemo, useState } from "preact/hooks";
|
||||
@@ -66,12 +66,8 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
||||
}
|
||||
|
||||
export function NoteTypeDropdownContent({ currentNoteType, currentNoteMime, note, setModalShown }: { currentNoteType?: NoteType, currentNoteMime?: string | null, note?: FNote | null, setModalShown: Dispatch<StateUpdater<boolean>> }) {
|
||||
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
|
||||
const mimeTypes = useMimeTypes();
|
||||
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
|
||||
const mimeTypes = useMemo(() => {
|
||||
mime_types.loadMimeTypes();
|
||||
return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled);
|
||||
}, [ codeNotesMimeTypes ]);
|
||||
const changeNoteType = useCallback(async (type: NoteType, mime?: string) => {
|
||||
if (!note || (type === currentNoteType && mime === currentNoteMime)) {
|
||||
return;
|
||||
@@ -130,8 +126,23 @@ export function NoteTypeDropdownContent({ currentNoteType, currentNoteMime, note
|
||||
}
|
||||
})}
|
||||
|
||||
<NoteTypeCodeNoteList mimeTypes={mimeTypes} changeNoteType={changeNoteType} setModalShown={setModalShown} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function NoteTypeCodeNoteList({ mimeTypes, changeNoteType, setModalShown }: {
|
||||
mimeTypes: MimeType[];
|
||||
changeNoteType(type: NoteType, mime: string): void;
|
||||
setModalShown(shown: boolean): void;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{mimeTypes.map(({ title, mime }) => (
|
||||
<FormListItem onClick={() => changeNoteType("code", mime)}>
|
||||
<FormListItem
|
||||
key={mime}
|
||||
onClick={() => changeNoteType("code", mime)}
|
||||
>
|
||||
{title}
|
||||
</FormListItem>
|
||||
))}
|
||||
@@ -142,6 +153,15 @@ export function NoteTypeDropdownContent({ currentNoteType, currentNoteMime, note
|
||||
);
|
||||
}
|
||||
|
||||
export function useMimeTypes() {
|
||||
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
|
||||
const mimeTypes = useMemo(() => {
|
||||
mime_types.loadMimeTypes();
|
||||
return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled);
|
||||
}, [ codeNotesMimeTypes ]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
function NoteTypeOptionsModal({ modalShown, setModalShown }: { modalShown: boolean, setModalShown: (shown: boolean) => void }) {
|
||||
return (
|
||||
<Modal
|
||||
|
||||
Reference in New Issue
Block a user