diff --git a/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java b/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java index a11267852..066ccba37 100644 --- a/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java +++ b/app/src/main/java/io/xpipe/app/browser/session/BrowserSessionComp.java @@ -30,8 +30,15 @@ public class BrowserSessionComp extends SimpleComp { @Override protected Region createSimple() { Predicate applicable = storeEntryWrapper -> { - return (storeEntryWrapper.getEntry().getStore() instanceof ShellStore) - && storeEntryWrapper.getEntry().getValidity().isUsable(); + if (!storeEntryWrapper.getEntry().getValidity().isUsable()) { + return false; + } + + if (storeEntryWrapper.getEntry().getStore() instanceof ShellStore) { + return true; + } + + return storeEntryWrapper.getEntry().getProvider().browserAction(model,storeEntryWrapper.getEntry(), null) != null; }; BiConsumer action = (w, busy) -> { ThreadHelper.runFailableAsync(() -> { @@ -43,6 +50,11 @@ public class BrowserSessionComp extends SimpleComp { if (entry.getStore() instanceof ShellStore fileSystem) { model.openFileSystemAsync(entry.ref(), null, busy); } + + var a = entry.getProvider().browserAction(model, entry, busy); + if (a != null) { + a.execute(); + } }); }; diff --git a/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java b/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java index 24bf7fbd0..42ef90e01 100644 --- a/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java @@ -1,5 +1,6 @@ package io.xpipe.app.ext; +import io.xpipe.app.browser.session.BrowserSessionModel; import io.xpipe.app.comp.base.MarkdownComp; import io.xpipe.app.comp.store.StoreEntryComp; import io.xpipe.app.comp.store.StoreEntryWrapper; @@ -15,6 +16,7 @@ import io.xpipe.core.dialog.Dialog; import io.xpipe.core.store.DataStore; import io.xpipe.core.util.JacksonizedValue; import javafx.beans.binding.Bindings; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.Property; import javafx.beans.property.SimpleStringProperty; import javafx.beans.value.ObservableValue; @@ -44,6 +46,14 @@ public interface DataStoreProvider { } } + default ActionProvider.Action launchAction(DataStoreEntry store) { + return null; + } + + default ActionProvider.Action browserAction(BrowserSessionModel sessionModel, DataStoreEntry store, BooleanProperty busy) { + return null; + } + default String browserDisplayName(DataStore store) { var e = DataStorage.get().getStoreDisplayName(store); return e.orElse("?"); diff --git a/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css b/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css index bec47fc7d..c521ef04c 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/bookmark.css @@ -1,6 +1,6 @@ .bookmark-list > .categories { - -fx-padding: 0.7em 1em 0.7em 1em; + -fx-padding: 1em; -fx-background-color: -color-bg-subtle; -fx-border-color: -color-border-default; -fx-border-width: 0 0 1 0; diff --git a/dist/changelogs/9.0.md b/dist/changelogs/9.0.md index 3b96887e3..1022fd83f 100644 --- a/dist/changelogs/9.0.md +++ b/dist/changelogs/9.0.md @@ -1,43 +1,59 @@ -## Education professional licenses - -There is now the possibility to use XPipe professional for free for students and faculty from accredited educational institutions (high schools, colleges, and universities). Just send an email to hello@xpipe.io with your official email address of your educational institution. - ## Translations A big new feature of XPipe 9 are translations. These were initially generated with DeepL and can be easily improved and corrected by anyone on GitHub. You can check them out in action and if there is any translation you don't like, submit a quick pull request to fix it. For instructions on how to do this, see https://github.com/xpipe-io/xpipe/lang. +You can change the language in the appearance settings. + +## VNC support + +This release comes with initial support for VNC. Any VNC connections are fully handled over automatic SSH tunnels and can therefore be established on top of any existing SSH connection you have in XPipe. + +Note that this feature right now is in an early stage and open for feedback. + +## RDP launcher + +RDP is a much more complex protocol than VNC, so for now RDP support is not built-in. It is instead realized similar to the terminal support, i.e. by launching your preferred RDP client with the connection information. + +Note that this feature right now is in an early stage and open for feedback. + ## SSH connection improvements -- The custom SSH connections now properly apply all configuration options of your user configuration file +- The custom SSH connections now properly apply all configuration options of your user configuration file. -They also now support defining multiple host entries in place, which is useful for cases where you want to use ProxyJump hosts in place without having to define them elsewhere. +- There is now support defining multiple host entries in place in a custom SSH connection. This is useful for cases where you want to use ProxyJump hosts in place without having to define them elsewhere. + +- The connection establishment has been reworked to reduce the amount of double prompts, e.g. for smartcards of 2FA, where user input is required twice. + +- There's now an option to not let XPipe interact with the system. In case a system that does not run a known command shell, e.g. a router, link, or some IOT device, XPipe was previously unable to detect the shell type and errored out after some time. This option fixes this problem. + +- Any value specified for the `RemoteCommand` config option will now be properly applied when launching a terminal. ## SSH X11 Forwarding You can now enable X11 forwarding for an SSH connection. -XPipe allows you to use the WSL2 X11 capabilities for your SSH connection. The only thing you need for this is a [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) distribution installed on your local system. XPipe it will automatically choose a compatible installed distribution if possible, but you can also use another one in the settings menu. +XPipe allows you to use the WSL2 X11 capabilities on Windows for your SSH connection. The only thing you need for this is a [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) distribution installed on your local system. XPipe it will automatically choose a compatible installed distribution if possible, but you can also use another one in the settings menu. This means that you don't need to install a separate X11 server on Windows. However, if you are using one anyway, XPipe will detect that and use the currently running X11 server. -## Keyboard control - -It is a goal to be able to use XPipe only with a keyboard. This can be done either for productivity reasons or for accessibility reasons. XPipe 9 introduces improved keyboard support with new shortcuts and improved focus control for navigating with the arrow keys, tab, space, and enter. - -## An improved logo - -The application logo has been improved with of regards to contrast and visibility, which often was a problem on dark backgrounds. it should now stand out on any background color. - ## Terminal improvements The terminal integrations have been reworked across the board. To better show which terminals are well supported and which aren't, there is now a status indicator for every available terminal. This will show you how good the XPipe integration with each one is and which terminals are recommended to be used with XPipe. -- The kitty terminal is now fully supported with tabs on both Linux and macOS +Furthermore, the kitty terminal is now fully supported with tabs on both Linux and macOS. + +## Improved keyboard control + +It is a goal to be able to use XPipe only with a keyboard. This can be done either for productivity reasons or for accessibility reasons. XPipe 9 introduces improved keyboard support with new shortcuts and improved focus control for navigating with the arrow keys, tab, space, and enter. + +## Improved logo + +The application logo has been improved with of regards to contrast and visibility, which often was a problem on dark backgrounds. It should now stand out on any background color. ## Other changes - Fix macOS app failing to automatically restart after update - The window title will now reflect which edition you use -- On Windows, the window title bar will now respect the color theme - Fix file names not being properly adjusted when transferred across file systems and some characters were not supported on the target system - Fix macOS desktop shortcuts not having an icon associated with them +- Upgrade to GraalVM 22 diff --git a/ext/base/src/main/java/io/xpipe/ext/base/action/LaunchAction.java b/ext/base/src/main/java/io/xpipe/ext/base/action/LaunchAction.java index b881d75e9..178ca98bf 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/action/LaunchAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/action/LaunchAction.java @@ -6,6 +6,7 @@ import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntryRef; import io.xpipe.app.util.TerminalLauncher; +import io.xpipe.core.store.DataStore; import io.xpipe.core.store.LaunchableStore; import io.xpipe.core.store.ShellStore; import io.xpipe.ext.base.script.ScriptStore; @@ -21,7 +22,7 @@ public class LaunchAction implements ActionProvider { @Override public DataStoreCallSite getDataStoreCallSite() { - return new DataStoreCallSite() { + return new DataStoreCallSite() { @Override public boolean canLinkTo() { @@ -29,27 +30,28 @@ public class LaunchAction implements ActionProvider { } @Override - public ActionProvider.Action createAction(DataStoreEntryRef store) { + public ActionProvider.Action createAction(DataStoreEntryRef store) { return new Action(store.get()); } @Override - public Class getApplicableClass() { - return LaunchableStore.class; + public Class getApplicableClass() { + return DataStore.class; } @Override - public boolean isApplicable(DataStoreEntryRef o) { - return o.get().getValidity().isUsable(); + public boolean isApplicable(DataStoreEntryRef o) { + return o.get().getValidity().isUsable() && ( + o.getStore() instanceof LaunchableStore || o.get().getProvider().launchAction(o.get()) != null); } @Override - public ObservableValue getName(DataStoreEntryRef store) { + public ObservableValue getName(DataStoreEntryRef store) { return AppI18n.observable("launch"); } @Override - public String getIcon(DataStoreEntryRef store) { + public String getIcon(DataStoreEntryRef store) { return "mdi2p-play"; } }; @@ -57,21 +59,22 @@ public class LaunchAction implements ActionProvider { @Override public DefaultDataStoreCallSite getDefaultDataStoreCallSite() { - return new DefaultDataStoreCallSite() { + return new DefaultDataStoreCallSite() { @Override - public ActionProvider.Action createAction(DataStoreEntryRef store) { + public ActionProvider.Action createAction(DataStoreEntryRef store) { return new Action(store.get()); } @Override - public Class getApplicableClass() { - return LaunchableStore.class; + public Class getApplicableClass() { + return DataStore.class; } @Override - public boolean isApplicable(DataStoreEntryRef o) { - return o.get().getValidity().isUsable(); + public boolean isApplicable(DataStoreEntryRef o) { + return o.get().getValidity().isUsable() && ( + o.getStore() instanceof LaunchableStore || o.get().getProvider().launchAction(o.get()) != null); } }; } @@ -96,6 +99,11 @@ public class LaunchAction implements ActionProvider { if (entry.getStore() instanceof LaunchableStore s) { s.launch(); + return; + } + + if (entry.getProvider().launchAction(entry) != null) { + entry.getProvider().launchAction(entry).execute(); } } } diff --git a/version b/version index 48c26da3e..dd98ee6cb 100644 --- a/version +++ b/version @@ -1 +1 @@ -8.6 +9.0