mirror of
https://github.com/zadam/trilium.git
synced 2025-12-03 22:14:24 +01:00
Prototype/mobile split (#7906)
This commit is contained in:
commit
4b7d243406
@ -29,6 +29,7 @@ import type AppContext from "../components/app_context.js";
|
|||||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
import NoteDetail from "../widgets/NoteDetail.jsx";
|
||||||
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
||||||
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
|
||||||
|
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
|
||||||
|
|
||||||
const MOBILE_CSS = `
|
const MOBILE_CSS = `
|
||||||
<style>
|
<style>
|
||||||
@ -142,33 +143,35 @@ export default class MobileLayout {
|
|||||||
.id("detail-container")
|
.id("detail-container")
|
||||||
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9")
|
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9")
|
||||||
.child(
|
.child(
|
||||||
new NoteWrapperWidget()
|
new SplitNoteContainer(() =>
|
||||||
.child(
|
new NoteWrapperWidget()
|
||||||
new FlexContainer("row")
|
.child(
|
||||||
.contentSized()
|
new FlexContainer("row")
|
||||||
.css("font-size", "larger")
|
.contentSized()
|
||||||
.css("align-items", "center")
|
.css("font-size", "larger")
|
||||||
.child(<ToggleSidebarButton />)
|
.css("align-items", "center")
|
||||||
.child(<NoteTitleWidget />)
|
.child(<ToggleSidebarButton />)
|
||||||
.child(<MobileDetailMenu />)
|
.child(<NoteTitleWidget />)
|
||||||
)
|
.child(<MobileDetailMenu />)
|
||||||
.child(<FloatingButtons items={MOBILE_FLOATING_BUTTONS} />)
|
)
|
||||||
.child(<PromotedAttributes />)
|
.child(<FloatingButtons items={MOBILE_FLOATING_BUTTONS} />)
|
||||||
.child(
|
.child(<PromotedAttributes />)
|
||||||
new ScrollingContainer()
|
.child(
|
||||||
.filling()
|
new ScrollingContainer()
|
||||||
.contentSized()
|
.filling()
|
||||||
.child(new ContentHeader()
|
.contentSized()
|
||||||
.child(<ReadOnlyNoteInfoBar />)
|
.child(new ContentHeader()
|
||||||
.child(<SharedInfoWidget />)
|
.child(<ReadOnlyNoteInfoBar />)
|
||||||
)
|
.child(<SharedInfoWidget />)
|
||||||
.child(<NoteDetail />)
|
)
|
||||||
.child(<NoteList media="screen" />)
|
.child(<NoteDetail />)
|
||||||
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
|
.child(<NoteList media="screen" />)
|
||||||
.child(<SearchResult />)
|
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
|
||||||
.child(<FilePropertiesWrapper />)
|
.child(<SearchResult />)
|
||||||
)
|
.child(<FilePropertiesWrapper />)
|
||||||
.child(<MobileEditorToolbar />)
|
)
|
||||||
|
.child(<MobileEditorToolbar />)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,26 +2,32 @@ import { t } from "../services/i18n.js";
|
|||||||
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
|
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
|
||||||
import appContext, { type CommandNames } from "../components/app_context.js";
|
import appContext, { type CommandNames } from "../components/app_context.js";
|
||||||
import type { ViewScope } from "../services/link.js";
|
import type { ViewScope } from "../services/link.js";
|
||||||
|
import utils, { isMobile } from "../services/utils.js";
|
||||||
|
import { getClosestNtxId } from "../widgets/widget_utils.js";
|
||||||
|
import type { LeafletMouseEvent } from "leaflet";
|
||||||
|
|
||||||
function openContextMenu(notePath: string, e: ContextMenuEvent, viewScope: ViewScope = {}, hoistedNoteId: string | null = null) {
|
function openContextMenu(notePath: string, e: ContextMenuEvent, viewScope: ViewScope = {}, hoistedNoteId: string | null = null) {
|
||||||
contextMenu.show({
|
contextMenu.show({
|
||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: e.pageY,
|
y: e.pageY,
|
||||||
items: getItems(),
|
items: getItems(e),
|
||||||
selectMenuItemHandler: ({ command }) => handleLinkContextMenuItem(command, notePath, viewScope, hoistedNoteId)
|
selectMenuItemHandler: ({ command }) => handleLinkContextMenuItem(command, e, notePath, viewScope, hoistedNoteId)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getItems(): MenuItem<CommandNames>[] {
|
function getItems(e: ContextMenuEvent | LeafletMouseEvent): MenuItem<CommandNames>[] {
|
||||||
|
const ntxId = getNtxId(e);
|
||||||
|
const isMobileSplitOpen = isMobile() && appContext.tabManager.getNoteContextById(ntxId).getMainContext().getSubContexts().length > 1;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ title: t("link_context_menu.open_note_in_new_tab"), command: "openNoteInNewTab", uiIcon: "bx bx-link-external" },
|
{ title: t("link_context_menu.open_note_in_new_tab"), command: "openNoteInNewTab", uiIcon: "bx bx-link-external" },
|
||||||
{ title: t("link_context_menu.open_note_in_new_split"), command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right" },
|
{ title: !isMobileSplitOpen ? t("link_context_menu.open_note_in_new_split") : t("link_context_menu.open_note_in_other_split"), command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right" },
|
||||||
{ title: t("link_context_menu.open_note_in_new_window"), command: "openNoteInNewWindow", uiIcon: "bx bx-window-open" },
|
{ title: t("link_context_menu.open_note_in_new_window"), command: "openNoteInNewWindow", uiIcon: "bx bx-window-open" },
|
||||||
{ title: t("link_context_menu.open_note_in_popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit" }
|
{ title: t("link_context_menu.open_note_in_popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit" }
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLinkContextMenuItem(command: string | undefined, notePath: string, viewScope = {}, hoistedNoteId: string | null = null) {
|
function handleLinkContextMenuItem(command: string | undefined, e: ContextMenuEvent | LeafletMouseEvent, notePath: string, viewScope = {}, hoistedNoteId: string | null = null) {
|
||||||
if (!hoistedNoteId) {
|
if (!hoistedNoteId) {
|
||||||
hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId ?? null;
|
hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId ?? null;
|
||||||
}
|
}
|
||||||
@ -29,15 +35,8 @@ function handleLinkContextMenuItem(command: string | undefined, notePath: string
|
|||||||
if (command === "openNoteInNewTab") {
|
if (command === "openNoteInNewTab") {
|
||||||
appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope });
|
appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope });
|
||||||
} else if (command === "openNoteInNewSplit") {
|
} else if (command === "openNoteInNewSplit") {
|
||||||
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();
|
const ntxId = getNtxId(e);
|
||||||
|
if (!ntxId) return;
|
||||||
if (!subContexts) {
|
|
||||||
logError("subContexts is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { ntxId } = subContexts[subContexts.length - 1];
|
|
||||||
|
|
||||||
appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope });
|
appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope });
|
||||||
} else if (command === "openNoteInNewWindow") {
|
} else if (command === "openNoteInNewWindow") {
|
||||||
appContext.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
|
appContext.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
|
||||||
@ -46,6 +45,18 @@ function handleLinkContextMenuItem(command: string | undefined, notePath: string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNtxId(e: ContextMenuEvent | LeafletMouseEvent) {
|
||||||
|
if (utils.isDesktop()) {
|
||||||
|
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();
|
||||||
|
if (!subContexts) return null;
|
||||||
|
return subContexts[subContexts.length - 1].ntxId;
|
||||||
|
} else if (e.target instanceof HTMLElement) {
|
||||||
|
return getClosestNtxId(e.target);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getItems,
|
getItems,
|
||||||
handleLinkContextMenuItem,
|
handleLinkContextMenuItem,
|
||||||
|
|||||||
@ -2595,4 +2595,25 @@ iframe.print-iframe {
|
|||||||
.calendar-view a.fc-daygrid-event {
|
.calendar-view a.fc-daygrid-event {
|
||||||
/* Workaround: set font weight only if the theme-next is not active */
|
/* Workaround: set font weight only if the theme-next is not active */
|
||||||
font-weight: var(--root-background, 800);
|
font-weight: var(--root-background, 800);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991px) {
|
||||||
|
body.mobile {
|
||||||
|
.split-note-container-widget {
|
||||||
|
flex-direction: column !important;
|
||||||
|
|
||||||
|
.note-split {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-split.visible + .note-split.visible {
|
||||||
|
border-top: 1px solid var(--main-border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#root-widget.virtual-keyboard-opened .note-split:not(:focus-within) {
|
||||||
|
max-height: 80px;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1879,6 +1879,7 @@
|
|||||||
"link_context_menu": {
|
"link_context_menu": {
|
||||||
"open_note_in_new_tab": "Open note in a new tab",
|
"open_note_in_new_tab": "Open note in a new tab",
|
||||||
"open_note_in_new_split": "Open note in a new split",
|
"open_note_in_new_split": "Open note in a new split",
|
||||||
|
"open_note_in_other_split": "Open note in the other split",
|
||||||
"open_note_in_new_window": "Open note in a new window",
|
"open_note_in_new_window": "Open note in a new window",
|
||||||
"open_note_in_popup": "Quick edit"
|
"open_note_in_popup": "Quick edit"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
|
|||||||
x: event.pageX,
|
x: event.pageX,
|
||||||
y: event.pageY,
|
y: event.pageY,
|
||||||
items: [
|
items: [
|
||||||
...link_context_menu.getItems(),
|
...link_context_menu.getItems(event),
|
||||||
{ kind: "separator" },
|
{ kind: "separator" },
|
||||||
{
|
{
|
||||||
title: t("board_view.insert-above"),
|
title: t("board_view.insert-above"),
|
||||||
@ -81,7 +81,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
|
|||||||
componentFn: () => NoteColorPicker({note})
|
componentFn: () => NoteColorPicker({note})
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, note.noteId),
|
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, event, note.noteId),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export function openCalendarContextMenu(e: ContextMenuEvent, note: FNote, parent
|
|||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: e.pageY,
|
y: e.pageY,
|
||||||
items: [
|
items: [
|
||||||
...link_context_menu.getItems(),
|
...link_context_menu.getItems(e),
|
||||||
{ kind: "separator" },
|
{ kind: "separator" },
|
||||||
getArchiveMenuItem(note),
|
getArchiveMenuItem(note),
|
||||||
{
|
{
|
||||||
@ -40,6 +40,6 @@ export function openCalendarContextMenu(e: ContextMenuEvent, note: FNote, parent
|
|||||||
componentFn: () => NoteColorPicker({note: note})
|
componentFn: () => NoteColorPicker({note: note})
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, note.noteId),
|
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, e, note.noteId),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export default function openContextMenu(noteId: string, e: LeafletMouseEvent, is
|
|||||||
let items: MenuItem<keyof CommandMappings>[] = [
|
let items: MenuItem<keyof CommandMappings>[] = [
|
||||||
...buildGeoLocationItem(e),
|
...buildGeoLocationItem(e),
|
||||||
{ kind: "separator" },
|
{ kind: "separator" },
|
||||||
...linkContextMenu.getItems(),
|
...linkContextMenu.getItems(e),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isEditable) {
|
if (isEditable) {
|
||||||
@ -32,14 +32,14 @@ export default function openContextMenu(noteId: string, e: LeafletMouseEvent, is
|
|||||||
x: e.originalEvent.pageX,
|
x: e.originalEvent.pageX,
|
||||||
y: e.originalEvent.pageY,
|
y: e.originalEvent.pageY,
|
||||||
items,
|
items,
|
||||||
selectMenuItemHandler: ({ command }, e) => {
|
selectMenuItemHandler: ({ command }) => {
|
||||||
if (command === "deleteFromMap") {
|
if (command === "deleteFromMap") {
|
||||||
appContext.triggerCommand(command, { noteId });
|
appContext.triggerCommand(command, { noteId });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass the events to the link context menu
|
// Pass the events to the link context menu
|
||||||
linkContextMenu.handleLinkContextMenuItem(command, noteId);
|
linkContextMenu.handleLinkContextMenuItem(command, e, noteId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,7 +174,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
|
|||||||
|
|
||||||
contextMenu.show({
|
contextMenu.show({
|
||||||
items: [
|
items: [
|
||||||
...link_context_menu.getItems(),
|
...link_context_menu.getItems(e),
|
||||||
{ kind: "separator" },
|
{ kind: "separator" },
|
||||||
{
|
{
|
||||||
title: t("table_view.row-insert-above"),
|
title: t("table_view.row-insert-above"),
|
||||||
@ -227,7 +227,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
|
|||||||
componentFn: () => NoteColorPicker({note: rowData.noteId})
|
componentFn: () => NoteColorPicker({note: rowData.noteId})
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, rowData.noteId),
|
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, e, rowData.noteId),
|
||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: e.pageY
|
y: e.pageY
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import appContext, { type CommandData, type CommandListenerData, type EventData,
|
|||||||
import type BasicWidget from "../basic_widget.js";
|
import type BasicWidget from "../basic_widget.js";
|
||||||
import Component from "../../components/component.js";
|
import Component from "../../components/component.js";
|
||||||
import splitService from "../../services/resizer.js";
|
import splitService from "../../services/resizer.js";
|
||||||
|
import { isMobile } from "../../services/utils.js";
|
||||||
|
import NoteContext from "../../components/note_context.js";
|
||||||
|
|
||||||
interface SplitNoteWidget extends BasicWidget {
|
interface SplitNoteWidget extends BasicWidget {
|
||||||
hasBeenAlreadyShown?: boolean;
|
hasBeenAlreadyShown?: boolean;
|
||||||
@ -49,13 +51,14 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
|||||||
|
|
||||||
this.child(widget);
|
this.child(widget);
|
||||||
|
|
||||||
if (noteContext.mainNtxId && noteContext.ntxId) {
|
if (noteContext.mainNtxId && noteContext.ntxId && !isMobile()) {
|
||||||
splitService.setupNoteSplitResizer([noteContext.mainNtxId,noteContext.ntxId]);
|
splitService.setupNoteSplitResizer([noteContext.mainNtxId,noteContext.ntxId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async openNewNoteSplitEvent({ ntxId, notePath, hoistedNoteId, viewScope }: EventData<"openNewNoteSplit">) {
|
async openNewNoteSplitEvent({ ntxId, notePath, hoistedNoteId, viewScope }: EventData<"openNewNoteSplit">) {
|
||||||
const mainNtxId = appContext.tabManager.getActiveMainContext()?.ntxId;
|
const activeContext = appContext.tabManager.getActiveMainContext();
|
||||||
|
const mainNtxId = activeContext?.ntxId;
|
||||||
if (!mainNtxId) {
|
if (!mainNtxId) {
|
||||||
console.warn("Missing main note context ID");
|
console.warn("Missing main note context ID");
|
||||||
return;
|
return;
|
||||||
@ -69,22 +72,30 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
|||||||
|
|
||||||
hoistedNoteId = hoistedNoteId || appContext.tabManager.getActiveContext()?.hoistedNoteId;
|
hoistedNoteId = hoistedNoteId || appContext.tabManager.getActiveContext()?.hoistedNoteId;
|
||||||
|
|
||||||
const noteContext = await appContext.tabManager.openEmptyTab(null, hoistedNoteId, mainNtxId);
|
|
||||||
if (!noteContext.ntxId) {
|
const subContexts = activeContext.getSubContexts();
|
||||||
logError("Failed to create new note context!");
|
let noteContext: NoteContext | undefined = undefined;
|
||||||
return;
|
if (isMobile() && subContexts.length > 1) {
|
||||||
|
noteContext = subContexts.find(s => s.ntxId !== ntxId);
|
||||||
|
}
|
||||||
|
if (!noteContext) {
|
||||||
|
noteContext = await appContext.tabManager.openEmptyTab(null, hoistedNoteId, mainNtxId);
|
||||||
|
// remove the original position of newly created note context
|
||||||
|
const ntxIds = appContext.tabManager.children.map((c) => c.ntxId).filter((id) => id !== noteContext?.ntxId) as string[];
|
||||||
|
|
||||||
|
// insert the note context after the originating note context
|
||||||
|
if (!noteContext.ntxId) {
|
||||||
|
logError("Failed to create new note context!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ntxIds.splice(ntxIds.indexOf(ntxId) + 1, 0, noteContext.ntxId);
|
||||||
|
|
||||||
|
this.triggerCommand("noteContextReorder", { ntxIdsInOrder: ntxIds });
|
||||||
|
|
||||||
|
// move the note context rendered widget after the originating widget
|
||||||
|
this.$widget.find(`[data-ntx-id="${noteContext.ntxId}"]`).insertAfter(this.$widget.find(`[data-ntx-id="${ntxId}"]`));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the original position of newly created note context
|
|
||||||
const ntxIds = appContext.tabManager.children.map((c) => c.ntxId).filter((id) => id !== noteContext.ntxId) as string[];
|
|
||||||
|
|
||||||
// insert the note context after the originating note context
|
|
||||||
ntxIds.splice(ntxIds.indexOf(ntxId) + 1, 0, noteContext.ntxId);
|
|
||||||
|
|
||||||
this.triggerCommand("noteContextReorder", { ntxIdsInOrder: ntxIds });
|
|
||||||
|
|
||||||
// move the note context rendered widget after the originating widget
|
|
||||||
this.$widget.find(`[data-ntx-id="${noteContext.ntxId}"]`).insertAfter(this.$widget.find(`[data-ntx-id="${ntxId}"]`));
|
|
||||||
|
|
||||||
await appContext.tabManager.activateNoteContext(noteContext.ntxId);
|
await appContext.tabManager.activateNoteContext(noteContext.ntxId);
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
import appContext from "../../components/app_context";
|
import appContext, { CommandMappings } from "../../components/app_context";
|
||||||
import contextMenu from "../../menus/context_menu";
|
import contextMenu, { MenuItem } from "../../menus/context_menu";
|
||||||
import branches from "../../services/branches";
|
import branches from "../../services/branches";
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
import note_create from "../../services/note_create";
|
import note_create from "../../services/note_create";
|
||||||
import tree from "../../services/tree";
|
import tree from "../../services/tree";
|
||||||
import ActionButton from "../react/ActionButton";
|
import ActionButton from "../react/ActionButton";
|
||||||
import { ParentComponent } from "../react/react_utils";
|
import { ParentComponent } from "../react/react_utils";
|
||||||
|
import BasicWidget from "../basic_widget";
|
||||||
|
|
||||||
export default function MobileDetailMenu() {
|
export default function MobileDetailMenu() {
|
||||||
const parentComponent = useContext(ParentComponent);
|
const parentComponent = useContext(ParentComponent);
|
||||||
@ -16,17 +17,33 @@ export default function MobileDetailMenu() {
|
|||||||
icon="bx bx-dots-vertical-rounded"
|
icon="bx bx-dots-vertical-rounded"
|
||||||
text=""
|
text=""
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
const note = appContext.tabManager.getActiveContextNote();
|
const ntxId = (parentComponent as BasicWidget | null)?.getClosestNtxId();
|
||||||
|
if (!ntxId) return;
|
||||||
|
|
||||||
contextMenu.show<"insertChildNote" | "delete" | "showRevisions">({
|
const noteContext = appContext.tabManager.getNoteContextById(ntxId);
|
||||||
|
const subContexts = noteContext.getMainContext().getSubContexts();
|
||||||
|
const isMainContext = noteContext?.isMainContext();
|
||||||
|
const note = noteContext.note;
|
||||||
|
|
||||||
|
const items: (MenuItem<keyof CommandMappings>)[] = [
|
||||||
|
{ title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" },
|
||||||
|
{ title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" },
|
||||||
|
{ kind: "separator" },
|
||||||
|
{ title: t("mobile_detail_menu.note_revisions"), command: "showRevisions", uiIcon: "bx bx-history" },
|
||||||
|
{ kind: "separator" },
|
||||||
|
subContexts.length < 2 && { title: t("create_pane_button.create_new_split"), command: "openNewNoteSplit", uiIcon: "bx bx-dock-right" },
|
||||||
|
!isMainContext && { title: t("close_pane_button.close_this_pane"), command: "closeThisNoteSplit", uiIcon: "bx bx-x" }
|
||||||
|
].filter(i => !!i) as MenuItem<keyof CommandMappings>[];
|
||||||
|
|
||||||
|
const lastItem = items.at(-1);
|
||||||
|
if (lastItem && "kind" in lastItem && lastItem.kind === "separator") {
|
||||||
|
items.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMenu.show<keyof CommandMappings>({
|
||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: e.pageY,
|
y: e.pageY,
|
||||||
items: [
|
items,
|
||||||
{ title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" },
|
|
||||||
{ title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" },
|
|
||||||
{ kind: "separator" },
|
|
||||||
{ title: t("mobile_detail_menu.note_revisions"), command: "showRevisions", uiIcon: "bx bx-history" }
|
|
||||||
],
|
|
||||||
selectMenuItemHandler: async ({ command }) => {
|
selectMenuItemHandler: async ({ command }) => {
|
||||||
if (command === "insertChildNote") {
|
if (command === "insertChildNote") {
|
||||||
note_create.createNote(appContext.tabManager.getActiveContextNotePath() ?? undefined);
|
note_create.createNote(appContext.tabManager.getActiveContextNotePath() ?? undefined);
|
||||||
@ -46,7 +63,7 @@ export default function MobileDetailMenu() {
|
|||||||
parentComponent.triggerCommand("setActiveScreen", { screen: "tree" });
|
parentComponent.triggerCommand("setActiveScreen", { screen: "tree" });
|
||||||
}
|
}
|
||||||
} else if (command && parentComponent) {
|
} else if (command && parentComponent) {
|
||||||
parentComponent.triggerCommand(command);
|
parentComponent.triggerCommand(command, { ntxId });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
forcePositionOnMobile: true
|
forcePositionOnMobile: true
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
import { useContext } from "preact/hooks";
|
|
||||||
import ActionButton from "../react/ActionButton";
|
import ActionButton from "../react/ActionButton";
|
||||||
import { ParentComponent } from "../react/react_utils";
|
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
|
import { useNoteContext } from "../react/hooks";
|
||||||
|
|
||||||
export default function ToggleSidebarButton() {
|
export default function ToggleSidebarButton() {
|
||||||
const parentComponent = useContext(ParentComponent);
|
const { noteContext, parentComponent } = useNoteContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActionButton
|
<div style={{ contain: "none", minWidth: 8 }}>
|
||||||
icon="bx bx-sidebar"
|
{ noteContext?.isMainContext() && <ActionButton
|
||||||
text={t("note_tree.toggle-sidebar")}
|
icon="bx bx-sidebar"
|
||||||
onClick={() => parentComponent?.triggerCommand("setActiveScreen", {
|
text={t("note_tree.toggle-sidebar")}
|
||||||
screen: "tree"
|
onClick={() => parentComponent?.triggerCommand("setActiveScreen", {
|
||||||
})}
|
screen: "tree"
|
||||||
/>
|
})}
|
||||||
|
/>}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,3 +19,9 @@ export function onWheelHorizontalScroll(event: WheelEvent) {
|
|||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
(event.currentTarget as HTMLElement).scrollLeft += event.deltaY + event.deltaX;
|
(event.currentTarget as HTMLElement).scrollLeft += event.deltaY + event.deltaX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getClosestNtxId(element: HTMLElement) {
|
||||||
|
const closestNtxEl = element.closest<HTMLElement>("[data-ntx-id]");
|
||||||
|
if (!closestNtxEl) return null;
|
||||||
|
return closestNtxEl.dataset.ntxId ?? null;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user