From cc1fb789c6d41c8b75e18d9309f649c14d38f27d Mon Sep 17 00:00:00 2001 From: crschnick Date: Sun, 21 May 2023 14:12:06 +0000 Subject: [PATCH] Final fixes [release] --- .../app/browser/BrowserFileListComp.java | 13 ++++++- .../app/browser/BrowserFileListCompEntry.java | 8 ++-- .../app/browser/BrowserFileListModel.java | 6 +++ .../app/browser/BrowserStatusBarComp.java | 2 +- .../xpipe/app/browser/OpenFileSystemComp.java | 3 +- .../browser/action/ApplicationPathAction.java | 11 ------ .../action/BrowserActionFormatter.java | 25 +++++++++++++ .../action/ExecuteApplicationAction.java | 12 ++++++ .../browser/action/ToFileCommandAction.java | 25 +++++++++++++ .../SourceCollectionContextMenu.java | 2 +- .../source/SourceEntryContextMenu.java | 2 +- .../comp/storage/store/StoreEntryComp.java | 5 ++- .../fxcomps/augment/ContextMenuAugment.java | 20 ++++++---- .../java/io/xpipe/app/util/FileBridge.java | 10 +++-- .../java/io/xpipe/app/util/FileOpener.java | 22 ++++++++++- .../java/io/xpipe/core/impl/FileNames.java | 2 +- dist/build.gradle | 2 +- .../ext/base/browser/CopyPathAction.java | 17 +++++++++ .../io/xpipe/ext/base/browser/JarAction.java | 11 ++---- .../io/xpipe/ext/base/browser/JavaAction.java | 14 +------ .../xpipe/ext/base/browser/JavapAction.java | 37 +++++++++++++++++++ .../browser/OpenNativeFileDetailsAction.java | 2 +- .../xpipe/ext/base/browser/UnzipAction.java | 17 +++++++-- ext/base/src/main/java/module-info.java | 1 + 24 files changed, 209 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/io/xpipe/app/browser/action/BrowserActionFormatter.java create mode 100644 app/src/main/java/io/xpipe/app/browser/action/ToFileCommandAction.java create mode 100644 ext/base/src/main/java/io/xpipe/ext/base/browser/JavapAction.java diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java index 9fc914cb..63cd1709 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java @@ -30,6 +30,7 @@ import javafx.scene.control.*; import javafx.scene.control.skin.TableViewSkin; import javafx.scene.control.skin.VirtualFlow; import javafx.scene.input.DragEvent; +import javafx.scene.input.MouseButton; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; @@ -221,7 +222,17 @@ final class BrowserFileListComp extends SimpleComp { table.setRowFactory(param -> { TableRow row = new TableRow<>(); - new ContextMenuAugment<>(true, true, () -> { + new ContextMenuAugment<>(event -> { + if (row.getItem() != null && row.getItem().getRawFileEntry().isDirectory()) { + return event.getButton() == MouseButton.SECONDARY; + } + + if (row.getItem() != null && !row.getItem().getRawFileEntry().isDirectory()) { + return event.getButton() == MouseButton.SECONDARY || event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2; + } + + return false; + }, () -> { if (row.getItem() != null && row.getItem().isSynthetic()) { return null; } diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileListCompEntry.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileListCompEntry.java index 51434049..1319ed8e 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileListCompEntry.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileListCompEntry.java @@ -49,11 +49,11 @@ public class BrowserFileListCompEntry { if (t.getButton() == MouseButton.PRIMARY && t.isShiftDown()) { var tv = ((TableView) row.getParent().getParent().getParent().getParent()); var all = tv.getItems(); - var min = tv.getSelectionModel().getSelectedItems().stream().mapToInt(entry -> all.indexOf(entry)).min().orElse(1); - var max = tv.getSelectionModel().getSelectedItems().stream().mapToInt(entry -> all.indexOf(entry)).max().orElse(all.size() - 1); - var end = all.indexOf(item); + var min = tv.getSelectionModel().getSelectedIndices().stream().mapToInt(value -> value).min().orElse(1); + var max = tv.getSelectionModel().getSelectedIndices().stream().mapToInt(value -> value).max().orElse(all.size() - 1); + var end = tv.getSelectionModel().getFocusedIndex(); var start = end > min ? min : max; - model.getSelection().setAll(all.subList(Math.min(start, end), Math.max(start, end) + 1)); + tv.getSelectionModel().selectRange(Math.min(start, end), Math.max(start, end) + 1); t.consume(); return; } diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java index 584b6fb7..35f37a3e 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java @@ -9,6 +9,7 @@ import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import lombok.Getter; @@ -34,6 +35,7 @@ public final class BrowserFileListModel { private final Property> shown = new SimpleObjectProperty<>(new ArrayList<>()); private final ObjectProperty> predicateProperty = new SimpleObjectProperty<>(path -> true); + private final ObservableList previousSelection = FXCollections.observableArrayList(); private final ObservableList selection = FXCollections.observableArrayList(); private final ObservableList selectedRaw = BindingsHelper.mappedContentBinding(selection, entry -> entry.getRawFileEntry()); @@ -48,6 +50,10 @@ public final class BrowserFileListModel { fileSystemModel.getFilter().addListener((observable, oldValue, newValue) -> { refreshShown(); }); + + selection.addListener((ListChangeListener) c -> { + previousSelection.setAll(c.getList()); + }); } public BrowserModel.Mode getMode() { diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java index 000d71ee..e84e99d7 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java @@ -60,7 +60,7 @@ public class BrowserStatusBarComp extends SimpleComp { AppFont.small(bar); // Use status bar as an extension of file list - new ContextMenuAugment<>(false, true, () -> new BrowserContextMenu(model, null)).augment(new SimpleCompStructure<>(bar)); + new ContextMenuAugment<>(() -> new BrowserContextMenu(model, null)).augment(new SimpleCompStructure<>(bar)); return bar; } diff --git a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java index dd2be8e7..adf33e45 100644 --- a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java +++ b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java @@ -15,6 +15,7 @@ import javafx.scene.control.ToolBar; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; +import javafx.scene.input.MouseButton; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; import javafx.scene.layout.VBox; @@ -57,7 +58,7 @@ public class OpenFileSystemComp extends SimpleComp { terminalBtn.disableProperty().bind(PlatformThread.sync(model.getNoDirectory())); var menuButton = new MenuButton(null, new FontIcon("mdral-folder_open")); - new ContextMenuAugment<>(true, false, () -> new BrowserContextMenu(model, null)).augment(new SimpleCompStructure<>(menuButton)); + new ContextMenuAugment<>(event -> event.getButton() == MouseButton.PRIMARY, () -> new BrowserContextMenu(model, null)).augment(new SimpleCompStructure<>(menuButton)); var filter = new BrowserFilterComp(model.getFilter()).createStructure(); Shortcuts.addShortcut(filter.toggleButton(), new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN)); diff --git a/app/src/main/java/io/xpipe/app/browser/action/ApplicationPathAction.java b/app/src/main/java/io/xpipe/app/browser/action/ApplicationPathAction.java index 2e1b471c..c6ad770e 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/ApplicationPathAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/ApplicationPathAction.java @@ -9,17 +9,6 @@ public interface ApplicationPathAction extends BrowserAction { public abstract String getExecutable(); - @Override - public default boolean isApplicable(OpenFileSystemModel model, List entries) { - if (entries.size() == 0) { - return false; - } - - return entries.stream().allMatch(entry -> isApplicable(model, entry)); - } - - boolean isApplicable(OpenFileSystemModel model, BrowserEntry entry); - @Override public default boolean isActive(OpenFileSystemModel model, List entries) { return model.getCache().isApplicationInPath(getExecutable()); diff --git a/app/src/main/java/io/xpipe/app/browser/action/BrowserActionFormatter.java b/app/src/main/java/io/xpipe/app/browser/action/BrowserActionFormatter.java new file mode 100644 index 00000000..7a8a212a --- /dev/null +++ b/app/src/main/java/io/xpipe/app/browser/action/BrowserActionFormatter.java @@ -0,0 +1,25 @@ +package io.xpipe.app.browser.action; + +import io.xpipe.app.browser.BrowserEntry; + +import java.util.List; + +public class BrowserActionFormatter { + + public static String filesArgument(List entries) { + return entries.size() == 1 ? entries.get(0).getOptionallyQuotedFileName() : "(" + entries.size() + ")"; + } + + public static String centerEllipsis(String input, int length) { + if (input == null) { + return ""; + } + + if (input.length() <= length) { + return input; + } + + var half = (length / 2) - 5; + return input.substring(0, half) + " ... " + input.substring(input.length() - half); + } +} diff --git a/app/src/main/java/io/xpipe/app/browser/action/ExecuteApplicationAction.java b/app/src/main/java/io/xpipe/app/browser/action/ExecuteApplicationAction.java index 348cb94e..7d5aae35 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/ExecuteApplicationAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/ExecuteApplicationAction.java @@ -18,12 +18,24 @@ public abstract class ExecuteApplicationAction implements LeafAction, Applicatio cc.discardOrThrow(); } } + + if (detach() && refresh()) { + throw new IllegalStateException(); + } + + if (refresh()) { + model.refreshSync(); + } } protected boolean detach() { return false; } + protected boolean refresh() { + return false; + } + protected abstract String createCommand(OpenFileSystemModel model, BrowserEntry entry); } diff --git a/app/src/main/java/io/xpipe/app/browser/action/ToFileCommandAction.java b/app/src/main/java/io/xpipe/app/browser/action/ToFileCommandAction.java new file mode 100644 index 00000000..7356bb5d --- /dev/null +++ b/app/src/main/java/io/xpipe/app/browser/action/ToFileCommandAction.java @@ -0,0 +1,25 @@ +package io.xpipe.app.browser.action; + +import io.xpipe.app.browser.BrowserEntry; +import io.xpipe.app.browser.OpenFileSystemModel; +import io.xpipe.app.util.FileOpener; +import io.xpipe.core.process.ShellControl; + +import java.util.List; + +public abstract class ToFileCommandAction implements LeafAction, ApplicationPathAction { + + @Override + public void execute(OpenFileSystemModel model, List entries) throws Exception { + ShellControl sc = model.getFileSystem().getShell().orElseThrow(); + for (BrowserEntry entry : entries) { + var command = createCommand(model, entry); + try (var cc = sc.command(command).workingDirectory(model.getCurrentDirectory().getPath()).start()) { + cc.discardErr(); + FileOpener.openCommandOutput(entry.getFileName(), entry, cc); + } + } + } + + protected abstract String createCommand(OpenFileSystemModel model, BrowserEntry entry); +} diff --git a/app/src/main/java/io/xpipe/app/comp/storage/collection/SourceCollectionContextMenu.java b/app/src/main/java/io/xpipe/app/comp/storage/collection/SourceCollectionContextMenu.java index 7fd5ff9d..5253920c 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/collection/SourceCollectionContextMenu.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/collection/SourceCollectionContextMenu.java @@ -17,7 +17,7 @@ public class SourceCollectionContextMenu> extends Con public SourceCollectionContextMenu( boolean showOnPrimaryButton, SourceCollectionWrapper group, Region renameTextField) { - super(showOnPrimaryButton, true, () -> createContextMenu(group, renameTextField)); + super(() -> createContextMenu(group, renameTextField)); } private static void onDelete(SourceCollectionWrapper group) { diff --git a/app/src/main/java/io/xpipe/app/comp/storage/source/SourceEntryContextMenu.java b/app/src/main/java/io/xpipe/app/comp/storage/source/SourceEntryContextMenu.java index 40c16a26..f1452719 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/source/SourceEntryContextMenu.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/source/SourceEntryContextMenu.java @@ -20,7 +20,7 @@ public class SourceEntryContextMenu> extends ContextM public SourceEntryContextMenu(boolean showOnPrimaryButton, SourceEntryWrapper entry, Region renameTextField) { - super(showOnPrimaryButton, true, () -> createContextMenu(entry, renameTextField)); + super(() -> createContextMenu(entry, renameTextField)); } protected static ContextMenu createContextMenu(SourceEntryWrapper entry, Region renameTextField) { diff --git a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryComp.java index 616b7793..3566cc53 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryComp.java @@ -26,6 +26,7 @@ import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.*; +import javafx.scene.input.MouseButton; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.layout.Region; @@ -164,7 +165,7 @@ public class StoreEntryComp extends SimpleComp { }); }); - new ContextMenuAugment<>(false, true, () -> StoreEntryComp.this.createContextMenu()).augment(new SimpleCompStructure<>(button)); + new ContextMenuAugment<>(() -> StoreEntryComp.this.createContextMenu()).augment(new SimpleCompStructure<>(button)); return button; } @@ -213,7 +214,7 @@ public class StoreEntryComp extends SimpleComp { private Comp createSettingsButton() { var settingsButton = new IconButtonComp("mdomz-settings"); settingsButton.styleClass("settings"); - settingsButton.apply(new ContextMenuAugment<>(true, false, () -> StoreEntryComp.this.createContextMenu())); + settingsButton.apply(new ContextMenuAugment<>(event -> event.getButton() == MouseButton.PRIMARY, () -> StoreEntryComp.this.createContextMenu())); settingsButton.apply(GrowAugment.create(false, true)); settingsButton.apply(s -> { s.get().prefWidthProperty().bind(Bindings.divide(s.get().heightProperty(), 1.35)); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/augment/ContextMenuAugment.java b/app/src/main/java/io/xpipe/app/fxcomps/augment/ContextMenuAugment.java index 77fe3e3d..03f93675 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/augment/ContextMenuAugment.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/augment/ContextMenuAugment.java @@ -3,22 +3,27 @@ package io.xpipe.app.fxcomps.augment; import io.xpipe.app.fxcomps.CompStructure; import javafx.scene.control.ContextMenu; import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import java.util.function.Predicate; import java.util.function.Supplier; public class ContextMenuAugment> implements Augment { - private final boolean showOnPrimaryButton; - private final boolean showOnSecondaryButton; + private final Predicate show; private final Supplier contextMenu; - public ContextMenuAugment(boolean showOnPrimaryButton, boolean showOnSecondaryButton, Supplier contextMenu) { - this.showOnPrimaryButton = showOnPrimaryButton; - this.showOnSecondaryButton = showOnSecondaryButton; + private static ContextMenu currentContextMenu; + + public ContextMenuAugment(Predicate show, Supplier contextMenu) { + this.show = show; this.contextMenu = contextMenu; } - private static ContextMenu currentContextMenu; + public ContextMenuAugment(Supplier contextMenu) { + this.show = event -> event.getButton() == MouseButton.SECONDARY; + this.contextMenu = contextMenu; + } @Override public void augment(S struc) { @@ -29,8 +34,7 @@ public class ContextMenuAugment> implements Augment { - try (var out = output.get()) { - in.transferTo(out); - } catch (Exception ex) { - ErrorEvent.fromThrowable(ex).handle(); + if (output != null) { + try (var out = output.get()) { + in.transferTo(out); + } catch (Exception ex) { + ErrorEvent.fromThrowable(ex).handle(); + } } }); entry.registerChange(); diff --git a/app/src/main/java/io/xpipe/app/util/FileOpener.java b/app/src/main/java/io/xpipe/app/util/FileOpener.java index 1a0f4c47..e6a8c3e5 100644 --- a/app/src/main/java/io/xpipe/app/util/FileOpener.java +++ b/app/src/main/java/io/xpipe/app/util/FileOpener.java @@ -4,9 +4,12 @@ import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.core.impl.FileNames; import io.xpipe.core.impl.LocalStore; +import io.xpipe.core.process.CommandControl; import io.xpipe.core.process.OsType; import io.xpipe.core.store.FileSystem; +import lombok.SneakyThrows; +import java.io.FilterInputStream; import java.nio.file.Path; import java.util.function.Consumer; @@ -75,11 +78,28 @@ public class FileOpener { } } catch (Exception e) { ErrorEvent.fromThrowable(e) - .description("Unable to open file " + file).handle(); + .description("Unable to open file " + file) + .handle(); } } public static void openString(String keyName, Object key, String input, Consumer output) { FileBridge.get().openString(keyName, key, input, output, file -> openInTextEditor(file)); } + + public static void openCommandOutput(String keyName, Object key, CommandControl cc) { + FileBridge.get() + .openIO( + keyName, + key, + () -> new FilterInputStream(cc.getStdout()) { + @Override + @SneakyThrows + public void close() { + cc.close(); + } + }, + null, + file -> openInTextEditor(file)); + } } diff --git a/core/src/main/java/io/xpipe/core/impl/FileNames.java b/core/src/main/java/io/xpipe/core/impl/FileNames.java index 6d020d3e..4589d555 100644 --- a/core/src/main/java/io/xpipe/core/impl/FileNames.java +++ b/core/src/main/java/io/xpipe/core/impl/FileNames.java @@ -76,7 +76,7 @@ public class FileNames { } var name = FileNames.getFileName(file); - var split = file.lastIndexOf("\\."); + var split = file.lastIndexOf("."); if (split == -1) { return name; } diff --git a/dist/build.gradle b/dist/build.gradle index 1301cdba..224ac993 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -41,7 +41,7 @@ if (rootProject.fullVersion) { apply from: 'portable.gradle' apply from: 'proguard.gradle' apply from: 'jreleaser.gradle' - //apply from: 'choco.gradle' + apply from: 'choco.gradle' //apply from: 'homebrew.gradle' //apply from: 'flatpak.gradle' diff --git a/ext/base/src/main/java/io/xpipe/ext/base/browser/CopyPathAction.java b/ext/base/src/main/java/io/xpipe/ext/base/browser/CopyPathAction.java index a1c899c8..17543eb4 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/browser/CopyPathAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/browser/CopyPathAction.java @@ -4,6 +4,7 @@ import io.xpipe.app.browser.BrowserEntry; import io.xpipe.app.browser.OpenFileSystemModel; import io.xpipe.app.browser.action.BranchAction; import io.xpipe.app.browser.action.BrowserAction; +import io.xpipe.app.browser.action.BrowserActionFormatter; import io.xpipe.app.browser.action.LeafAction; import io.xpipe.core.impl.FileNames; @@ -36,6 +37,10 @@ public class CopyPathAction implements BrowserAction, BranchAction { new LeafAction() { @Override public String getName(OpenFileSystemModel model, List entries) { + if (entries.size() == 1) { + return " " + BrowserActionFormatter.centerEllipsis(entries.get(0).getRawFileEntry().getPath(), 50); + } + return "Absolute Path"; } @@ -52,6 +57,10 @@ public class CopyPathAction implements BrowserAction, BranchAction { new LeafAction() { @Override public String getName(OpenFileSystemModel model, List entries) { + if (entries.size() == 1) { + return "\"" + BrowserActionFormatter.centerEllipsis(entries.get(0).getRawFileEntry().getPath(), 50) + "\""; + } + return "Absolute Path (Quoted)"; } @@ -73,6 +82,10 @@ public class CopyPathAction implements BrowserAction, BranchAction { new LeafAction() { @Override public String getName(OpenFileSystemModel model, List entries) { + if (entries.size() == 1) { + return " " + BrowserActionFormatter.centerEllipsis(FileNames.getFileName(entries.get(0).getRawFileEntry().getPath()), 50); + } + return "File Name"; } @@ -90,6 +103,10 @@ public class CopyPathAction implements BrowserAction, BranchAction { new LeafAction() { @Override public String getName(OpenFileSystemModel model, List entries) { + if (entries.size() == 1) { + return "\"" + BrowserActionFormatter.centerEllipsis(FileNames.getFileName(entries.get(0).getRawFileEntry().getPath()), 50) + "\""; + } + return "File Name (Quoted)"; } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/browser/JarAction.java b/ext/base/src/main/java/io/xpipe/ext/base/browser/JarAction.java index ae2b0441..5c329b40 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/browser/JarAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/browser/JarAction.java @@ -2,12 +2,14 @@ package io.xpipe.ext.base.browser; import io.xpipe.app.browser.BrowserEntry; import io.xpipe.app.browser.OpenFileSystemModel; +import io.xpipe.app.browser.action.BrowserActionFormatter; +import io.xpipe.app.browser.action.MultiExecuteAction; import io.xpipe.app.browser.icon.FileType; import io.xpipe.core.process.ShellControl; import java.util.List; -public class JarAction extends JavaAction implements FileTypeAction { +public class JarAction extends MultiExecuteAction implements JavaAction, FileTypeAction { @Override public Category getCategory() { @@ -19,11 +21,6 @@ public class JarAction extends JavaAction implements FileTypeAction { return super.isApplicable(model, entries) && FileTypeAction.super.isApplicable(model, entries); } - @Override - public boolean isApplicable(OpenFileSystemModel model, BrowserEntry entry) { - return entry.getFileName().endsWith(".jar"); - } - @Override protected String createCommand(ShellControl sc, OpenFileSystemModel model, BrowserEntry entry) { return "java -jar " + entry.getOptionallyQuotedFileName(); @@ -31,7 +28,7 @@ public class JarAction extends JavaAction implements FileTypeAction { @Override public String getName(OpenFileSystemModel model, List entries) { - return "java -jar " + filesArgument(entries); + return "java -jar " + BrowserActionFormatter.filesArgument(entries); } @Override diff --git a/ext/base/src/main/java/io/xpipe/ext/base/browser/JavaAction.java b/ext/base/src/main/java/io/xpipe/ext/base/browser/JavaAction.java index 7da62a50..3b36b17c 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/browser/JavaAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/browser/JavaAction.java @@ -1,21 +1,11 @@ package io.xpipe.ext.base.browser; -import io.xpipe.app.browser.BrowserEntry; -import io.xpipe.app.browser.OpenFileSystemModel; import io.xpipe.app.browser.action.ApplicationPathAction; -import io.xpipe.app.browser.action.MultiExecuteAction; -import java.util.List; - -public abstract class JavaAction extends MultiExecuteAction implements ApplicationPathAction { +public interface JavaAction extends ApplicationPathAction { @Override - public String getName(OpenFileSystemModel model, List entries) { - return "Java"; - } - - @Override - public String getExecutable() { + default String getExecutable() { return "java"; } } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/browser/JavapAction.java b/ext/base/src/main/java/io/xpipe/ext/base/browser/JavapAction.java new file mode 100644 index 00000000..7804c06f --- /dev/null +++ b/ext/base/src/main/java/io/xpipe/ext/base/browser/JavapAction.java @@ -0,0 +1,37 @@ +package io.xpipe.ext.base.browser; + +import io.xpipe.app.browser.BrowserEntry; +import io.xpipe.app.browser.OpenFileSystemModel; +import io.xpipe.app.browser.action.BrowserActionFormatter; +import io.xpipe.app.browser.action.ToFileCommandAction; +import io.xpipe.app.browser.icon.FileType; + +import java.util.List; + +public class JavapAction extends ToFileCommandAction implements FileTypeAction, JavaAction { + + @Override + public Category getCategory() { + return Category.CUSTOM; + } + + @Override + public boolean isApplicable(OpenFileSystemModel model, List entries) { + return super.isApplicable(model, entries) && FileTypeAction.super.isApplicable(model, entries); + } + + @Override + public String getName(OpenFileSystemModel model, List entries) { + return "javap -c -p " + BrowserActionFormatter.filesArgument(entries); + } + + @Override + public FileType getType() { + return FileType.byId("class"); + } + + @Override + protected String createCommand(OpenFileSystemModel model, BrowserEntry entry) { + return "javap -c -p " + entry.getOptionallyQuotedFileName(); + } +} diff --git a/ext/base/src/main/java/io/xpipe/ext/base/browser/OpenNativeFileDetailsAction.java b/ext/base/src/main/java/io/xpipe/ext/base/browser/OpenNativeFileDetailsAction.java index 82879897..6dd7db6c 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/browser/OpenNativeFileDetailsAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/browser/OpenNativeFileDetailsAction.java @@ -59,7 +59,7 @@ public class OpenNativeFileDetailsAction implements LeafAction { @Override public boolean isApplicable(OpenFileSystemModel model, List entries) { var sc = model.getFileSystem().getShell(); - return sc.isPresent() && !sc.get().getOsType().equals(OsType.WINDOWS); + return model.isLocal() && !sc.get().getOsType().equals(OsType.WINDOWS); } @Override diff --git a/ext/base/src/main/java/io/xpipe/ext/base/browser/UnzipAction.java b/ext/base/src/main/java/io/xpipe/ext/base/browser/UnzipAction.java index 9ef22e35..ff3ec430 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/browser/UnzipAction.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/browser/UnzipAction.java @@ -3,12 +3,13 @@ package io.xpipe.ext.base.browser; import io.xpipe.app.browser.BrowserEntry; import io.xpipe.app.browser.OpenFileSystemModel; import io.xpipe.app.browser.action.ExecuteApplicationAction; +import io.xpipe.app.browser.icon.FileType; import io.xpipe.core.impl.FileNames; import io.xpipe.core.process.OsType; import java.util.List; -public class UnzipAction extends ExecuteApplicationAction { +public class UnzipAction extends ExecuteApplicationAction implements FileTypeAction { @Override public String getExecutable() { @@ -16,8 +17,8 @@ public class UnzipAction extends ExecuteApplicationAction { } @Override - public boolean isApplicable(OpenFileSystemModel model, BrowserEntry entry) { - return entry.getRawFileEntry().getPath().endsWith(".zip") && !OsType.getLocal().equals(OsType.WINDOWS); + public boolean isApplicable(OpenFileSystemModel model, List entries) { + return FileTypeAction.super.isApplicable(model, entries) && !model.getFileSystem().getShell().orElseThrow().getOsType().equals(OsType.WINDOWS); } @Override @@ -25,6 +26,11 @@ public class UnzipAction extends ExecuteApplicationAction { return "unzip -o " + entry.getOptionallyQuotedFileName() + " -d " + FileNames.quoteIfNecessary(FileNames.getBaseName(entry.getFileName())); } + @Override + protected boolean refresh() { + return true; + } + @Override public Category getCategory() { return Category.CUSTOM; @@ -34,4 +40,9 @@ public class UnzipAction extends ExecuteApplicationAction { public String getName(OpenFileSystemModel model, List entries) { return "unzip [...]"; } + + @Override + public FileType getType() { + return FileType.byId("zip"); + } } diff --git a/ext/base/src/main/java/module-info.java b/ext/base/src/main/java/module-info.java index 453779eb..d46862bc 100644 --- a/ext/base/src/main/java/module-info.java +++ b/ext/base/src/main/java/module-info.java @@ -43,6 +43,7 @@ open module io.xpipe.ext.base { RenameAction, DeleteAction, UnzipAction, + JavapAction, JarAction; provides ActionProvider with DeleteStoreChildrenAction,