mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-05-19 13:58:37 -04:00
Various fixes
This commit is contained in:
@@ -5,7 +5,7 @@ import io.xpipe.app.beacon.BlobManager;
|
||||
import io.xpipe.app.util.FixedSizeInputStream;
|
||||
import io.xpipe.beacon.BeaconClientException;
|
||||
import io.xpipe.beacon.api.FsReadExchange;
|
||||
import io.xpipe.core.store.ConnectionFileSystem;
|
||||
import io.xpipe.app.ext.ConnectionFileSystem;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.xpipe.app.beacon.impl;
|
||||
import io.xpipe.app.beacon.AppBeaconServer;
|
||||
import io.xpipe.app.beacon.BlobManager;
|
||||
import io.xpipe.beacon.api.FsWriteExchange;
|
||||
import io.xpipe.core.store.ConnectionFileSystem;
|
||||
import io.xpipe.app.ext.ConnectionFileSystem;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@@ -7,7 +7,7 @@ import io.xpipe.app.util.FileBridge;
|
||||
import io.xpipe.app.util.FileOpener;
|
||||
import io.xpipe.core.process.ElevationFunction;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.store.ConnectionFileSystem;
|
||||
import io.xpipe.app.ext.ConnectionFileSystem;
|
||||
import io.xpipe.core.store.FileEntry;
|
||||
import io.xpipe.core.store.FileInfo;
|
||||
import io.xpipe.core.store.FileNames;
|
||||
|
||||
@@ -100,9 +100,9 @@ public class AppI18n {
|
||||
Locale.setDefault(Locale.ENGLISH);
|
||||
|
||||
// Load bundled JDK locale resources by initializing the classes
|
||||
SupportedLocale.ALL.forEach(supportedLocale -> {
|
||||
supportedLocale.getLocale().getDisplayName();
|
||||
});
|
||||
for (var value : SupportedLocale.values()) {
|
||||
value.getLocale().getDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLanguage.getValue() == null && PlatformState.getCurrent() == PlatformState.RUNNING) {
|
||||
|
||||
@@ -30,7 +30,6 @@ public class AppProperties {
|
||||
UUID buildUuid;
|
||||
String sentryUrl;
|
||||
String arch;
|
||||
List<String> languages;
|
||||
|
||||
@Getter
|
||||
boolean image;
|
||||
@@ -95,9 +94,6 @@ public class AppProperties {
|
||||
.orElse(UUID.randomUUID());
|
||||
sentryUrl = System.getProperty("io.xpipe.app.sentryUrl");
|
||||
arch = System.getProperty("io.xpipe.app.arch");
|
||||
languages = Arrays.stream(System.getProperty("io.xpipe.app.languages").split(","))
|
||||
.sorted()
|
||||
.toList();
|
||||
staging = Optional.ofNullable(System.getProperty("io.xpipe.app.staging"))
|
||||
.map(Boolean::parseBoolean)
|
||||
.orElse(false);
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package io.xpipe.core.store;
|
||||
package io.xpipe.app.ext;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.xpipe.core.store.FileEntry;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.InputStream;
|
||||
@@ -172,7 +175,8 @@ public class ConnectionFileSystem implements FileSystem {
|
||||
// Since we are only closing, just swallow all exceptions
|
||||
try {
|
||||
shellControl.close();
|
||||
} catch (Exception ignored) {
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).omit().expected().handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.terminal.ExternalTerminalType;
|
||||
import io.xpipe.app.update.XPipeDistributionType;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.app.util.PlatformThread;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.util.ModuleHelper;
|
||||
@@ -91,7 +90,7 @@ public class AppPrefs {
|
||||
public final BooleanProperty denyTempScriptCreation =
|
||||
mapVaultShared(new SimpleBooleanProperty(false), "denyTempScriptCreation", Boolean.class, false);
|
||||
final Property<ExternalPasswordManager> passwordManager =
|
||||
mapVaultShared(new SimpleObjectProperty<>(), "passwordManager", ExternalPasswordManager.class, false);
|
||||
mapVaultShared(new SimpleObjectProperty<>(ExternalPasswordManager.NONE), "passwordManager", ExternalPasswordManager.class, false);
|
||||
final StringProperty passwordManagerCommand =
|
||||
mapLocal(new SimpleStringProperty(""), "passwordManagerCommand", String.class, false);
|
||||
final ObjectProperty<StartupBehaviour> startupBehaviour = mapLocal(
|
||||
@@ -144,7 +143,7 @@ public class AppPrefs {
|
||||
mapLocal(new SimpleBooleanProperty(false), "developerPrintInitFiles", Boolean.class, false);
|
||||
|
||||
final ObjectProperty<SupportedLocale> language = mapLocal(
|
||||
new SimpleObjectProperty<>(SupportedLocale.getEnglish()), "language", SupportedLocale.class, false);
|
||||
new SimpleObjectProperty<>(SupportedLocale.getInitial()), "language", SupportedLocale.class, false);
|
||||
|
||||
final BooleanProperty requireDoubleClickForConnections =
|
||||
mapLocal(new SimpleBooleanProperty(false), "requireDoubleClickForConnections", Boolean.class, false);
|
||||
|
||||
@@ -19,6 +19,7 @@ import atlantafx.base.controls.ProgressSliderSkin;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AppearanceCategory extends AppPrefsCategory {
|
||||
@@ -71,7 +72,7 @@ public class AppearanceCategory extends AppPrefsCategory {
|
||||
|
||||
private Comp<?> languageChoice() {
|
||||
var prefs = AppPrefs.get();
|
||||
var c = ChoiceComp.ofTranslatable(prefs.language, SupportedLocale.ALL, false);
|
||||
var c = ChoiceComp.ofTranslatable(prefs.language, Arrays.asList(SupportedLocale.values()), false);
|
||||
var visit = new ButtonComp(AppI18n.observable("translate"), new FontIcon("mdi2w-web"), () -> {
|
||||
Hyperlinks.open(Hyperlinks.TRANSLATE);
|
||||
});
|
||||
|
||||
@@ -16,6 +16,23 @@ public interface ExternalPasswordManager extends PrefsChoiceValue {
|
||||
|
||||
String retrievePassword(String key);
|
||||
|
||||
ExternalPasswordManager NONE = new ExternalPasswordManager() {
|
||||
@Override
|
||||
public String getDocsLink() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String retrievePassword(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "none";
|
||||
}
|
||||
};
|
||||
|
||||
ExternalPasswordManager COMMAND = new ExternalPasswordManager() {
|
||||
|
||||
private static ShellControl SHELL;
|
||||
@@ -153,7 +170,7 @@ public interface ExternalPasswordManager extends PrefsChoiceValue {
|
||||
}
|
||||
};
|
||||
|
||||
List<ExternalPasswordManager> ALL = Stream.of(COMMAND, WINDOWS_CREDENTIAL_MANAGER)
|
||||
List<ExternalPasswordManager> ALL = Stream.of(NONE, COMMAND, WINDOWS_CREDENTIAL_MANAGER)
|
||||
.filter(externalPasswordManager -> externalPasswordManager.isSelectable())
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ public class PasswordManagerCategory extends AppPrefsCategory {
|
||||
|
||||
@Value
|
||||
private static class Choice {
|
||||
|
||||
public static Choice ofOther(ExternalPasswordManager externalPasswordManager) {
|
||||
return new Choice(externalPasswordManager.getId(), null, externalPasswordManager.getDocsLink(),externalPasswordManager);
|
||||
}
|
||||
|
||||
String id;
|
||||
String template;
|
||||
String docsLink;
|
||||
@@ -48,6 +53,7 @@ public class PasswordManagerCategory extends AppPrefsCategory {
|
||||
@Override
|
||||
protected Comp<?> create() {
|
||||
var choices = new ArrayList<Choice>();
|
||||
choices.add(Choice.ofOther(ExternalPasswordManager.NONE));
|
||||
ExternalPasswordManagerTemplate.ALL.forEach(externalPasswordManagerTemplate -> {
|
||||
choices.add(new Choice(
|
||||
externalPasswordManagerTemplate.getId(),
|
||||
@@ -55,15 +61,7 @@ public class PasswordManagerCategory extends AppPrefsCategory {
|
||||
externalPasswordManagerTemplate.getDocsLink(),
|
||||
ExternalPasswordManager.COMMAND));
|
||||
});
|
||||
ExternalPasswordManager.ALL.stream()
|
||||
.filter(externalPasswordManager -> externalPasswordManager != ExternalPasswordManager.COMMAND)
|
||||
.forEach(externalPasswordManager -> {
|
||||
choices.add(new Choice(
|
||||
externalPasswordManager.getId(),
|
||||
null,
|
||||
externalPasswordManager.getDocsLink(),
|
||||
externalPasswordManager));
|
||||
});
|
||||
choices.add(Choice.ofOther(ExternalPasswordManager.WINDOWS_CREDENTIAL_MANAGER));
|
||||
|
||||
var prefs = AppPrefs.get();
|
||||
var testPasswordManagerValue = new SimpleStringProperty();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.xpipe.app.prefs;
|
||||
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.ext.PrefsChoiceValue;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@@ -9,25 +8,43 @@ import javafx.beans.value.ObservableValue;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class SupportedLocale implements PrefsChoiceValue {
|
||||
public enum SupportedLocale implements PrefsChoiceValue {
|
||||
|
||||
ENGLISH(Locale.ENGLISH, "en", false),
|
||||
GERMAN(Locale.GERMAN, "de", false),
|
||||
DUTCH(Locale.of("nl"), "nl", false),
|
||||
SPANISH(Locale.of("es"), "es", false),
|
||||
FRENCH(Locale.FRENCH, "fr", true),
|
||||
ITALIAN(Locale.ITALIAN, "it", false),
|
||||
PORTUGUESE(Locale.of("pt"), "pt", false),
|
||||
RUSSIAN(Locale.of("ru"), "ru", true),
|
||||
JAPANESE(Locale.of("ja"), "ja", false),
|
||||
CHINESE(Locale.CHINESE, "zh", true),
|
||||
DANISH(Locale.of("da"), "da", false),
|
||||
INDONESIAN(Locale.of("id"), "id", false),
|
||||
SWEDISH(Locale.of("sv"), "sv", false),
|
||||
POLISH(Locale.of("pl"), "pl", false),
|
||||
TURKISH(Locale.of("tr"), "tr", true);
|
||||
|
||||
public static final List<SupportedLocale> ALL = AppProperties.get().getLanguages().stream()
|
||||
.map(s -> {
|
||||
var split = s.split("-");
|
||||
var loc = split.length == 2 ? Locale.of(split[0], split[1]) : Locale.of(s);
|
||||
return new SupportedLocale(loc, s);
|
||||
})
|
||||
.toList();
|
||||
private final Locale locale;
|
||||
private final String id;
|
||||
private final boolean setDefault;
|
||||
|
||||
public static SupportedLocale getInitial() {
|
||||
var s = Locale.getDefault();
|
||||
return Arrays.stream(values())
|
||||
.filter(supportedLocale -> supportedLocale.isSetDefault() && supportedLocale.getLocale().getLanguage().equals(s.getLanguage()))
|
||||
.findFirst()
|
||||
.orElse(getEnglish());
|
||||
}
|
||||
|
||||
public static SupportedLocale getEnglish() {
|
||||
return ALL.stream()
|
||||
return Arrays.stream(values())
|
||||
.filter(supportedLocale -> supportedLocale.getId().equals("en"))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.util.ModuleHelper;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
@@ -22,6 +23,8 @@ public enum XPipeDistributionType {
|
||||
PORTABLE("portable", false, () -> new PortableUpdater(true)),
|
||||
NATIVE_INSTALLATION("install", true, () -> new GitHubUpdater(true)),
|
||||
HOMEBREW("homebrew", true, () -> new PortableUpdater(true)),
|
||||
APT_REPO("apt", true, () -> new PortableUpdater(true)),
|
||||
RPM_REPO("rpm", true, () -> new PortableUpdater(true)),
|
||||
WEBTOP("webtop", true, () -> new PortableUpdater(false)),
|
||||
CHOCO("choco", true, () -> new PortableUpdater(true));
|
||||
|
||||
@@ -132,6 +135,23 @@ public enum XPipeDistributionType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OsType.getLocal() == OsType.LINUX) {
|
||||
var aptOut = sc.command("apt show xpipe").readStdoutIfPossible();
|
||||
if (aptOut.isPresent()) {
|
||||
var fromRepo = aptOut.get().lines().anyMatch(s -> {
|
||||
return s.contains("APT-Sources") && s.contains("apt.xpipe.io");
|
||||
});
|
||||
if (fromRepo) {
|
||||
return APT_REPO;
|
||||
}
|
||||
}
|
||||
|
||||
var yumRepo = sc.command(CommandBuilder.of().add("test", "-f").addFile("/etc/yum.repos.d/rpm.xpipe.io.repo")).executeAndCheck();
|
||||
if (yumRepo) {
|
||||
return RPM_REPO;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
}
|
||||
|
||||
@@ -126,7 +126,6 @@ project.ext {
|
||||
authors = 'Christopher Schnick'
|
||||
javafxVersion = '24-ea+15'
|
||||
platformName = getPlatformName()
|
||||
languages = ["en", "nl", "es", "fr", "de", "it", "pt", "ru", "ja", "zh", "tr", "da", "id", "sv", "pl"]
|
||||
jvmRunArgs = [
|
||||
"--add-opens", "java.base/java.lang=io.xpipe.app",
|
||||
"--add-opens", "java.base/java.lang=io.xpipe.core",
|
||||
@@ -140,7 +139,6 @@ project.ext {
|
||||
"--add-opens", "javafx.graphics/com.sun.javafx.tk.quantum=io.xpipe.app",
|
||||
"-Xmx2g",
|
||||
"-Dio.xpipe.app.arch=$rootProject.arch",
|
||||
"-Dio.xpipe.app.languages=${String.join(",", languages)}",
|
||||
"-Dfile.encoding=UTF-8",
|
||||
"-Dvisualvm.display.name=XPipe",
|
||||
"-Djavafx.preloader=io.xpipe.app.core.AppPreloader",
|
||||
|
||||
1
dist/jpackage.gradle
vendored
1
dist/jpackage.gradle
vendored
@@ -59,7 +59,6 @@ jlink {
|
||||
// '--strip-debug',
|
||||
'--no-header-files',
|
||||
'--no-man-pages',
|
||||
'--include-locales', "${String.join(",", languages)}",
|
||||
'--compress', 'zip-9',
|
||||
'--ignore-signing-information'
|
||||
]
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.xpipe.ext.base.service;
|
||||
import io.xpipe.app.comp.Comp;
|
||||
import io.xpipe.app.comp.store.*;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.ActionProvider;
|
||||
import io.xpipe.app.ext.DataStoreProvider;
|
||||
import io.xpipe.app.ext.DataStoreUsageCategory;
|
||||
import io.xpipe.app.ext.SingletonSessionStoreProvider;
|
||||
@@ -20,6 +21,24 @@ import java.util.List;
|
||||
|
||||
public abstract class AbstractServiceStoreProvider implements SingletonSessionStoreProvider, DataStoreProvider {
|
||||
|
||||
@Override
|
||||
public ActionProvider.Action launchAction(DataStoreEntry store) {
|
||||
return new ActionProvider.Action() {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
AbstractServiceStore serviceStore = store.getStore().asNeeded();
|
||||
serviceStore.startSessionIfNeeded();
|
||||
var l = serviceStore.requiresTunnel()
|
||||
? serviceStore.getSession().getLocalPort()
|
||||
: serviceStore.getRemotePort();
|
||||
var base = "localhost:" + l;
|
||||
var full = serviceStore.getServiceProtocolType().formatAddress(base);
|
||||
serviceStore.getServiceProtocolType().open(full);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String displayName(DataStoreEntry entry) {
|
||||
AbstractServiceStore s = entry.getStore().asNeeded();
|
||||
return DataStorage.get().getStoreEntryDisplayName(s.getHost().get()) + " - Port " + s.getRemotePort();
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package io.xpipe.ext.base.service;
|
||||
|
||||
import io.xpipe.app.ext.ActionProvider;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
public class ServiceOpenAction implements ActionProvider {
|
||||
|
||||
@Override
|
||||
public DefaultDataStoreCallSite<?> getDefaultDataStoreCallSite() {
|
||||
return new DefaultDataStoreCallSite<AbstractServiceStore>() {
|
||||
@Override
|
||||
public ActionProvider.Action createAction(DataStoreEntryRef<AbstractServiceStore> store) {
|
||||
return new Action(store.getStore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<AbstractServiceStore> getApplicableClass() {
|
||||
return AbstractServiceStore.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
AbstractServiceStore serviceStore;
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
serviceStore.startSessionIfNeeded();
|
||||
var l = serviceStore.requiresTunnel()
|
||||
? serviceStore.getSession().getLocalPort()
|
||||
: serviceStore.getRemotePort();
|
||||
var base = "localhost:" + l;
|
||||
var full = serviceStore.getServiceProtocolType().formatAddress(base);
|
||||
serviceStore.getServiceProtocolType().open(full);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,6 @@ open module io.xpipe.ext.base {
|
||||
StoreStartAction,
|
||||
StorePauseAction,
|
||||
StoreRestartAction,
|
||||
ServiceOpenAction,
|
||||
ServiceCopyAddressAction,
|
||||
CloneStoreAction,
|
||||
RefreshChildrenStoreAction,
|
||||
|
||||
Reference in New Issue
Block a user