mirror of
https://github.com/xpipe-io/xpipe.git
synced 2025-04-17 09:43:37 +00:00
Rework
This commit is contained in:
parent
8b75699649
commit
a50869da6d
79 changed files with 298 additions and 292 deletions
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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) -> {
|
||||
|
|
|
@ -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",
|
||||
() -> {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
5
lang/strings/translations_da.properties
generated
5
lang/strings/translations_da.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_de.properties
generated
5
lang/strings/translations_de.properties
generated
|
@ -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.
|
||||
|
|
2
lang/strings/translations_en.properties
generated
2
lang/strings/translations_en.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_es.properties
generated
5
lang/strings/translations_es.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_fr.properties
generated
5
lang/strings/translations_fr.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_id.properties
generated
5
lang/strings/translations_id.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_it.properties
generated
5
lang/strings/translations_it.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_ja.properties
generated
5
lang/strings/translations_ja.properties
generated
|
@ -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接続のトラブルシューティングに役立つ。
|
||||
|
|
5
lang/strings/translations_nl.properties
generated
5
lang/strings/translations_nl.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_pl.properties
generated
5
lang/strings/translations_pl.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_pt.properties
generated
5
lang/strings/translations_pt.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_ru.properties
generated
5
lang/strings/translations_ru.properties
generated
|
@ -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-соединениями.
|
||||
|
|
5
lang/strings/translations_sv.properties
generated
5
lang/strings/translations_sv.properties
generated
|
@ -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.
|
||||
|
|
5
lang/strings/translations_tr.properties
generated
5
lang/strings/translations_tr.properties
generated
|
@ -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=Açı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.
|
||||
|
|
5
lang/strings/translations_zh.properties
generated
5
lang/strings/translations_zh.properties
generated
|
@ -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 连接的故障。
|
||||
|
|
Loading…
Add table
Reference in a new issue