diff --git a/app/src/main/java/io/xpipe/app/icon/SystemIconCache.java b/app/src/main/java/io/xpipe/app/icon/SystemIconCache.java index ffc548f77..f1701b739 100644 --- a/app/src/main/java/io/xpipe/app/icon/SystemIconCache.java +++ b/app/src/main/java/io/xpipe/app/icon/SystemIconCache.java @@ -26,7 +26,7 @@ public class SystemIconCache { private static final Path DIRECTORY = AppProperties.get().getDataDir().resolve("cache").resolve("icons").resolve("raster"); private static final int[] sizes = new int[] {16, 24, 40, 80}; - public static final int VERSION = 2; + public static final int VERSION = 3; public static Path getDirectory(SystemIconSource source) { var target = DIRECTORY.resolve(source.getId()); diff --git a/app/src/main/java/io/xpipe/app/process/ShellControl.java b/app/src/main/java/io/xpipe/app/process/ShellControl.java index f1c964548..1e3a9b7a7 100644 --- a/app/src/main/java/io/xpipe/app/process/ShellControl.java +++ b/app/src/main/java/io/xpipe/app/process/ShellControl.java @@ -190,7 +190,7 @@ public interface ShellControl extends ProcessControl { ShellControl elevated(ElevationFunction elevationFunction); - ShellControl withInitSnippet(ShellTerminalInitCommand snippet); + ShellControl withInitSnippet(ShellTerminalInitCommand snippet, boolean append); Optional getActiveReplacementBackgroundSession() throws Exception; diff --git a/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java b/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java index 13f5d5527..226f9d24f 100644 --- a/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java +++ b/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java @@ -341,8 +341,8 @@ public class WrapperShellControl implements ShellControl { } @Override - public ShellControl withInitSnippet(ShellTerminalInitCommand snippet) { - return parent.withInitSnippet(snippet); + public ShellControl withInitSnippet(ShellTerminalInitCommand snippet, boolean append) { + return parent.withInitSnippet(snippet, append); } @Override diff --git a/app/src/main/java/io/xpipe/app/terminal/TerminalPromptManager.java b/app/src/main/java/io/xpipe/app/terminal/TerminalPromptManager.java index bcac78450..6a086fb53 100644 --- a/app/src/main/java/io/xpipe/app/terminal/TerminalPromptManager.java +++ b/app/src/main/java/io/xpipe/app/terminal/TerminalPromptManager.java @@ -13,7 +13,7 @@ public class TerminalPromptManager { } try { - sc.withInitSnippet(p.terminalCommand()); + sc.withInitSnippet(p.terminalCommand(), false); } catch (Exception e) { ErrorEventFactory.fromThrowable(e).handle(); } diff --git a/dist/changelog/19.0.md b/dist/changelog/19.0.md index f53fe733d..3a3018b0a 100644 --- a/dist/changelog/19.0.md +++ b/dist/changelog/19.0.md @@ -2,10 +2,14 @@ You can now connect to devices in your Netbird network via SSH and your locally installed netbird command-line client. This integration supports multiple accounts as well to switch between different profiles. +![Netbird](https://xpipe.io/assets/images/BlogPage/netbird.png) + ## SFTP support There is now support for systems which do only support pure SFTP and not SSH shell sessions. These can be opened in the file browser as normal, although with limited functionality as there is no way to execute commands on these systems. +![SFTP](https://xpipe.io/assets/images/BlogPage/sftp.png) + ## Legacy system support Up until now, the testing was done on *relatively* up-to-date machines that were not considered EOL. However, in practice, legacy systems are still used. With XPipe 19, the handling of older Unix-based systems has been greatly improved. As long as you can connect to it via SSH somehow, it should work now. @@ -21,6 +25,11 @@ The following things have been implemented to improve legacy system support: - Add full recognition for AIX system versions - Improve non-Linux Unix-based system name formatting +![AIX](https://xpipe.io/assets/images/BlogPage/aix.png) + +![HP-UX](https://xpipe.io/assets/images/BlogPage/hpux.png) + + You are running old systems? Then feel free to test how XPipe 19 handles for you, and report anything that doesn't work yet. ## Abstract hosts and direct connections @@ -29,8 +38,12 @@ Up until now, the handling of systems which did not support shell connections ha Essentially, you can now specify the target address inline or choose an existing host from xpipe. XPipe will then automatically adapt the connection based on what is possible. E.g. if you want to open a web service on a device without shell access, e.g. some embedded device, just specify the hostname and optional gateway. You can then open the website in the browser while also having a nice grouping of various connection entries for an abstract host in case you have more connections added for that host: +![Abstract host config](https://xpipe.io/assets/images/BlogPage/abstract-host-config.png) + You can also quickly convert existing connections entries like services and direct RDP/VNC connections to an abstract host entry to allow for better organization. +![Abstract host](https://xpipe.io/assets/images/BlogPage/abstract-host.png) + ## License updates The license prices have been adjusted by 12% to $45/$90 per year due to the dollar depreciating, which reduced the effective revenue for us as an EU-based company. The licenses are now as expensive as they were 6 months ago for anyone not living in the US. @@ -57,7 +70,7 @@ There is also now a checkout page for chinese users, which supports common chine - The custom icon cache now always registers when it is out of date, prompting you to refresh - You can now automatically start service tunnels as well when XPipe is launched - Add support to automatically add unsupported SSH MAC type -- The nixpkg package now also supports macOS +- The nixpkg package now also supports macOS and has been reworked as a flake. If you use XPipe on Nix, take a look at https://github.com/xpipe-io/nixpkg for the changes - Add option to control application behavior on system hibernation - Add possible workaround when default beacon HTTP server port was not usable - Improve reliability of shell session restarts when a connection was interrupted diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStoreSetup.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStoreSetup.java index e2659938f..47c3edbe2 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStoreSetup.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStoreSetup.java @@ -13,10 +13,10 @@ import java.util.*; public class ScriptStoreSetup { public static void controlWithDefaultScripts(ShellControl pc) { - controlWithScripts(pc, getEnabledScripts()); + controlWithScripts(pc, getEnabledScripts(), false); } - public static void controlWithScripts(ShellControl pc, List> enabledScripts) { + public static void controlWithScripts(ShellControl pc, List> enabledScripts, boolean append) { try { var dialect = pc.getShellDialect(); if (dialect == null) { @@ -34,10 +34,16 @@ public class ScriptStoreSetup { .filter(store -> store.getStore().isInitScript()) .filter(store -> finalDialect == null || store.getStore().isCompatible(finalDialect)) .toList(); + if (!append) { + initFlattened = initFlattened.reversed(); + } var bringFlattened = flatten(enabledScripts).stream() .filter(store -> store.getStore().isShellScript()) .filter(store -> finalDialect == null || store.getStore().isCompatible(finalDialect)) .toList(); + if (!append) { + bringFlattened = bringFlattened.reversed(); + } // Optimize if we have nothing to do if (initFlattened.isEmpty() && bringFlattened.isEmpty()) { @@ -55,9 +61,10 @@ public class ScriptStoreSetup { public boolean canPotentiallyRunInDialect(ShellDialect dialect) { return s.getStore().isCompatible(dialect); } - }); + }, append); }); if (!bringFlattened.isEmpty()) { + var finalBringFlattened = bringFlattened; pc.withInitSnippet(new ShellTerminalInitCommand() { String dir; @@ -65,7 +72,7 @@ public class ScriptStoreSetup { @Override public Optional terminalContent(ShellControl shellControl) throws Exception { if (dir == null) { - dir = initScriptsDirectory(shellControl, bringFlattened); + dir = initScriptsDirectory(shellControl, finalBringFlattened); } if (dir == null) { @@ -80,7 +87,7 @@ public class ScriptStoreSetup { public boolean canPotentiallyRunInDialect(ShellDialect dialect) { return true; } - }); + }, append); } } catch (StackOverflowError t) { throw ErrorEventFactory.expected( diff --git a/ext/base/src/main/java/io/xpipe/ext/base/store/ShellStoreProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/store/ShellStoreProvider.java index 51e3418d9..6edd64453 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/store/ShellStoreProvider.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/store/ShellStoreProvider.java @@ -28,8 +28,9 @@ public interface ShellStoreProvider extends DataStoreProvider { var replacement = ProcessControlProvider.get().replace(entry.ref()); ShellStore store = replacement.getStore().asNeeded(); var control = store.standaloneControl(); - ScriptStoreSetup.controlWithDefaultScripts(control); + // These prepend scripts, not append TerminalPromptManager.configurePromptScript(control); + ScriptStoreSetup.controlWithDefaultScripts(control); TerminalLaunch.builder().entry(replacement.get()).command(control).launch(); }; } diff --git a/version b/version index cef446d72..61e815922 100644 --- a/version +++ b/version @@ -1 +1 @@ -19.0-19 +19.0-20