feat(mobile/note_actions): integrate code language switcher

This commit is contained in:
Elian Doran 2026-02-03 18:58:04 +02:00
parent 52b41b1bb0
commit 0d8453f6a7
No known key found for this signature in database
4 changed files with 61 additions and 23 deletions

View File

@ -409,6 +409,7 @@ body.desktop .tabulator-popup-container,
.dropdown-menu.static {
box-shadow: unset;
backdrop-filter: unset !important;
}
.dropend .dropdown-toggle::after {

View File

@ -0,0 +1,3 @@
.code-note-switcher-modal .dropdown-menu {
background: none !important;
}

View File

@ -1,14 +1,18 @@
import "./mobile_detail_menu.css";
import { createPortal, useState } from "preact/compat";
import FNote, { NotePathRecord } from "../../entities/fnote";
import { t } from "../../services/i18n";
import note_create from "../../services/note_create";
import server from "../../services/server";
import { BacklinksList, useBacklinkCount } from "../FloatingButtonsDefinitions";
import { NoteInfoContent } from "../layout/StatusBar";
import ActionButton from "../react/ActionButton";
import { FormDropdownDivider, FormListItem } from "../react/FormList";
import { useNoteContext } from "../react/hooks";
import { useNoteContext, useNoteProperty } from "../react/hooks";
import Modal from "../react/Modal";
import { NoteTypeCodeNoteList, useMimeTypes } from "../ribbon/BasicPropertiesTab";
import { NoteContextMenu } from "../ribbon/NoteActions";
import NoteActionsCustom from "../ribbon/NoteActionsCustom";
import { NotePathsWidget, useSortedNotePaths } from "../ribbon/NotePathsTab";
@ -22,6 +26,7 @@ export default function MobileDetailMenu() {
const [ notePathsModalShown, setNotePathsModalShown ] = useState(false);
const [ noteInfoModalShown, setNoteInfoModalShown ] = useState(false);
const [ similarNotesModalShown, setSimilarNotesModalShown ] = useState(false);
const [ codeNoteSwitcherModalShown, setCodeNoteSwitcherModalShown ] = useState(false);
const sortedNotePaths = useSortedNotePaths(note, hoistedNoteId);
const backlinksCount = useBacklinkCount(note, viewScope?.viewMode === "default");
@ -76,7 +81,8 @@ export default function MobileDetailMenu() {
>{t("close_pane_button.close_this_pane")}</FormListItem>
</>}
<FormDropdownDivider />
<FormListItem icon="bx bx-info-circle" onClick={() => setNoteInfoModalShown(true)} >{t("note_info_widget.title")}</FormListItem>
{note.type === "code" && <FormListItem icon={"bx bx-code"} onClick={() => setCodeNoteSwitcherModalShown(true)}>{t("status_bar.code_note_switcher")}</FormListItem>}
<FormListItem icon="bx bx-info-circle" onClick={() => setNoteInfoModalShown(true)}>{t("note_info_widget.title")}</FormListItem>
<FormListItem icon="bx bx-bar-chart" onClick={() => setSimilarNotesModalShown(true)}>{t("similar_notes.title")}</FormListItem>
<FormDropdownDivider />
</>}
@ -95,6 +101,7 @@ export default function MobileDetailMenu() {
<NotePathsModal note={note} modalShown={notePathsModalShown} notePath={noteContext?.notePath} sortedNotePaths={sortedNotePaths} setModalShown={setNotePathsModalShown} />
<NoteInfoModal note={note} modalShown={noteInfoModalShown} setModalShown={setNoteInfoModalShown} />
<SimilarNotesModal note={note} modalShown={similarNotesModalShown} setModalShown={setSimilarNotesModalShown} />
<CodeNoteSwitcherModal note={note} modalShown={codeNoteSwitcherModalShown} setModalShown={setCodeNoteSwitcherModalShown} />
</>
), document.body)}
</div>
@ -168,3 +175,30 @@ function SimilarNotesModal({ note, modalShown, setModalShown }: { note: FNote |
</Modal>
);
}
function CodeNoteSwitcherModal({ note, modalShown, setModalShown }: { note: FNote | null | undefined } & WithModal) {
const currentNoteMime = useNoteProperty(note, "mime");
const mimeTypes = useMimeTypes();
return (
<Modal
className="code-note-switcher-modal"
size="md"
title={t("status_bar.code_note_switcher")}
show={modalShown}
onHidden={() => setModalShown(false)}
>
<div className="dropdown-menu static show">
{note && <NoteTypeCodeNoteList
currentMimeType={currentNoteMime}
mimeTypes={mimeTypes}
changeNoteType={(type, mime) => {
server.put(`notes/${note.noteId}/type`, { type, mime });
setModalShown(false);
}}
// setModalShown={() => setModalShown(true)}
/>}
</div>
</Modal>
);
}

View File

@ -1,5 +1,4 @@
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";
@ -117,19 +116,18 @@ export function NoteTypeDropdownContent({ currentNoteType, currentNoteMime, note
onClick={() => changeNoteType(type, mime)}
>{title}</FormListItem>
);
} else {
return (
<>
<FormDropdownDivider />
<FormListItem
checked={checked}
disabled
>
<strong>{title}</strong>
</FormListItem>
</>
);
}
return (
<>
<FormDropdownDivider />
<FormListItem
checked={checked}
disabled
>
<strong>{title}</strong>
</FormListItem>
</>
);
})}
{!noCodeNotes && <NoteTypeCodeNoteList mimeTypes={mimeTypes} changeNoteType={changeNoteType} setModalShown={setModalShown} />}
@ -141,7 +139,7 @@ export function NoteTypeCodeNoteList({ currentMimeType, mimeTypes, changeNoteTyp
currentMimeType?: string;
mimeTypes: MimeType[];
changeNoteType(type: NoteType, mime: string): void;
setModalShown(shown: boolean): void;
setModalShown?(shown: boolean): void;
}) {
return (
<>
@ -155,8 +153,10 @@ export function NoteTypeCodeNoteList({ currentMimeType, mimeTypes, changeNoteTyp
</FormListItem>
))}
<FormDropdownDivider />
<FormListItem icon="bx bx-cog" onClick={() => setModalShown(true)}>{t("basic_properties.configure_code_notes")}</FormListItem>
{setModalShown && <>
<FormDropdownDivider />
<FormListItem icon="bx bx-cog" onClick={() => setModalShown(true)}>{t("basic_properties.configure_code_notes")}</FormListItem>
</>}
</>
);
}
@ -195,7 +195,7 @@ function ProtectedNoteSwitch({ note }: { note?: FNote | null }) {
onChange={(shouldProtect) => note && protected_session.protectNote(note.noteId, shouldProtect, false)}
/>
</div>
)
);
}
function EditabilitySelect({ note }: { note?: FNote | null }) {
@ -417,9 +417,9 @@ function findTypeTitle(type?: NoteType, mime?: string | null) {
const found = mimeTypes.find((mt) => mt.mime === mime);
return found ? found.title : mime;
} else {
const noteType = NOTE_TYPES.find((nt) => nt.type === type);
return noteType ? noteType.title : type;
}
const noteType = NOTE_TYPES.find((nt) => nt.type === type);
return noteType ? noteType.title : type;
}