From 7e64e31dfe7d4d30b68991ace7fae258000f27e7 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sat, 17 May 2025 23:51:37 +0800 Subject: [PATCH 1/7] Fix: The button for toggling the left pane visibility in the launcher was initially not visible on startup --- apps/client/src/widgets/buttons/left_pane_toggle.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/buttons/left_pane_toggle.ts b/apps/client/src/widgets/buttons/left_pane_toggle.ts index 88528add5..80725a3e8 100644 --- a/apps/client/src/widgets/buttons/left_pane_toggle.ts +++ b/apps/client/src/widgets/buttons/left_pane_toggle.ts @@ -32,10 +32,8 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { } refreshIcon() { - if (document.hasFocus() || this.currentLeftPaneVisible === true) { - super.refreshIcon(); - splitService.setupLeftPaneResizer(this.currentLeftPaneVisible); - } + super.refreshIcon(); + splitService.setupLeftPaneResizer(this.currentLeftPaneVisible); } entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { From c65f0d4249bee56b7913a808445eb99294ffb77e Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 18 May 2025 10:22:49 +0800 Subject: [PATCH 2/7] Fix (left pane toggle logic): properly handle both synced and current window visibility states --- apps/client/src/widgets/buttons/left_pane_toggle.ts | 8 +++++--- apps/client/src/widgets/containers/left_pane_container.ts | 8 +++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/client/src/widgets/buttons/left_pane_toggle.ts b/apps/client/src/widgets/buttons/left_pane_toggle.ts index 80725a3e8..99fa0530b 100644 --- a/apps/client/src/widgets/buttons/left_pane_toggle.ts +++ b/apps/client/src/widgets/buttons/left_pane_toggle.ts @@ -19,10 +19,10 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { return "bx-sidebar"; } - return options.is("leftPaneVisible") ? "bx-chevrons-left" : "bx-chevrons-right"; + return this.currentLeftPaneVisible ? "bx-chevrons-left" : "bx-chevrons-right"; }; - this.settings.title = () => (options.is("leftPaneVisible") ? t("left_pane_toggle.hide_panel") : t("left_pane_toggle.show_panel")); + this.settings.title = () => (this.currentLeftPaneVisible ? t("left_pane_toggle.hide_panel") : t("left_pane_toggle.show_panel")); this.settings.command = () => (this.currentLeftPaneVisible ? "hideLeftPane" : "showLeftPane"); @@ -38,7 +38,9 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { if (loadResults.isOptionReloaded("leftPaneVisible") && document.hasFocus()) { - this.currentLeftPaneVisible = options.is("leftPaneVisible"); + // options.is("leftPaneVisible") changed — it may or may not be the same as currentLeftPaneVisible, but as long as the window is focused, the left pane visibility should be toggled. + // See PR description for detailed explanation of multi-window edge cases: https://github.com/TriliumNext/Notes/pull/1962 + this.currentLeftPaneVisible = !this.currentLeftPaneVisible; this.refreshIcon(); } } diff --git a/apps/client/src/widgets/containers/left_pane_container.ts b/apps/client/src/widgets/containers/left_pane_container.ts index 2b8221553..c9016b8ae 100644 --- a/apps/client/src/widgets/containers/left_pane_container.ts +++ b/apps/client/src/widgets/containers/left_pane_container.ts @@ -4,20 +4,26 @@ import appContext, { type EventData } from "../../components/app_context.js"; import type Component from "../../components/component.js"; export default class LeftPaneContainer extends FlexContainer { + private currentLeftPaneVisible: boolean; + constructor() { super("column"); + this.currentLeftPaneVisible = options.is("leftPaneVisible"); + this.id("left-pane"); this.css("height", "100%"); this.collapsible(); } isEnabled() { - return super.isEnabled() && options.is("leftPaneVisible"); + return super.isEnabled() && this.currentLeftPaneVisible; } entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { if (loadResults.isOptionReloaded("leftPaneVisible") && document.hasFocus()) { + // options.is("leftPaneVisible") changed — it may or may not be the same as currentLeftPaneVisible, but as long as the window is focused, the left pane visibility should be toggled. + this.currentLeftPaneVisible = !this.currentLeftPaneVisible; const visible = this.isEnabled(); this.toggleInt(visible); From 22b64a0dc4110b8061b851eb90686b25f6d83994 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 18 May 2025 16:24:13 +0800 Subject: [PATCH 3/7] fix(ui): Exclude launcher pane width from Split calculation; Record Split state for multiple windows --- apps/client/src/services/resizer.ts | 30 +++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/client/src/services/resizer.ts b/apps/client/src/services/resizer.ts index 1cce0f993..4b80db7ba 100644 --- a/apps/client/src/services/resizer.ts +++ b/apps/client/src/services/resizer.ts @@ -3,7 +3,11 @@ import Split from "split.js" export const DEFAULT_GUTTER_SIZE = 5; +let leftPaneWidth: number; +let reservedPx: number; +let layoutOrientation: string; let leftInstance: ReturnType | null; +let rightPaneWidth: number; let rightInstance: ReturnType | null; function setupLeftPaneResizer(leftPaneVisible: boolean) { @@ -14,27 +18,34 @@ function setupLeftPaneResizer(leftPaneVisible: boolean) { $("#left-pane").toggle(leftPaneVisible); + layoutOrientation = layoutOrientation ?? options.get("layoutOrientation"); + reservedPx = reservedPx ?? (layoutOrientation === "vertical" ? ($("#launcher-pane").outerWidth() || 0) : 0); + // Window resizing causes `window.innerWidth` to change, so `reservedWidth` needs to be recalculated each time. + const reservedWidth = reservedPx / window.innerWidth * 100; if (!leftPaneVisible) { - $("#rest-pane").css("width", "100%"); - + $("#rest-pane").css("width", layoutOrientation === "vertical" ? `calc(100% - ${reservedWidth})` : "100%"); return; } - let leftPaneWidth = options.getInt("leftPaneWidth"); + leftPaneWidth = leftPaneWidth ?? (options.getInt("leftPaneWidth") ?? 0); if (!leftPaneWidth || leftPaneWidth < 5) { leftPaneWidth = 5; } + const restPaneWidth = 100 - leftPaneWidth - reservedWidth; if (leftPaneVisible) { // Delayed initialization ensures that all DOM elements are fully rendered and part of the layout, // preventing Split.js from retrieving incorrect dimensions due to #left-pane not being rendered yet, // which would cause the minSize setting to have no effect. requestAnimationFrame(() => { leftInstance = Split(["#left-pane", "#rest-pane"], { - sizes: [leftPaneWidth, 100 - leftPaneWidth], + sizes: [leftPaneWidth, restPaneWidth], gutterSize: DEFAULT_GUTTER_SIZE, minSize: [150, 300], - onDragEnd: (sizes) => options.save("leftPaneWidth", Math.round(sizes[0])) + onDragEnd: (sizes) => { + leftPaneWidth = Math.round(sizes[0]); + options.save("leftPaneWidth", Math.round(sizes[0])); + } }); }); } @@ -54,7 +65,7 @@ function setupRightPaneResizer() { return; } - let rightPaneWidth = options.getInt("rightPaneWidth"); + rightPaneWidth = rightPaneWidth ?? (options.getInt("rightPaneWidth") ?? 0); if (!rightPaneWidth || rightPaneWidth < 5) { rightPaneWidth = 5; } @@ -63,8 +74,11 @@ function setupRightPaneResizer() { rightInstance = Split(["#center-pane", "#right-pane"], { sizes: [100 - rightPaneWidth, rightPaneWidth], gutterSize: DEFAULT_GUTTER_SIZE, - minSize: [ 300, 180 ], - onDragEnd: (sizes) => options.save("rightPaneWidth", Math.round(sizes[1])) + minSize: [300, 180], + onDragEnd: (sizes) => { + rightPaneWidth = Math.round(sizes[1]); + options.save("rightPaneWidth", Math.round(sizes[1])); + } }); } } From 0e9c381df4f2e446a791b7312a6756eb785547f5 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 18 May 2025 18:19:54 +0800 Subject: [PATCH 4/7] fix(launcher-pane): Prevent the launcher pane from being compressed --- apps/client/src/stylesheets/theme-next/shell.css | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 2bcdf942f..a77715136 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -127,6 +127,7 @@ body.layout-horizontal > .horizontal { --launcher-pane-button-gap: var(--launcher-pane-vert-button-gap); width: var(--launcher-pane-size) !important; + min-width: var(--launcher-pane-size) !important; padding-bottom: var(--launcher-pane-button-gap); } From 9682253ceda280bc9cd00f4314443ffcaf2141f9 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 18 May 2025 18:38:52 +0800 Subject: [PATCH 5/7] fix: Incorrectly calculating rest-pane width in https://github.com/TriliumNext/Notes/pull/1962 --- apps/client/src/services/resizer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/services/resizer.ts b/apps/client/src/services/resizer.ts index 4b80db7ba..be148f3ec 100644 --- a/apps/client/src/services/resizer.ts +++ b/apps/client/src/services/resizer.ts @@ -23,7 +23,7 @@ function setupLeftPaneResizer(leftPaneVisible: boolean) { // Window resizing causes `window.innerWidth` to change, so `reservedWidth` needs to be recalculated each time. const reservedWidth = reservedPx / window.innerWidth * 100; if (!leftPaneVisible) { - $("#rest-pane").css("width", layoutOrientation === "vertical" ? `calc(100% - ${reservedWidth})` : "100%"); + $("#rest-pane").css("width", layoutOrientation === "vertical" ? `${(100 - reservedWidth) * 100}%` : "100%"); return; } From 0d09a7558fba4a44c7bcbfe10f302a5212537528 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 18 May 2025 20:19:30 +0800 Subject: [PATCH 6/7] fix: Incorrectly calculating rest-pane width --- apps/client/src/services/resizer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/services/resizer.ts b/apps/client/src/services/resizer.ts index be148f3ec..e0dc40995 100644 --- a/apps/client/src/services/resizer.ts +++ b/apps/client/src/services/resizer.ts @@ -23,7 +23,7 @@ function setupLeftPaneResizer(leftPaneVisible: boolean) { // Window resizing causes `window.innerWidth` to change, so `reservedWidth` needs to be recalculated each time. const reservedWidth = reservedPx / window.innerWidth * 100; if (!leftPaneVisible) { - $("#rest-pane").css("width", layoutOrientation === "vertical" ? `${(100 - reservedWidth) * 100}%` : "100%"); + $("#rest-pane").css("width", layoutOrientation === "vertical" ? `${100 - reservedWidth}%` : "100%"); return; } From 025c6a4e0ebeeeb1a5cccd808dfb2fc9dc31421c Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Tue, 20 May 2025 14:33:01 +0800 Subject: [PATCH 7/7] fix(leftpaneVisibility): Make leftpane visibility switch no longer depend on entitiesReloadedEvent --- apps/client/src/components/app_context.ts | 3 +++ .../src/components/root_command_executor.ts | 6 +++--- .../src/widgets/buttons/left_pane_toggle.ts | 12 ++++------- .../widgets/containers/left_pane_container.ts | 21 +++++++++---------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index 1855876d3..b64678011 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -283,6 +283,9 @@ export type CommandMappings = { type EventMappings = { initialRenderComplete: {}; frocaReloaded: {}; + setLeftPaneVisibility: { + leftPaneVisible: boolean | null; + } protectedSessionStarted: {}; notesReloaded: { noteIds: string[]; diff --git a/apps/client/src/components/root_command_executor.ts b/apps/client/src/components/root_command_executor.ts index 1e16fae81..8e7df9494 100644 --- a/apps/client/src/components/root_command_executor.ts +++ b/apps/client/src/components/root_command_executor.ts @@ -78,15 +78,15 @@ export default class RootCommandExecutor extends Component { } hideLeftPaneCommand() { - options.save(`leftPaneVisible`, "false"); + appContext.triggerEvent("setLeftPaneVisibility", { leftPaneVisible: false }); } showLeftPaneCommand() { - options.save(`leftPaneVisible`, "true"); + appContext.triggerEvent("setLeftPaneVisibility", { leftPaneVisible: true }); } toggleLeftPaneCommand() { - options.toggle("leftPaneVisible"); + appContext.triggerEvent("setLeftPaneVisibility", { leftPaneVisible: null }); } async showBackendLogCommand() { diff --git a/apps/client/src/widgets/buttons/left_pane_toggle.ts b/apps/client/src/widgets/buttons/left_pane_toggle.ts index 99fa0530b..22a902622 100644 --- a/apps/client/src/widgets/buttons/left_pane_toggle.ts +++ b/apps/client/src/widgets/buttons/left_pane_toggle.ts @@ -35,13 +35,9 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { super.refreshIcon(); splitService.setupLeftPaneResizer(this.currentLeftPaneVisible); } - - entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - if (loadResults.isOptionReloaded("leftPaneVisible") && document.hasFocus()) { - // options.is("leftPaneVisible") changed — it may or may not be the same as currentLeftPaneVisible, but as long as the window is focused, the left pane visibility should be toggled. - // See PR description for detailed explanation of multi-window edge cases: https://github.com/TriliumNext/Notes/pull/1962 - this.currentLeftPaneVisible = !this.currentLeftPaneVisible; - this.refreshIcon(); - } + + setLeftPaneVisibilityEvent({ leftPaneVisible }: EventData<"setLeftPaneVisibility">) { + this.currentLeftPaneVisible = leftPaneVisible ?? !this.currentLeftPaneVisible; + this.refreshIcon(); } } diff --git a/apps/client/src/widgets/containers/left_pane_container.ts b/apps/client/src/widgets/containers/left_pane_container.ts index c9016b8ae..d95f5091a 100644 --- a/apps/client/src/widgets/containers/left_pane_container.ts +++ b/apps/client/src/widgets/containers/left_pane_container.ts @@ -20,18 +20,17 @@ export default class LeftPaneContainer extends FlexContainer { return super.isEnabled() && this.currentLeftPaneVisible; } - entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - if (loadResults.isOptionReloaded("leftPaneVisible") && document.hasFocus()) { - // options.is("leftPaneVisible") changed — it may or may not be the same as currentLeftPaneVisible, but as long as the window is focused, the left pane visibility should be toggled. - this.currentLeftPaneVisible = !this.currentLeftPaneVisible; - const visible = this.isEnabled(); - this.toggleInt(visible); + setLeftPaneVisibilityEvent({ leftPaneVisible }: EventData<"setLeftPaneVisibility">) { + this.currentLeftPaneVisible = leftPaneVisible ?? !this.currentLeftPaneVisible; + const visible = this.isEnabled(); + this.toggleInt(visible); - if (visible) { - this.triggerEvent("focusTree", {}); - } else { - this.triggerEvent("focusOnDetail", { ntxId: appContext.tabManager.getActiveContext()?.ntxId }); - } + if (visible) { + this.triggerEvent("focusTree", {}); + } else { + this.triggerEvent("focusOnDetail", { ntxId: appContext.tabManager.getActiveContext()?.ntxId }); } + + options.save("leftPaneVisible", this.currentLeftPaneVisible.toString()); } }