Add ssh config support plus polishing

This commit is contained in:
crschnick 2023-07-30 20:22:32 +00:00
parent c70d6da314
commit 5be0748c9f
13 changed files with 50 additions and 37 deletions

View file

@ -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<String> value;
private final boolean lazy;
private final String identifier;
private final String fileType;
private final ObservableValue<String> fileType;
public IntegratedTextAreaComp(Property<String> value, boolean lazy, String identifier, String fileType) {
public IntegratedTextAreaComp(
Property<String> value, boolean lazy, String identifier, ObservableValue<String> 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;
}

View file

@ -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 {

View file

@ -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));

View file

@ -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<CompStructure<VBox>> {
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<CompStructure<VBox>> {
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));

View file

@ -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);

View file

@ -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,

View file

@ -48,11 +48,11 @@ public class OptionsBuilder {
public OptionsBuilder choice(IntegerProperty selectedIndex, Map<String, OptionsBuilder> 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);

View file

@ -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<>();
};
},

View file

@ -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> {
T get() throws Exception;
}
public static class Choice extends Dialog {
private final ChoiceElement element;

View file

@ -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<SecretValue> value);
ShellControl elevationPassword(FailableSupplier<SecretValue> value);
ShellControl initWith(String cmds);
@ -107,7 +107,7 @@ public interface ShellControl extends ProcessControl {
ShellControl startTimeout(int ms);
Dialog.FailableSupplier<SecretValue> getElevationPassword();
FailableSupplier<SecretValue> getElevationPassword();
default ShellControl subShell(@NonNull ShellDialect type) {
return subShell(p -> type.getOpenCommand(), new TerminalOpenFunction() {

View file

@ -0,0 +1,6 @@
package io.xpipe.core.util;
public interface FailableSupplier<T> {
T get() throws Exception;
}

View file

@ -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<UUID> parse(Dialog.FailableSupplier<String> supplier) {
public static Optional<UUID> parse(FailableSupplier<String> supplier) {
try {
var s = supplier.get();
return Optional.of(UUID.fromString(s));

View file

@ -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 <id> <remote file path>`, you are able to forward the file contents to the stdout
3. Using the command `xpipe sink <id> <remote file path>`, 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 <id>`, you are able to log into a remote shell connection in your existing terminal session
- Using the command `xpipe drain <id> <remote file path>`, you are able to forward the file contents to the stdout
- Using the command `xpipe sink <id> <remote file path>`, 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