From c21a1b2bdc8149af281fc5067463eb22ee75aeba Mon Sep 17 00:00:00 2001 From: crschnick Date: Thu, 23 Jan 2025 23:17:45 +0000 Subject: [PATCH] Various fixes --- .../app/beacon/impl/FsReadExchangeImpl.java | 2 +- .../app/beacon/impl/FsWriteExchangeImpl.java | 2 +- .../app/browser/file/BrowserFileOpener.java | 2 +- .../main/java/io/xpipe/app/core/AppI18n.java | 6 +-- .../java/io/xpipe/app/core/AppProperties.java | 4 -- .../xpipe/app/ext}/ConnectionFileSystem.java | 8 +++- .../java/io/xpipe/app/prefs/AppPrefs.java | 5 +-- .../xpipe/app/prefs/AppearanceCategory.java | 3 +- .../app/prefs/ExternalPasswordManager.java | 19 ++++++++- .../app/prefs/PasswordManagerCategory.java | 16 ++++---- .../io/xpipe/app/prefs/SupportedLocale.java | 39 +++++++++++++----- .../app/update/XPipeDistributionType.java | 20 +++++++++ build.gradle | 2 - dist/jpackage.gradle | 1 - .../service/AbstractServiceStoreProvider.java | 19 +++++++++ .../ext/base/service/ServiceOpenAction.java | 41 ------------------- ext/base/src/main/java/module-info.java | 1 - 17 files changed, 108 insertions(+), 82 deletions(-) rename {core/src/main/java/io/xpipe/core/store => app/src/main/java/io/xpipe/app/ext}/ConnectionFileSystem.java (95%) delete mode 100644 ext/base/src/main/java/io/xpipe/ext/base/service/ServiceOpenAction.java diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/FsReadExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/FsReadExchangeImpl.java index 590a3f229..0f938e6bd 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/FsReadExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/FsReadExchangeImpl.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/FsWriteExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/FsWriteExchangeImpl.java index d3207064c..f2f347eb2 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/FsWriteExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/FsWriteExchangeImpl.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileOpener.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileOpener.java index 80a31116a..1917a9d0c 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileOpener.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileOpener.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/AppI18n.java b/app/src/main/java/io/xpipe/app/core/AppI18n.java index 6c1a58094..6c00d6f06 100644 --- a/app/src/main/java/io/xpipe/app/core/AppI18n.java +++ b/app/src/main/java/io/xpipe/app/core/AppI18n.java @@ -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) { diff --git a/app/src/main/java/io/xpipe/app/core/AppProperties.java b/app/src/main/java/io/xpipe/app/core/AppProperties.java index 04e0aa039..82eb6414a 100644 --- a/app/src/main/java/io/xpipe/app/core/AppProperties.java +++ b/app/src/main/java/io/xpipe/app/core/AppProperties.java @@ -30,7 +30,6 @@ public class AppProperties { UUID buildUuid; String sentryUrl; String arch; - List 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); diff --git a/core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java b/app/src/main/java/io/xpipe/app/ext/ConnectionFileSystem.java similarity index 95% rename from core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java rename to app/src/main/java/io/xpipe/app/ext/ConnectionFileSystem.java index 00bd1ecc6..215ee5a50 100644 --- a/core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java +++ b/app/src/main/java/io/xpipe/app/ext/ConnectionFileSystem.java @@ -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(); } } } diff --git a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java index ca7fe5084..ee0dc6903 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java @@ -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 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 = mapLocal( @@ -144,7 +143,7 @@ public class AppPrefs { mapLocal(new SimpleBooleanProperty(false), "developerPrintInitFiles", Boolean.class, false); final ObjectProperty 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); diff --git a/app/src/main/java/io/xpipe/app/prefs/AppearanceCategory.java b/app/src/main/java/io/xpipe/app/prefs/AppearanceCategory.java index cadc26211..778a82128 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppearanceCategory.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppearanceCategory.java @@ -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); }); diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java b/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java index e7aaa657c..fd6e759d0 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java @@ -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 ALL = Stream.of(COMMAND, WINDOWS_CREDENTIAL_MANAGER) + List ALL = Stream.of(NONE, COMMAND, WINDOWS_CREDENTIAL_MANAGER) .filter(externalPasswordManager -> externalPasswordManager.isSelectable()) .toList(); } diff --git a/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java b/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java index f147d8f3f..addd04bb2 100644 --- a/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java +++ b/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java @@ -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(); + 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(); diff --git a/app/src/main/java/io/xpipe/app/prefs/SupportedLocale.java b/app/src/main/java/io/xpipe/app/prefs/SupportedLocale.java index 1a31c6944..f51671bf5 100644 --- a/app/src/main/java/io/xpipe/app/prefs/SupportedLocale.java +++ b/app/src/main/java/io/xpipe/app/prefs/SupportedLocale.java @@ -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 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(); diff --git a/app/src/main/java/io/xpipe/app/update/XPipeDistributionType.java b/app/src/main/java/io/xpipe/app/update/XPipeDistributionType.java index a6f35c9d9..edb6044d0 100644 --- a/app/src/main/java/io/xpipe/app/update/XPipeDistributionType.java +++ b/app/src/main/java/io/xpipe/app/update/XPipeDistributionType.java @@ -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(); } diff --git a/build.gradle b/build.gradle index c05667425..fffbf500d 100644 --- a/build.gradle +++ b/build.gradle @@ -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", diff --git a/dist/jpackage.gradle b/dist/jpackage.gradle index 3495b2eed..493658c18 100644 --- a/dist/jpackage.gradle +++ b/dist/jpackage.gradle @@ -59,7 +59,6 @@ jlink { // '--strip-debug', '--no-header-files', '--no-man-pages', - '--include-locales', "${String.join(",", languages)}", '--compress', 'zip-9', '--ignore-signing-information' ] diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java index 1f1ddbb55..d987628f7 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java @@ -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(); diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceOpenAction.java b/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceOpenAction.java deleted file mode 100644 index 072180da5..000000000 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceOpenAction.java +++ /dev/null @@ -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() { - @Override - public ActionProvider.Action createAction(DataStoreEntryRef store) { - return new Action(store.getStore()); - } - - @Override - public Class 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); - } - } -} diff --git a/ext/base/src/main/java/module-info.java b/ext/base/src/main/java/module-info.java index 6b6d06123..774a6162c 100644 --- a/ext/base/src/main/java/module-info.java +++ b/ext/base/src/main/java/module-info.java @@ -80,7 +80,6 @@ open module io.xpipe.ext.base { StoreStartAction, StorePauseAction, StoreRestartAction, - ServiceOpenAction, ServiceCopyAddressAction, CloneStoreAction, RefreshChildrenStoreAction,