From 0238bfdf707fc84c91d2df784a490fab96c21162 Mon Sep 17 00:00:00 2001 From: crschnick Date: Fri, 20 Jun 2025 22:39:17 +0000 Subject: [PATCH] Fixes --- .../xpipe/app/action/ActionConfirmComp.java | 3 + .../xpipe/app/action/ActionJacksonMapper.java | 10 ++- .../xpipe/app/action/ActionShortcutComp.java | 23 ++++++ .../app/browser/action/BrowserAction.java | 8 +- .../impl/ApplyFileEditActionProvider.java | 4 +- .../impl/TransferFilesActionProvider.java | 8 +- .../app/browser/file/BrowserFileListComp.java | 13 ++++ .../menu/impl/NewItemMenuProvider.java | 16 +++- .../java/io/xpipe/app/ext/ShellSession.java | 4 +- .../app/hub/action/BatchStoreAction.java | 8 ++ .../app/hub/action/MultiStoreAction.java | 9 +++ .../hub/action/impl/ScanHubBatchProvider.java | 8 ++ .../xpipe/app/hub/comp/StoreCreationMenu.java | 7 +- .../hub/comp/StoreEntryListStatusBarComp.java | 5 +- .../java/io/xpipe/core/store/FilePath.java | 2 +- dist/changelogs/17.0.md | 78 +++++++++++-------- .../script/RunScriptActionProviderMenu.java | 9 +++ lang/strings/translations_en.properties | 10 ++- 18 files changed, 164 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/io/xpipe/app/action/ActionConfirmComp.java b/app/src/main/java/io/xpipe/app/action/ActionConfirmComp.java index 9a81dd508..6fd53bf1b 100644 --- a/app/src/main/java/io/xpipe/app/action/ActionConfirmComp.java +++ b/app/src/main/java/io/xpipe/app/action/ActionConfirmComp.java @@ -2,6 +2,8 @@ package io.xpipe.app.action; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.SimpleComp; +import io.xpipe.app.core.AppFont; +import io.xpipe.app.core.AppFontSizes; import io.xpipe.app.hub.action.BatchStoreAction; import io.xpipe.app.hub.action.MultiStoreAction; import io.xpipe.app.hub.action.StoreAction; @@ -73,6 +75,7 @@ public class ActionConfirmComp extends SimpleComp { grid.add(value, 1, row); row++; } + AppFontSizes.lg(grid); return grid; }); } diff --git a/app/src/main/java/io/xpipe/app/action/ActionJacksonMapper.java b/app/src/main/java/io/xpipe/app/action/ActionJacksonMapper.java index ce9c4da68..aee0711bf 100644 --- a/app/src/main/java/io/xpipe/app/action/ActionJacksonMapper.java +++ b/app/src/main/java/io/xpipe/app/action/ActionJacksonMapper.java @@ -1,5 +1,7 @@ package io.xpipe.app.action; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.SerializationFeature; import io.xpipe.app.hub.action.BatchStoreAction; import io.xpipe.app.hub.action.MultiStoreAction; import io.xpipe.app.hub.action.StoreAction; @@ -41,8 +43,10 @@ public class ActionJacksonMapper { var object = (ObjectNode) tree; var ref = tree.get("ref"); + var mapper = JacksonMapper.newMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + if (ref != null && !ref.isArray() && StoreAction.class.isAssignableFrom(clazz.get())) { - var action = JacksonMapper.getDefault().treeToValue(tree, clazz.get()); + var action = mapper.treeToValue(tree, clazz.get()); return (T) action; } @@ -56,7 +60,7 @@ public class ActionJacksonMapper { object.remove("ref"); for (JsonNode batchRef : ref) { object.set("ref", batchRef); - var action = JacksonMapper.getDefault().treeToValue(object, clazz.get()); + var action = mapper.treeToValue(object, clazz.get()); batchActions.add((StoreAction) action); } return (T) BatchStoreAction.builder().actions(batchActions).build(); @@ -66,7 +70,7 @@ public class ActionJacksonMapper { if (makeMulti) { object.remove("ref"); object.set("refs", ref); - var action = JacksonMapper.getDefault().treeToValue(object, clazz.get()); + var action = mapper.treeToValue(object, clazz.get()); return (T) action; } diff --git a/app/src/main/java/io/xpipe/app/action/ActionShortcutComp.java b/app/src/main/java/io/xpipe/app/action/ActionShortcutComp.java index 19ead9702..ac32e0f73 100644 --- a/app/src/main/java/io/xpipe/app/action/ActionShortcutComp.java +++ b/app/src/main/java/io/xpipe/app/action/ActionShortcutComp.java @@ -1,5 +1,6 @@ package io.xpipe.app.action; +import io.xpipe.app.beacon.AppBeaconServer; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.SimpleComp; import io.xpipe.app.comp.base.ButtonComp; @@ -8,6 +9,7 @@ import io.xpipe.app.comp.base.TextFieldComp; import io.xpipe.app.core.AppI18n; import io.xpipe.app.util.*; +import javafx.beans.binding.Bindings; import javafx.beans.property.Property; import javafx.beans.property.SimpleStringProperty; import javafx.scene.layout.Region; @@ -31,6 +33,7 @@ public class ActionShortcutComp extends SimpleComp { var options = new OptionsBuilder(); options.nameAndDescription("actionDesktopShortcut").addComp(createDesktopComp()); options.nameAndDescription("actionUrlShortcut").addComp(createUrlComp()); + options.nameAndDescription("actionApiCall").addComp(createApiComp()); // options.nameAndDescription("actionMacro") // .addComp(createMacroComp()); return options.build(); @@ -80,6 +83,26 @@ public class ActionShortcutComp extends SimpleComp { return group; } + private Comp createApiComp() { + var url = "curl -X POST \"http://localhost:" + AppBeaconServer.get().getPort() + "/action\" ..."; + var text = AppI18n.observable("actionApiUrl", url); + var prop = new SimpleStringProperty(); + prop.bind(text); + + var copyButton = new ButtonComp(null, new FontIcon("mdi2c-clipboard-multiple-outline"), () -> { + if (action.getValue() instanceof SerializableAction sa) { + ClipboardHelper.copyUrl(sa.toNode().toPrettyString()); + } + }) + .grow(false, true) + .tooltipKey("copyBody"); + var field = new TextFieldComp(prop, true); + field.grow(true, false); + field.apply(struc -> struc.get().setEditable(false)); + var group = new InputGroupComp(List.of(field, copyButton)); + return group; + } + private Comp createMacroComp() { var button = new ButtonComp( AppI18n.observable("createMacro"), new FontIcon("mdi2c-clipboard-multiple-outline"), onCreateMacro); 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 1643083c1..2e2fb0234 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 @@ -6,6 +6,7 @@ import io.xpipe.app.browser.file.BrowserEntry; import io.xpipe.app.browser.file.BrowserFileSystemTabModel; import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.hub.action.StoreAction; +import io.xpipe.core.store.FileEntry; import io.xpipe.core.store.FilePath; import io.xpipe.core.store.FileSystemStore; @@ -44,7 +45,7 @@ public abstract class BrowserAction extends StoreAction { if (isFile) { return files.getFirst().getParent(); } else { - var dir = files.getFirst().getParent(); + var dir = files.getFirst(); if (!model.getFileSystem().directoryExists(dir)) { throw new IllegalArgumentException("Directory does not exist: " + dir); } @@ -84,6 +85,11 @@ public abstract class BrowserAction extends StoreAction { return be.get(); } + var current = model.getCurrentDirectory(); + if (current != null && filePath.equals(current.getPath())) { + return new BrowserEntry(current, model.getFileList()); + } + return null; }) .filter(browserEntry -> browserEntry != null) diff --git a/app/src/main/java/io/xpipe/app/browser/action/impl/ApplyFileEditActionProvider.java b/app/src/main/java/io/xpipe/app/browser/action/impl/ApplyFileEditActionProvider.java index 1d76e44bc..34ea2fec8 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/impl/ApplyFileEditActionProvider.java +++ b/app/src/main/java/io/xpipe/app/browser/action/impl/ApplyFileEditActionProvider.java @@ -48,8 +48,8 @@ public class ApplyFileEditActionProvider implements ActionProvider { @Override public Map toDisplayMap() { var map = new LinkedHashMap(); - map.put("action", getDisplayName()); - map.put("target", target); + map.put("Action", getDisplayName()); + map.put("Target", target); return map; } } diff --git a/app/src/main/java/io/xpipe/app/browser/action/impl/TransferFilesActionProvider.java b/app/src/main/java/io/xpipe/app/browser/action/impl/TransferFilesActionProvider.java index 0b97ca9d3..45cc7f130 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/impl/TransferFilesActionProvider.java +++ b/app/src/main/java/io/xpipe/app/browser/action/impl/TransferFilesActionProvider.java @@ -50,14 +50,14 @@ public class TransferFilesActionProvider implements ActionProvider { @Override public Map toDisplayMap() { var map = new LinkedHashMap(); - map.put("action", getDisplayName()); + map.put("Action", getDisplayName()); map.put( - "sources", + "Sources", operation.getFiles().stream() .map(fileEntry -> fileEntry.getName()) .collect(Collectors.joining("\n"))); - map.put("target", DataStorage.get().getStoreEntryDisplayName(target.get())); - map.put("targetDirectory", operation.getTarget().getPath().toString()); + map.put("Target system", DataStorage.get().getStoreEntryDisplayName(target.get())); + map.put("Target directory", operation.getTarget().getPath().toString()); return map; } diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java index d17ab0357..6863f177a 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListComp.java @@ -75,6 +75,19 @@ public final class BrowserFileListComp extends SimpleComp { sizeCol.textProperty().bind(AppI18n.observable("size")); sizeCol.setCellValueFactory(param -> new ReadOnlyStringWrapper( param.getValue().getRawFileEntry().resolved().getSize())); + sizeCol.setComparator((size1, size2) -> { + if (size1 == null && size2 == null) return 0; + if (size1 == null) return -1; + if (size2 == null) return 1; + + try { + long long1 = Long.parseLong(size1); + long long2 = Long.parseLong(size2); + return Long.compare(long1, long2); + } catch (NumberFormatException e) { + return size1.compareTo(size2); + } + }); sizeCol.setCellFactory(col -> new FileSizeCell()); sizeCol.setResizable(false); sizeCol.setReorderable(false); diff --git a/app/src/main/java/io/xpipe/app/browser/menu/impl/NewItemMenuProvider.java b/app/src/main/java/io/xpipe/app/browser/menu/impl/NewItemMenuProvider.java index 920c15c19..b716a3b0e 100644 --- a/app/src/main/java/io/xpipe/app/browser/menu/impl/NewItemMenuProvider.java +++ b/app/src/main/java/io/xpipe/app/browser/menu/impl/NewItemMenuProvider.java @@ -15,6 +15,7 @@ import io.xpipe.app.core.AppI18n; import io.xpipe.app.util.LabelGraphic; import io.xpipe.app.util.OptionsBuilder; import io.xpipe.core.process.OsType; +import io.xpipe.core.store.FileKind; import io.xpipe.core.store.FilePath; import javafx.beans.property.SimpleStringProperty; @@ -66,8 +67,11 @@ public class NewItemMenuProvider implements BrowserMenuBranchProvider { return; } + var fixedFiles = entries.stream().map(browserEntry -> browserEntry.getRawFileEntry().getKind() == FileKind.DIRECTORY ? + browserEntry.getRawFileEntry().getPath() : browserEntry.getRawFileEntry().getPath().getParent()) + .toList(); var builder = NewFileActionProvider.Action.builder(); - builder.initEntries(model, entries); + builder.initFiles(model, fixedFiles); builder.name(name.getValue()); builder.build().executeAsync(); }); @@ -102,8 +106,11 @@ public class NewItemMenuProvider implements BrowserMenuBranchProvider { return; } + var fixedFiles = entries.stream().map(browserEntry -> browserEntry.getRawFileEntry().getKind() == FileKind.DIRECTORY ? + browserEntry.getRawFileEntry().getPath() : browserEntry.getRawFileEntry().getPath().getParent()) + .toList(); var builder = NewDirectoryActionProvider.Action.builder(); - builder.initEntries(model, entries); + builder.initFiles(model, fixedFiles); builder.name(name.getValue()); builder.build().executeAsync(); }); @@ -143,8 +150,11 @@ public class NewItemMenuProvider implements BrowserMenuBranchProvider { return; } + var fixedFiles = entries.stream().map(browserEntry -> browserEntry.getRawFileEntry().getKind() == FileKind.DIRECTORY ? + browserEntry.getRawFileEntry().getPath() : browserEntry.getRawFileEntry().getPath().getParent()) + .toList(); var builder = NewLinkActionProvider.Action.builder(); - builder.initEntries(model, entries); + builder.initFiles(model, fixedFiles); builder.name(linkName.getValue()); builder.target(FilePath.of(target.getValue())); builder.build().executeAsync(); diff --git a/app/src/main/java/io/xpipe/app/ext/ShellSession.java b/app/src/main/java/io/xpipe/app/ext/ShellSession.java index d7663a720..393211210 100644 --- a/app/src/main/java/io/xpipe/app/ext/ShellSession.java +++ b/app/src/main/java/io/xpipe/app/ext/ShellSession.java @@ -26,7 +26,9 @@ public class ShellSession extends Session { try { shellControl.start(); - startAliveListener(); + if (shellControl.getShellDialect().getDumbMode().supportsAnyPossibleInteraction()) { + startAliveListener(); + } } catch (Exception ex) { try { stop(); diff --git a/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java b/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java index 81fe3d43f..969b6acee 100644 --- a/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java +++ b/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java @@ -1,6 +1,7 @@ package io.xpipe.app.hub.action; import io.xpipe.app.action.*; +import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntryRef; import io.xpipe.core.store.DataStore; @@ -21,6 +22,13 @@ public final class BatchStoreAction extends SerializableAct private final List> actions; + @Override + public String getShortcutName() { + var names = actions.size() > 3 ? actions.size() + "..." : actions.stream().map(a -> DataStorage.get().getStoreEntryDisplayName(a.getRef().get())).collect( + Collectors.joining(", ")); + return names + " (" + getDisplayName() + ")"; + } + @Override public void executeImpl() throws Exception { for (AbstractAction action : actions) { diff --git a/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java b/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java index e0a42348e..04c0bf0fb 100644 --- a/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java +++ b/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java @@ -3,6 +3,7 @@ package io.xpipe.app.hub.action; import io.xpipe.app.action.ActionJacksonMapper; import io.xpipe.app.action.SerializableAction; import io.xpipe.app.action.StoreContextAction; +import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntryRef; import io.xpipe.core.store.DataStore; @@ -15,6 +16,7 @@ import lombok.experimental.SuperBuilder; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @SuperBuilder public abstract class MultiStoreAction extends SerializableAction implements StoreContextAction { @@ -22,6 +24,13 @@ public abstract class MultiStoreAction extends Serializable @Getter protected final List> refs; + @Override + public String getShortcutName() { + var names = refs.size() > 3 ? refs.size() + "..." : refs.stream().map(ref -> DataStorage.get().getStoreEntryDisplayName(ref.get())).collect( + Collectors.joining(", ")); + return names + " (" + getDisplayName() + ")"; + } + @Override protected boolean beforeExecute() { for (DataStoreEntryRef ref : refs) { diff --git a/app/src/main/java/io/xpipe/app/hub/action/impl/ScanHubBatchProvider.java b/app/src/main/java/io/xpipe/app/hub/action/impl/ScanHubBatchProvider.java index a09234238..2b2e27a6a 100644 --- a/app/src/main/java/io/xpipe/app/hub/action/impl/ScanHubBatchProvider.java +++ b/app/src/main/java/io/xpipe/app/hub/action/impl/ScanHubBatchProvider.java @@ -1,5 +1,6 @@ package io.xpipe.app.hub.action.impl; +import io.xpipe.app.action.AbstractAction; import io.xpipe.app.core.AppI18n; import io.xpipe.app.ext.ShellStore; import io.xpipe.app.hub.action.BatchHubProvider; @@ -16,6 +17,8 @@ import javafx.beans.value.ObservableValue; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; +import java.util.List; + public class ScanHubBatchProvider implements BatchHubProvider { @Override @@ -50,6 +53,11 @@ public class ScanHubBatchProvider implements BatchHubProvider { return "scanStoreBatch"; } + @Override + public AbstractAction createBatchAction(List> dataStoreEntryRefs) { + return Action.builder().refs(dataStoreEntryRefs).build(); + } + @Jacksonized @SuperBuilder public static class Action extends MultiStoreAction { diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java b/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java index c231e8b8d..135412890 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StoreCreationMenu.java @@ -110,11 +110,8 @@ public class StoreCreationMenu { } Platform.runLater(() -> { - StoreCreationDialog.showCreation( - defaultProvider != null - ? DataStoreProviders.byId(defaultProvider).orElseThrow() - : null, - category); + var onlyItem = menu.getItems().getFirst(); + onlyItem.fire(); }); // Fix weird JavaFX NPE diff --git a/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryListStatusBarComp.java b/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryListStatusBarComp.java index eebaf54e2..4d4defa64 100644 --- a/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryListStatusBarComp.java +++ b/app/src/main/java/io/xpipe/app/hub/comp/StoreEntryListStatusBarComp.java @@ -183,9 +183,6 @@ public class StoreEntryListStatusBarComp extends SimpleComp { var l = new ArrayList<>( StoreViewState.get().getEffectiveBatchModeSelection().getList()); var mapped = l.stream().map(w -> w.getEntry().ref()).toList(); - var action = ((BatchHubProvider) s).createBatchAction(mapped); - if (action != null) { - action.executeAsync(); - } + ((BatchHubProvider) s).execute(mapped); } } diff --git a/core/src/main/java/io/xpipe/core/store/FilePath.java b/core/src/main/java/io/xpipe/core/store/FilePath.java index 52129185b..0b273d182 100644 --- a/core/src/main/java/io/xpipe/core/store/FilePath.java +++ b/core/src/main/java/io/xpipe/core/store/FilePath.java @@ -48,7 +48,7 @@ public final class FilePath { return false; } FilePath filePath = (FilePath) o; - return Objects.equals(value, filePath.value); + return Objects.equals(normalize().removeTrailingSlash().value, filePath.normalize().removeTrailingSlash().value); } @Override diff --git a/dist/changelogs/17.0.md b/dist/changelogs/17.0.md index cdab97bcf..2a63a4560 100644 --- a/dist/changelogs/17.0.md +++ b/dist/changelogs/17.0.md @@ -1,44 +1,22 @@ +Note: This release includes all features for XPipe 17 with barely any testing. This means that you should not use this build for any kind of production use yet. It is mostly for internal testing. + XPipe 17 is a large-scale rework of many existing parts of XPipe. It focuses on fixing many longstanding issues and limitations, so that future updates can easily bring new integrations without having to deal with that baggage. -## File browser - -- Actions which modify a single file will now automatically refresh the file list to show updated changes -- There is now a new file browser action to compute directory sizes -- The transfer speed in the file browser on Windows for multiple files has been optimized -- Renaming a file now moves the caret to the end of the base file name -- The file browser now works much better in small windows sizes -- Fix size sorting using alphabetical order instead of actual size (Thanks to @RustyRaptor for the PR) -- Fix terminal sometimes not being launched with the correct working directory of the current path -- Fix file deletion not showing errors when the operation failed in cmd -- Fix file renaming not working if previous rename operation was cancelled -- Fix file transfer kill button sometimes not working when transfer was frozen - -## Connection hub - -Proper functionality to organize a collection of hundreds of connections was always somewhat limited until now. There is now an additional index-based organization mechanism where you can assign and move indices of connections to have them listed at a certain place in relation to other connections. This can also be combined with the existing sorting methods like time and alphabetical sorting. - -Furthermore, there are also more improvements in the connection hub: -- Renaming connection entries can now be done quickly from the context menu without having to open the configuration dialog -- You can now set connection configurations to be frozen, meaning that the connection entry can't be modified or deleted. This is helpful for templating and team vault setups -- When editing an incomplete connection configuration, the focus will automatically jump to the first incomplete/invalid value. This makes keyboard usage easier - -## SSH - -They are two major changes regarding SSH in this release. - -First, there is now proper support for jump servers. While gateways worked similar to jump servers, they were a different concept and did not work for cases where the ProxyJump functionality was required. You can now configure an SSH connection in its advanced settings to be treated as a jump server. This will result in XPipe using the ProxyJump syntax when this connection is used as a gateway for other SSH connections. This works for all kinds of connections, including config connections. - -Second, the SSH implementation for devices that don't provide a full shell, e.g. embedded devices and other limited systems, has been completely reworked. This fixes many issues where connections to such systems were not possible or failed. You can now designate an SSH connection as a limited system in its advanced settings, even without the homelab plan. This will then allow you to directly launch the connection, without any issues. - ## Actions There is now a new action system, which maps most UI actions to fixed schemas. Essentially, this means that you can now automate almost any action you can perform from the UI via desktop shortcuts, URLs, HTTP API calls, and more. You can configure action shortcuts with the new action configuration dialog and control how to call the action from it. Furthermore, it is also now possible to control how all of these actions are run. For production systems, for example, you can configure that all actions that perform some kind of modification, like deleting a file, have to be confirmed first. This gives you an added layer of protection to double-check any operation before actually executing it. +## SSH + +There is now proper support for jump servers. While gateways worked similar to jump servers, they were a different concept and did not work for cases where the ProxyJump functionality was required. You can now configure an SSH connection in its advanced settings to be treated as a jump server. This will result in XPipe using the ProxyJump syntax when this connection is used as a gateway for other SSH connections. This works for all kinds of connections, including config connections. + +Furthermore, the SSH implementation for devices that don't provide a full shell, e.g. embedded devices and other limited systems, has been completely reworked. This fixes many issues where connections to such systems were not possible or failed. You can now designate an SSH connection as a limited system in its advanced settings, even without the homelab plan. This will then allow you to directly launch the connection, without any issues. + ## VNC -Up until now, the internal VNC implementation of XPipe did a somewhat acceptable job for most connections. However, it is not able to match dedicated VNC clients when it comes to more advanced features and authentication methods. There's simply not Le development capacity to maintain all of these additional VNC features. For this reason, there is now support to also use an external VNC client with XPipe, it just as with any other tool integrations. +Up until now, the internal VNC implementation of XPipe did a somewhat acceptable job for most connections. However, it is not able to match dedicated VNC clients when it comes to more advanced features and authentication methods. There's simply not the development capacity to maintain all of these additional VNC features. For this reason, there is now support to also use an external VNC client with XPipe, just as with any other tool integrations. The current integrations include: - TigerVNC @@ -52,11 +30,42 @@ The current integrations include: XPipe adopts many of the new features of macOS 26 right away. if you are using the macOS beta, you have access to these right away. -The application window now uses the new Liquid Glass theming. The application icon has also been reworked with Liquid Glass in mind. There's also support for the new apple containers framework, which has just been released. Searching for available connections on the local machine will make apple containers show up if you have installed the package. +The application window now uses the new Liquid Glass theming. The application icon has also been reworked with Liquid Glass in mind. + +There's also support for the new apple containers framework, which has just been released. Searching for available connections on the local machine will make apple containers show up if you have installed the package. + +## Windows ARM + +There is now a native Windows ARM build. This release is also available in choco and winget. + +Note that you will have to uninstall any old x64 XPipe installation for the upgrade. + +## File browser + +- Actions which modify a single file, e.g. a file edit, will now automatically refresh the file list to show updated changes +- There is now a new file browser action to compute directory sizes +- The transfer speed in the file browser on Windows for multiple files has been improved +- Renaming a file now moves the caret to the end of the base file name +- The file browser now works much better in small windows sizes +- Fix size sorting using alphabetical order instead of actual size (Thanks to @RustyRaptor for the PR) +- Fix terminal sometimes not being launched with the correct working directory of the current path +- Fix file deletion not showing errors when the operation failed in cmd +- Fix file renaming not working if previous rename operation was cancelled +- Fix file transfer kill button sometimes not working when transfer was frozen +- Fix file browser listing not working for older PowerShell systems + +## Connection hub + +Proper functionality to organize a collection of hundreds of connections was always somewhat limited until now. There is now an additional index-based organization mechanism where you can assign and move indices of connections to have them listed at a certain place in relation to other connections. This can also be combined with the existing sorting methods like time and alphabetical sorting. + +Furthermore, there are also more improvements in the connection hub: +- Renaming connection entries can now be done quickly from the context menu without having to open the configuration dialog +- You can now set connection configurations to be frozen, meaning that the connection entry can't be modified or deleted. This is helpful for templating and team vault setups +- When editing an incomplete connection configuration, the focus will automatically jump to the first incomplete/invalid value. This makes keyboard usage easier ## HTTP API -The HTTP API has been improved in various areas. The action system is integrated in it, meaning that you can call any action from the API. Furthermore, there are now more API endpoints for categories so that you have proper control over them as well. There is also now a way to encrypt and decrypt secrets via the API, allowing you to create connections with integrated secrets with it as well. +The HTTP API has been improved in various areas. The action system is integrated in it, meaning that you can call any action from the API. Furthermore, there are now more API endpoints for categories so that you have proper control over them as well. There is also now a way to encrypt and decrypt secrets via the API, allowing you to create connections with integrated secrets with it as well. ## Other @@ -68,7 +77,6 @@ The HTTP API has been improved in various areas. The action system is integrated - You can now specify an alternative user for shell environments to switch to via sudo - You can now specify a git username and password in the settings menu if your local system does not have a git client with configured credentials - You can now disable icon sources without having to remove them -- There is now a native Windows ARM build. Note that you will have to uninstall any old x64 XPipe installation for the upgrade - Active tunnels are now periodically refreshed to check if the underlying tunnel was closed - Fix clipboard data of other formats, e.g. files, being cleared after expiration of a copied password - Fix pwsh connections on Linux/macOS freezing on sudo elevation @@ -78,3 +86,5 @@ The HTTP API has been improved in various areas. The action system is integrated - Fix text color on hover having low contrast in some themes - There is now support for nushell - Fix SSH agent variables being wrong on macOS when using homebrew ssh +- Fix connection search freezing on Ubuntu systems with LXD snap stub installed + diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptActionProviderMenu.java b/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptActionProviderMenu.java index c07139d90..ce4ebaa74 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptActionProviderMenu.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/RunScriptActionProviderMenu.java @@ -222,6 +222,15 @@ public class RunScriptActionProviderMenu implements HubBranchProvider> getChildren(DataStoreEntryRef store) { + return getChildren(); + } + + @Override + public List getChildren(List> batch) { + return getChildren(); + } + + private List> getChildren() { if (hierarchy.isLeaf()) { return List.of( new TerminalRunActionProvider(hierarchy), diff --git a/lang/strings/translations_en.properties b/lang/strings/translations_en.properties index 2c17ec6b7..4484ccd0d 100644 --- a/lang/strings/translations_en.properties +++ b/lang/strings/translations_en.properties @@ -1506,11 +1506,13 @@ actionShortcuts=Action shortcuts actionStore=Action store actionStoreDescription=The store entry to run the action on actionStores=Action stores -actionStoreDescriptions=The store entries to run the action on +actionStoresDescription=The store entries to run the action on actionDesktopShortcut=Desktop shortcut actionDesktopShortcutDescription=Create a shortcut for this action on your desktop -actionUrlShortcut=URL a shortcut +actionUrlShortcut=URL shortcut actionUrlShortcutDescription=Copy a URL that can trigger this actions when opened +actionApiCall=API request +actionApiCallDescription=Call this action from the HTTP API actionMacro=Action macro actionMacroDescription=Create a macro with advanced functionality for this action createMacro=Create macro @@ -1538,4 +1540,6 @@ includeRoot=Include root excludeRoot=Exclude root freezeConfiguration=Freeze configuration unfreezeConfiguration=Unfreeze configuration -waylandScalingTitle=Wayland scaling \ No newline at end of file +waylandScalingTitle=Wayland scaling +actionApiUrl=$URL$ (Copy json body) +copyBody=Copy request body