From 00cdda34c85263f5bc744bd77f5cfecdacd6cc9b Mon Sep 17 00:00:00 2001 From: crschnick Date: Fri, 6 Jun 2025 06:51:03 +0000 Subject: [PATCH] Fixes --- .../app/browser/BrowserFullSessionComp.java | 5 +- .../app/browser/BrowserSessionTabsComp.java | 24 +++++---- .../xpipe/app/comp/base/LoadingIconComp.java | 18 ++++--- .../app/comp/base/LoadingOverlayComp.java | 51 +++++++++---------- .../xpipe/app/comp/base/ModalOverlayComp.java | 2 +- .../app/comp/store/DenseStoreEntryComp.java | 3 +- .../comp/store/StandardStoreEntryComp.java | 2 +- .../xpipe/app/comp/store/StoreEntryComp.java | 25 ++++++--- .../io/xpipe/app/util/ScanDialogBase.java | 2 +- .../io/xpipe/app/resources/style/browser.css | 11 +++- .../io/xpipe/app/resources/style/style.css | 4 +- 11 files changed, 86 insertions(+), 61 deletions(-) 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 ffc417591..b80ab6cd1 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFullSessionComp.java @@ -8,6 +8,7 @@ import io.xpipe.app.comp.SimpleComp; 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.AppFontSizes; import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.core.window.AppMainWindow; import io.xpipe.app.ext.ShellStore; @@ -61,9 +62,9 @@ public class BrowserFullSessionComp extends SimpleComp { .bind(Bindings.createObjectBinding( () -> new Insets(tabs.getHeaderHeight().get(), 0, 0, 0), tabs.getHeaderHeight())); }); - var loadingIndicator = LoadingOverlayComp.noProgress(Comp.empty(), model.getBusy()) + var loadingIndicator = new LoadingIconComp(model.getBusy(), AppFontSizes::xxxl) .apply(struc -> { - AnchorPane.setTopAnchor(struc.get(), 3.0); + AnchorPane.setTopAnchor(struc.get(), 0.0); AnchorPane.setRightAnchor(struc.get(), 0.0); }) .styleClass("tab-loading-indicator"); 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 5eba37c95..d43fb47c4 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserSessionTabsComp.java @@ -4,6 +4,7 @@ import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.SimpleComp; import io.xpipe.app.comp.base.LoadingIconComp; import io.xpipe.app.comp.base.PrettyImageHelper; +import io.xpipe.app.comp.base.StackComp; import io.xpipe.app.core.App; import io.xpipe.app.core.AppFontSizes; import io.xpipe.app.core.AppI18n; @@ -419,17 +420,20 @@ public class BrowserSessionTabsComp extends SimpleComp { }); if (tabModel.getIcon() != null) { - var loading = new LoadingIconComp(tabModel.getBusy(), AppFontSizes::base).createRegion(); - loading.setPrefWidth(16); - loading.setPrefHeight(16); + var loading = new LoadingIconComp(tabModel.getBusy(), AppFontSizes::base); + loading.prefWidth(16); + loading.prefHeight(16); + var image = tabModel.getIcon(); - var logo = PrettyImageHelper.ofFixedSizeSquare(image, 16).createRegion(); - tab.graphicProperty() - .bind(Bindings.createObjectBinding( - () -> { - return tabModel.getBusy().get() ? loading : logo; - }, - PlatformThread.sync(tabModel.getBusy()))); + var logo = PrettyImageHelper.ofFixedSizeSquare(image, 16); + logo.apply(struc -> { + struc.get().opacityProperty().bind(PlatformThread.sync(Bindings.createDoubleBinding(() -> { + return !tabModel.getBusy().get() ? 1.0 : 0.15; + }, tabModel.getBusy()))); + }); + + var stack = new StackComp(List.of(logo, loading)); + tab.setGraphic(stack.createRegion()); } if (tabModel.getBrowserModel() instanceof BrowserFullSessionModel sessionModel) { diff --git a/app/src/main/java/io/xpipe/app/comp/base/LoadingIconComp.java b/app/src/main/java/io/xpipe/app/comp/base/LoadingIconComp.java index 16d2afb10..d287fe56d 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/LoadingIconComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/LoadingIconComp.java @@ -43,6 +43,9 @@ public class LoadingIconComp extends SimpleComp { label.setText(Character.toString(chars[0])); label.getStyleClass().add("loading-icon-comp"); + label.setPrefWidth(16); + label.setPrefHeight(16); + var timer = new AnimationTimer() { long init = 0; @@ -55,7 +58,7 @@ public class LoadingIconComp extends SimpleComp { } var nowMs = now; - if ((nowMs - init) > 300 * 1_000_000L) { + if ((nowMs - init) > 250 * 1_000_000L) { label.setText(Character.toString(chars[index])); init = nowMs; index = (index + 1) % chars.length; @@ -64,11 +67,14 @@ public class LoadingIconComp extends SimpleComp { }; show.subscribe(val -> { - if (val) { - timer.start(); - } else { - timer.stop(); - } + PlatformThread.runLaterIfNeeded(() -> { + label.setVisible(val); + if (val) { + timer.start(); + } else { + timer.stop(); + } + }); }); return label; diff --git a/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java b/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java index 41c6ed435..0b07adb4e 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java @@ -4,8 +4,6 @@ import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.CompStructure; import io.xpipe.app.comp.SimpleCompStructure; import io.xpipe.app.core.AppFontSizes; -import io.xpipe.app.prefs.AppPrefs; -import io.xpipe.app.util.PlatformThread; import io.xpipe.app.util.ThreadHelper; import javafx.application.Platform; @@ -15,22 +13,16 @@ import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.layout.StackPane; -import atlantafx.base.controls.RingProgressIndicator; - public class LoadingOverlayComp extends Comp> { private final Comp comp; - private final ObservableValue showLoading; - private final ObservableValue progress; + private final ObservableValue loading; + private final boolean showIcon; - public LoadingOverlayComp(Comp comp, ObservableValue loading, ObservableValue progress) { + public LoadingOverlayComp(Comp comp, ObservableValue loading, boolean showIcon) { this.comp = comp; - this.showLoading = PlatformThread.sync(loading); - this.progress = PlatformThread.sync(progress); - } - - public static LoadingOverlayComp noProgress(Comp comp, ObservableValue loading) { - return new LoadingOverlayComp(comp, loading, new SimpleDoubleProperty(-1)); + this.loading = loading; + this.showIcon = showIcon; } @Override @@ -38,11 +30,22 @@ public class LoadingOverlayComp extends Comp> { var compStruc = comp.createStructure(); var r = compStruc.get(); - var loading = new LoadingIconComp(showLoading, AppFontSizes::xxxl).createRegion(); - - var loadingOverlay = new StackPane(loading); + var loadingOverlay = new StackPane(); + if (showIcon) { + var loading = new LoadingIconComp(this.loading, AppFontSizes::title).createRegion(); + loading.prefWidthProperty() + .bind(Bindings.createDoubleBinding( + () -> { + return Math.min(r.getHeight() - 20, 50); + }, + r.heightProperty())); + loading.prefHeightProperty().bind(loading.prefWidthProperty()); + loading.managedProperty().bind(loading.visibleProperty()); + loadingOverlay.getChildren().add(loading); + } loadingOverlay.getStyleClass().add("loading-comp"); - loadingOverlay.setVisible(showLoading.getValue()); + loadingOverlay.setVisible(showIcon && this.loading.getValue()); + loadingOverlay.setManaged(showIcon && this.loading.getValue()); var listener = new ChangeListener() { @Override @@ -55,7 +58,7 @@ public class LoadingOverlayComp extends Comp> { } catch (InterruptedException ignored) { } - if (!showLoading.getValue()) { + if (!LoadingOverlayComp.this.loading.getValue()) { Platform.runLater(() -> { loadingOverlay.setVisible(false); loadingOverlay.setManaged(false); @@ -69,7 +72,7 @@ public class LoadingOverlayComp extends Comp> { } catch (InterruptedException ignored) { } - if (showLoading.getValue()) { + if (LoadingOverlayComp.this.loading.getValue()) { Platform.runLater(() -> { loadingOverlay.setVisible(true); loadingOverlay.setManaged(true); @@ -79,18 +82,10 @@ public class LoadingOverlayComp extends Comp> { } } }; - showLoading.addListener(listener); + this.loading.addListener(listener); var stack = new StackPane(r, loadingOverlay); - loading.prefWidthProperty() - .bind(Bindings.createDoubleBinding( - () -> { - return Math.min(r.getHeight() - 20, 50); - }, - r.heightProperty())); - loading.prefHeightProperty().bind(loading.prefWidthProperty()); - stack.prefWidthProperty().bind(r.prefWidthProperty()); stack.prefHeightProperty().bind(r.prefHeightProperty()); 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 cd0f90ecc..a9d45412f 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 @@ -250,7 +250,7 @@ public class ModalOverlayComp extends SimpleComp { if (newValue.getContent() instanceof ModalOverlayContentComp mocc) { var busy = mocc.busy(); if (busy != null) { - var loading = LoadingOverlayComp.noProgress(Comp.of(() -> modalBox), busy); + var loading = new LoadingOverlayComp(Comp.of(() -> modalBox), busy, true); return loading.createRegion(); } } 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 4e68f9d10..368a1d56d 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 @@ -2,6 +2,7 @@ package io.xpipe.app.comp.store; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.augment.GrowAugment; +import io.xpipe.app.core.AppFontSizes; import io.xpipe.app.util.PlatformThread; import io.xpipe.core.process.OsType; @@ -88,7 +89,7 @@ public class DenseStoreEntryComp extends StoreEntryComp { } }); - var storeIcon = createIcon(28, 24); + var storeIcon = createIcon(28, 24, AppFontSizes::xxxl); GridPane.setHalignment(storeIcon, HPos.CENTER); grid.add(storeIcon, 1, 0); grid.getColumnConstraints().add(new ColumnConstraints(34)); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StandardStoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/StandardStoreEntryComp.java index 9cea0fd31..d271277fc 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StandardStoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StandardStoreEntryComp.java @@ -54,7 +54,7 @@ public class StandardStoreEntryComp extends StoreEntryComp { } }); - var storeIcon = createIcon(46, 40); + var storeIcon = createIcon(46, 40, AppFontSizes::title); grid.add(storeIcon, 1, 0, 1, 2); grid.getColumnConstraints().add(new ColumnConstraints(52)); 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 10187c6f2..46ae9d6e7 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 @@ -5,9 +5,7 @@ import io.xpipe.app.comp.SimpleComp; import io.xpipe.app.comp.SimpleCompStructure; import io.xpipe.app.comp.augment.ContextMenuAugment; import io.xpipe.app.comp.augment.GrowAugment; -import io.xpipe.app.comp.base.IconButtonComp; -import io.xpipe.app.comp.base.LabelComp; -import io.xpipe.app.comp.base.LoadingOverlayComp; +import io.xpipe.app.comp.base.*; import io.xpipe.app.core.*; import io.xpipe.app.ext.ActionProvider; import io.xpipe.app.prefs.AppPrefs; @@ -20,6 +18,7 @@ import io.xpipe.app.util.*; import io.xpipe.core.process.OsType; import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ObservableDoubleValue; import javafx.css.PseudoClass; import javafx.geometry.Insets; @@ -37,6 +36,8 @@ import org.kordamp.ikonli.javafx.FontIcon; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; public abstract class StoreEntryComp extends SimpleComp { @@ -154,8 +155,8 @@ public abstract class StoreEntryComp extends SimpleComp { () -> this.createContextMenu()) .augment(button); - var loading = LoadingOverlayComp.noProgress( - Comp.of(() -> button), getWrapper().getEffectiveBusy()); + var loading = new LoadingOverlayComp( + Comp.of(() -> button), getWrapper().getEffectiveBusy(), false); if (OsType.getLocal() == OsType.MACOS) { AppFontSizes.base(button); } else if (OsType.getLocal() == OsType.LINUX) { @@ -212,8 +213,18 @@ public abstract class StoreEntryComp extends SimpleComp { return button; } - protected Node createIcon(int w, int h) { - return new StoreIconComp(getWrapper(), w, h).createRegion(); + protected Node createIcon(int w, int h, Consumer fontSize) { + var icon = new StoreIconComp(getWrapper(), w, h); + icon.apply(struc -> { + struc.get().opacityProperty().bind(Bindings.createDoubleBinding(() -> { + return !getWrapper().getEffectiveBusy().get() ? 1.0 : 0.15; + }, getWrapper().getEffectiveBusy())); + }); + var loading = new LoadingIconComp(getWrapper().getEffectiveBusy(), fontSize); + loading.prefWidth(w); + loading.prefHeight(h); + var stack = new StackComp(List.of(icon, loading)); + return stack.createRegion(); } protected Region createButtonBar() { diff --git a/app/src/main/java/io/xpipe/app/util/ScanDialogBase.java b/app/src/main/java/io/xpipe/app/util/ScanDialogBase.java index 52a7b52bc..779f9de06 100644 --- a/app/src/main/java/io/xpipe/app/util/ScanDialogBase.java +++ b/app/src/main/java/io/xpipe/app/util/ScanDialogBase.java @@ -144,7 +144,7 @@ public class ScanDialogBase { onUpdate(); entries.addListener((ListChangeListener>) c -> onUpdate()); - var comp = LoadingOverlayComp.noProgress(Comp.of(() -> stackPane), busy).vgrow(); + var comp = new LoadingOverlayComp(Comp.of(() -> stackPane), busy, true).vgrow(); return comp; } } 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 765f35c71..a55a11c2e 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 @@ -190,6 +190,14 @@ -fx-text-fill: transparent; } +.browser .overview .simple-titled-pane-comp { + -fx-background-radius: 4; +} + +.root:nord .browser .overview .simple-titled-pane-comp { + -fx-background-radius: 0; +} + .browser .overview-file-list { -fx-border-width: 0; } @@ -231,14 +239,13 @@ -fx-opacity: 0; } -.browser .tab-loading-indicator .loading-comp { +.browser .tab-loading-indicator { -fx-min-width: 2.5em; -fx-pref-width: 2.5em; -fx-max-width: 2.5em; -fx-min-height: 2.5em; -fx-pref-height: 2.5em; -fx-max-height: 2.5em; - -fx-background-color: transparent; } .browser.chooser .left { diff --git a/app/src/main/resources/io/xpipe/app/resources/style/style.css b/app/src/main/resources/io/xpipe/app/resources/style/style.css index d8a229982..c7d10f08a 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/style.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/style.css @@ -64,11 +64,11 @@ } .root:light .loading-comp { - -fx-background-color: rgba(100, 100, 100, 0.5); + -fx-background-color: rgba(100, 100, 100, 0.3); } .root:dark .loading-comp { - -fx-background-color: rgba(0, 0, 0, 0.5); + -fx-background-color: rgba(0, 0, 0, 0.4); } .icon-browser {