diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileChooserSessionComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileChooserSessionComp.java index 920224611..27852dd84 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileChooserSessionComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileChooserSessionComp.java @@ -143,7 +143,6 @@ public class BrowserFileChooserSessionComp extends ModalOverlayContentComp { var vertical = new VerticalComp(List.of(bookmarkTopBar, bookmarksContainer)).styleClass("left"); var splitPane = new LeftSplitPaneComp(vertical, stack) .withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth()) - .withOnDividerChange(AppLayoutModel.get().getSavedState()::setBrowserConnectionsWidth) .styleClass("background") .apply(struc -> { struc.getLeft().setMinWidth(200); 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 c07faad7a..ffc417591 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java @@ -9,6 +9,7 @@ import io.xpipe.app.comp.base.*; import io.xpipe.app.comp.store.StoreEntryWrapper; import io.xpipe.app.comp.store.StoreViewState; import io.xpipe.app.core.AppLayoutModel; +import io.xpipe.app.core.window.AppMainWindow; import io.xpipe.app.ext.ShellStore; import io.xpipe.app.util.BindingsHelper; import io.xpipe.app.util.PlatformThread; @@ -73,10 +74,13 @@ public class BrowserFullSessionComp extends SimpleComp { loadingStack.apply(struc -> struc.get().setPickOnBounds(false)); var delayedStack = new DelayedInitComp( left, () -> StoreViewState.get() != null && StoreViewState.get().isInitialized()); + delayedStack.hide(AppMainWindow.getInstance().getStage().widthProperty().lessThan(1000)); var splitPane = new LeftSplitPaneComp(delayedStack, loadingStack) .withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth()) .withOnDividerChange(d -> { - AppLayoutModel.get().getSavedState().setBrowserConnectionsWidth(d); + if (d > 0.0) { + AppLayoutModel.get().getSavedState().setBrowserConnectionsWidth(d); + } leftSplit.set(d); }); splitPane.apply(struc -> { 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 ed23d3daa..1263e3f7c 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java @@ -3,6 +3,7 @@ package io.xpipe.app.browser; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.SimpleComp; import io.xpipe.app.comp.base.PrettyImageHelper; +import io.xpipe.app.core.App; import io.xpipe.app.core.AppI18n; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.util.BooleanScope; @@ -217,8 +218,23 @@ public class BrowserSessionTabsComp extends SimpleComp { headerArea .paddingProperty() .bind(Bindings.createObjectBinding( - () -> new Insets(2, 0, 4, -leftPadding.get() + 3), leftPadding)); - tabs.setPadding(new Insets(0, 0, 0, -5)); + () -> { + var w = App.getApp().getStage().getWidth(); + if (w >= 1000) { + return + new Insets(2, 0, 4, -leftPadding.get() + 3); + } else { + return new Insets(2, 0, 4, -leftPadding.get() - 4); + } + }, App.getApp().getStage().widthProperty(), leftPadding)); + tabs.paddingProperty().bind(Bindings.createObjectBinding(() -> { + var w = App.getApp().getStage().getWidth(); + if (w >= 1000) { + return new Insets(0, 0, 0, -5); + } else { + return new Insets(0, 0, 0, 5); + } + }, App.getApp().getStage().widthProperty())); headerHeight.bind(headerArea.heightProperty()); }); } 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 1aff471c7..c23efd889 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 @@ -3,6 +3,9 @@ package io.xpipe.app.comp.base; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.CompStructure; +import javafx.application.Platform; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.value.ChangeListener; import javafx.scene.control.SplitPane; import javafx.scene.layout.Region; @@ -30,32 +33,55 @@ public class LeftSplitPaneComp extends Comp { if (initialWidth != null) { sidebar.setPrefWidth(initialWidth); } - var r = new SplitPane(sidebar, c); + var r = new SplitPane(c); AtomicBoolean setInitial = new AtomicBoolean(false); r.widthProperty().addListener((observable, oldValue, newValue) -> { - if (newValue.doubleValue() <= 0) { + if (newValue.doubleValue() <= 0 || !r.getItems().contains(sidebar)) { return; } - if (!setInitial.get() && initialWidth != null) { + if (!setInitial.get() && initialWidth != null && r.getDividers().size() > 0) { r.getDividers().getFirst().setPosition(initialWidth / newValue.doubleValue()); setInitial.set(true); } }); - SplitPane.setResizableWithParent(sidebar, false); - r.getDividers().getFirst().positionProperty().addListener((observable, oldValue, newValue) -> { - if (r.getWidth() <= 0) { + var dividerPosition = new SimpleDoubleProperty(); + ChangeListener changeListener = (observable, oldValue, newValue) -> { + if (r.getWidth() <= 0 || !r.getItems().contains(sidebar)) { return; } if (onDividerChange != null) { onDividerChange.accept(newValue.doubleValue() * r.getWidth()); } + + dividerPosition.set(newValue.doubleValue()); + }; + + sidebar.managedProperty().subscribe(m -> { + if (!m) { + r.getDividers().getFirst().positionProperty().removeListener(changeListener); + r.getItems().remove(sidebar); + if (onDividerChange != null) { + onDividerChange.accept(0.0); + } + } else if (!r.getItems().contains(sidebar)) { + r.getItems().addFirst(sidebar); + var d = dividerPosition.get(); + r.getDividers().getFirst().setPosition(d); + r.layout(); + if (onDividerChange != null) { + onDividerChange.accept(d); + } + r.getDividers().getFirst().positionProperty().addListener(changeListener); + } }); + + SplitPane.setResizableWithParent(sidebar, false); r.getStyleClass().add("side-split-pane-comp"); - return new Structure(sidebar, c, r, r.getDividers().getFirst()); + return new Structure(sidebar, c, r); } public LeftSplitPaneComp withInitialWidth(double val) { @@ -74,7 +100,6 @@ public class LeftSplitPaneComp extends Comp { Region left; Region center; SplitPane pane; - SplitPane.Divider divider; @Override public SplitPane get() { diff --git a/app/src/main/java/io/xpipe/app/comp/store/DenseStoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/DenseStoreEntryComp.java index fb1d644d2..3ccda5cf8 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/DenseStoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/DenseStoreEntryComp.java @@ -3,6 +3,7 @@ package io.xpipe.app.comp.store; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.augment.GrowAugment; import io.xpipe.app.util.PlatformThread; +import io.xpipe.app.util.Rect; import io.xpipe.core.process.OsType; import javafx.beans.binding.Bindings; @@ -11,6 +12,7 @@ import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.layout.*; +import javafx.scene.shape.Rectangle; public class DenseStoreEntryComp extends StoreEntryComp { diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java index 70d02acc8..2999cb227 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java @@ -41,10 +41,24 @@ public abstract class StoreEntryComp extends SimpleComp { public static final PseudoClass FAILED = PseudoClass.getPseudoClass("failed"); public static final PseudoClass INCOMPLETE = PseudoClass.getPseudoClass("incomplete"); - public static final ObservableDoubleValue INFO_NO_CONTENT_WIDTH = - App.getApp().getStage().widthProperty().divide(2.1).add(-100); - public static final ObservableDoubleValue INFO_WITH_CONTENT_WIDTH = - App.getApp().getStage().widthProperty().divide(2.1).add(-200); + public static final ObservableDoubleValue INFO_NO_CONTENT_WIDTH = Bindings.createDoubleBinding(() -> { + var w = App.getApp().getStage().getWidth(); + if (w >= 1000) { + return (w / 2.1) - 100; + } else { + return (w / 1.7) - 50; + } + + }, App.getApp().getStage().widthProperty()); + public static final ObservableDoubleValue INFO_WITH_CONTENT_WIDTH = Bindings.createDoubleBinding(() -> { + var w = App.getApp().getStage().getWidth(); + if (w >= 1000) { + return (w / 2.1) - 200; + } else { + return (w / 1.7) - 150; + } + + }, App.getApp().getStage().widthProperty()); protected final StoreSection section; protected final Comp content; diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreLayoutComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreLayoutComp.java index 632c1395c..a586063b9 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreLayoutComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreLayoutComp.java @@ -6,8 +6,10 @@ import io.xpipe.app.comp.base.DelayedInitComp; import io.xpipe.app.comp.base.LeftSplitPaneComp; import io.xpipe.app.core.AppActionLinkDetector; import io.xpipe.app.core.AppLayoutModel; +import io.xpipe.app.core.window.AppMainWindow; import io.xpipe.app.util.InputHelper; +import javafx.beans.property.SimpleBooleanProperty; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; @@ -25,11 +27,16 @@ public class StoreLayoutComp extends SimpleComp { private Region createContent() { var left = new StoreSidebarComp(); + left.hide(AppMainWindow.getInstance().getStage().widthProperty().lessThan(1000)); left.minWidth(270); left.maxWidth(500); var comp = new LeftSplitPaneComp(left, new StoreEntryListComp()) .withInitialWidth(AppLayoutModel.get().getSavedState().getSidebarWidth()) .withOnDividerChange(aDouble -> { + if (aDouble == 0.0) { + return; + } + AppLayoutModel.get().getSavedState().setSidebarWidth(aDouble); }); comp.styleClass("store-layout"); diff --git a/app/src/main/java/io/xpipe/app/terminal/PowerShellTerminalType.java b/app/src/main/java/io/xpipe/app/terminal/PowerShellTerminalType.java index c96b2fd16..f76e4475b 100644 --- a/app/src/main/java/io/xpipe/app/terminal/PowerShellTerminalType.java +++ b/app/src/main/java/io/xpipe/app/terminal/PowerShellTerminalType.java @@ -47,7 +47,7 @@ public class PowerShellTerminalType extends ExternalTerminalType.SimplePathType return CommandBuilder.of() .add("-ExecutionPolicy", "Bypass") .add("-File") - .addFile(configuration.getScriptFile()); + .addQuoted(configuration.getScriptFile().toString()); } return CommandBuilder.of() diff --git a/app/src/main/java/io/xpipe/app/terminal/ZellijTerminalMultiplexer.java b/app/src/main/java/io/xpipe/app/terminal/ZellijTerminalMultiplexer.java index b1253891e..9dfc99875 100644 --- a/app/src/main/java/io/xpipe/app/terminal/ZellijTerminalMultiplexer.java +++ b/app/src/main/java/io/xpipe/app/terminal/ZellijTerminalMultiplexer.java @@ -31,14 +31,16 @@ public class ZellijTerminalMultiplexer implements TerminalMultiplexer { "zellij attach --create-background xpipe", "zellij -s xpipe action new-tab --name \"" + escape(config.getDisplayName(), false, true) + "\"", "zellij -s xpipe action write-chars -- " + escape(command, true, true) + "\\;exit", - "zellij -s xpipe action write 10"); + "zellij -s xpipe action write 10", + "zellij -s xpipe action clear" + ); } @Override public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config) throws Exception { return ShellScript.lines( - "zellij delete-session -f xpipe", + "zellij delete-session -f xpipe > /dev/null 2>&1", "zellij attach --create-background xpipe", "zellij -s xpipe run -c --name \"" + escape(config.getDisplayName(), false, true) + "\" -- " + escape(command, false, false), diff --git a/build.gradle b/build.gradle index dbd1e7ef3..4932050dd 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { plugins { id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id 'org.gradlex.extra-java-module-info' version '1.10.1' apply false + id 'org.gradlex.extra-java-module-info' version '1.12' apply false id("com.diffplug.spotless") version "7.0.2" apply false }