feat(mobile): more stable fixed tree for launch bar config

This commit is contained in:
Elian Doran
2026-02-04 16:46:22 +02:00
parent 62534e0e93
commit ac3b289c9e
4 changed files with 42 additions and 45 deletions

View File

@@ -1694,40 +1694,6 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
}
}
@media (max-width: 991px) {
body.mobile.force-fixed-tree #mobile-sidebar-wrapper {
padding-top: 0;
position: static;
height: 40vh;
width: 100vw;
transform: none !important;
background-color: var(--left-pane-background-color) !important;
border-bottom: 0.5px solid var(--main-border-color);
}
body.mobile.force-fixed-tree #mobile-sidebar-container {
display: none !important;
}
body.mobile.force-fixed-tree #mobile-sidebar-wrapper .quick-search {
display: none;
}
body.mobile.force-fixed-tree .component > button.bx-sidebar {
visibility: hidden;
padding: 0;
width: 6px;
}
body.mobile.force-fixed-tree #mobile-rest-container {
flex-direction: column !important;
}
body.mobile.force-fixed-tree #detail-container {
flex-grow: 1;
}
}
#launcher-pane {
color: var(--launcher-pane-text-color);
background-color: var(--launcher-pane-background-color);

View File

@@ -744,7 +744,7 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i
background-color: rgba(0, 0, 0, 0.5);
}
body.mobile:not(.force-fixed-tree) #mobile-sidebar-wrapper {
body.mobile #mobile-sidebar-wrapper {
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
border-inline-end: 1px solid var(--subtle-border-color);

View File

@@ -3,6 +3,29 @@
font-family: var(--detail-font-family);
font-size: var(--detail-font-size);
contain: none;
&.fixed-tree {
display: flex;
flex-direction: column;
height: 100%;
.fixed-note-tree-container {
height: 60%;
border-bottom: 1px solid var(--main-border-color);
.tree-wrapper {
padding: 0;
}
.tree {
padding: 0;
}
ul {
margin: 0;
}
}
}
}
body.prefers-centered-content .note-detail {
@@ -12,4 +35,4 @@ body.prefers-centered-content .note-detail {
.note-detail > * {
contain: none;
}
}

View File

@@ -1,5 +1,7 @@
import "./NoteDetail.css";
import clsx from "clsx";
import { use } from "i18next";
import { isValidElement, VNode } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
@@ -12,8 +14,9 @@ import { t } from "../services/i18n";
import protected_session_holder from "../services/protected_session_holder";
import toast from "../services/toast.js";
import { dynamicRequire, isElectron, isMobile } from "../services/utils";
import NoteTreeWidget from "./note_tree";
import { ExtendedNoteType, TYPE_MAPPINGS, TypeWidget } from "./note_types";
import { useNoteContext, useTriliumEvent } from "./react/hooks";
import { useLegacyWidget, useNote, useNoteContext, useTriliumEvent } from "./react/hooks";
import { NoteListWithLinks } from "./react/NoteList";
import { TypeWidgetProps } from "./type_widgets/type_widget";
@@ -36,6 +39,7 @@ export default function NoteDetail() {
const [ noteTypesToRender, setNoteTypesToRender ] = useState<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({});
const [ activeNoteType, setActiveNoteType ] = useState<ExtendedNoteType>();
const widgetRequestId = useRef(0);
const hasFixedTree = noteContext?.hoistedNoteId === "_lbMobileRoot" && isMobile();
const props: TypeWidgetProps = {
note: note!,
@@ -119,13 +123,6 @@ export default function NoteDetail() {
}
});
// Fixed tree for launch bar config on mobile.
useEffect(() => {
if (!isMobile) return;
const hasFixedTree = noteContext?.hoistedNoteId === "_lbMobileRoot";
document.body.classList.toggle("force-fixed-tree", hasFixedTree);
}, [ note ]);
// Handle toast notifications.
useEffect(() => {
if (!isElectron()) return;
@@ -215,8 +212,13 @@ export default function NoteDetail() {
return (
<div
ref={containerRef}
class={`component note-detail ${isFullHeight ? "full-height" : ""}`}
class={clsx("component note-detail", {
"full-height": isFullHeight,
"fixed-tree": hasFixedTree
})}
>
{hasFixedTree && <FixedTree />}
{Object.entries(noteTypesToRender).map(([ itemType, Element ]) => {
return <NoteDetailWrapper
Element={Element}
@@ -231,6 +233,12 @@ export default function NoteDetail() {
);
}
function FixedTree() {
const { noteContext } = useNoteContext();
const [ treeEl ] = useLegacyWidget(() => new NoteTreeWidget(), { noteContext });
return <div class="fixed-note-tree-container">{treeEl}</div>;
}
/**
* Wraps a single note type widget, in order to keep it in the DOM even after the user has switched away to another note type. This allows faster loading of the same note type again. The properties are cached, so that they are updated only
* while the widget is visible, to avoid rendering in the background. When not visible, the DOM element is simply hidden.