From 5be0748c9f0d6491f6a41a10ff3b312f8635f4d7 Mon Sep 17 00:00:00 2001 From: crschnick Date: Sun, 30 Jul 2023 20:22:32 +0000 Subject: [PATCH] Add ssh config support plus polishing --- .../app/comp/base/IntegratedTextAreaComp.java | 17 +++++++++++------ .../comp/storage/store/DenseStoreEntryComp.java | 4 ++-- .../storage/store/StandardStoreEntryComp.java | 4 ++-- .../xpipe/app/fxcomps/impl/ChoicePaneComp.java | 11 ++++++----- .../java/io/xpipe/app/fxcomps/impl/SvgView.java | 2 +- .../main/java/io/xpipe/app/util/JfxHelper.java | 4 ++-- .../java/io/xpipe/app/util/OptionsBuilder.java | 12 ++++++++---- .../app/util/SecretRetrievalStrategyHelper.java | 3 ++- .../main/java/io/xpipe/core/dialog/Dialog.java | 6 +----- .../io/xpipe/core/process/ShellControl.java | 6 +++--- .../io/xpipe/core/util/FailableSupplier.java | 6 ++++++ .../java/io/xpipe/core/util/UuidHelper.java | 4 +--- dist/changelogs/1.5.0.md | 8 +++++--- 13 files changed, 50 insertions(+), 37 deletions(-) create mode 100644 core/src/main/java/io/xpipe/core/util/FailableSupplier.java diff --git a/app/src/main/java/io/xpipe/app/comp/base/IntegratedTextAreaComp.java b/app/src/main/java/io/xpipe/app/comp/base/IntegratedTextAreaComp.java index 0064438b..b6c1b390 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/IntegratedTextAreaComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/IntegratedTextAreaComp.java @@ -7,6 +7,7 @@ import io.xpipe.app.fxcomps.impl.TextAreaComp; import io.xpipe.app.util.FileOpener; import javafx.application.Platform; import javafx.beans.property.Property; +import javafx.beans.value.ObservableValue; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; @@ -18,9 +19,10 @@ public class IntegratedTextAreaComp extends SimpleComp { private final Property value; private final boolean lazy; private final String identifier; - private final String fileType; + private final ObservableValue fileType; - public IntegratedTextAreaComp(Property value, boolean lazy, String identifier, String fileType) { + public IntegratedTextAreaComp( + Property value, boolean lazy, String identifier, ObservableValue fileType) { this.value = value; this.lazy = lazy; this.identifier = identifier; @@ -47,12 +49,15 @@ public class IntegratedTextAreaComp extends SimpleComp { } private Region createOpenButton(Region container) { - var name = identifier + (fileType != null ? "." + fileType : ""); var button = new IconButtonComp( "mdal-edit", - () -> FileOpener.openString(name, this, value.getValue(), (s) -> { - Platform.runLater(() -> value.setValue(s)); - })) + () -> FileOpener.openString( + identifier + (fileType.getValue() != null ? "." + fileType.getValue() : ""), + this, + value.getValue(), + (s) -> { + Platform.runLater(() -> value.setValue(s)); + })) .createRegion(); return button; } diff --git a/app/src/main/java/io/xpipe/app/comp/storage/store/DenseStoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/storage/store/DenseStoreEntryComp.java index c5230dc3..af74ace7 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/store/DenseStoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/store/DenseStoreEntryComp.java @@ -23,8 +23,8 @@ public class DenseStoreEntryComp extends StoreEntryComp { grid.setHgap(8); if (showIcon) { - var storeIcon = createIcon(30, 25); - grid.getColumnConstraints().add(new ColumnConstraints(30)); + var storeIcon = createIcon(26, 21); + grid.getColumnConstraints().add(new ColumnConstraints(26)); grid.add(storeIcon, 0, 0); GridPane.setHalignment(storeIcon, HPos.CENTER); } else { diff --git a/app/src/main/java/io/xpipe/app/comp/storage/store/StandardStoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/storage/store/StandardStoreEntryComp.java index b8a8625e..e8909911 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/store/StandardStoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/store/StandardStoreEntryComp.java @@ -17,10 +17,10 @@ public class StandardStoreEntryComp extends StoreEntryComp { var name = createName().createRegion(); var grid = new GridPane(); - grid.setHgap(10); + grid.setHgap(7); grid.setVgap(0); - var storeIcon = createIcon(45, 35); + var storeIcon = createIcon(50, 39); grid.add(storeIcon, 0, 0, 1, 2); grid.getColumnConstraints().add(new ColumnConstraints(50)); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoicePaneComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoicePaneComp.java index 0f34be51..f1cf8591 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoicePaneComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoicePaneComp.java @@ -1,6 +1,5 @@ package io.xpipe.app.fxcomps.impl; -import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.SimpleCompStructure; @@ -37,8 +36,8 @@ public class ChoicePaneComp extends Comp> { cb.setConverter(new StringConverter<>() { @Override public String toString(Entry object) { - if (object == null) { - return AppI18n.get("app.none"); + if (object == null || object.name() == null) { + return ""; } return object.name().getValue(); @@ -53,9 +52,11 @@ public class ChoicePaneComp extends Comp> { var vbox = new VBox(transformer.apply(cb)); vbox.setFillWidth(true); cb.prefWidthProperty().bind(vbox.widthProperty()); - SimpleChangeListener.apply(cb.valueProperty(), n-> { + SimpleChangeListener.apply(cb.valueProperty(), n -> { if (n == null) { - vbox.getChildren().remove(1); + if (vbox.getChildren().size() > 1) { + vbox.getChildren().remove(1); + } } else { var region = n.comp().createRegion(); region.setPadding(new Insets(0, 0, 0, 10)); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgView.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgView.java index 8b4aa1ba..d51f89b2 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgView.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgView.java @@ -93,7 +93,7 @@ public class SvgView { private WebView createWebView() { var wv = new WebView(); - // Sometimes a web view might not render when the background is said to transparent, at least according to stack + // Sometimes a web view might not render when the background is set to transparent, at least according to stack // overflow wv.setPageFill(Color.valueOf("#00000001")); // wv.setPageFill(Color.BLACK); diff --git a/app/src/main/java/io/xpipe/app/util/JfxHelper.java b/app/src/main/java/io/xpipe/app/util/JfxHelper.java index 6c60f2fb..fe58f6b9 100644 --- a/app/src/main/java/io/xpipe/app/util/JfxHelper.java +++ b/app/src/main/java/io/xpipe/app/util/JfxHelper.java @@ -69,12 +69,12 @@ public class JfxHelper { return text; } - var size = AppFont.getPixelSize(1) + AppFont.getPixelSize(-2) + 2; + var size = AppFont.getPixelSize(1) + AppFont.getPixelSize(-2) + 8; var graphic = new PrettyImageComp(new SimpleStringProperty(image), size, size).createRegion(); var hbox = new HBox(graphic, text); hbox.setAlignment(Pos.CENTER_LEFT); - hbox.setSpacing(8); + hbox.setSpacing(10); // graphic.fitWidthProperty().bind(Bindings.createDoubleBinding(() -> header.getHeight() + // desc.getHeight() + 2, diff --git a/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java b/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java index ac27b4df..1722ccda 100644 --- a/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java +++ b/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java @@ -48,11 +48,11 @@ public class OptionsBuilder { public OptionsBuilder choice(IntegerProperty selectedIndex, Map options) { var list = options.entrySet().stream() .map(e -> new ChoicePaneComp.Entry( - AppI18n.observable(e.getKey()), e.getValue().buildComp())) + AppI18n.observable(e.getKey()), e.getValue() != null ? e.getValue().buildComp() : Comp.empty())) .toList(); var validatorList = - options.values().stream().map(builder -> builder.buildEffectiveValidator()).toList(); - var selected = new SimpleObjectProperty<>(list.get(selectedIndex.getValue())); + options.values().stream().map(builder -> builder != null ? builder.buildEffectiveValidator() : new SimpleValidator()).toList(); + var selected = new SimpleObjectProperty<>(selectedIndex.getValue() != -1 ? list.get(selectedIndex.getValue()) : null); selected.addListener((observable, oldValue, newValue) -> { selectedIndex.setValue(newValue != null ? list.indexOf(newValue) : null); }); @@ -65,7 +65,11 @@ public class OptionsBuilder { validatorMap.put(null, new SimpleValidator()); var orVal = new ExclusiveValidator<>(validatorMap, selected); - options.values().forEach(builder -> props.addAll(builder.props)); + options.values().forEach(builder -> { + if (builder != null) { + props.addAll(builder.props); + } + }); props.add(selectedIndex); allValidators.add(orVal); pushComp(pane); diff --git a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java index d5d41582..8a8a39d0 100644 --- a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java +++ b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategyHelper.java @@ -86,7 +86,7 @@ public class SecretRetrievalStrategyHelper { ? 1 : strat instanceof SecretRetrievalStrategy.PasswordManager ? 2 - : strat instanceof SecretRetrievalStrategy.CustomCommand ? 3 : strat instanceof SecretRetrievalStrategy.Prompt ? 4 : 0); + : strat instanceof SecretRetrievalStrategy.CustomCommand ? 3 : strat instanceof SecretRetrievalStrategy.Prompt ? 4 : strat == null ? -1 : 0); return new OptionsBuilder() .choice(selected, map) .bindChoice( @@ -97,6 +97,7 @@ public class SecretRetrievalStrategyHelper { case 2 -> passwordManager; case 3 -> customCommand; case 4 -> new SimpleObjectProperty<>(new SecretRetrievalStrategy.Prompt()); + case 5 -> new SimpleObjectProperty<>(); default -> new SimpleObjectProperty<>(); }; }, diff --git a/core/src/main/java/io/xpipe/core/dialog/Dialog.java b/core/src/main/java/io/xpipe/core/dialog/Dialog.java index 847d2f42..c2d9f950 100644 --- a/core/src/main/java/io/xpipe/core/dialog/Dialog.java +++ b/core/src/main/java/io/xpipe/core/dialog/Dialog.java @@ -1,6 +1,7 @@ package io.xpipe.core.dialog; import io.xpipe.core.charsetter.Charsetter; +import io.xpipe.core.util.FailableSupplier; import io.xpipe.core.util.SecretValue; import java.util.ArrayList; @@ -457,11 +458,6 @@ public abstract class Dialog { protected abstract DialogElement next(String answer) throws Exception; - public interface FailableSupplier { - - T get() throws Exception; - } - public static class Choice extends Dialog { private final ChoiceElement element; diff --git a/core/src/main/java/io/xpipe/core/process/ShellControl.java b/core/src/main/java/io/xpipe/core/process/ShellControl.java index 196a589b..62f263b9 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellControl.java +++ b/core/src/main/java/io/xpipe/core/process/ShellControl.java @@ -1,7 +1,7 @@ package io.xpipe.core.process; -import io.xpipe.core.dialog.Dialog; import io.xpipe.core.util.FailableFunction; +import io.xpipe.core.util.FailableSupplier; import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.XPipeSystemId; import lombok.NonNull; @@ -99,7 +99,7 @@ public interface ShellControl extends ProcessControl { default ShellControl elevationPassword(SecretValue value) { return elevationPassword(() -> value); } - ShellControl elevationPassword(Dialog.FailableSupplier value); + ShellControl elevationPassword(FailableSupplier value); ShellControl initWith(String cmds); @@ -107,7 +107,7 @@ public interface ShellControl extends ProcessControl { ShellControl startTimeout(int ms); - Dialog.FailableSupplier getElevationPassword(); + FailableSupplier getElevationPassword(); default ShellControl subShell(@NonNull ShellDialect type) { return subShell(p -> type.getOpenCommand(), new TerminalOpenFunction() { diff --git a/core/src/main/java/io/xpipe/core/util/FailableSupplier.java b/core/src/main/java/io/xpipe/core/util/FailableSupplier.java new file mode 100644 index 00000000..a530fbf7 --- /dev/null +++ b/core/src/main/java/io/xpipe/core/util/FailableSupplier.java @@ -0,0 +1,6 @@ +package io.xpipe.core.util; + +public interface FailableSupplier { + + T get() throws Exception; +} diff --git a/core/src/main/java/io/xpipe/core/util/UuidHelper.java b/core/src/main/java/io/xpipe/core/util/UuidHelper.java index 73903243..ff03f8c2 100644 --- a/core/src/main/java/io/xpipe/core/util/UuidHelper.java +++ b/core/src/main/java/io/xpipe/core/util/UuidHelper.java @@ -1,7 +1,5 @@ package io.xpipe.core.util; -import io.xpipe.core.dialog.Dialog; - import java.util.Optional; import java.util.UUID; @@ -15,7 +13,7 @@ public class UuidHelper { } } - public static Optional parse(Dialog.FailableSupplier supplier) { + public static Optional parse(FailableSupplier supplier) { try { var s = supplier.get(); return Optional.of(UUID.fromString(s)); diff --git a/dist/changelogs/1.5.0.md b/dist/changelogs/1.5.0.md index 985e4035..dbcf2048 100644 --- a/dist/changelogs/1.5.0.md +++ b/dist/changelogs/1.5.0.md @@ -29,9 +29,10 @@ To start off, it comes with a few new commands to read and write files on remote The workflow is designed as follows: -1. You can list all available connections and their ids to use with `xpipe list` -2. Using the command `xpipe drain `, you are able to forward the file contents to the stdout -3. Using the command `xpipe sink `, you are able to forward content from your stdin to the remote file +- You can list all available connections and their ids to use with `xpipe list` +- Using the command `xpipe launch `, you are able to log into a remote shell connection in your existing terminal session +- Using the command `xpipe drain `, you are able to forward the file contents to the stdout +- Using the command `xpipe sink `, you are able to forward content from your stdin to the remote file The id system is flexible, allowing you to only specify as much of the id as is necessary. @@ -64,6 +65,7 @@ This also comes with full support of the feature set for these environments - Fix desktop directory not being determined correctly on Windows when it was moved from the default location - Rework threading in navigation bar in browser to improve responsiveness - Recheck if prepared update is still the latest one prior to installing it +- Properly use shell script file extension for external editor when creating shell environments - Built-in documentation popups now honour the dark mode setting - Properly detect applications such as editors and terminals when they are present in the path on Windows - Rework operation mode handling to properly honor the startup mode setting