This commit is contained in:
crschnick 2025-04-13 18:00:58 +00:00
parent 8b75699649
commit a50869da6d
79 changed files with 298 additions and 292 deletions

View file

@ -2,9 +2,7 @@ package io.xpipe.app.beacon;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.resources.AppResources;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.MarkdownHelper;
import io.xpipe.beacon.BeaconConfig;
import io.xpipe.beacon.BeaconInterface;
import io.xpipe.core.process.OsType;
@ -18,14 +16,12 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
public class AppBeaconServer {

View file

@ -1,7 +1,6 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.TerminalPrepareExchange;
import com.sun.net.httpserver.HttpExchange;
@ -9,7 +8,7 @@ import com.sun.net.httpserver.HttpExchange;
public class TerminalPrepareExchangeImpl extends TerminalPrepareExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) throws BeaconClientException {
public Object handle(HttpExchange exchange, Request msg) {
var term = AppPrefs.get().terminalType().getValue();
var unicode = term.supportsUnicode();
var escapes = term.supportsEscapes();

View file

@ -221,20 +221,24 @@ public class BrowserSessionTabsComp extends SimpleComp {
() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
return
new Insets(2, 0, 4, -leftPadding.get() + 3);
return new Insets(2, 0, 4, -leftPadding.get() + 3);
} else {
return new Insets(2, 0, 4, -leftPadding.get() - 4);
}
}, App.getApp().getStage().widthProperty(), leftPadding));
tabs.paddingProperty().bind(Bindings.createObjectBinding(() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
return new Insets(0, 0, 0, -5);
} else {
return new Insets(0, 0, 0, 5);
}
}, App.getApp().getStage().widthProperty()));
},
App.getApp().getStage().widthProperty(),
leftPadding));
tabs.paddingProperty()
.bind(Bindings.createObjectBinding(
() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
return new Insets(0, 0, 0, -5);
} else {
return new Insets(0, 0, 0, 5);
}
},
App.getApp().getStage().widthProperty()));
headerHeight.bind(headerArea.heightProperty());
});
}

View file

