diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java index 9c9d7dd3d..0bcf51a26 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java @@ -80,7 +80,6 @@ public class BrowserFullSessionComp extends SimpleRegionBuilder { loadingStack.apply(struc -> struc.setPickOnBounds(false)); var delayedStack = new DelayedInitComp( left, () -> StoreViewState.get() != null && StoreViewState.get().isInitialized()); - delayedStack.hide(AppSizeBreakpoints.compactMode()); var splitPane = new LeftSplitPaneComp(delayedStack, loadingStack) .withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth()) .withOnDividerChange(d -> { diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java index 03edc736b..dfddbe3f8 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java @@ -8,6 +8,7 @@ import io.xpipe.app.comp.base.PrettyImageHelper; import io.xpipe.app.comp.base.StackComp; import io.xpipe.app.core.AppFontSizes; import io.xpipe.app.core.AppI18n; +import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.core.AppSizeBreakpoints; import io.xpipe.app.platform.LabelGraphic; import io.xpipe.app.platform.MenuHelper; @@ -269,24 +270,24 @@ public class BrowserSessionTabsComp extends SimpleRegionBuilder { .paddingProperty() .bind(Bindings.createObjectBinding( () -> { - if (!AppSizeBreakpoints.compactMode().get()) { + if (!AppLayoutModel.get().getPortraitLayoutCollapsed().get()) { return new Insets(2, 0, 4, -leftPadding.get() + 3); } else { return new Insets(2, 0, 4, -leftPadding.get() - 4); } }, - AppSizeBreakpoints.compactMode(), + AppLayoutModel.get().getPortraitLayoutCollapsed(), leftPadding)); tabs.paddingProperty() .bind(Bindings.createObjectBinding( () -> { - if (!AppSizeBreakpoints.compactMode().get()) { + if (!AppLayoutModel.get().getPortraitLayoutCollapsed().get()) { return new Insets(0, 0, 0, -5); } else { return new Insets(0, 0, 0, 5); } }, - AppSizeBreakpoints.compactMode())); + AppLayoutModel.get().getPortraitLayoutCollapsed())); headerHeight.bind(headerArea.heightProperty()); }); } diff --git a/app/src/main/java/io/xpipe/app/comp/base/AppLayoutComp.java b/app/src/main/java/io/xpipe/app/comp/base/AppLayoutComp.java index 8d016d85d..63e267cc4 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/AppLayoutComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/AppLayoutComp.java @@ -3,12 +3,16 @@ package io.xpipe.app.comp.base; import io.xpipe.app.comp.BaseRegionBuilder; import io.xpipe.app.comp.RegionStructure; import io.xpipe.app.comp.RegionStructureBuilder; +import io.xpipe.app.core.AppI18n; import io.xpipe.app.core.AppLayoutModel; +import io.xpipe.app.core.AppSizeBreakpoints; import io.xpipe.app.issue.TrackEvent; +import io.xpipe.app.platform.LabelGraphic; import io.xpipe.app.platform.PlatformThread; import io.xpipe.app.terminal.TerminalDockHubManager; import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ObservableValue; import javafx.scene.Node; import javafx.scene.Parent; diff --git a/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java b/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java index 84fcb88f3..9311ea32a 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java @@ -4,6 +4,7 @@ import io.xpipe.app.comp.BaseRegionBuilder; import io.xpipe.app.comp.RegionStructure; import io.xpipe.app.comp.RegionStructureBuilder; +import io.xpipe.app.core.AppLayoutModel; import javafx.application.Platform; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.value.ChangeListener; @@ -30,7 +31,7 @@ public class LeftSplitPaneComp extends RegionStructureBuilder { + return new LabelGraphic.IconGraphic("mdi2a-arrow-expand-horizontal"); + }, portraitExpanded), () -> { + portraitExpanded.set(!portraitExpanded.get()); + return false; + }); + AppSizeBreakpoints.portraitMode().subscribe(v -> { + if (v) { + AppLayoutModel.get().getQueueEntries().add(toggleExpand); + portraitExpanded.set(false); + } else { + AppLayoutModel.get().getQueueEntries().remove(toggleExpand); + portraitExpanded.set(true); + } + }); + portraitLayoutCollapsed.bind(Bindings.createBooleanBinding(() -> { + return AppSizeBreakpoints.portraitMode().get() && !portraitExpanded.get(); + }, portraitExpanded, AppSizeBreakpoints.portraitMode())); + } public static void reset() { @@ -263,6 +284,13 @@ public class AppLayoutModel { } public QueueEntry(ObservableValue name, LabelGraphic icon, Supplier action) { + this.name = name; + this.icon = new ReadOnlyObjectWrapper<>(icon); + this.action = action; + this.top = false; + } + + public QueueEntry(ObservableValue name, ObservableValue icon, Supplier action) { this.name = name; this.icon = icon; this.action = action; @@ -270,7 +298,7 @@ public class AppLayoutModel { } ObservableValue name; - LabelGraphic icon; + ObservableValue icon; Supplier action; boolean top; diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StoreLayoutComp.java b/app/src/main/java/io/xpipe/app/hub/comp/StoreLayoutComp.java index ceb6cf329..3758beada 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StoreLayoutComp.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StoreLayoutComp.java @@ -30,7 +30,6 @@ public class StoreLayoutComp extends SimpleRegionBuilder { private Region createContent() { var filterTrigger = new ObservableSubscriber(); var left = new StoreSidebarComp(filterTrigger); - left.hide(AppSizeBreakpoints.compactMode()); left.minWidth(285); left.maxWidth(500); left.minHeight(0); diff --git a/app/src/main/java/io/xpipe/app/prefs/AppPrefsComp.java b/app/src/main/java/io/xpipe/app/prefs/AppPrefsComp.java index 3c87fe2d2..bdcea7058 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppPrefsComp.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppPrefsComp.java @@ -1,6 +1,9 @@ package io.xpipe.app.prefs; +import io.xpipe.app.comp.RegionBuilder; import io.xpipe.app.comp.SimpleRegionBuilder; +import io.xpipe.app.comp.base.LeftSplitPaneComp; +import io.xpipe.app.comp.base.StackComp; import io.xpipe.app.comp.base.VerticalComp; import io.xpipe.app.platform.PlatformThread; import io.xpipe.app.util.BooleanScope; @@ -12,6 +15,8 @@ import javafx.scene.layout.*; import net.synedra.validatorfx.GraphicDecorationStackPane; +import java.util.List; + public class AppPrefsComp extends SimpleRegionBuilder { @Override @@ -83,17 +88,16 @@ public class AppPrefsComp extends SimpleRegionBuilder { scrollPane.setFitToWidth(true); HBox.setHgrow(scrollPane, Priority.ALWAYS); - var sidebar = new AppPrefsSidebarComp().build(); - sidebar.setMinWidth(260); - sidebar.setPrefWidth(260); - sidebar.setMaxWidth(260); - sidebar.setMinHeight(0); + var sidebar = new AppPrefsSidebarComp(); + var sidebarWrapper = new StackComp(List.of(sidebar)); + sidebarWrapper.padding(new Insets(4)); + sidebarWrapper.minWidth(150); + sidebarWrapper.maxWidth(350); - var split = new HBox(sidebar, scrollPane); - HBox.setMargin(sidebar, new Insets(4)); - split.setFillHeight(true); - split.getStyleClass().add("prefs"); - return split; + var split = new LeftSplitPaneComp(sidebarWrapper, RegionBuilder.of(() -> scrollPane)); + split.withInitialWidth(265); + split.style("prefs"); + return split.build(); } private double computeCategoryOffset(Region box, ScrollPane scrollPane, AppPrefsCategory val) { diff --git a/app/src/main/java/io/xpipe/app/terminal/TerminalDockHubManager.java b/app/src/main/java/io/xpipe/app/terminal/TerminalDockHubManager.java index 5926c40d9..53f8b35dc 100644 --- a/app/src/main/java/io/xpipe/app/terminal/TerminalDockHubManager.java +++ b/app/src/main/java/io/xpipe/app/terminal/TerminalDockHubManager.java @@ -19,6 +19,7 @@ import io.xpipe.app.util.OsType; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.SimpleBooleanProperty; import javafx.collections.ListChangeListener; import javafx.scene.input.KeyCode; @@ -138,7 +139,7 @@ public class TerminalDockHubManager { AppI18n.observable( "toggleTerminalDock", new KeyCodeCombination(KeyCode.T, KeyCombination.SHORTCUT_DOWN).getDisplayText()), - new LabelGraphic.NodeGraphic(() -> { + new ReadOnlyObjectWrapper<>(new LabelGraphic.NodeGraphic(() -> { var inner = new FontIcon(); inner.iconCodeProperty() .bind(PlatformThread.sync(Bindings.createObjectBinding( @@ -153,7 +154,7 @@ public class TerminalDockHubManager { inner.getStyleClass().add("graphic"); inner.getStyleClass().add("terminal-dock-button"); return inner; - }), + })), () -> { refreshDockStatus(); diff --git a/app/src/main/resources/io/xpipe/app/resources/style/prefs.css b/app/src/main/resources/io/xpipe/app/resources/style/prefs.css index 15e6c4ee2..856f70077 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/prefs.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/prefs.css @@ -89,7 +89,11 @@ -fx-effect: NONE; } - .root:seamless-frame .prefs .scroll-bar:vertical { -fx-padding: 9 1 5 1; } + +.prefs .split-pane-divider { + -fx-padding: 0 2 0 3; + -fx-background-color: transparent; +}