From 0064569fb23d421d7a1cd790cc18f2fa413b9ac2 Mon Sep 17 00:00:00 2001 From: crschnick Date: Sat, 6 Apr 2024 12:36:25 +0000 Subject: [PATCH] Rework --- .../app/browser/action/BrowserAction.java | 5 -- .../xpipe/app/comp/store/StoreEntryComp.java | 2 +- .../xpipe/app/core/AppExtensionManager.java | 26 ++++++++-- .../java/io/xpipe/app/ext/ActionProvider.java | 5 -- .../io/xpipe/app/ext/PrefsChoiceValue.java | 19 +++---- .../java/io/xpipe/app/ext/PrefsProvider.java | 5 -- .../java/io/xpipe/app/ext/ScanProvider.java | 5 -- .../xpipe/app/ext/XPipeServiceProviders.java | 36 ------------- .../app/fxcomps/impl/StringSourceComp.java | 40 +++++++++++++++ .../xpipe/app/fxcomps/impl/TextFieldComp.java | 4 +- .../java/io/xpipe/app/prefs/AppPrefs.java | 1 + .../xpipe/app/prefs/LocalShellCategory.java | 5 -- .../java/io/xpipe/app/prefs/SshCategory.java | 28 ++++++++++ .../io/xpipe/app/util/LicenseProvider.java | 5 -- .../java/io/xpipe/app/util/PlatformState.java | 22 ++++---- .../java/io/xpipe/app/util/StringSource.java | 51 +++++++++++++++++++ .../io/xpipe/core/process/ShellDialects.java | 5 -- .../io/xpipe/core/util/ModuleLayerLoader.java | 8 +-- lang/app/strings/translations_en.properties | 2 + lang/proc/strings/translations_en.properties | 2 + 20 files changed, 169 insertions(+), 107 deletions(-) delete mode 100644 app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java create mode 100644 app/src/main/java/io/xpipe/app/fxcomps/impl/StringSourceComp.java create mode 100644 app/src/main/java/io/xpipe/app/prefs/SshCategory.java create mode 100644 app/src/main/java/io/xpipe/app/util/StringSource.java diff --git a/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java b/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java index a024c04e8..7b10bdb13 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/BrowserAction.java @@ -92,11 +92,6 @@ public interface BrowserAction { .toList()); } - @Override - public boolean requiresFullDaemon() { - return true; - } - @Override public boolean prioritizeLoading() { return false; diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java index e9348cd68..c102b2ef3 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java @@ -95,7 +95,7 @@ public abstract class StoreEntryComp extends SimpleComp { wrapper.executeDefaultAction(); }); }); - new ContextMenuAugment<>(mouseEvent -> mouseEvent.isSecondaryButtonDown(), null, () -> this.createContextMenu()).augment(new SimpleCompStructure<>(button)); + new ContextMenuAugment<>(mouseEvent -> mouseEvent.getButton() == MouseButton.SECONDARY, null, () -> this.createContextMenu()).augment(button); var loading = LoadingOverlayComp.noProgress( Comp.of(() -> button), diff --git a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java index a1b009b0e..0f9ebf347 100644 --- a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java +++ b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java @@ -1,11 +1,16 @@ package io.xpipe.app.core; +import com.fasterxml.jackson.databind.jsontype.NamedType; import io.xpipe.app.exchange.MessageExchangeImpls; +import io.xpipe.app.ext.DataStoreProvider; +import io.xpipe.app.ext.DataStoreProviders; import io.xpipe.app.ext.ExtensionException; -import io.xpipe.app.ext.XPipeServiceProviders; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.TrackEvent; +import io.xpipe.core.process.ProcessControlProvider; +import io.xpipe.core.util.JacksonMapper; import io.xpipe.core.util.ModuleHelper; +import io.xpipe.core.util.ModuleLayerLoader; import io.xpipe.core.util.XPipeInstallation; import lombok.Getter; import lombok.Value; @@ -47,9 +52,24 @@ public class AppExtensionManager { } if (load) { - // INSTANCE.addNativeLibrariesToPath(); try { - XPipeServiceProviders.load(INSTANCE.extendedLayer); + ModuleLayerLoader.loadAll(INSTANCE.extendedLayer, true, t -> { + ErrorEvent.fromThrowable(t).handle(); + }); + ProcessControlProvider.init(INSTANCE.extendedLayer); + TrackEvent.info("Loading extension providers ..."); + DataStoreProviders.init(INSTANCE.extendedLayer); + for (DataStoreProvider p : DataStoreProviders.getAll()) { + TrackEvent.trace("Loaded data store provider " + p.getId()); + JacksonMapper.configure(objectMapper -> { + for (Class storeClass : p.getStoreClasses()) { + objectMapper.registerSubtypes(new NamedType(storeClass)); + } + }); + } + ModuleLayerLoader.loadAll(INSTANCE.extendedLayer, false, t -> { + ErrorEvent.fromThrowable(t).handle(); + }); MessageExchangeImpls.loadAll(); } catch (Throwable t) { throw new ExtensionException( diff --git a/app/src/main/java/io/xpipe/app/ext/ActionProvider.java b/app/src/main/java/io/xpipe/app/ext/ActionProvider.java index 208b637e9..187ee42b6 100644 --- a/app/src/main/java/io/xpipe/app/ext/ActionProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/ActionProvider.java @@ -144,11 +144,6 @@ public interface ActionProvider { .toList()); } - @Override - public boolean requiresFullDaemon() { - return true; - } - @Override public boolean prioritizeLoading() { return false; diff --git a/app/src/main/java/io/xpipe/app/ext/PrefsChoiceValue.java b/app/src/main/java/io/xpipe/app/ext/PrefsChoiceValue.java index 8e3f87436..cd611df51 100644 --- a/app/src/main/java/io/xpipe/app/ext/PrefsChoiceValue.java +++ b/app/src/main/java/io/xpipe/app/ext/PrefsChoiceValue.java @@ -30,20 +30,15 @@ public interface PrefsChoiceValue extends Translatable { } } - @SuppressWarnings("unchecked") static List getSupported(Class type) { - try { - return (List) type.getDeclaredField("SUPPORTED").get(null); - } catch (IllegalAccessException | NoSuchFieldException e) { - var all = getAll(type); - if (all == null) { - throw new AssertionError(); - } - - return all.stream() - .filter(t -> ((PrefsChoiceValue) t).isSelectable()) - .toList(); + var all = getAll(type); + if (all == null) { + throw new AssertionError(); } + + return all.stream() + .filter(t -> ((PrefsChoiceValue) t).isSelectable()) + .toList(); } default boolean isAvailable() { diff --git a/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java b/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java index 14039c655..b69d480fb 100644 --- a/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java @@ -35,11 +35,6 @@ public abstract class PrefsProvider { .collect(Collectors.toList()); } - @Override - public boolean requiresFullDaemon() { - return true; - } - @Override public boolean prioritizeLoading() { return false; diff --git a/app/src/main/java/io/xpipe/app/ext/ScanProvider.java b/app/src/main/java/io/xpipe/app/ext/ScanProvider.java index 3da157de0..6a7670a8f 100644 --- a/app/src/main/java/io/xpipe/app/ext/ScanProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/ScanProvider.java @@ -63,11 +63,6 @@ public abstract class ScanProvider { .collect(Collectors.toList()); } - @Override - public boolean requiresFullDaemon() { - return true; - } - @Override public boolean prioritizeLoading() { return false; diff --git a/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java b/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java deleted file mode 100644 index 298b7e11e..000000000 --- a/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.xpipe.app.ext; - -import com.fasterxml.jackson.databind.jsontype.NamedType; -import io.xpipe.app.issue.ErrorEvent; -import io.xpipe.app.issue.TrackEvent; -import io.xpipe.core.process.ProcessControlProvider; -import io.xpipe.core.util.JacksonMapper; -import io.xpipe.core.util.ModuleLayerLoader; - -public class XPipeServiceProviders { - - public static void load(ModuleLayer layer) { - var hasDaemon = true; - ModuleLayerLoader.loadAll(layer, hasDaemon, true, t -> { - ErrorEvent.fromThrowable(t).handle(); - }); - ProcessControlProvider.init(layer); - - TrackEvent.info("Loading extension providers ..."); - DataStoreProviders.init(layer); - for (DataStoreProvider p : DataStoreProviders.getAll()) { - TrackEvent.trace("Loaded data store provider " + p.getId()); - JacksonMapper.configure(objectMapper -> { - for (Class storeClass : p.getStoreClasses()) { - objectMapper.registerSubtypes(new NamedType(storeClass)); - } - }); - } - - ModuleLayerLoader.loadAll(layer, hasDaemon, false, t -> { - ErrorEvent.fromThrowable(t).handle(); - }); - - TrackEvent.info("Finished loading extension providers"); - } -} diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/StringSourceComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/StringSourceComp.java new file mode 100644 index 000000000..302610210 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/StringSourceComp.java @@ -0,0 +1,40 @@ +package io.xpipe.app.fxcomps.impl; + +import io.xpipe.app.fxcomps.SimpleComp; +import io.xpipe.app.storage.DataStoreEntryRef; +import io.xpipe.app.util.StringSource; +import io.xpipe.core.store.ShellStore; +import javafx.beans.property.Property; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ObservableValue; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.layout.Region; + +public class StringSourceComp extends SimpleComp { + + private final Property> fileSystem; + private final Property stringSource; + + public StringSourceComp(ObservableValue> fileSystem, Property stringSource) { + this.stringSource = stringSource; + this.fileSystem = new SimpleObjectProperty<>(); + fileSystem.subscribe(val -> { + this.fileSystem.setValue(val); + }); + } + + @Override + protected Region createSimple() { + var tab = new TabPane(); + + var inPlace = new SimpleObjectProperty<>(stringSource.getValue() instanceof StringSource.InPlace i ? i.get() : null); + var stringField = new TextAreaComp(inPlace); + tab.getTabs().add(new Tab()); + + var fs = stringSource.getValue() instanceof StringSource.File f ? f.getFile() : null; + var file = new SimpleObjectProperty<>(stringSource.getValue() instanceof StringSource.File f ? f.getFile() : null); + // new ContextualFileReferenceChoiceComp(fileSystem, file); + return null; + } +} diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/TextFieldComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/TextFieldComp.java index 66183eef2..eea8bf4ca 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/TextFieldComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/TextFieldComp.java @@ -30,6 +30,9 @@ public class TextFieldComp extends Comp> { value.setValue(val); }); } + lastAppliedValue.addListener((c, o, n) -> { + currentValue.setValue(n); + }); } @Override @@ -39,7 +42,6 @@ public class TextFieldComp extends Comp> { currentValue.setValue(n != null && n.length() > 0 ? n : null); }); lastAppliedValue.addListener((c, o, n) -> { - currentValue.setValue(n); PlatformThread.runLaterIfNeeded(() -> { // Check if control value is the same. Then don't set it as that might cause bugs if (Objects.equals(text.getText(), n) 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 f319a258b..132705078 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java @@ -144,6 +144,7 @@ public class AppPrefs { new RdpCategory(), new SyncCategory(), new VaultCategory(), + new SshCategory(), new LocalShellCategory(), new SecurityCategory(), new PasswordManagerCategory(), diff --git a/app/src/main/java/io/xpipe/app/prefs/LocalShellCategory.java b/app/src/main/java/io/xpipe/app/prefs/LocalShellCategory.java index b51696f61..04186e08a 100644 --- a/app/src/main/java/io/xpipe/app/prefs/LocalShellCategory.java +++ b/app/src/main/java/io/xpipe/app/prefs/LocalShellCategory.java @@ -2,8 +2,6 @@ package io.xpipe.app.prefs; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.util.OptionsBuilder; -import io.xpipe.core.process.OsType; -import javafx.beans.property.SimpleBooleanProperty; public class LocalShellCategory extends AppPrefsCategory { @@ -18,9 +16,6 @@ public class LocalShellCategory extends AppPrefsCategory { return new OptionsBuilder() .addTitle("localShell") .sub(new OptionsBuilder() - .nameAndDescription("useBundledTools") - .addToggle(prefs.useBundledTools) - .hide(new SimpleBooleanProperty(!OsType.getLocal().equals(OsType.WINDOWS))) .nameAndDescription("useLocalFallbackShell") .addToggle(prefs.useLocalFallbackShell)) .buildComp(); diff --git a/app/src/main/java/io/xpipe/app/prefs/SshCategory.java b/app/src/main/java/io/xpipe/app/prefs/SshCategory.java new file mode 100644 index 000000000..c64a2790b --- /dev/null +++ b/app/src/main/java/io/xpipe/app/prefs/SshCategory.java @@ -0,0 +1,28 @@ +package io.xpipe.app.prefs; + +import io.xpipe.app.fxcomps.Comp; +import io.xpipe.app.util.OptionsBuilder; +import io.xpipe.core.process.OsType; +import javafx.beans.property.SimpleBooleanProperty; + +public class SshCategory extends AppPrefsCategory { + + @Override + protected String getId() { + return "ssh"; + } + + @Override + protected Comp create() { + var prefs = AppPrefs.get(); + return new OptionsBuilder() + .addTitle("sshConfiguration") + .sub(new OptionsBuilder() + .nameAndDescription("useBundledTools") + .addToggle(prefs.useBundledTools) + .hide(new SimpleBooleanProperty(!OsType.getLocal().equals(OsType.WINDOWS))) + .addComp(prefs.getCustomComp("x11WslInstance")) + .hide(new SimpleBooleanProperty(!OsType.getLocal().equals(OsType.WINDOWS)))) + .buildComp(); + } +} diff --git a/app/src/main/java/io/xpipe/app/util/LicenseProvider.java b/app/src/main/java/io/xpipe/app/util/LicenseProvider.java index e979a1f1e..0e76b0a73 100644 --- a/app/src/main/java/io/xpipe/app/util/LicenseProvider.java +++ b/app/src/main/java/io/xpipe/app/util/LicenseProvider.java @@ -42,11 +42,6 @@ public abstract class LicenseProvider { .orElseThrow(() -> ExtensionException.corrupt("Missing license provider")); } - @Override - public boolean requiresFullDaemon() { - return true; - } - @Override public boolean prioritizeLoading() { return true; diff --git a/app/src/main/java/io/xpipe/app/util/PlatformState.java b/app/src/main/java/io/xpipe/app/util/PlatformState.java index 4632cdba3..23dd3a204 100644 --- a/app/src/main/java/io/xpipe/app/util/PlatformState.java +++ b/app/src/main/java/io/xpipe/app/util/PlatformState.java @@ -1,17 +1,14 @@ package io.xpipe.app.util; import io.xpipe.app.core.check.AppSystemFontCheck; -import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.issue.TrackEvent; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.core.process.OsType; import javafx.application.Platform; -import javafx.scene.input.Clipboard; import lombok.Getter; import lombok.Setter; import java.awt.*; -import java.awt.datatransfer.StringSelection; import java.util.Optional; import java.util.concurrent.CountDownLatch; @@ -28,15 +25,16 @@ public enum PlatformState { private static Exception lastError; public static void teardown() { - PlatformThread.runLaterIfNeededBlocking(() -> { - try { - // Fix to preserve clipboard contents after shutdown - var string = Clipboard.getSystemClipboard().getString(); - var s = new StringSelection(string); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(s, s); - } catch (IllegalStateException ignored) { - } - }); + // This is bad and can get sometimes stuck +// PlatformThread.runLaterIfNeededBlocking(() -> { +// try { +// // Fix to preserve clipboard contents after shutdown +// var string = Clipboard.getSystemClipboard().getString(); +// var s = new StringSelection(string); +// Toolkit.getDefaultToolkit().getSystemClipboard().setContents(s, s); +// } catch (IllegalStateException ignored) { +// } +// }); Platform.exit(); setCurrent(PlatformState.EXITED); diff --git a/app/src/main/java/io/xpipe/app/util/StringSource.java b/app/src/main/java/io/xpipe/app/util/StringSource.java new file mode 100644 index 000000000..746b141a1 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/util/StringSource.java @@ -0,0 +1,51 @@ +package io.xpipe.app.util; + +import io.xpipe.app.issue.ErrorEvent; +import io.xpipe.app.storage.ContextualFileReference; +import io.xpipe.core.store.ShellStore; +import lombok.EqualsAndHashCode; +import lombok.Value; + +public abstract class StringSource { + + public abstract String get() throws Exception; + + @Value + @EqualsAndHashCode(callSuper = true) + public static class InPlace extends StringSource { + + String value; + + @Override + public String get() { + return value; + } + } + + @Value + @EqualsAndHashCode(callSuper = true) + public static class File extends StringSource { + + ShellStore host; + ContextualFileReference file; + + @Override + public String get() throws Exception { + if (host == null || file == null) { + return ""; + } + + try (var sc = host.control().start()) { + var path = file.toAbsoluteFilePath(sc); + if (!sc.getShellDialect().createFileExistsCommand(sc, path).executeAndCheck()) { + throw ErrorEvent.expected( + new IllegalArgumentException("File " + path + " does not exist")); + } + + var abs = file.toAbsoluteFilePath(sc); + var content = sc.getShellDialect().getFileReadCommand(sc, abs).readStdoutOrThrow(); + return content; + } + } + } +} diff --git a/core/src/main/java/io/xpipe/core/process/ShellDialects.java b/core/src/main/java/io/xpipe/core/process/ShellDialects.java index 1767e14c6..407b92dd3 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellDialects.java +++ b/core/src/main/java/io/xpipe/core/process/ShellDialects.java @@ -79,11 +79,6 @@ public class ShellDialects { OVH_BASTION = byId("ovhBastion"); } - @Override - public boolean requiresFullDaemon() { - return false; - } - @Override public boolean prioritizeLoading() { return true; diff --git a/core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java b/core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java index 1be9e5e63..9c80809af 100644 --- a/core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java +++ b/core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java @@ -6,14 +6,10 @@ import java.util.function.Consumer; public interface ModuleLayerLoader { static void loadAll( - ModuleLayer layer, boolean hasDaemon, boolean prioritization, Consumer errorHandler) { + ModuleLayer layer, boolean prioritization, Consumer errorHandler) { ServiceLoader.load(layer, ModuleLayerLoader.class).stream().forEach(moduleLayerLoaderProvider -> { var instance = moduleLayerLoaderProvider.get(); try { - if (instance.requiresFullDaemon() && !hasDaemon) { - return; - } - if (instance.prioritizeLoading() != prioritization) { return; } @@ -27,7 +23,5 @@ public interface ModuleLayerLoader { void init(ModuleLayer layer); - boolean requiresFullDaemon(); - boolean prioritizeLoading(); } diff --git a/lang/app/strings/translations_en.properties b/lang/app/strings/translations_en.properties index 98c3ae992..29f75f8e5 100644 --- a/lang/app/strings/translations_en.properties +++ b/lang/app/strings/translations_en.properties @@ -428,3 +428,5 @@ goodMorning=Good morning goodAfternoon=Good afternoon goodNight=Good night addVisual=Visual ... +ssh=SSH +sshConfiguration=SSH Configuration diff --git a/lang/proc/strings/translations_en.properties b/lang/proc/strings/translations_en.properties index 6622dd8ba..9222d8252 100644 --- a/lang/proc/strings/translations_en.properties +++ b/lang/proc/strings/translations_en.properties @@ -287,3 +287,5 @@ vncUsername=Username vncUsernameDescription=The optional VNC username vncPassword=Password vncPasswordDescription=The VNC password +x11WslInstance=X11 Forward WSL instance +x11WslInstanceDescription=The local Windows Subsystem for Linux distribution to use as an X11 server when using X11 forwarding in an SSH connection. This distribution must be a WSL2 distribution.\n\nRequires a restart to apply.