@ -489,10 +489,8 @@ public final class BrowserFileListComp extends SimpleComp {
}
var hasOwner = fileList.getAll().getValue().stream()
.map(browserEntry -> formatOwner(browserEntry))
.filter(s -> s != null)
.count()
> 0;
.map(browserEntry -> formatOwner(browserEntry))
.anyMatch(s -> s != null);
if (hasOwner) {
ownerCol.setPrefWidth(fileList.getAll().getValue().stream()
.map(browserEntry -> formatOwner(browserEntry))

View file

@ -64,9 +64,9 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
fileList = new BrowserFileListModel(selectionMode, this);
}
public Optional<FileEntry> findFile(String path) {
public Optional<FileEntry> findFile(FilePath path) {
return getFileList().getAll().getValue().stream()
.filter(browserEntry -> browserEntry.getFileName().equals(path)
.filter(browserEntry -> browserEntry.getFileName().equals(path.toString())
|| browserEntry.getRawFileEntry().getPath().equals(path))
.findFirst()
.map(browserEntry -> browserEntry.getRawFileEntry());

View file

@ -13,7 +13,6 @@ import io.xpipe.app.util.PlatformThread;
import io.xpipe.core.process.OsType;
import javafx.animation.Animation;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.geometry.Pos;
import javafx.scene.image.ImageView;

View file

@ -3,7 +3,6 @@ package io.xpipe.app.comp.base;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.control.SplitPane;

View file

@ -11,7 +11,6 @@ import io.xpipe.core.process.OsType;
import javafx.animation.*;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ObservableDoubleValue;

View file

@ -3,7 +3,6 @@ package io.xpipe.app.comp.store;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.augment.GrowAugment;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.util.Rect;
import io.xpipe.core.process.OsType;
import javafx.beans.binding.Bindings;
@ -12,7 +11,6 @@ import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.shape.Rectangle;
public class DenseStoreEntryComp extends StoreEntryComp {

View file

@ -11,7 +11,6 @@ import io.xpipe.app.util.PlatformThread;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ObservableStringValue;
import javafx.collections.FXCollections;
import lombok.Getter;

View file

@ -96,7 +96,8 @@ public class StoreChoiceComp<T extends DataStore> extends SimpleComp {
&& (applicableCheck == null || applicableCheck.test(e.ref()));
};
var applicableMatch = StoreViewState.get().getCurrentTopLevelSection().anyMatches(applicable);
var applicableMatch =
StoreViewState.get().getCurrentTopLevelSection().anyMatches(applicable);
if (!applicableMatch) {
selectedCategory.set(initialCategory);
}

View file

@ -43,7 +43,8 @@ public class StoreCreationDialog {
DataStorage.get().updateEntry(e, newE);
if (madeValid) {
StoreViewState.get().triggerStoreListUpdate();
if (validated && e.getProvider().shouldShowScan()
if (validated
&& e.getProvider().shouldShowScan()
&& AppPrefs.get()
.openConnectionSearchWindowOnConnectionCreation()
.get()) {

View file

@ -1,8 +1,8 @@
package io.xpipe.app.comp.store;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.BooleanScope;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener;
@ -72,8 +72,7 @@ public class StoreEntryBatchSelectComp extends SimpleComp {
}
var count = section.getShownChildren().getList().stream()
.filter(c ->
StoreViewState.get().isBatchModeSelected(c.getWrapper()))
.filter(c -> StoreViewState.get().isBatchModeSelected(c.getWrapper()))
.count();
checkBox.setIndeterminate(
count > 0 && count != section.getShownChildren().getList().size());

View file

@ -41,24 +41,26 @@ public abstract class StoreEntryComp extends SimpleComp {
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();
if (w >= 1000) {
return (w / 2.1) - 100;
} else {
return (w / 1.7) - 50;
}
}, App.getApp().getStage().widthProperty());
public static final ObservableDoubleValue INFO_WITH_CONTENT_WIDTH = Bindings.createDoubleBinding(() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
return (w / 2.1) - 200;
} else {
return (w / 1.7) - 150;
}
}, App.getApp().getStage().widthProperty());
public static final ObservableDoubleValue INFO_NO_CONTENT_WIDTH = Bindings.createDoubleBinding(
() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
return (w / 2.1) - 100;
} else {
return (w / 1.7) - 50;
}
},
App.getApp().getStage().widthProperty());
public static final ObservableDoubleValue INFO_WITH_CONTENT_WIDTH = Bindings.createDoubleBinding(
() -> {
var w = App.getApp().getStage().getWidth();
if (w >= 1000) {
return (w / 2.1) - 200;
} else {
return (w / 1.7) - 150;
}
},
App.getApp().getStage().widthProperty());
protected final StoreSection section;
protected final Comp<?> content;

View file

@ -14,7 +14,6 @@ import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
@ -126,17 +125,17 @@ public class StoreEntryListStatusBarComp extends SimpleComp {
return Comp.empty();
}
var childrenRefs = StoreViewState.get().getEffectiveBatchModeSelection()
var childrenRefs = StoreViewState.get()
.getEffectiveBatchModeSelection()
.mapped(storeEntryWrapper -> storeEntryWrapper.getEntry().<T>ref());
var batchActions = s.getChildren(childrenRefs.getList());
var button = new ButtonComp(
s.getName(), new SimpleObjectProperty<>(s.getIcon()), () -> {
if (batchActions.size() > 0) {
return;
}
var button = new ButtonComp(s.getName(), new SimpleObjectProperty<>(s.getIcon()), () -> {
if (batchActions.size() > 0) {
return;
}
runActions(s, busy);
});
runActions(s, busy);
});
if (batchActions.size() > 0) {
button.apply(new ContextMenuAugment<>(
mouseEvent -> mouseEvent.getButton() == MouseButton.PRIMARY, keyEvent -> false, () -> {
@ -152,7 +151,8 @@ public class StoreEntryListStatusBarComp extends SimpleComp {
}
@SuppressWarnings("unchecked")
private <T extends DataStore> MenuItem buildMenuItemForAction(List<DataStoreEntryRef<T>> batch, ActionProvider a, BooleanProperty busy) {
private <T extends DataStore> MenuItem buildMenuItemForAction(
List<DataStoreEntryRef<T>> batch, ActionProvider a, BooleanProperty busy) {
ActionProvider.BatchDataStoreCallSite<T> s =
(ActionProvider.BatchDataStoreCallSite<T>) a.getBatchDataStoreCallSite();
var name = s.getName();

View file

@ -38,7 +38,8 @@ public class StoreIntroComp extends SimpleComp {
var scanButton = new Button(null, new FontIcon("mdi2m-magnify"));
scanButton.textProperty().bind(AppI18n.observable("detectConnections"));
scanButton.setOnAction(event -> ScanDialog.showSingleAsync(DataStorage.get().local()));
scanButton.setOnAction(
event -> ScanDialog.showSingleAsync(DataStorage.get().local()));
scanButton.setDefaultButton(true);
var scanPane = new StackPane(scanButton);
scanPane.setAlignment(Pos.CENTER);

View file

@ -9,7 +9,6 @@ import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.core.window.AppMainWindow;
import io.xpipe.app.util.InputHelper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;

View file

@ -12,7 +12,6 @@ import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.beans.value.ObservableIntegerValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import lombok.Getter;
@ -163,10 +162,7 @@ public class StoreSection {
ObservableIntegerValue updateObservable) {
if (e.getEntry().getValidity() == DataStoreEntry.Validity.LOAD_FAILED) {
return new StoreSection(
e,
DerivedObservableList.arrayList(true),
DerivedObservableList.arrayList(true),
depth);
e, DerivedObservableList.arrayList(true), DerivedObservableList.arrayList(true), depth);
}
var allChildren = all.filtered(
@ -192,7 +188,16 @@ public class StoreSection {
var l = new ArrayList<>(parents);
l.add(e);
var cached = allChildren.mapped(c -> create(
l, c, depth + 1, all, selected, entryFilter, filterString, category, visibilityObservable, updateObservable));
l,
c,
depth + 1,
all,
selected,
entryFilter,
filterString,
category,
visibilityObservable,
updateObservable));
var ordered = sorted(cached, category, updateObservable);
var filtered = ordered.filtered(
section -> {

View file

@ -27,10 +27,12 @@ public class StoreViewState {
private final StringProperty filter = new SimpleStringProperty();
@Getter
private final DerivedObservableList<StoreEntryWrapper> allEntries = DerivedObservableList.synchronizedArrayList(true);
private final DerivedObservableList<StoreEntryWrapper> allEntries =
DerivedObservableList.synchronizedArrayList(true);
@Getter
private final DerivedObservableList<StoreCategoryWrapper> categories = DerivedObservableList.synchronizedArrayList(true);
private final DerivedObservableList<StoreCategoryWrapper> categories =
DerivedObservableList.synchronizedArrayList(true);
@Getter
private final IntegerProperty entriesListVisibilityObservable = new SimpleIntegerProperty();
@ -48,7 +50,8 @@ public class StoreViewState {
private final BooleanProperty batchMode = new SimpleBooleanProperty(false);
@Getter
private final DerivedObservableList<StoreEntryWrapper> batchModeSelection = DerivedObservableList.synchronizedArrayList(true);
private final DerivedObservableList<StoreEntryWrapper> batchModeSelection =
DerivedObservableList.synchronizedArrayList(true);
private final Set<StoreEntryWrapper> batchModeSelectionSet = new HashSet<>();
@ -56,8 +59,8 @@ public class StoreViewState {
private boolean initialized = false;
@Getter
private final DerivedObservableList<StoreEntryWrapper> effectiveBatchModeSelection =
batchModeSelection.filtered(storeEntryWrapper -> {
private final DerivedObservableList<StoreEntryWrapper> effectiveBatchModeSelection = batchModeSelection.filtered(
storeEntryWrapper -> {
if (!storeEntryWrapper.getValidity().getValue().isUsable()) {
return false;
}
@ -67,7 +70,9 @@ public class StoreViewState {
}
return true;
}, entriesListVisibilityObservable, entriesListUpdateObservable);
},
entriesListVisibilityObservable,
entriesListUpdateObservable);
@Getter
private StoreSection currentTopLevelSection;
@ -165,10 +170,7 @@ public class StoreViewState {
entriesListUpdateObservable);
} catch (Exception exception) {
currentTopLevelSection = new StoreSection(
null,
DerivedObservableList.arrayList(true),
DerivedObservableList.arrayList(true),
0);
null, DerivedObservableList.arrayList(true), DerivedObservableList.arrayList(true), 0);
ErrorEvent.fromThrowable(exception).handle();
}
}

View file

@ -4,7 +4,6 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.update.*;
import io.xpipe.app.util.LocalExec;
import io.xpipe.app.util.LocalShell;
import io.xpipe.app.util.Translatable;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellScript;
@ -26,10 +25,8 @@ public enum AppDistributionType implements Translatable {
NATIVE_INSTALLATION("install", true, () -> new GitHubUpdater(true)),
HOMEBREW("homebrew", true, () -> {
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
return new CommandUpdater(ShellScript.lines(
"brew upgrade --cask xpipe-io/tap/" + pkg,
AppRestart.getTerminalRestartCommand()
));
return new CommandUpdater(
ShellScript.lines("brew upgrade --cask xpipe-io/tap/" + pkg, AppRestart.getTerminalRestartCommand()));
}),
APT_REPO("apt", true, () -> {
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
@ -37,31 +34,28 @@ public enum AppDistributionType implements Translatable {
"echo \"+ sudo apt update && sudo apt install -y " + pkg + "\"",
"sudo apt update",
"sudo apt install -y " + pkg,
AppRestart.getTerminalRestartCommand()
));
AppRestart.getTerminalRestartCommand()));
}),
RPM_REPO("rpm", true, () -> {
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
return new CommandUpdater(ShellScript.lines(
"echo \"+ sudo yum upgrade " + pkg + " --refresh -y\"",
"sudo yum upgrade " + pkg + " --refresh -y",
AppRestart.getTerminalRestartCommand()
));
AppRestart.getTerminalRestartCommand()));
}),
WEBTOP("webtop", true, () -> new WebtopUpdater()),
CHOCO("choco", true, () -> {
var systemWide = Files.exists(XPipeInstallation.getCurrentInstallationBasePath().resolve("system"));
var systemWide =
Files.exists(XPipeInstallation.getCurrentInstallationBasePath().resolve("system"));
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
if (systemWide) {
return new CommandUpdater(ShellScript.lines(
"powershell -Command \"Start-Process -Verb runAs -FilePath choco -ArgumentList upgrade, " + pkg + "\"",
AppRestart.getTerminalRestartCommand()
));
"powershell -Command \"Start-Process -Verb runAs -FilePath choco -ArgumentList upgrade, " + pkg
+ "\"",
AppRestart.getTerminalRestartCommand()));
} else {
return new CommandUpdater(ShellScript.lines(
"choco upgrade " + pkg,
AppRestart.getTerminalRestartCommand()
));
return new CommandUpdater(
ShellScript.lines("choco upgrade " + pkg, AppRestart.getTerminalRestartCommand()));
}
});
@ -144,7 +138,7 @@ public enum AppDistributionType implements Translatable {
public static AppDistributionType determine() {
var base = XPipeInstallation.getCurrentInstallationBasePath();
if (OsType.getLocal().equals(OsType.MACOS)) {
if (!base.toString().equals(XPipeInstallation.getLocalDefaultInstallationBasePath())) {
if (!base.equals(XPipeInstallation.getLocalDefaultInstallationBasePath())) {
return PORTABLE;
}
@ -172,7 +166,8 @@ public enum AppDistributionType implements Translatable {
}
if (OsType.getLocal().equals(OsType.WINDOWS)) {
var out = LocalExec.readStdoutIfPossible("choco", "list", AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe");
var out = LocalExec.readStdoutIfPossible(
"choco", "list", AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe");
if (out.isPresent()) {
if (out.get().contains(AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe")) {
return CHOCO;

View file

@ -26,7 +26,8 @@ public class AppRestart {
} else {
var exe = loc.resolve(XPipeInstallation.getDaemonExecutablePath(OsType.getLocal()));
if (ShellDialects.isPowershell(dialect)) {
var escapedList = arguments.stream().map(s -> s.replaceAll("\"", "`\"")).toList();
var escapedList =
arguments.stream().map(s -> s.replaceAll("\"", "`\"")).toList();
var argumentList = String.join(" ", escapedList);
return "Start-Process -FilePath \"" + exe + "\" -ArgumentList \"" + argumentList + "\"";
} else {
@ -44,12 +45,12 @@ public class AppRestart {
if (OsType.getLocal().equals(OsType.LINUX)) {
return "nohup \"" + loc + "/bin/xpiped\"" + suffix + "</dev/null >/dev/null 2>&1 & disown";
} else if (OsType.getLocal().equals(OsType.MACOS)) {
return "(sleep 1;open \"" + loc + "\" --args" + suffix
+ "</dev/null &>/dev/null) & disown";
return "(sleep 1;open \"" + loc + "\" --args" + suffix + "</dev/null &>/dev/null) & disown";
} else {
var exe = loc.resolve(XPipeInstallation.getDaemonExecutablePath(OsType.getLocal()));
if (ShellDialects.isPowershell(dialect)) {
var escapedList = arguments.stream().map(s -> s.replaceAll("\"", "`\"")).toList();
var escapedList =
arguments.stream().map(s -> s.replaceAll("\"", "`\"")).toList();
var argumentList = String.join(" ", escapedList);
return "Start-Process -FilePath \"" + exe + "\" -ArgumentList \"" + argumentList + "\"";
} else {

View file

@ -14,7 +14,6 @@ import io.xpipe.app.util.*;
import io.xpipe.core.process.OsType;
import io.xpipe.core.util.FailableRunnable;
import io.xpipe.core.util.XPipeDaemonMode;
import io.xpipe.core.util.XPipeInstallation;
import javafx.application.Platform;

View file

@ -34,7 +34,8 @@ public class ContainerStoreState extends ShellStoreState {
return false;
}
return containerState.toLowerCase().contains("running") || containerState.toLowerCase().contains("up");
return containerState.toLowerCase().contains("running")
|| containerState.toLowerCase().contains("up");
}
@Override

View file

@ -109,7 +109,7 @@ public class SystemIconCache {
}
}
private static ImageColorScheme rasterizeSizes(Path path, Path dir, String name, boolean dark) throws IOException {
private static ImageColorScheme rasterizeSizes(Path path, Path dir, String name, boolean dark) {
TrackEvent.trace("Rasterizing image " + path.getFileName().toString());
try {
ImageColorScheme c = null;

View file

@ -10,8 +10,6 @@ import io.xpipe.core.process.ShellScript;
import com.fasterxml.jackson.annotation.JsonTypeName;
import java.util.regex.Pattern;
@JsonTypeName("bitwarden")
public class BitwardenPasswordManager implements PasswordManager {

View file

@ -2,14 +2,10 @@ package io.xpipe.app.prefs;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.LabelComp;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.comp.base.TileButtonComp;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.core.AppDistributionType;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.JfxHelper;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.core.process.OsType;
@ -32,7 +28,12 @@ public class AboutCategory extends AppPrefsCategory {
protected Comp<?> create() {
var props = createProperties().padding(new Insets(0, 0, 0, 5));
var update = new UpdateCheckComp().prefWidth(600);
return new VerticalComp(List.of(props, Comp.hspacer(8), update, Comp.hspacer(13), Comp.hseparator().padding(Insets.EMPTY).maxWidth(600)))
return new VerticalComp(List.of(
props,
Comp.hspacer(8),
update,
Comp.hspacer(13),
Comp.hseparator().padding(Insets.EMPTY).maxWidth(600)))
.apply(s -> s.get().setFillWidth(true))
.apply(struc -> struc.get().setSpacing(15))
.styleClass("information")

View file

@ -209,6 +209,13 @@ public class AppPrefs {
final BooleanProperty censorMode = mapLocal(new SimpleBooleanProperty(false), "censorMode", Boolean.class, false);
final BooleanProperty sshVerboseOutput =
mapLocal(new SimpleBooleanProperty(false), "sshVerboseOutput", Boolean.class, false);
public ObservableBooleanValue sshVerboseOutput() {
return sshVerboseOutput;
}
public ObservableBooleanValue censorMode() {
return censorMode;
}
@ -302,8 +309,7 @@ public class AppPrefs {
new WorkspacesCategory(),
new DeveloperCategory(),
new TroubleshootCategory(),
new LinksCategory()
)
new LinksCategory())
.toList();
this.selectedCategory = new SimpleObjectProperty<>(categories.getFirst());
}

View file

@ -8,20 +8,18 @@ import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.*;
import lombok.val;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import lombok.val;
public class AppPrefsComp extends SimpleComp {
@Override
protected Region createSimple() {
var categories = AppPrefs.get().getCategories().stream().filter(appPrefsCategory -> appPrefsCategory.show()).toList();
var categories = AppPrefs.get().getCategories().stream()
.filter(appPrefsCategory -> appPrefsCategory.show())
.toList();
var list = categories.stream()
.<Comp<?>>map(appPrefsCategory -> {
var r = appPrefsCategory
@ -29,7 +27,8 @@ public class AppPrefsComp extends SimpleComp {
.styleClass("prefs-container")
.styleClass(appPrefsCategory.getId());
return r;
}).toList();
})
.toList();
var box = new VerticalComp(list)
.maxWidth(850)
.styleClass("prefs-box")
@ -40,9 +39,9 @@ public class AppPrefsComp extends SimpleComp {
var externalUpdate = new SimpleBooleanProperty();
scrollPane.vvalueProperty().addListener((observable, oldValue, newValue) -> {
if (externalUpdate.get()) {
return;
}
if (externalUpdate.get()) {
return;
}
BooleanScope.executeExclusive(externalUpdate, () -> {
var offset = newValue.doubleValue();
@ -93,7 +92,12 @@ public class AppPrefsComp extends SimpleComp {
private double computeCategoryOffset(VBox box, ScrollPane scrollPane, AppPrefsCategory val) {
var node = box.lookup("." + val.getId());
if (node != null && scrollPane.getHeight() > 0.0) {
var s = Math.min(box.getHeight(), node.getBoundsInParent().getMinY() > 0.0 ? node.getBoundsInParent().getMinY() + 20 : 0.0) / box.getHeight();
var s = Math.min(
box.getHeight(),
node.getBoundsInParent().getMinY() > 0.0
? node.getBoundsInParent().getMinY() + 20
: 0.0)
/ box.getHeight();
var off = (scrollPane.getHeight() * s * 1.05) / box.getHeight();
return s + off;
} else {

View file

@ -6,7 +6,6 @@ import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppRestart;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.util.PlatformThread;
import javafx.css.PseudoClass;

View file

@ -66,8 +66,7 @@ public class AppearanceCategory extends AppPrefsCategory {
.maxWidth(getCompWidth()),
prefs.windowOpacity)
.pref(prefs.saveWindowLocation)
.addToggle(prefs.saveWindowLocation)
)
.addToggle(prefs.saveWindowLocation))
.buildComp();
}
@ -76,7 +75,7 @@ public class AppearanceCategory extends AppPrefsCategory {
var c = ChoiceComp.ofTranslatable(prefs.theme, AppTheme.Theme.ALL, false)
.styleClass("theme-switcher");
c.apply(struc -> {
Supplier<ListCell<AppTheme.Theme>> cell = () -> new ListCell<AppTheme.Theme>() {
Supplier<ListCell<AppTheme.Theme>> cell = () -> new ListCell<>() {
@Override
protected void updateItem(AppTheme.Theme theme, boolean empty) {
super.updateItem(theme, empty);
@ -101,7 +100,7 @@ public class AppearanceCategory extends AppPrefsCategory {
return cell.get();
});
});
c.minWidth(getCompWidth() / 2);
c.minWidth(getCompWidth() / 2.0);
return c;
}

View file

@ -178,9 +178,7 @@ public interface ExternalEditorType extends PrefsChoiceValue {
var command = CommandBuilder.of()
.add(ExternalApplicationHelper.replaceVariableArgument(format, "FILE", file.toString()));
if (AppPrefs.get().customEditorCommandInTerminal().get()) {
TerminalLauncher.openDirect(
file.toString(),
sc -> new ShellScript(command.buildFull(sc)));
TerminalLauncher.openDirect(file.toString(), sc -> new ShellScript(command.buildFull(sc)));
} else {
ExternalApplicationHelper.startAsync(command);
}

View file

@ -1,12 +1,10 @@
package io.xpipe.app.prefs;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.base.TextFieldComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.OptionsBuilder;
public class HttpApiCategory extends AppPrefsCategory {

View file

@ -1,23 +1,11 @@
package io.xpipe.app.prefs;
import atlantafx.base.theme.Styles;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.LabelComp;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.comp.base.TileButtonComp;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.core.AppDistributionType;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.JfxHelper;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.core.process.OsType;
import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import java.util.List;
public class LinksCategory extends AppPrefsCategory {
@ -81,9 +69,7 @@ public class LinksCategory extends AppPrefsCategory {
@Override
protected Comp<?> create() {
return createLinks()
.styleClass("information")
.styleClass("about-tab")
.apply(struc -> struc.get().setPrefWidth(600));
return createLinks().styleClass("information").styleClass("about-tab").apply(struc -> struc.get()
.setPrefWidth(600));
}
}

View file

@ -15,6 +15,7 @@ public class SshCategory extends AppPrefsCategory {
protected Comp<?> create() {
var prefs = AppPrefs.get();
var options = new OptionsBuilder().addTitle("sshConfiguration");
options.sub(new OptionsBuilder().pref(prefs.sshVerboseOutput).addToggle(prefs.sshVerboseOutput));
if (OsType.getLocal() == OsType.WINDOWS) {
options.sub(new OptionsBuilder()
.addComp(prefs.getCustomComp("x11WslInstance").maxWidth(getCompWidth())));

View file

@ -4,7 +4,6 @@ import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.ChoiceComp;
import io.xpipe.app.ext.PrefsChoiceValue;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.core.process.OsType;
public class SystemCategory extends AppPrefsCategory {
@ -25,13 +24,13 @@ public class SystemCategory extends AppPrefsCategory {
prefs.startupBehaviour,
PrefsChoiceValue.getSupported(StartupBehaviour.class),
false)
.minWidth(getCompWidth() / 2))
.minWidth(getCompWidth() / 2.0))
.pref(prefs.closeBehaviour)
.addComp(ChoiceComp.ofTranslatable(
prefs.closeBehaviour,
PrefsChoiceValue.getSupported(CloseBehaviour.class),
false)
.minWidth(getCompWidth() / 2)));
.minWidth(getCompWidth() / 2.0)));
builder.sub(localShellBuilder);
builder.sub(new OptionsBuilder().pref(prefs.developerMode).addToggle(prefs.developerMode));
return builder.buildComp();

View file

@ -127,18 +127,18 @@ public class TerminalCategory extends AppPrefsCategory {
h.maxWidth(getCompWidth());
var terminalTest = new ButtonComp(AppI18n.observable("test"), new FontIcon("mdi2p-play"), () -> {
ThreadHelper.runFailableAsync(() -> {
var term = AppPrefs.get().terminalType().getValue();
if (term != null) {
TerminalLauncher.open(
"Test",
ProcessControlProvider.get()
.createLocalProcessControl(true)
.command("echo Test"),
UUID.randomUUID());
}
});
})
ThreadHelper.runFailableAsync(() -> {
var term = AppPrefs.get().terminalType().getValue();
if (term != null) {
TerminalLauncher.open(
"Test",
ProcessControlProvider.get()
.createLocalProcessControl(true)
.command("echo Test"),
UUID.randomUUID());
}
});
})
.padding(new Insets(6, 11, 6, 5))
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT));
@ -239,7 +239,6 @@ public class TerminalCategory extends AppPrefsCategory {
return new OptionsBuilder().nameAndDescription("terminalMultiplexer").addComp(choice);
}
private OptionsBuilder terminalPrompt() {
var prefs = AppPrefs.get();
var choiceBuilder = OptionsChoiceBuilder.builder()

View file

@ -10,7 +10,6 @@ import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.UserReportComp;
import io.xpipe.app.terminal.ExternalTerminalType;
import io.xpipe.app.terminal.TerminalLauncher;
import io.xpipe.app.util.DesktopHelper;
import io.xpipe.app.util.FileOpener;
@ -61,7 +60,8 @@ public class TroubleshootCategory extends AppPrefsCategory {
XPipeInstallation.getDaemonDebugScriptPath(OsType.getLocal()));
TerminalLauncher.openDirectFallback(
"XPipe Debug",
sc -> new ShellScript(sc.getShellDialect().runScriptCommand(sc, script)));
sc -> new ShellScript(
sc.getShellDialect().runScriptCommand(sc, script)));
});
e.consume();
})
@ -70,21 +70,18 @@ public class TroubleshootCategory extends AppPrefsCategory {
if (AppLogs.get().isWriteToFile()) {
b.addComp(
new TileButtonComp(
"openCurrentLogFile",
"openCurrentLogFileDescription",
"mdmz-text_snippet",
e -> {
AppLogs.get().flush();
ThreadHelper.sleep(100);
FileOpener.openInTextEditor(AppLogs.get()
.getSessionLogsDirectory()
.resolve("xpipe.log")
.toString());
e.consume();
})
.grow(true, false),
null);
new TileButtonComp(
"openCurrentLogFile", "openCurrentLogFileDescription", "mdmz-text_snippet", e -> {
AppLogs.get().flush();
ThreadHelper.sleep(100);
FileOpener.openInTextEditor(AppLogs.get()
.getSessionLogsDirectory()
.resolve("xpipe.log")
.toString());
e.consume();
})
.grow(true, false),
null);
}
b.addComp(

View file

@ -1,8 +1,6 @@
package io.xpipe.app.prefs;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.ChoiceComp;
import io.xpipe.app.ext.PrefsChoiceValue;
import io.xpipe.app.util.OptionsBuilder;
public class UpdatesCategory extends AppPrefsCategory {
@ -15,8 +13,7 @@ public class UpdatesCategory extends AppPrefsCategory {
public Comp<?> create() {
var prefs = AppPrefs.get();
var builder = new OptionsBuilder();
builder
.addTitle("updates")
builder.addTitle("updates")
.sub(new OptionsBuilder()
.pref(prefs.automaticallyCheckForUpdates)
.addToggle(prefs.automaticallyCheckForUpdates)

View file

@ -6,10 +6,8 @@ import io.xpipe.app.comp.base.ModalButton;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageSyncHandler;
import io.xpipe.app.storage.DataStorageUserHandler;
import io.xpipe.app.util.DesktopHelper;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.app.util.OptionsBuilder;
@ -80,10 +78,10 @@ public class VaultCategory extends AppPrefsCategory {
.hide(new SimpleBooleanProperty(
DataStorageSyncHandler.getInstance().supportsSync())));
builder.sub(new OptionsBuilder()
.pref(prefs.lockVaultOnHibernation)
.addToggle(prefs.lockVaultOnHibernation)
.pref(prefs.encryptAllVaultData)
.addToggle(encryptVault));
.pref(prefs.lockVaultOnHibernation)
.addToggle(prefs.lockVaultOnHibernation)
.pref(prefs.encryptAllVaultData)
.addToggle(encryptVault));
return builder.buildComp();
}
}

View file

@ -276,7 +276,7 @@ public class DataStoreEntry extends StorageElement {
notes = null;
}
DataStorageNode node = null;
DataStorageNode node;
try {
var fileNode = mapper.readTree(storeFile.toFile());
node = DataStorageNode.readPossiblyEncryptedNode(fileNode);

View file

@ -26,8 +26,7 @@ public class ScreenTerminalMultiplexer implements TerminalMultiplexer {
}
@Override
public ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception {
public ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config) {
// Screen has a limit of 100 chars for commands
var effectiveCommand = command.length() > 90
? ScriptHelper.createExecScript(control, command).toString()
@ -37,8 +36,7 @@ public class ScreenTerminalMultiplexer implements TerminalMultiplexer {
}
@Override
public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception {
public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config) {
// Screen has a limit of 100 chars for commands
var effectiveCommand = command.length() > 90
? ScriptHelper.createExecScript(control, command).toString()

View file

@ -87,8 +87,7 @@ public class TerminalLauncher {
}
public static void openDirect(String title, ShellScript command) throws Exception {
openDirect(
title, sc -> command, AppPrefs.get().terminalType().getValue());
openDirect(title, sc -> command, AppPrefs.get().terminalType().getValue());
}
public static void openDirectFallback(String title, FailableFunction<ShellControl, ShellScript, Exception> command)
@ -96,18 +95,12 @@ public class TerminalLauncher {
// We can't use the SSH bridge and other stuff
var type = ExternalTerminalType.determineFallbackTerminalToOpen(
AppPrefs.get().terminalType().getValue());
openDirect(
title,
command,
type);
openDirect(title, command, type);
}
public static void openDirect(String title, FailableFunction<ShellControl, ShellScript, Exception> command)
throws Exception {
openDirect(
title,
command,
AppPrefs.get().terminalType().getValue());
openDirect(title, command, AppPrefs.get().terminalType().getValue());
}
public static void openDirect(
@ -310,8 +303,7 @@ public class TerminalLauncher {
}
private static Optional<TerminalLaunchConfiguration> launchProxy(
UUID request, TerminalLaunchConfiguration launchConfiguration)
throws Exception {
UUID request, TerminalLaunchConfiguration launchConfiguration) throws Exception {
var proxyControl = TerminalProxyManager.getProxy();
if (proxyControl.isEmpty()) {
return Optional.empty();

View file

@ -91,7 +91,7 @@ public class TerminalLauncherManager {
req.setShellPid(shell.pid());
}
public static void waitExchange(UUID request) throws BeaconClientException, BeaconServerException {
public static void waitExchange(UUID request) throws BeaconServerException {
TerminalLaunchRequest req;
synchronized (entries) {
req = entries.get(request);

View file

@ -3,7 +3,6 @@ package io.xpipe.app.terminal;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.process.ShellScript;
import io.xpipe.core.process.TerminalInitScriptConfig;
import io.xpipe.core.util.ValidationException;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@ -21,15 +20,13 @@ public interface TerminalMultiplexer {
return l;
}
default void checkComplete() throws ValidationException {}
default void checkComplete() {}
String getDocsLink();
void checkSupported(ShellControl sc) throws Exception;
ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception;
ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config);
ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception;
ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config);
}

View file

@ -25,15 +25,13 @@ public class TmuxTerminalMultiplexer implements TerminalMultiplexer {
}
@Override
public ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception {
public ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config) {
return ShellScript.lines("tmux new-window -t xpipe -n \"" + escape(config.getDisplayName(), true) + "\" "
+ escape(command, false));
}
@Override
public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception {
public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config) {
return ShellScript.lines(
"tmux kill-session -t xpipe",
"tmux new-session -d -s xpipe",

View file

@ -65,7 +65,7 @@ public interface WarpTerminalType extends ExternalTerminalType, TrackableTermina
}
@Override
public void launch(TerminalLaunchConfiguration configuration) throws Exception {
public void launch(TerminalLaunchConfiguration configuration) {
if (!configuration.isPreferTabs()) {
DesktopHelper.openUrl("warp://action/new_window?path=" + configuration.getScriptFile());
} else {

View file

@ -25,20 +25,17 @@ public class ZellijTerminalMultiplexer implements TerminalMultiplexer {
}
@Override
public ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception {
public ShellScript launchScriptExternal(ShellControl control, String command, TerminalInitScriptConfig config) {
return ShellScript.lines(
"zellij attach --create-background xpipe",
"zellij -s xpipe action new-tab --name \"" + escape(config.getDisplayName(), false, true) + "\"",
"zellij -s xpipe action write-chars -- " + escape(" " + command, true, true) + "\\;exit",
"zellij -s xpipe action write 10",
"zellij -s xpipe action clear"
);
"zellij -s xpipe action clear");
}
@Override
public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config)
throws Exception {
public ShellScript launchScriptSession(ShellControl control, String command, TerminalInitScriptConfig config) {
return ShellScript.lines(
"zellij delete-session -f xpipe > /dev/null 2>&1",
"zellij attach --create-background xpipe",

View file

@ -97,9 +97,11 @@ public class AppDownloads {
if (ptbAvailable != null) {
var b = ptbAvailable.asBoolean();
if (b) {
GlobalTimer.delay(() -> {
AppLayoutModel.get().getPtbAvailable().set(true);
}, Duration.ofSeconds(20));
GlobalTimer.delay(
() -> {
AppLayoutModel.get().getPtbAvailable().set(true);
},
Duration.ofSeconds(20));
}
}
return ver;

View file

@ -1,7 +1,6 @@
package io.xpipe.app.update;
import io.xpipe.app.core.AppLogs;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.AppRestart;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.ext.ProcessControlProvider;
@ -65,7 +64,7 @@ public class AppInstaller {
});
}
public abstract void installLocal(Path file) throws Exception;
public abstract void installLocal(Path file);
public abstract String getExtension();
@ -73,7 +72,7 @@ public class AppInstaller {
public static final class Msi extends InstallerAssetType {
@Override
public void installLocal(Path file) throws Exception {
public void installLocal(Path file) {
var logsDir =
AppLogs.get().getSessionLogsDirectory().getParent().toString();
var logFile = FileNames.join(
@ -133,8 +132,7 @@ public class AppInstaller {
file,
logFile,
args,
AppRestart.getBackgroundRestartCommand(ShellDialects.CMD)
);
AppRestart.getBackgroundRestartCommand(ShellDialects.CMD));
}
private String getPowershellCommand(String file, String logFile, boolean systemWide) {
@ -157,8 +155,7 @@ public class AppInstaller {
file,
logFile,
startProcessProperty,
AppRestart.getBackgroundRestartCommand(ShellDialects.POWERSHELL)
);
AppRestart.getBackgroundRestartCommand(ShellDialects.POWERSHELL));
}
}
@ -208,8 +205,7 @@ public class AppInstaller {
cd ~
runinstaller || read -rsp "Update failed ..."$'\\n' -n 1 key
""",
file, file,
AppRestart.getTerminalRestartCommand()));
file, file, AppRestart.getTerminalRestartCommand()));
runAndClose(() -> {
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> command);
@ -239,8 +235,7 @@ public class AppInstaller {
cd ~
runinstaller || echo "Update failed ..." && read -rs -k 1 key
""",
file, file,
AppRestart.getTerminalRestartCommand()));
file, file, AppRestart.getTerminalRestartCommand()));
runAndClose(() -> {
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> command);

View file

@ -5,13 +5,9 @@ import io.xpipe.app.core.AppCache;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.terminal.TerminalLauncher;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.LocalShell;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.ShellScript;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

View file

@ -10,7 +10,6 @@ import javafx.scene.layout.StackPane;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@ -31,7 +30,12 @@ public class CommandDialog {
out = ExceptionUtils.getStackTrace(t);
}
acc.append(e.getKey()).append(" (exit code ").append(e.getValue().getExitCode()).append("):\n").append(out).append("\n\n");
acc.append(e.getKey())
.append(" (exit code ")
.append(e.getValue().getExitCode())
.append("):\n")
.append(out)
.append("\n\n");
}
show(acc.toString());
});
@ -59,8 +63,7 @@ public class CommandDialog {
var text = new TextArea(out);
text.setWrapText(true);
text.setEditable(false);
text.setPrefRowCount(
Math.max(8, (int) out.lines().count()));
text.setPrefRowCount(Math.max(8, (int) out.lines().count()));
var sp = new StackPane(text);
return sp;
})

View file

@ -3,7 +3,6 @@ package io.xpipe.app.util;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
@ -21,7 +20,8 @@ public class DerivedObservableList<T> {
public static <T> DerivedObservableList<T> synchronizedArrayList(boolean unique) {
var list = new ArrayList<T>();
return new DerivedObservableList<>(list, FXCollections.synchronizedObservableList(FXCollections.observableList(list)), unique);
return new DerivedObservableList<>(
list, FXCollections.synchronizedObservableList(FXCollections.observableList(list)), unique);
}
public static <T> DerivedObservableList<T> arrayList(boolean unique) {
@ -219,7 +219,8 @@ public class DerivedObservableList<T> {
public DerivedObservableList<T> filtered(ObservableValue<Predicate<T>> predicate) {
var d = this.<T>createNewDerived();
Runnable runnable = () -> {
d.setContent(predicate.getValue() != null
d.setContent(
predicate.getValue() != null
? listStream().filter(predicate.getValue()).toList()
: list);
};

View file

@ -94,10 +94,10 @@ public class OptionsChoiceBuilder {
if (allowNull) {
properties.add(new SimpleObjectProperty<>());
}
for (int i = 0; i < sub.size(); i++) {
var compatible = sub.get(i).isInstance(s.getValue());
for (Class<?> aClass : sub) {
var compatible = aClass.isInstance(s.getValue());
properties.add(
new SimpleObjectProperty<>(compatible ? s.getValue() : createDefaultInstanceForClass(sub.get(i))));
new SimpleObjectProperty<>(compatible ? s.getValue() : createDefaultInstanceForClass(aClass)));
}
property.addListener((obs, oldValue, newValue) -> {

View file

@ -28,7 +28,8 @@ public class ScanDialog {
private static void showSingle(DataStoreEntry initialStore, ScanDialogAction action) {
var comp = new ScanSingleDialogComp(initialStore != null ? initialStore.ref() : null, action);
var modal = ModalOverlay.of("scanAlertTitle", comp);
var queueEntry = new AppLayoutModel.QueueEntry(AppI18n.observable("scanConnections"), new LabelGraphic.IconGraphic("mdi2l-layers-plus"), () -> {});
var queueEntry = new AppLayoutModel.QueueEntry(
AppI18n.observable("scanConnections"), new LabelGraphic.IconGraphic("mdi2l-layers-plus"), () -> {});
var button = new ModalButton(
"ok",
() -> {
@ -48,7 +49,8 @@ public class ScanDialog {
public static void showMulti(List<DataStoreEntryRef<ShellStore>> entries, ScanDialogAction action) {
var comp = new ScanMultiDialogComp(entries, action);
var modal = ModalOverlay.of("scanAlertTitle", comp);
var queueEntry = new AppLayoutModel.QueueEntry(AppI18n.observable("scanConnections"), new LabelGraphic.IconGraphic("mdi2l-layers-plus"), () -> {});
var queueEntry = new AppLayoutModel.QueueEntry(
AppI18n.observable("scanConnections"), new LabelGraphic.IconGraphic("mdi2l-layers-plus"), () -> {});
var button = new ModalButton(
"ok",
() -> {

View file

@ -39,13 +39,18 @@ public interface ScanDialogAction {
ScanProvider.ScanOpportunity operation = scanProvider.create(entry, sc);
if (operation != null) {
if (!operation.isDisabled()) {
selected.removeIf(o -> o.getProvider().equals(operation.getProvider()) && o.isDisabled());
selected.removeIf(
o -> o.getProvider().equals(operation.getProvider()) && o.isDisabled());
all.removeIf(o -> o.getProvider().equals(operation.getProvider()) && o.isDisabled());
}
if (!operation.isDisabled() && selected.stream().noneMatch(o -> o.getProvider().equals(operation.getProvider()))) {
if (!operation.isDisabled()
&& selected.stream()
.noneMatch(o -> o.getProvider().equals(operation.getProvider()))) {
selected.add(operation);
}
if (!all.contains(operation) && all.stream().noneMatch(o -> o.getProvider().equals(operation.getProvider()))) {
if (!all.contains(operation)
&& all.stream()
.noneMatch(o -> o.getProvider().equals(operation.getProvider()))) {
all.add(operation);
}
}

View file

@ -1,8 +1,6 @@
package io.xpipe.app.util;
import io.xpipe.app.comp.base.ModalOverlayContentComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.storage.DataStoreEntryRef;

View file

@ -7,7 +7,6 @@ import lombok.experimental.SuperBuilder;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
@ -42,7 +41,7 @@ public abstract class AesSecretValue extends EncryptedSecretValue {
return "AES/GCM/NoPadding";
}
protected abstract SecretKey getSecretKey() throws InvalidKeySpecException;
protected abstract SecretKey getSecretKey();
@Override
@SneakyThrows

View file

@ -35,7 +35,8 @@ public class XPipeInstallation {
var suffix = (arguments != null ? " " + arguments : "");
var modeOption = mode != null ? " -Dio.xpipe.app.mode=" + mode.getDisplayName() : "";
if (OsType.getLocal().equals(OsType.LINUX)) {
return "nohup \"" + installationBase + "/bin/xpiped\"" + modeOption + suffix + "</dev/null >/dev/null 2>&1 & disown";
return "nohup \"" + installationBase + "/bin/xpiped\"" + modeOption + suffix
+ "</dev/null >/dev/null 2>&1 & disown";
} else if (OsType.getLocal().equals(OsType.MACOS)) {
if (restart) {
return "(sleep 1;open \"" + installationBase + "\" --args" + modeOption + suffix

View file

@ -78,7 +78,7 @@ public class RunScriptActionMenu implements ActionProvider {
@Override
public BatchDataStoreCallSite<ShellStore> getBatchDataStoreCallSite() {
return new BatchDataStoreCallSite<ShellStore>() {
return new BatchDataStoreCallSite<>() {
@Override
public ObservableValue<String> getName() {
@ -111,7 +111,6 @@ public class RunScriptActionMenu implements ActionProvider {
ScriptHierarchy hierarchy;
@Override
public LeafDataStoreCallSite<?> getLeafDataStoreCallSite() {
return new LeafDataStoreCallSite<ShellStore>() {
@ -144,7 +143,7 @@ public class RunScriptActionMenu implements ActionProvider {
@Override
public BatchDataStoreCallSite<ShellStore> getBatchDataStoreCallSite() {
return new BatchDataStoreCallSite<ShellStore>() {
return new BatchDataStoreCallSite<>() {
@Override
public ObservableValue<String> getName() {
@ -612,7 +611,10 @@ public class RunScriptActionMenu implements ActionProvider {
var compatible = batch.stream().allMatch(ref -> {
var state = ref.get().getStorePersistentState();
if (state instanceof SystemState systemState) {
return scriptRef.getStore().getMinimumDialect().isCompatibleTo(systemState.getShellDialect());
return scriptRef
.getStore()
.getMinimumDialect()
.isCompatibleTo(systemState.getShellDialect());
} else {
return false;
}

View file

@ -7,7 +7,6 @@ import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.storage.ContextualFileReference;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.*;
import io.xpipe.core.store.FilePath;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
@ -153,7 +152,7 @@ public class SshIdentityStrategyHelper {
Property<SshIdentityStrategy.File> fileProperty,
Predicate<Path> perUserFile,
boolean allowSync) {
var keyPath = new SimpleObjectProperty<FilePath>(
var keyPath = new SimpleObjectProperty<>(
fileProperty.getValue() != null && fileProperty.getValue().getFile() != null
? fileProperty.getValue().getFile().toAbsoluteFilePath(null)
: null);

View file

@ -50,7 +50,7 @@ public class StoreRestartAction implements ActionProvider {
@Override
public BatchDataStoreCallSite<?> getBatchDataStoreCallSite() {
return new BatchDataStoreCallSite<DataStore>() {
return new BatchDataStoreCallSite<>() {
@Override
public ObservableValue<String> getName() {

View file

@ -61,7 +61,7 @@ public class IncusContainerEditRunConfigAction implements ActionProvider {
var file = FilePath.of("/run/incus/" + d.getContainerName() + "/lxc.conf");
var model =
BrowserFullSessionModel.DEFAULT.openFileSystemSync(elevatedRef, m -> file.getParent(), null, true);
var found = model.findFile(file.toString());
var found = model.findFile(file);
if (found.isEmpty()) {
return;
}

View file

@ -61,7 +61,7 @@ public class LxdContainerEditRunConfigAction implements ActionProvider {
var file = FilePath.of("/run/lxd/" + d.getContainerName() + "/lxc.conf");
var model =
BrowserFullSessionModel.DEFAULT.openFileSystemSync(elevatedRef, m -> file.getParent(), null, true);
var found = model.findFile(file.toString());
var found = model.findFile(file);
if (found.isEmpty()) {
return;
}

View file

@ -10,8 +10,8 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.DataStoreFormatter;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.app.util.StoreStateFormat;
import io.xpipe.app.util.SimpleValidator;
import io.xpipe.app.util.StoreStateFormat;
import io.xpipe.core.store.DataStore;
import io.xpipe.ext.base.service.FixedServiceGroupStore;
import io.xpipe.ext.base.store.ShellStoreProvider;

View file

@ -198,6 +198,7 @@ updateReadyDescriptionPortable=En opdatering er tilgængelig til download
updateRestart=Genstart for at opdatere
never=Aldrig
updateAvailableTooltip=Opdatering tilgængelig
ptbAvailableTooltip=Offentlig testversion tilgængelig
visitGithubRepository=Besøg GitHub-arkivet
updateAvailable=Opdatering tilgængelig: $VERSION$
downloadUpdate=Download opdatering
@ -1259,7 +1260,7 @@ enterLicenseKey=Indtast licensnøgle for at opgradere
isOnlySupported=understøttes kun med mindst en $TYPE$ -licens
areOnlySupported=understøttes kun med mindst en $TYPE$ -licens
openApiDocs=API-dokumentation
openApiDocsDescription=HTTP API-dokumentationen følger med XPipe, inklusive en OpenAPI .yaml-specifikation. Du kan åbne den i din webbrowser.
openApiDocsDescription=HTTP API-dokumentationen er tilgængelig online, inklusive en OpenAPI .yaml-specifikation. Du kan åbne den i din webbrowser eller din foretrukne HTTP-klient.
openApiDocsButton=Åbn dokumenter
pythonApi=Python API
personalConnection=Denne forbindelse og alle dens børn er kun tilgængelige for din bruger, da de afhænger af en personlig identitet.
@ -1376,3 +1377,5 @@ passwordManagerKey=Nøgle til adgangskodehåndtering
passwordManagerAgent=Ekstern password manager-agent
dockerComposeProject.displayName=Docker compose-projektet
dockerComposeProject.displayDescription=Grupper containere i et sammensat projekt sammen
sshVerboseOutput=Aktiver verbose SSH-output
sshVerboseOutputDescription=Dette udskriver en masse fejlsøgningsinformation, når der oprettes forbindelse via SSH. Nyttig til fejlfinding af problemer med SSH-forbindelser.

View file

@ -199,6 +199,7 @@ updateReadyDescriptionPortable=Ein Update ist zum Download verfügbar
updateRestart=Neustart zur Aktualisierung
never=Niemals
updateAvailableTooltip=Update verfügbar
ptbAvailableTooltip=Öffentliche Testversion verfügbar
visitGithubRepository=GitHub Repository besuchen
updateAvailable=Update verfügbar: $VERSION$
downloadUpdate=Update herunterladen
@ -1244,7 +1245,7 @@ enterLicenseKey=Lizenzschlüssel für das Upgrade eingeben
isOnlySupported=wird nur mit mindestens einer $TYPE$ Lizenz unterstützt
areOnlySupported=werden nur mit mindestens einer $TYPE$ Lizenz unterstützt
openApiDocs=API-Dokumentation
openApiDocsDescription=Die HTTP-API-Dokumentation ist im Lieferumfang von XPipe enthalten, einschließlich einer OpenAPI .yaml-Spezifikation. Du kannst sie in deinem Webbrowser öffnen.
openApiDocsDescription=Die Dokumentation der HTTP-API ist online verfügbar, einschließlich einer OpenAPI .yaml-Spezifikation. Du kannst sie in deinem Webbrowser oder deinem bevorzugten HTTP-Client öffnen.
openApiDocsButton=Docs öffnen
pythonApi=Python-API
personalConnection=Diese Verbindung und alle ihre Kinder sind nur für deinen Nutzer verfügbar, da sie von einer persönlichen Identität abhängen.
@ -1362,3 +1363,5 @@ passwordManagerKey=Passwortmanager-Schlüssel
passwordManagerAgent=Externer Passwortmanager-Agent
dockerComposeProject.displayName=Docker compose Projekt
dockerComposeProject.displayDescription=Container eines zusammengesetzten Projekts zusammenfassen
sshVerboseOutput=Ausführliche SSH-Ausgabe aktivieren
sshVerboseOutputDescription=Damit werden bei einer Verbindung über SSH viele Debug-Informationen ausgegeben. Nützlich für die Fehlersuche bei Problemen mit SSH-Verbindungen.

View file

@ -1398,3 +1398,5 @@ passwordManagerKey=Password manager key
passwordManagerAgent=External password manager agent
dockerComposeProject.displayName=Docker compose project
dockerComposeProject.displayDescription=Group containers of a composed project together
sshVerboseOutput=Enable verbose SSH output
sshVerboseOutputDescription=This will print a lot of debug information when connecting via SSH. Useful for troubleshooting issues with SSH connections.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Se puede descargar una actualización
updateRestart=Reiniciar para actualizar
never=Nunca
updateAvailableTooltip=Actualización disponible
ptbAvailableTooltip=Disponible versión de prueba pública
visitGithubRepository=Visita el repositorio GitHub
updateAvailable=Actualización disponible: $VERSION$
downloadUpdate=Descargar actualización
@ -1214,7 +1215,7 @@ enterLicenseKey=Introduce la clave de licencia para actualizar
isOnlySupported=sólo es compatible al menos con la licencia $TYPE$
areOnlySupported=sólo se admiten con una licencia de al menos $TYPE$
openApiDocs=Documentación API
openApiDocsDescription=La documentación de la API HTTP se incluye con XPipe, incluida una especificación OpenAPI .yaml. Puedes abrirla en tu navegador web.
openApiDocsDescription=La documentación de la API HTTP está disponible en Internet, incluida una especificación OpenAPI .yaml. Puedes abrirla en tu navegador web o en tu cliente HTTP preferido.
openApiDocsButton=Abrir documentos
pythonApi=API de Python
personalConnection=Esta conexión y todos sus hijos sólo están disponibles para tu usuario, ya que dependen de una identidad personal.
@ -1331,3 +1332,5 @@ passwordManagerKey=Clave del gestor de contraseñas
passwordManagerAgent=Agente gestor de contraseñas externo
dockerComposeProject.displayName=Proyecto Docker Compose
dockerComposeProject.displayDescription=Agrupar contenedores de un proyecto compuesto
sshVerboseOutput=Activar la salida detallada SSH
sshVerboseOutputDescription=Esto imprimirá mucha información de depuración cuando te conectes mediante SSH. Es útil para solucionar problemas con las conexiones SSH.

View file

@ -194,6 +194,7 @@ updateReadyDescriptionPortable=Une mise à jour est disponible au téléchargeme
updateRestart=Redémarre pour mettre à jour
never=Jamais
updateAvailableTooltip=Mise à jour disponible
ptbAvailableTooltip=Test public disponible
visitGithubRepository=Visiter le dépôt GitHub
updateAvailable=Mise à jour disponible : $VERSION$
downloadUpdate=Télécharger la mise à jour
@ -1249,7 +1250,7 @@ enterLicenseKey=Saisis la clé de licence pour la mise à niveau
isOnlySupported=n'est pris en charge qu'avec au moins une licence $TYPE$
areOnlySupported=ne sont pris en charge qu'avec au moins une licence $TYPE$
openApiDocs=Documentation de l'API
openApiDocsDescription=La documentation de l'API HTTP est fournie avec XPipe, y compris une spécification OpenAPI .yaml. Tu peux l'ouvrir dans ton navigateur web.
openApiDocsDescription=La documentation de l'API HTTP est disponible en ligne, y compris une spécification OpenAPI .yaml. Tu peux l'ouvrir dans ton navigateur web ou dans ton client HTTP préféré.
openApiDocsButton=Open docs
pythonApi=API Python
personalConnection=Cette connexion et tous ses enfants ne sont disponibles que pour ton utilisateur car ils dépendent d'une identité personnelle.
@ -1366,3 +1367,5 @@ passwordManagerKey=Clé du gestionnaire de mots de passe
passwordManagerAgent=Agent externe de gestion des mots de passe
dockerComposeProject.displayName=Projet Docker compose
dockerComposeProject.displayDescription=Regrouper les conteneurs d'un projet composé
sshVerboseOutput=Activer la sortie verbeuse de SSH
sshVerboseOutputDescription=Ceci imprimera beaucoup d'informations de débogage lors d'une connexion via SSH. Utile pour résoudre les problèmes liés aux connexions SSH.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Pembaruan tersedia untuk diunduh
updateRestart=Mulai ulang untuk memperbarui
never=Tidak pernah
updateAvailableTooltip=Pembaruan tersedia
ptbAvailableTooltip=Tersedia Uji Coba Publik
visitGithubRepository=Kunjungi repositori GitHub
updateAvailable=Pembaruan tersedia: $VERSION$
downloadUpdate=Unduh pembaruan
@ -1214,7 +1215,7 @@ enterLicenseKey=Masukkan kunci lisensi untuk meningkatkan
isOnlySupported=hanya didukung dengan setidaknya lisensi $TYPE$
areOnlySupported=hanya didukung dengan setidaknya lisensi $TYPE$
openApiDocs=Dokumentasi API
openApiDocsDescription=Dokumentasi API HTTP dibundel dengan XPipe, termasuk spesifikasi OpenAPI .yaml. Anda dapat membukanya di browser web Anda.
openApiDocsDescription=Dokumentasi API HTTP tersedia secara online, termasuk spesifikasi OpenAPI .yaml. Anda dapat membukanya di browser web atau klien HTTP pilihan Anda.
openApiDocsButton=Buka dokumen
pythonApi=API Python
personalConnection=Sambungan ini dan semua anak sambungannya hanya tersedia untuk pengguna Anda karena bergantung pada identitas pribadi.
@ -1331,3 +1332,5 @@ passwordManagerKey=Kunci pengelola kata sandi
passwordManagerAgent=Agen pengelola kata sandi eksternal
dockerComposeProject.displayName=Proyek penulisan Docker
dockerComposeProject.displayDescription=Mengelompokkan wadah dari proyek yang disusun bersama-sama
sshVerboseOutput=Mengaktifkan keluaran SSH yang bertele-tele
sshVerboseOutputDescription=Ini akan mencetak banyak informasi debug saat menyambung melalui SSH. Berguna untuk memecahkan masalah pada koneksi SSH.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Un aggiornamento è disponibile per il download
updateRestart=Riavviare per aggiornare
never=Mai
updateAvailableTooltip=Aggiornamento disponibile
ptbAvailableTooltip=Disponibile la versione di prova pubblica
visitGithubRepository=Visita il repository GitHub
updateAvailable=Aggiornamento disponibile: $VERSION$
downloadUpdate=Scarica l'aggiornamento
@ -1214,7 +1215,7 @@ enterLicenseKey=Inserisci la chiave di licenza per aggiornare
isOnlySupported=è supportato solo con almeno una licenza $TYPE$
areOnlySupported=sono supportati solo con una licenza di almeno $TYPE$
openApiDocs=Documentazione API
openApiDocsDescription=La documentazione dell'API HTTP viene fornita con XPipe e include una specifica OpenAPI .yaml. Puoi aprirla nel tuo browser web.
openApiDocsDescription=La documentazione dell'API HTTP è disponibile online, compresa una specifica OpenAPI .yaml. Puoi aprirla nel tuo browser web o nel tuo client HTTP preferito.
openApiDocsButton=Documenti aperti
pythonApi=API Python
personalConnection=Questa connessione e tutti i suoi figli sono disponibili solo per il tuo utente in quanto dipendono da un'identità personale.
@ -1331,3 +1332,5 @@ passwordManagerKey=Chiave del gestore di password
passwordManagerAgent=Agente esterno per la gestione delle password
dockerComposeProject.displayName=Progetto Docker compose
dockerComposeProject.displayDescription=Raggruppa i contenitori di un progetto composto
sshVerboseOutput=Abilita l'output verboso di SSH
sshVerboseOutputDescription=Stampa molte informazioni di debug quando ci si connette tramite SSH. È utile per risolvere i problemi delle connessioni SSH.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=アップデートがダウンロードできる
updateRestart=再起動して更新する
never=決して
updateAvailableTooltip=更新可能
ptbAvailableTooltip=パブリックテストビルド
visitGithubRepository=GitHub リポジトリを見る
updateAvailable=アップデート可能:$VERSION$
downloadUpdate=ダウンロード更新
@ -1214,7 +1215,7 @@ enterLicenseKey=ライセンスキーを入力してアップグレードする
isOnlySupported=は、少なくとも$TYPE$ ライセンスでのみサポートされる。
areOnlySupported=は、少なくとも$TYPE$ ライセンスでのみサポートされる。
openApiDocs=APIドキュメント
openApiDocsDescription=XPipeには、OpenAPI .yaml仕様を含むHTTP APIドキュメントがバンドルされている。ウェブブラウザで開くことができる。
openApiDocsDescription=HTTP APIドキュメントは、OpenAPI .yaml仕様を含めてオンラインで入手できる。ウェブブラウザやお好みのHTTPクライアントで開くことができる。
openApiDocsButton=ドキュメントを開く
pythonApi=Python API
personalConnection=この接続とそのすべての子は、個人のIDに依存するため、あなたのユーザーのみが利用できる。
@ -1331,3 +1332,5 @@ passwordManagerKey=パスワードマネージャーキー
passwordManagerAgent=外部パスワードマネージャーエージェント
dockerComposeProject.displayName=Docker composeプロジェクト
dockerComposeProject.displayDescription=構成されたプロジェクトのコンテナをグループ化する
sshVerboseOutput=冗長なSSH出力を有効にする
sshVerboseOutputDescription=SSHで接続するときに、多くのデバッグ情報を表示する。SSH接続のトラブルシューティングに役立つ。

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Er is een update beschikbaar om te downloaden
updateRestart=Opnieuw opstarten om bij te werken
never=Nooit
updateAvailableTooltip=Update beschikbaar
ptbAvailableTooltip=Publieke testversie beschikbaar
visitGithubRepository=Bezoek GitHub archief
updateAvailable=Update beschikbaar: $VERSION$
downloadUpdate=Update downloaden
@ -1214,7 +1215,7 @@ enterLicenseKey=Licentiesleutel invoeren om te upgraden
isOnlySupported=wordt alleen ondersteund met minimaal een $TYPE$ licentie
areOnlySupported=worden alleen ondersteund met minimaal een $TYPE$ licentie
openApiDocs=API-documentatie
openApiDocsDescription=De HTTP API documentatie is gebundeld met XPipe, inclusief een OpenAPI .yaml specificatie. Je kunt deze openen in je webbrowser.
openApiDocsDescription=De HTTP API documentatie is online beschikbaar, inclusief een OpenAPI .yaml specificatie. Je kunt deze openen in je webbrowser of in de HTTP-client van je voorkeur.
openApiDocsButton=Open documenten
pythonApi=Python API
personalConnection=Deze verbinding en al haar kinderen zijn alleen beschikbaar voor jouw gebruiker omdat ze afhankelijk zijn van een persoonlijke identiteit.
@ -1331,3 +1332,5 @@ passwordManagerKey=Wachtwoordmanager sleutel
passwordManagerAgent=Externe wachtwoordbeheerder agent
dockerComposeProject.displayName=Docker compose project
dockerComposeProject.displayDescription=Groepeer containers van een samengesteld project
sshVerboseOutput=Uitgebreide SSH-uitvoer inschakelen
sshVerboseOutputDescription=Hiermee wordt veel debug-informatie afgedrukt bij het verbinden via SSH. Nuttig voor het oplossen van problemen met SSH-verbindingen.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Aktualizacja jest dostępna do pobrania
updateRestart=Uruchom ponownie, aby zaktualizować
never=Nigdy
updateAvailableTooltip=Dostępna aktualizacja
ptbAvailableTooltip=Dostępna publiczna wersja testowa
visitGithubRepository=Odwiedź repozytorium GitHub
updateAvailable=Aktualizacja dostępna: $VERSION$
downloadUpdate=Pobierz aktualizację
@ -1215,7 +1216,7 @@ enterLicenseKey=Wprowadź klucz licencyjny do aktualizacji
isOnlySupported=jest obsługiwany tylko z licencją $TYPE$
areOnlySupported=są obsługiwane tylko z co najmniej licencją $TYPE$
openApiDocs=Dokumentacja API
openApiDocsDescription=Dokumentacja API HTTP jest dołączona do XPipe, w tym specyfikacja OpenAPI .yaml. Możesz ją otworzyć w przeglądarce internetowej.
openApiDocsDescription=Dokumentacja API HTTP jest dostępna online, w tym specyfikacja OpenAPI .yaml. Możesz ją otworzyć w przeglądarce internetowej lub preferowanym kliencie HTTP.
openApiDocsButton=Otwórz dokumenty
pythonApi=API Python
personalConnection=To połączenie i wszystkie jego elementy podrzędne są dostępne tylko dla Twojego użytkownika, ponieważ zależą od tożsamości osobistej.
@ -1332,3 +1333,5 @@ passwordManagerKey=Klucz menedżera haseł
passwordManagerAgent=Agent zewnętrznego menedżera haseł
dockerComposeProject.displayName=Projekt Docker compose
dockerComposeProject.displayDescription=Grupuj razem kontenery złożonego projektu
sshVerboseOutput=Włącz szczegółowe dane wyjściowe SSH
sshVerboseOutputDescription=Spowoduje to wydrukowanie wielu informacji debugowania podczas łączenia się przez SSH. Przydatne do rozwiązywania problemów z połączeniami SSH.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Uma atualização está disponível para transfer
updateRestart=Reinicia para atualizar
never=Nunca mais
updateAvailableTooltip=Atualização disponível
ptbAvailableTooltip=Compilação de teste pública disponível
visitGithubRepository=Visita o repositório GitHub
updateAvailable=Atualização disponível: $VERSION$
downloadUpdate=Atualização da transferência
@ -1214,7 +1215,7 @@ enterLicenseKey=Introduzir a chave de licença para atualizar
isOnlySupported=só é suportado com, pelo menos, uma licença $TYPE$
areOnlySupported=só são suportados com, pelo menos, uma licença $TYPE$
openApiDocs=Documentação API
openApiDocsDescription=A documentação da API HTTP é fornecida com o XPipe, incluindo uma especificação OpenAPI .yaml. Podes abri-la no teu navegador web.
openApiDocsDescription=A documentação da API HTTP está disponível online, incluindo uma especificação OpenAPI .yaml. Podes abri-la no teu browser da Web ou no teu cliente HTTP preferido.
openApiDocsButton=Abre documentos
pythonApi=API Python
personalConnection=Esta ligação e todos os seus filhos só estão disponíveis para o teu utilizador, uma vez que dependem de uma identidade pessoal.
@ -1331,3 +1332,5 @@ passwordManagerKey=Chave do gestor de senhas
passwordManagerAgent=Agente externo de gestão de palavras-passe
dockerComposeProject.displayName=Projeto Docker compose
dockerComposeProject.displayDescription=Agrupa contentores de um projeto composto
sshVerboseOutput=Habilita a saída verbosa do SSH
sshVerboseOutputDescription=Imprime muitas informações de depuração ao se conectar via SSH. Útil para solucionar problemas com conexões SSH.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Обновление доступно для за
updateRestart=Перезагрузка для обновления
never=Никогда
updateAvailableTooltip=Обновление доступно
ptbAvailableTooltip=Доступна публичная тестовая сборка
visitGithubRepository=Посетите репозиторий GitHub
updateAvailable=Доступно обновление: $VERSION$
downloadUpdate=Скачать обновление
@ -1214,7 +1215,7 @@ enterLicenseKey=Введите лицензионный ключ для обно
isOnlySupported=поддерживается только при наличии лицензии $TYPE$
areOnlySupported=поддерживаются только при наличии лицензии $TYPE$
openApiDocs=Документация по API
openApiDocsDescription=В комплекте с XPipe идет документация по HTTP API, включая спецификацию OpenAPI в формате .yaml. Ты можешь открыть ее в своем веб-браузере.
openApiDocsDescription=Документация по HTTP API доступна онлайн, включая спецификацию OpenAPI .yaml. Ты можешь открыть ее в своем браузере или в предпочитаемом HTTP-клиенте.
openApiDocsButton=Открытые документы
pythonApi=Python API
personalConnection=Это соединение и все его дочерние элементы доступны только твоему пользователю, так как зависят от персональной идентификации.
@ -1331,3 +1332,5 @@ passwordManagerKey=Ключ менеджера паролей
passwordManagerAgent=Внешний агент менеджера паролей
dockerComposeProject.displayName=Проект Docker compose
dockerComposeProject.displayDescription=Группировать контейнеры составленного проекта вместе
sshVerboseOutput=Включить подробный вывод SSH
sshVerboseOutputDescription=При подключении по SSH будет выведено много отладочной информации. Полезно для устранения проблем с SSH-соединениями.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=En uppdatering finns tillgänglig för nedladdnin
updateRestart=Starta om för att uppdatera
never=Aldrig
updateAvailableTooltip=Uppdatering tillgänglig
ptbAvailableTooltip=Offentlig testversion tillgänglig
visitGithubRepository=Besök GitHub-förvaret
updateAvailable=Uppdatering tillgänglig: $VERSION$
downloadUpdate=Ladda ner uppdatering
@ -1214,7 +1215,7 @@ enterLicenseKey=Ange licensnyckel för att uppgradera
isOnlySupported=stöds endast med minst en $TYPE$ -licens
areOnlySupported=stöds endast med minst en $TYPE$ -licens
openApiDocs=API-dokumentation
openApiDocsDescription=HTTP API-dokumentationen levereras tillsammans med XPipe, inklusive en OpenAPI .yaml-specifikation. Du kan öppna den i din webbläsare.
openApiDocsDescription=HTTP API-dokumentationen finns tillgänglig online, inklusive en OpenAPI .yaml-specifikation. Du kan öppna den i din webbläsare eller i den HTTP-klient du föredrar.
openApiDocsButton=Öppna dokument
pythonApi=Python API
personalConnection=Denna anslutning och alla dess barn är endast tillgängliga för din användare eftersom de är beroende av en personlig identitet.
@ -1331,3 +1332,5 @@ passwordManagerKey=Nyckel för lösenordshanterare
passwordManagerAgent=Agent för extern lösenordshanterare
dockerComposeProject.displayName=Docker compose-projekt
dockerComposeProject.displayDescription=Gruppera containrar för ett sammansatt projekt tillsammans
sshVerboseOutput=Aktivera utförlig SSH-utdata
sshVerboseOutputDescription=Detta skriver ut en hel del felsökningsinformation när du ansluter via SSH. Användbart för felsökning av problem med SSH-anslutningar.

View file

@ -190,6 +190,7 @@ updateReadyDescriptionPortable=Bir güncelleme indirilebilir
updateRestart=Güncellemek için yeniden başlatın
never=Asla
updateAvailableTooltip=Güncelleme mevcut
ptbAvailableTooltip=Herkese Açık Test Yapısı mevcut
visitGithubRepository=GitHub deposunu ziyaret edin
updateAvailable=Güncelleme mevcut: $VERSION$
downloadUpdate=Güncellemeyi indirin
@ -1214,7 +1215,7 @@ enterLicenseKey=Yükseltmek için lisans anahtarını girin
isOnlySupported=yalnızca en az $TYPE$ lisansı ile desteklenir
areOnlySupported=yalnızca en az bir $TYPE$ lisansı ile desteklenir
openApiDocs=API belgeleri
openApiDocsDescription=HTTP API belgeleri, OpenAPI .yaml belirtimi de dahil olmak üzere XPipe ile birlikte gelir. Web tarayıcınızda açabilirsiniz.
openApiDocsDescription=HTTP API belgeleri, OpenAPI .yaml spesifikasyonu da dahil olmak üzere çevrimiçi olarak mevcuttur. Web tarayıcınızda veya tercih ettiğiniz HTTP istemcisinde açabilirsiniz.
openApiDocsButton=ık dokümanlar
pythonApi=Python API
personalConnection=Bu bağlantı ve tüm çocukları, kişisel bir kimliğe bağlı oldukları için yalnızca kullanıcınız tarafından kullanılabilir.
@ -1331,3 +1332,5 @@ passwordManagerKey=Parola yöneticisi anahtarı
passwordManagerAgent=Harici parola yöneticisi aracısı
dockerComposeProject.displayName=Docker compose projesi
dockerComposeProject.displayDescription=Oluşturulan bir projenin kapsayıcılarını birlikte gruplama
sshVerboseOutput=Ayrıntılı SSH çıktısını etkinleştirme
sshVerboseOutputDescription=Bu, SSH üzerinden bağlanırken birçok hata ayıklama bilgisi yazdıracaktır. SSH bağlantıları ile ilgili sorunları gidermek için kullanışlıdır.

View file

@ -232,6 +232,7 @@ updateReadyDescriptionPortable=可下载更新
updateRestart=重新启动更新
never=从不
updateAvailableTooltip=可更新
ptbAvailableTooltip=公开测试版本可用
visitGithubRepository=访问 GitHub 代码库
updateAvailable=可更新:$VERSION$
downloadUpdate=下载更新
@ -1423,7 +1424,7 @@ enterLicenseKey=输入许可证密钥进行升级
isOnlySupported=至少要有$TYPE$ 许可证才支持
areOnlySupported=至少需要$TYPE$ 许可证才能支持
openApiDocs=API 文档
openApiDocsDescription=XPipe 中捆绑了 HTTP API 文档,包括 OpenAPI .yaml 规范。您可以在网络浏览器中打开它。
openApiDocsDescription=HTTP API 文档在线提供,包括 OpenAPI .yaml 规范。你可以在网络浏览器或你喜欢的 HTTP 客户端中打开它。
openApiDocsButton=打开文档
pythonApi=Python API
personalConnection=此连接及其所有子连接仅对您的用户开放,因为它们取决于个人身份。
@ -1556,3 +1557,5 @@ passwordManagerKey=密码管理器密钥
passwordManagerAgent=外部密码管理器代理
dockerComposeProject.displayName=Docker compose 项目
dockerComposeProject.displayDescription=将组成项目的容器组合在一起
sshVerboseOutput=启用 SSH 冗余输出
sshVerboseOutputDescription=通过 SSH 连接时,它会打印大量调试信息。有助于排除 SSH 连接的故障。