From 4bf1ede5a8ac1037bb60f8071e2488c2507cdf3d Mon Sep 17 00:00:00 2001 From: crschnick Date: Wed, 29 Apr 2026 07:28:47 +0000 Subject: [PATCH] Rework --- .../io/xpipe/app/comp/base/PrettyImageComp.java | 7 ++++++- .../io/xpipe/app/comp/base/SideMenuBarComp.java | 7 ++++++- .../io/xpipe/app/core/window/AppMainWindow.java | 2 +- .../io/xpipe/app/core/window/AppSideWindow.java | 2 +- .../io/xpipe/app/core/window/AppWindowStyle.java | 4 ++-- .../io/xpipe/app/ext/ProcessControlProvider.java | 3 ++- .../main/java/io/xpipe/app/util/AskpassAlert.java | 10 ++++++++-- .../io/xpipe/app/util/RemoteDesktopDockComp.java | 12 ++++++++++-- .../app/util/RemoteDesktopDockContentEntry.java | 4 ++++ .../java/io/xpipe/app/util/RemoteDesktopWindow.java | 6 ++++-- .../java/io/xpipe/app/vnc/InternalVncClient.java | 13 ++++++++++--- 11 files changed, 54 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/io/xpipe/app/comp/base/PrettyImageComp.java b/app/src/main/java/io/xpipe/app/comp/base/PrettyImageComp.java index 5fb73203e..101d84e5b 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/PrettyImageComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/PrettyImageComp.java @@ -15,6 +15,7 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; +import java.lang.ref.WeakReference; import java.util.function.Consumer; public class PrettyImageComp extends SimpleRegionBuilder { @@ -113,8 +114,12 @@ public class PrettyImageComp extends SimpleRegionBuilder { value.subscribe(update); if (AppPrefs.get() != null) { + var ref = new WeakReference<>(update); AppPrefs.get().theme().addListener((observable, oldValue, newValue) -> { - update.accept(value.getValue()); + var v = ref.get(); + if (v != null) { + v.accept(value.getValue()); + } }); } diff --git a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java index 35b1ee029..7b59ca368 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java @@ -58,13 +58,18 @@ public class SideMenuBarComp extends RegionBuilder { value.setValue(e); } }); - b.describe(d -> d.name(e.name())); var stack = createStyle(e, b); var shortcut = e.combination(); if (shortcut != null) { stack.apply(struc -> struc.getProperties().put("shortcut", shortcut)); } + b.describe(d -> { + d.name(e.name()); + if (shortcut != null) { + d.shortcut(shortcut); + } + }); vbox.getChildren().add(stack.build()); } diff --git a/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java b/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java index c947bfafe..5bd4f85ba 100644 --- a/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java @@ -118,7 +118,7 @@ public class AppMainWindow { AppWindowStyle.addStylesheets(stage.getScene()); AppWindowStyle.addClickShield(stage); AppWindowStyle.addMaximizedPseudoClass(stage); - AppWindowStyle.addFontSize(stage); + AppWindowStyle.addFontSize(scene); AppTheme.initThemeHandlers(stage); AppWindowTitle.getTitle().subscribe(s -> { diff --git a/app/src/main/java/io/xpipe/app/core/window/AppSideWindow.java b/app/src/main/java/io/xpipe/app/core/window/AppSideWindow.java index 19c6d833a..c8357c666 100644 --- a/app/src/main/java/io/xpipe/app/core/window/AppSideWindow.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppSideWindow.java @@ -39,7 +39,7 @@ public class AppSideWindow { event.consume(); }); AppWindowBounds.fixInvalidStagePosition(s); - AppWindowStyle.addFontSize(s); + AppWindowStyle.addFontSize(s.getScene()); a.getDialogPane().getScene().addEventHandler(KeyEvent.KEY_PRESSED, event -> { if (new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN).match(event)) { s.close(); diff --git a/app/src/main/java/io/xpipe/app/core/window/AppWindowStyle.java b/app/src/main/java/io/xpipe/app/core/window/AppWindowStyle.java index 2af5a558a..4137a6f57 100644 --- a/app/src/main/java/io/xpipe/app/core/window/AppWindowStyle.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppWindowStyle.java @@ -27,8 +27,8 @@ public class AppWindowStyle { }); } - public static void addFontSize(Stage stage) { - stage.getScene().rootProperty().subscribe(root -> { + public static void addFontSize(Scene scene) { + scene.rootProperty().subscribe(root -> { AppFontSizes.base(root); }); } diff --git a/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java b/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java index 4177c05bd..6f4d847a1 100644 --- a/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java @@ -47,7 +47,8 @@ public abstract class ProcessControlProvider { public abstract ShellStore subShellEnvironment(DataStoreEntryRef s, ShellDialect dialect); public abstract RemoteDesktopDockContentEntry createVncSession( - DataStoreEntryRef ref + DataStoreEntryRef ref, + Runnable onKill ); public abstract DataStoreEntryRef elevated(DataStoreEntryRef e); diff --git a/app/src/main/java/io/xpipe/app/util/AskpassAlert.java b/app/src/main/java/io/xpipe/app/util/AskpassAlert.java index 8b3d3104f..5fa30d137 100644 --- a/app/src/main/java/io/xpipe/app/util/AskpassAlert.java +++ b/app/src/main/java/io/xpipe/app/util/AskpassAlert.java @@ -23,15 +23,21 @@ import javafx.stage.Window; public class AskpassAlert { public static SecretQueryResult queryRaw(String prompt, InPlaceSecretValue secretValue, boolean stealFocus) { + prompt = prompt.strip(); + if (prompt.endsWith(":") || prompt.endsWith("?")) { + prompt = prompt.substring(0, prompt.length() - 1); + } + var prop = new SimpleObjectProperty<>(secretValue); + var finalPrompt = prompt; var r = AppSideWindow.showBlockingAlert(alert -> { alert.initModality(Modality.NONE); alert.setTitle(AppI18n.get("askpassAlertTitle")); - alert.setHeaderText(prompt); + alert.setHeaderText(finalPrompt); alert.setAlertType(Alert.AlertType.CONFIRMATION); // Link to help page for double prompt - if (SecretManager.disableCachingForPrompt(prompt)) { + if (SecretManager.disableCachingForPrompt(finalPrompt)) { var type = new ButtonType("Help", ButtonBar.ButtonData.HELP); alert.getButtonTypes().add(type); var button = alert.getDialogPane().lookupButton(type); diff --git a/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockComp.java b/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockComp.java index a1a135a01..6eda4f10f 100644 --- a/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockComp.java +++ b/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockComp.java @@ -81,15 +81,20 @@ public class RemoteDesktopDockComp extends SimpleRegionBuilder { private void fillToolbar(Region content, ToolBar bar, List list) { var w = RemoteDesktopWindow.get(); + bar.getItems().forEach(node -> node.getProperties().clear()); bar.getItems().clear(); for (var entry : list) { + var entryRef = new WeakReference<>(entry); var graphic = PrettyImageHelper.ofFixedSizeSquare(entry.getIcon(), 16).style("graphic").build(); var label = new LabelComp(entry.getName()).build(); label.setGraphic(graphic); var close = new IconButtonComp("mdi2c-close", () -> { - w.close(entry); + var v = entryRef.get(); + if (v != null) { + w.close(v); + } }).style("close-button") .describe(d -> d.nameKey("close")).build(); AppFontSizes.sm(close); @@ -108,7 +113,10 @@ public class RemoteDesktopDockComp extends SimpleRegionBuilder { b.getStyleClass().add("tab-button"); b.getProperties().put("entry", entry); b.setOnAction(event -> { - w.select(entry); + var v = entryRef.get(); + if (v != null) { + w.select(v); + } event.consume(); }); bar.getItems().add(b); diff --git a/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockContentEntry.java b/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockContentEntry.java index 26372b783..b34df19d3 100644 --- a/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockContentEntry.java +++ b/app/src/main/java/io/xpipe/app/util/RemoteDesktopDockContentEntry.java @@ -6,6 +6,10 @@ import lombok.Getter; @Getter public abstract class RemoteDesktopDockContentEntry { + private final Runnable onKill; + + protected RemoteDesktopDockContentEntry(Runnable onKill) {this.onKill = onKill;} + public abstract BaseRegionBuilder comp(); public abstract void init() throws Exception; diff --git a/app/src/main/java/io/xpipe/app/util/RemoteDesktopWindow.java b/app/src/main/java/io/xpipe/app/util/RemoteDesktopWindow.java index 5815a1305..8b0b2f10d 100644 --- a/app/src/main/java/io/xpipe/app/util/RemoteDesktopWindow.java +++ b/app/src/main/java/io/xpipe/app/util/RemoteDesktopWindow.java @@ -115,7 +115,8 @@ public class RemoteDesktopWindow { AppWindowStyle.addStylesheets(stage.getScene()); AppWindowStyle.addClickShield(stage); AppWindowStyle.addMaximizedPseudoClass(stage); - AppWindowStyle.addFontSize(stage); + AppWindowStyle.addFontSize(scene); + AppWindowStyle.addNavigationPseudoClasses(scene); AppTheme.initThemeHandlers(stage); setupWindowListeners(); @@ -179,9 +180,10 @@ public class RemoteDesktopWindow { model.closeWindow(entry); } - public void trackInternal(String name, String icon, DataStoreColor color, DataStoreEntry e, RemoteDesktopDockContentEntry entry) { + public RemoteDesktopDockEntry trackInternal(String name, String icon, DataStoreColor color, DataStoreEntry e, RemoteDesktopDockContentEntry entry) { var toTrack = new RemoteDesktopDockEntry(name, icon, color, e, null, entry, null, null); model.track(toTrack); + return toTrack; } public void trackExternal(String name, String icon, DataStoreColor color, DataStoreEntry e, int w, int h, Process process, Duration maxWait, Predicate filter) { diff --git a/app/src/main/java/io/xpipe/app/vnc/InternalVncClient.java b/app/src/main/java/io/xpipe/app/vnc/InternalVncClient.java index 212389f34..d57181bc5 100644 --- a/app/src/main/java/io/xpipe/app/vnc/InternalVncClient.java +++ b/app/src/main/java/io/xpipe/app/vnc/InternalVncClient.java @@ -8,11 +8,14 @@ import io.xpipe.app.storage.DataStorage; import io.xpipe.app.util.DocumentationLink; import com.fasterxml.jackson.annotation.JsonTypeName; +import io.xpipe.app.util.RemoteDesktopDockEntry; import io.xpipe.app.util.RemoteDesktopWindow; import javafx.beans.property.ReadOnlyBooleanWrapper; import lombok.Builder; import lombok.extern.jackson.Jacksonized; +import java.util.concurrent.atomic.AtomicReference; + @Builder @Jacksonized @JsonTypeName("integratedXPipeVncClient") @@ -22,12 +25,16 @@ public class InternalVncClient implements ExternalVncClient { public void launch(VncLaunchConfig configuration) throws Exception { var w = RemoteDesktopWindow.get(); w.show(); - var session = ProcessControlProvider.get().createVncSession(configuration.getEntry()); - w.trackInternal(DataStorage.get().getStoreEntryDisplayName(configuration.getEntry().get()), + var ref = new AtomicReference(); + var session = ProcessControlProvider.get().createVncSession(configuration.getEntry(), () -> { + w.close(ref.get()); + }); + ref.set(w.trackInternal( + DataStorage.get().getStoreEntryDisplayName(configuration.getEntry().get()), configuration.getEntry().get().getEffectiveIconFile(), DataStorage.get().getEffectiveColor(configuration.getEntry().get()), configuration.getEntry().get(), - session); + session)); } @Override