diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileSystemTabComp.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileSystemTabComp.java index 4b745d555..3bb32e501 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileSystemTabComp.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileSystemTabComp.java @@ -6,6 +6,7 @@ import io.xpipe.app.comp.*; import io.xpipe.app.comp.augment.ContextMenuAugment; import io.xpipe.app.comp.base.*; import io.xpipe.app.core.AppFontSizes; +import io.xpipe.app.core.AppSizeBreakpoints; import io.xpipe.app.platform.InputHelper; import io.xpipe.app.platform.MenuHelper; import io.xpipe.app.platform.PlatformThread; @@ -121,6 +122,18 @@ public class BrowserFileSystemTabComp extends SimpleRegionBuilder { topBar.getChildren().setAll(leftBox, new Spacer(6), navBar.get(), new Spacer(6), rightBox); topBar.setMinWidth(0); + var showAll = Bindings.createBooleanBinding(() -> { + return !AppSizeBreakpoints.portraitMode().get() || !navBar.textField().isFocused(); + }, AppSizeBreakpoints.portraitMode(), navBar.textField().focusedProperty()); + leftBox.visibleProperty().bind(showAll); + leftBox.managedProperty().bind(leftBox.visibleProperty()); + rightBox.visibleProperty().bind(showAll); + rightBox.managedProperty().bind(leftBox.visibleProperty()); + topBar.getChildren().get(1).visibleProperty().bind(showAll); + topBar.getChildren().get(1).managedProperty().bind(showAll); + topBar.getChildren().get(3).visibleProperty().bind(showAll); + topBar.getChildren().get(3).managedProperty().bind(showAll); + if (model.getBrowserModel() instanceof BrowserFullSessionModel fullSessionModel) { var pinButton = new Button(); RegionDescriptor.builder().nameKey("pinTab").build().apply(pinButton); diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserHistoryTabComp.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserHistoryTabComp.java index c63f13604..c4a915471 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserHistoryTabComp.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserHistoryTabComp.java @@ -6,6 +6,7 @@ import io.xpipe.app.comp.RegionBuilder; import io.xpipe.app.comp.SimpleRegionBuilder; import io.xpipe.app.comp.base.*; import io.xpipe.app.core.AppI18n; +import io.xpipe.app.core.AppSizeBreakpoints; import io.xpipe.app.platform.DerivedObservableList; import io.xpipe.app.platform.LabelGraphic; import io.xpipe.app.prefs.AppPrefs; @@ -70,7 +71,7 @@ public class BrowserHistoryTabComp extends SimpleRegionBuilder { var state = BrowserHistorySavedStateImpl.get(); var welcome = new BrowserGreetingComp(); - var header = new LabelComp(AppI18n.observable("browserWelcomeSystems")); + var header = new LabelComp(AppI18n.observable("browserWelcomeSystems")).apply(label -> label.setWrapText(true)); var vbox = new VerticalComp(List.of(welcome, RegionBuilder.vspacer(4), header)); vbox.apply(struc -> struc.setAlignment(Pos.CENTER_LEFT)); @@ -108,7 +109,6 @@ public class BrowserHistoryTabComp extends SimpleRegionBuilder { layout.style("welcome"); layout.spacing(14); layout.maxWidth(1000); - layout.padding(new Insets(45, 40, 40, 50)); layout.apply(struc -> { struc.setMaxWidth(1000); }); @@ -147,7 +147,9 @@ public class BrowserHistoryTabComp extends SimpleRegionBuilder { } }); }) - .minWidth(300) + .apply(button -> button.minWidthProperty().bind(Bindings.createDoubleBinding(() -> { + return AppSizeBreakpoints.portraitMode().get() ? 170.0 : 300.0; + }, AppSizeBreakpoints.portraitMode()))) .describe( d -> d.name(new ReadOnlyStringWrapper(DataStorage.get().getStoreEntryDisplayName(entry.get())))) .disable(disable) diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserNavBarComp.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserNavBarComp.java index 3998f587f..a78a64140 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserNavBarComp.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserNavBarComp.java @@ -9,6 +9,7 @@ import io.xpipe.app.comp.base.ButtonComp; import io.xpipe.app.comp.base.PrettyImageHelper; import io.xpipe.app.comp.base.TextFieldComp; import io.xpipe.app.core.AppFontSizes; +import io.xpipe.app.core.AppSizeBreakpoints; import io.xpipe.app.platform.LabelGraphic; import io.xpipe.app.platform.MenuHelper; import io.xpipe.app.platform.PlatformThread; @@ -93,8 +94,10 @@ public class BrowserNavBarComp extends RegionStructureBuilder { return !pathRegion.isFocused() - && !model.getInOverview().get(); + && !model.getInOverview().get() + && !AppSizeBreakpoints.portraitMode().get(); }, + AppSizeBreakpoints.portraitMode(), pathRegion.focusedProperty(), PlatformThread.sync(model.getInOverview()))); var stack = new StackPane(pathRegion, breadcrumbsRegion); @@ -167,7 +170,7 @@ public class BrowserNavBarComp extends RegionStructureBuilder { struc.focusedProperty().subscribe(val -> { struc.pseudoClassStateChanged( - INVISIBLE, !val && !model.getInOverview().get()); + INVISIBLE, !val && !model.getInOverview().get() && !AppSizeBreakpoints.portraitMode().get()); if (val) { Platform.runLater(() -> { @@ -176,6 +179,11 @@ public class BrowserNavBarComp extends RegionStructureBuilder { + struc.pseudoClassStateChanged( + INVISIBLE, !struc.isFocused() && !model.getInOverview().get() && !AppSizeBreakpoints.portraitMode().get()); + }); + struc.addEventHandler(KeyEvent.KEY_PRESSED, ke -> { if (ke.getCode().equals(KeyCode.ENTER)) { ke.consume(); @@ -186,7 +194,7 @@ public class BrowserNavBarComp extends RegionStructureBuilder { - struc.pseudoClassStateChanged(INVISIBLE, !val && !struc.isFocused()); + struc.pseudoClassStateChanged(INVISIBLE, !val && !struc.isFocused() && !AppSizeBreakpoints.portraitMode().get()); }); }); }); diff --git a/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayComp.java b/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayComp.java index aa1b1cac5..f8aba8e0a 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/ModalOverlayComp.java @@ -5,6 +5,7 @@ import io.xpipe.app.comp.RegionBuilder; import io.xpipe.app.core.AppFontSizes; import io.xpipe.app.core.AppI18n; import io.xpipe.app.core.AppLogs; +import io.xpipe.app.core.AppSizeBreakpoints; import io.xpipe.app.platform.LabelGraphic; import io.xpipe.app.platform.PlatformThread; import io.xpipe.app.util.BooleanScope; @@ -309,12 +310,13 @@ public class ModalOverlayComp extends RegionBuilder { private ObservableDoubleValue modalBoxWidth(ModalPane pane, Region r) { return Bindings.createDoubleBinding( () -> { - var max = pane.getWidth() - 120; + var max = pane.getWidth() - (AppSizeBreakpoints.portraitMode().get() ? 30 : 120); if (r.getPrefWidth() != Region.USE_COMPUTED_SIZE) { return Math.min(max, r.getPrefWidth() + 50); } return max; }, + AppSizeBreakpoints.portraitMode(), pane.widthProperty(), r.prefWidthProperty()); } diff --git a/app/src/main/java/io/xpipe/app/hub/comp/DenseStoreEntryComp.java b/app/src/main/java/io/xpipe/app/hub/comp/DenseStoreEntryComp.java index c1b5633f4..823cf0191 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/DenseStoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/DenseStoreEntryComp.java @@ -10,6 +10,7 @@ import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; +import javafx.scene.control.OverrunStyle; import javafx.scene.layout.*; public class DenseStoreEntryComp extends StoreEntryComp { @@ -54,6 +55,9 @@ public class DenseStoreEntryComp extends StoreEntryComp { summary)); } + information.visibleProperty().bind(information.widthProperty().greaterThan(40)); + information.setTextOverrun(OverrunStyle.CLIP); + return information; } @@ -102,12 +106,26 @@ public class DenseStoreEntryComp extends StoreEntryComp { grid.add(storeIcon, 1, 0); grid.getColumnConstraints().add(new ColumnConstraints(34)); - var controlsSize = content != null ? 140 : 70; - var custom = new ColumnConstraints(0, controlsSize, controlsSize); + var contentRegion = content != null ? content.build() : null; + var customWidth = Bindings.createDoubleBinding(() -> { + if (AppSizeBreakpoints.compactMode().get()) { + return contentRegion != null && contentRegion.isVisible() ? 120.0 : 40.0; + } + + return contentRegion != null && contentRegion.isVisible() ? 140.0 : 70.0; + }, INFO_WIDTH, AppSizeBreakpoints.compactMode()); + var infoWidth = Bindings.createDoubleBinding(() -> { + return INFO_WIDTH.get() - (customWidth.get()); + }, INFO_WIDTH, customWidth); + + var custom = new ColumnConstraints(); + custom.setMinWidth(0); + custom.prefWidthProperty().bind(customWidth); + custom.maxWidthProperty().bind(custom.prefWidthProperty()); custom.setHalignment(HPos.RIGHT); var infoCC = new ColumnConstraints(); - infoCC.prefWidthProperty().bind(content != null ? INFO_WITH_CONTENT_WIDTH : INFO_NO_CONTENT_WIDTH); + infoCC.prefWidthProperty().bind(infoWidth); infoCC.setHalignment(HPos.LEFT); var nameCC = new ColumnConstraints(); @@ -132,7 +150,7 @@ public class DenseStoreEntryComp extends StoreEntryComp { grid.addRow(0, info); grid.getColumnConstraints().addAll(infoCC, custom); - var cr = content != null ? content.build() : new Region(); + var cr = contentRegion != null ? contentRegion : new Region(); cr.getStyleClass().add("custom-content"); var bb = createButtonBar(name); var controls = new HBox(cr, bb); diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StandardStoreEntryComp.java b/app/src/main/java/io/xpipe/app/hub/comp/StandardStoreEntryComp.java index 9c7e31535..d50f66183 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StandardStoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StandardStoreEntryComp.java @@ -11,6 +11,7 @@ import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; +import javafx.scene.control.OverrunStyle; import javafx.scene.layout.*; public class StandardStoreEntryComp extends StoreEntryComp { @@ -83,20 +84,30 @@ public class StandardStoreEntryComp extends StoreEntryComp { nameCC.setPrefWidth(100); grid.getColumnConstraints().addAll(nameCC); + var contentRegion = content != null ? content.build() : null; + var customWidth = Bindings.createDoubleBinding(() -> { + if (AppSizeBreakpoints.compactMode().get()) { + return contentRegion != null && contentRegion.isVisible() ? 125.0 : 55.0; + } + + return contentRegion != null && contentRegion.isVisible() ? 140.0 : 70.0; + }, INFO_WIDTH, AppSizeBreakpoints.compactMode()); + var infoWidth = Bindings.createDoubleBinding(() -> { + return INFO_WIDTH.get() - (customWidth.get()); + }, INFO_WIDTH, customWidth); + grid.add(createInformation(), 3, 0, 1, 2); var info = new ColumnConstraints(); - info.prefWidthProperty().bind(content != null ? INFO_WITH_CONTENT_WIDTH : INFO_NO_CONTENT_WIDTH); + info.prefWidthProperty().bind(infoWidth); info.setHalignment(HPos.LEFT); grid.getColumnConstraints().add(info); var custom = new ColumnConstraints(); custom.setMinWidth(0); - custom.prefWidthProperty().bind(Bindings.createDoubleBinding(() -> { - return AppSizeBreakpoints.compactMode().get() ? 10.0 : content != null ? 140.0 : 70.0; - }, AppSizeBreakpoints.compactMode())); + custom.prefWidthProperty().bind(customWidth); custom.maxWidthProperty().bind(custom.prefWidthProperty()); custom.setHalignment(HPos.RIGHT); - var cr = content != null ? content.build() : new Region(); + var cr = contentRegion != null ? contentRegion : new Region(); cr.getStyleClass().add("custom-content"); var bb = createButtonBar(name); var controls = new HBox(cr, bb); @@ -134,6 +145,9 @@ public class StandardStoreEntryComp extends StoreEntryComp { : RegionBuilder.empty(); information.setGraphic(state.build()); + information.visibleProperty().bind(information.widthProperty().greaterThan(40)); + information.setTextOverrun(OverrunStyle.CLIP); + return information; } } diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryComp.java index b035ba7bc..e17623f7d 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryComp.java @@ -49,29 +49,15 @@ public abstract class StoreEntryComp extends SimpleRegionBuilder { public static final PseudoClass FAILED = PseudoClass.getPseudoClass("failed"); public static final PseudoClass INCOMPLETE = PseudoClass.getPseudoClass("incomplete"); - public static final ObservableDoubleValue INFO_NO_CONTENT_WIDTH = Bindings.createDoubleBinding( - () -> { - var w = App.getApp().getStage().getWidth(); - var contentSpacer = AppSizeBreakpoints.compactMode().get() ? 10 : 70; - if (w > 2000) { - return (w / 1.8) - (240 - contentSpacer); - } else if (w >= 1000) { - return (w / 2.0) - (240 - contentSpacer); - } else { - return (w / 1.7) - (190 - contentSpacer); - } - }, - App.getApp().getStage().widthProperty(), - AppSizeBreakpoints.compactMode()); - public static final ObservableDoubleValue INFO_WITH_CONTENT_WIDTH = Bindings.createDoubleBinding( + public static final ObservableDoubleValue INFO_WIDTH = Bindings.createDoubleBinding( () -> { var w = App.getApp().getStage().getWidth(); if (w > 2000) { - return (w / 1.8) - 240; + return (w / 1.8) - 100; } else if (w >= 1000) { - return (w / 2.0) - 240; + return (w / 2.0) - 100; } else { - return (w / 1.7) - 190; + return (w / 1.7) - 50; } }, App.getApp().getStage().widthProperty()); @@ -801,6 +787,10 @@ public abstract class StoreEntryComp extends SimpleRegionBuilder { var branch = p instanceof HubBranchProvider b ? b : null; var cs = leaf != null ? leaf : branch; + if (cs == null || (leaf != null && leaf.isDefault())) { + return null; + } + var name = cs.getName(getWrapper().getEntry().ref()); var icon = cs.getIcon(getWrapper().getEntry().ref()); var item = branch != null diff --git a/app/src/main/resources/io/xpipe/app/resources/style/browser.css b/app/src/main/resources/io/xpipe/app/resources/style/browser.css index a6593d7da..da17002d7 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/browser.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/browser.css @@ -49,6 +49,15 @@ -fx-background-radius: 0 6 0 0; } +.browser .welcome { + -fx-padding: 40; +} + +.root:portrait .browser .welcome { + -fx-padding: 20; +} + + .browser .welcome .button:hover { -fx-background-color: -color-neutral-muted; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/modal-overlay-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/modal-overlay-comp.css index d385a65c6..792454c91 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/modal-overlay-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/modal-overlay-comp.css @@ -15,6 +15,10 @@ -fx-padding: 15 27 10 27; } +.root:portrait .modal-overlay-comp .modal-box > .content { + -fx-padding: 10 18 10 18; +} + .modal-overlay-comp .modal-box .button-bar .button { -fx-padding: 0.45em 0.8em 0.45em 0.8em; -fx-border-width: 1px;