mirror of
https://github.com/xpipe-io/xpipe.git
synced 2025-04-17 01:33:36 +00:00
Migrate all actions, fix various bugs
This commit is contained in:
parent
51bbf8ad67
commit
7be8087b19
19 changed files with 298 additions and 207 deletions
|
@ -171,13 +171,18 @@ public class StoreEntryComp extends SimpleComp {
|
|||
var button = new IconButtonComp(
|
||||
actionProvider.getIcon(entry.getEntry().getStore().asNeeded()), () -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
var action = actionProvider.createAction(entry.getEntry().getStore().asNeeded());
|
||||
var action = actionProvider.createAction(
|
||||
entry.getEntry().getStore().asNeeded());
|
||||
action.execute();
|
||||
});
|
||||
});
|
||||
button.apply(new FancyTooltipAugment<>(
|
||||
actionProvider.getName(entry.getEntry().getStore().asNeeded())));
|
||||
button.disable(Bindings.not(p.getValue()));
|
||||
if (!actionProvider.showIfDisabled()) {
|
||||
button.hide(Bindings.not(p.getValue()));
|
||||
} else {
|
||||
button.disable(Bindings.not(p.getValue()));
|
||||
}
|
||||
list.add(button);
|
||||
}
|
||||
|
||||
|
@ -227,7 +232,8 @@ public class StoreEntryComp extends SimpleComp {
|
|||
var item = new MenuItem(null, new FontIcon(icon));
|
||||
item.setOnAction(event -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
var action = actionProvider.createAction(entry.getEntry().getStore().asNeeded());
|
||||
var action = actionProvider.createAction(
|
||||
entry.getEntry().getStore().asNeeded());
|
||||
action.execute();
|
||||
});
|
||||
});
|
||||
|
@ -245,7 +251,8 @@ public class StoreEntryComp extends SimpleComp {
|
|||
|
||||
if (AppPrefs.get().developerMode().getValue()) {
|
||||
var browse = new MenuItem(I18n.get("browse"), new FontIcon("mdi2f-folder-open-outline"));
|
||||
browse.setOnAction(event -> DesktopHelper.browsePath(entry.getEntry().getDirectory()));
|
||||
browse.setOnAction(
|
||||
event -> DesktopHelper.browsePath(entry.getEntry().getDirectory()));
|
||||
contextMenu.getItems().add(browse);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ public class DataStateProviderImpl extends DataStateProvider {
|
|||
|
||||
@Override
|
||||
public void putState(DataStore store, String key, Object value) {
|
||||
if (DataStorage.get() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = DataStorage.get().getEntryByStore(store);
|
||||
if (entry.isEmpty()) {
|
||||
return;
|
||||
|
@ -22,6 +26,10 @@ public class DataStateProviderImpl extends DataStateProvider {
|
|||
|
||||
@Override
|
||||
public <T> T getState(DataStore store, String key, Class<T> c, Supplier<T> def) {
|
||||
if (DataStorage.get() == null) {
|
||||
return def.get();
|
||||
}
|
||||
|
||||
var entry = DataStorage.get().getEntryByStore(store);
|
||||
if (entry.isEmpty()) {
|
||||
return def.get();
|
||||
|
|
|
@ -74,10 +74,6 @@ public abstract class DataStorage {
|
|||
}
|
||||
|
||||
public static DataStorage get() {
|
||||
if (INSTANCE == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
@ -175,6 +171,10 @@ public abstract class DataStorage {
|
|||
}
|
||||
|
||||
public Optional<DataSourceCollection> getCollectionForName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.ofNullable(getInternalCollection());
|
||||
}
|
||||
|
||||
return sourceCollections.stream()
|
||||
.filter(c -> name.equalsIgnoreCase(c.getName()))
|
||||
.findAny();
|
||||
|
|
|
@ -13,7 +13,7 @@ public abstract class TerminalProvider {
|
|||
|
||||
@Override
|
||||
public void init(ModuleLayer layer) {
|
||||
ServiceLoader.load(layer, TerminalProvider.class).findFirst().orElseThrow();
|
||||
INSTANCE = ServiceLoader.load(layer, TerminalProvider.class).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,12 +7,14 @@ import io.xpipe.app.exchange.cli.*;
|
|||
import io.xpipe.app.issue.EventHandlerImpl;
|
||||
import io.xpipe.app.storage.DataStateProviderImpl;
|
||||
import io.xpipe.app.util.ProxyManagerProviderImpl;
|
||||
import io.xpipe.app.util.TerminalProvider;
|
||||
import io.xpipe.app.util.XPipeDaemonProvider;
|
||||
import io.xpipe.core.util.DataStateProvider;
|
||||
import io.xpipe.core.util.ProxyManagerProvider;
|
||||
import io.xpipe.extension.Cache;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.extension.event.EventHandler;
|
||||
import io.xpipe.extension.util.ModuleLayerLoader;
|
||||
import io.xpipe.extension.util.XPipeDaemon;
|
||||
import org.slf4j.spi.SLF4JServiceProvider;
|
||||
|
||||
|
@ -99,6 +101,7 @@ open module io.xpipe.app {
|
|||
uses MessageExchangeImpl;
|
||||
uses io.xpipe.app.util.TerminalProvider;
|
||||
|
||||
provides ModuleLayerLoader with TerminalProvider.Loader;
|
||||
provides DataStateProvider with
|
||||
DataStateProviderImpl;
|
||||
provides ProxyManagerProvider with
|
||||
|
|
|
@ -41,7 +41,7 @@ public interface OsType {
|
|||
|
||||
@Override
|
||||
public String getTempDirectory(ShellProcessControl pc) throws Exception {
|
||||
return pc.executeStringSimpleCommand(ShellTypes.CMD, ShellTypes.CMD.getPrintVariableCommand("TEMP"));
|
||||
return pc.executeStringSimpleCommand(pc.getShellType().getPrintEnvironmentVariableCommand("TEMP"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,7 +52,7 @@ public interface OsType {
|
|||
@Override
|
||||
public Map<String, String> getProperties(ShellProcessControl pc) throws Exception {
|
||||
try (CommandProcessControl c =
|
||||
pc.subShell(ShellTypes.CMD).command("systeminfo").start()) {
|
||||
pc.command("systeminfo").start()) {
|
||||
var text = c.readOrThrow();
|
||||
return PropertiesFormatsParser.parse(text, ":");
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package io.xpipe.core.process;
|
||||
|
||||
import io.xpipe.core.util.FailableBiFunction;
|
||||
import io.xpipe.core.util.FailableFunction;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public abstract class ProcessControlProvider {
|
||||
|
||||
|
@ -18,21 +18,22 @@ public abstract class ProcessControlProvider {
|
|||
}
|
||||
|
||||
public static ShellProcessControl createLocal() {
|
||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createLocalProcessControl()).findFirst().orElseThrow();
|
||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.createLocalProcessControl()).filter(
|
||||
Objects::nonNull).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public static ShellProcessControl createSub(
|
||||
ShellProcessControl parent,
|
||||
@NonNull Function<ShellProcessControl, String> commandFunction,
|
||||
BiFunction<ShellProcessControl, String, String> terminalCommand) {
|
||||
@NonNull FailableFunction<ShellProcessControl, String, Exception> commandFunction,
|
||||
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand) {
|
||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.sub(parent, commandFunction, terminalCommand)).filter(
|
||||
Objects::nonNull).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public static CommandProcessControl createCommand(
|
||||
ShellProcessControl parent,
|
||||
@NonNull Function<ShellProcessControl, String> command,
|
||||
Function<ShellProcessControl, String> terminalCommand) {
|
||||
@NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||
FailableFunction<ShellProcessControl, String, Exception> terminalCommand) {
|
||||
return INSTANCES.stream().map(localProcessControlProvider -> localProcessControlProvider.command(parent, command, terminalCommand)).filter(
|
||||
Objects::nonNull).findFirst().orElseThrow();
|
||||
}
|
||||
|
@ -44,13 +45,13 @@ public abstract class ProcessControlProvider {
|
|||
|
||||
public abstract ShellProcessControl sub(
|
||||
ShellProcessControl parent,
|
||||
@NonNull Function<ShellProcessControl, String> commandFunction,
|
||||
BiFunction<ShellProcessControl, String, String> terminalCommand);
|
||||
@NonNull FailableFunction<ShellProcessControl, String, Exception> commandFunction,
|
||||
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand);
|
||||
|
||||
public abstract CommandProcessControl command(
|
||||
ShellProcessControl parent,
|
||||
@NonNull Function<ShellProcessControl, String> command,
|
||||
Function<ShellProcessControl, String> terminalCommand);
|
||||
@NonNull FailableFunction<ShellProcessControl, String, Exception> command,
|
||||
FailableFunction<ShellProcessControl, String, Exception> terminalCommand);
|
||||
|
||||
public abstract ShellProcessControl createLocalProcessControl();
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package io.xpipe.core.process;
|
||||
|
||||
import io.xpipe.core.util.FailableBiFunction;
|
||||
import io.xpipe.core.util.FailableFunction;
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface ShellProcessControl extends ProcessControl {
|
||||
|
@ -87,18 +87,18 @@ public interface ShellProcessControl extends ProcessControl {
|
|||
}
|
||||
|
||||
ShellProcessControl subShell(
|
||||
@NonNull Function<ShellProcessControl, String> command,
|
||||
BiFunction<ShellProcessControl, String, String> terminalCommand);
|
||||
FailableFunction<ShellProcessControl, String, Exception> command,
|
||||
FailableBiFunction<ShellProcessControl, String, String, Exception> terminalCommand);
|
||||
|
||||
void executeLine(String command) throws Exception;
|
||||
|
||||
@Override
|
||||
ShellProcessControl start() throws Exception;
|
||||
|
||||
CommandProcessControl command(Function<ShellProcessControl, String> command);
|
||||
CommandProcessControl command(FailableFunction<ShellProcessControl, String, Exception> command);
|
||||
|
||||
CommandProcessControl command(
|
||||
Function<ShellProcessControl, String> command, Function<ShellProcessControl, String> terminalCommand);
|
||||
FailableFunction<ShellProcessControl, String, Exception> command, FailableFunction<ShellProcessControl, String, Exception> terminalCommand);
|
||||
|
||||
default CommandProcessControl command(String command) {
|
||||
return command(shellProcessControl -> command);
|
||||
|
|
|
@ -60,11 +60,9 @@ public interface ShellType {
|
|||
String getEchoCommand(String s, boolean toErrorStream);
|
||||
|
||||
|
||||
default String getPrintVariableCommand(String name) {
|
||||
return getPrintVariableCommand("", name);
|
||||
}
|
||||
String getPrintVariableCommand(String name);
|
||||
|
||||
String getPrintVariableCommand(String prefix, String name);
|
||||
String getPrintExitCodeCommand(String prefix);
|
||||
|
||||
default String getPrintEnvironmentVariableCommand(String name) {
|
||||
return getPrintVariableCommand(name);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableBiFunction<T1, T2, R, E extends Throwable> {
|
||||
|
||||
R apply(T1 var1, T2 var2) throws E;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package io.xpipe.core.util;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableFunction<T, R, E extends Throwable> {
|
||||
|
||||
R apply(T var1) throws E;
|
||||
}
|
|
@ -2,38 +2,61 @@ package io.xpipe.ext.base.actions;
|
|||
|
||||
import io.xpipe.core.impl.FileStore;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.extension.util.ActionProvider;
|
||||
import io.xpipe.extension.util.DesktopHelper;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import lombok.Value;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class FileBrowseAction implements DataStoreActionProvider<FileStore> {
|
||||
public class FileBrowseAction implements ActionProvider {
|
||||
|
||||
@Override
|
||||
public Class<FileStore> getApplicableClass() {
|
||||
return FileStore.class;
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
FileStore store;
|
||||
|
||||
@Override
|
||||
public boolean requiresPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
DesktopHelper.browseFileInDirectory(Path.of(store.getFile()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(FileStore o) throws Exception {
|
||||
return o.getFileSystem().equals(new LocalStore()) && Files.exists(Path.of(o.getFile()));
|
||||
}
|
||||
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||
return new DataStoreCallSite<FileStore>() {
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(FileStore store) {
|
||||
return I18n.observable("base.browseFile");
|
||||
}
|
||||
@Override
|
||||
public ActionProvider.Action createAction(FileStore store) {
|
||||
return new Action(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(FileStore store) {
|
||||
return "mdi2f-folder-open-outline";
|
||||
}
|
||||
@Override
|
||||
public Class<FileStore> getApplicableClass() {
|
||||
return FileStore.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(FileStore store) throws Exception {
|
||||
DesktopHelper.browseFileInDirectory(Path.of(store.getFile()));
|
||||
@Override
|
||||
public boolean isApplicable(FileStore o) throws Exception {
|
||||
return o.getFileSystem().equals(new LocalStore()) && Files.exists(Path.of(o.getFile()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(FileStore store) {
|
||||
return I18n.observable("base.browseFile");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(FileStore store) {
|
||||
return "mdi2f-folder-open-outline";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,39 +4,62 @@ import io.xpipe.app.util.ExternalEditor;
|
|||
import io.xpipe.core.impl.FileStore;
|
||||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.store.DataFlow;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.extension.util.ActionProvider;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import lombok.Value;
|
||||
|
||||
public class FileEditAction implements DataStoreActionProvider<FileStore> {
|
||||
public class FileEditAction implements ActionProvider {
|
||||
|
||||
@Override
|
||||
public Class<FileStore> getApplicableClass() {
|
||||
return FileStore.class;
|
||||
}
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(FileStore o) throws Exception {
|
||||
return o.getFlow().equals(DataFlow.INPUT_OUTPUT);
|
||||
}
|
||||
FileStore store;
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(FileStore store) {
|
||||
return I18n.observable("base.editFile");
|
||||
}
|
||||
@Override
|
||||
public boolean requiresPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(FileStore store) {
|
||||
return "mdal-edit";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(FileStore store) throws Exception {
|
||||
if (store.getFileSystem().equals(new LocalStore())) {
|
||||
ExternalEditor.get().openInEditor(store.getFile());
|
||||
} else {
|
||||
ExternalEditor.get()
|
||||
.startEditing(store.getFileName(), store.getFileExtension(), store, () -> store.openInput(), () -> store.openOutput());
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
if (store.getFileSystem().equals(new LocalStore())) {
|
||||
ExternalEditor.get().openInEditor(store.getFile());
|
||||
} else {
|
||||
ExternalEditor.get()
|
||||
.startEditing(store.getFileName(), store.getFileExtension(), store, () -> store.openInput(), () -> store.openOutput());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||
return new DataStoreCallSite<FileStore>() {
|
||||
|
||||
@Override
|
||||
public ActionProvider.Action createAction(FileStore store) {
|
||||
return new Action(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<FileStore> getApplicableClass() {
|
||||
return FileStore.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(FileStore o) throws Exception {
|
||||
return o.getFlow().equals(DataFlow.INPUT_OUTPUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(FileStore store) {
|
||||
return I18n.observable("base.editFile");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(FileStore store) {
|
||||
return "mdal-edit";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,52 +3,76 @@ package io.xpipe.ext.base.actions;
|
|||
import io.xpipe.app.core.AppActionLinkDetector;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.DataStoreProviders;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.extension.util.ActionProvider;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import lombok.Value;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
|
||||
public class ShareStoreAction implements DataStoreActionProvider<DataStore> {
|
||||
public class ShareStoreAction implements ActionProvider {
|
||||
|
||||
@Override
|
||||
public boolean showIfDisabled() {
|
||||
return false;
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
DataStore store;
|
||||
|
||||
@Override
|
||||
public boolean requiresPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String create(DataStore store) {
|
||||
return "xpipe://add/store/" + SecretValue.encrypt(store.toString()).getEncryptedValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
var string = create(store);
|
||||
var selection = new StringSelection(string);
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
AppActionLinkDetector.setLastDetectedAction(string);
|
||||
clipboard.setContents(selection, selection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<DataStore> getApplicableClass() {
|
||||
return DataStore.class;
|
||||
}
|
||||
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||
return new DataStoreCallSite<DataStore>() {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(DataStore o) throws Exception {
|
||||
return DataStoreProviders.byStore(o).isShareable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(DataStore store) {
|
||||
return I18n.observable("base.copyShareLink");
|
||||
}
|
||||
@Override
|
||||
public boolean showIfDisabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(DataStore store) {
|
||||
return "mdi2c-clipboard-list-outline";
|
||||
}
|
||||
@Override
|
||||
public ActionProvider.Action createAction(DataStore store) {
|
||||
return new Action(store);
|
||||
}
|
||||
|
||||
public static String create(DataStore store) {
|
||||
return "xpipe://add/store/" + SecretValue.encrypt(store.toString()).getEncryptedValue();
|
||||
}
|
||||
@Override
|
||||
public Class<DataStore> getApplicableClass() {
|
||||
return DataStore.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(DataStore store) throws Exception {
|
||||
var string = create(store);
|
||||
var selection = new StringSelection(string);
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
AppActionLinkDetector.setLastDetectedAction(string);
|
||||
clipboard.setContents(selection, selection);
|
||||
@Override
|
||||
public boolean isApplicable(DataStore o) throws Exception {
|
||||
return DataStoreProviders.byStore(o).isShareable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(DataStore store) {
|
||||
return I18n.observable("base.copyShareLink");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(DataStore store) {
|
||||
return "mdi2c-clipboard-list-outline";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +1,84 @@
|
|||
package io.xpipe.ext.base.actions;
|
||||
|
||||
import io.xpipe.core.store.StreamDataStore;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.extension.event.ErrorEvent;
|
||||
import io.xpipe.extension.util.ActionProvider;
|
||||
import io.xpipe.extension.util.DesktopHelper;
|
||||
import io.xpipe.extension.util.ThreadHelper;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.stage.FileChooser;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public class StreamExportAction implements DataStoreActionProvider<StreamDataStore> {
|
||||
@Override
|
||||
public Class<StreamDataStore> getApplicableClass() {
|
||||
return StreamDataStore.class;
|
||||
}
|
||||
public class StreamExportAction implements ActionProvider {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(StreamDataStore o) throws Exception {
|
||||
return o.getFlow() != null && o.getFlow().hasInput();
|
||||
}
|
||||
@Value
|
||||
static class Action implements ActionProvider.Action {
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(StreamDataStore store) {
|
||||
return I18n.observable("base.exportStream");
|
||||
}
|
||||
StreamDataStore store;
|
||||
|
||||
@Override
|
||||
public String getIcon(StreamDataStore store) {
|
||||
return "mdi2f-file-export-outline";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(StreamDataStore store) throws Exception {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle(I18n.get("browseFileTitle"));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(I18n.get("anyFile"), "."));
|
||||
var outputFile = fileChooser.showSaveDialog(null);
|
||||
if (outputFile == null) {
|
||||
return;
|
||||
@Override
|
||||
public boolean requiresPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ThreadHelper.runAsync(() -> {
|
||||
try (InputStream inputStream = store.openInput()) {
|
||||
try (OutputStream outputStream = Files.newOutputStream(outputFile.toPath())) {
|
||||
inputStream.transferTo(outputStream);
|
||||
}
|
||||
DesktopHelper.browseFileInDirectory(outputFile.toPath());
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle(I18n.get("browseFileTitle"));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(I18n.get("anyFile"), "."));
|
||||
var outputFile = fileChooser.showSaveDialog(null);
|
||||
if (outputFile == null) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
ThreadHelper.runAsync(() -> {
|
||||
try (InputStream inputStream = store.openInput()) {
|
||||
try (OutputStream outputStream = Files.newOutputStream(outputFile.toPath())) {
|
||||
inputStream.transferTo(outputStream);
|
||||
}
|
||||
DesktopHelper.browseFileInDirectory(outputFile.toPath());
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStoreCallSite<?> getDataStoreCallSite() {
|
||||
return new DataStoreCallSite<StreamDataStore>() {
|
||||
|
||||
@Override
|
||||
public Action createAction(StreamDataStore store) {
|
||||
return new Action(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(StreamDataStore o) throws Exception {
|
||||
return o.getFlow() != null && o.getFlow().hasInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StreamDataStore> getApplicableClass() {
|
||||
return StreamDataStore.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ObservableValue<String> getName(StreamDataStore store) {
|
||||
return I18n.observable("base.exportStream");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIcon(StreamDataStore store) {
|
||||
return "mdi2f-file-export-outline";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import io.xpipe.ext.base.*;
|
|||
import io.xpipe.ext.base.actions.*;
|
||||
import io.xpipe.ext.base.apps.*;
|
||||
import io.xpipe.extension.DataSourceProvider;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.DataStoreProvider;
|
||||
import io.xpipe.extension.DataSourceTarget;
|
||||
import io.xpipe.extension.util.ActionProvider;
|
||||
|
@ -22,8 +21,7 @@ open module io.xpipe.ext.base {
|
|||
requires static net.synedra.validatorfx;
|
||||
requires static io.xpipe.app;
|
||||
|
||||
provides ActionProvider with AddStoreAction;
|
||||
provides DataStoreActionProvider with
|
||||
provides ActionProvider with AddStoreAction,
|
||||
StreamExportAction,
|
||||
ShareStoreAction,
|
||||
FileBrowseAction,
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.extension.event.ErrorEvent;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public interface DataStoreActionProvider<T extends DataStore> {
|
||||
|
||||
static List<DataStoreActionProvider<?>> ALL = new ArrayList<>();
|
||||
|
||||
public static void init(ModuleLayer layer) {
|
||||
if (ALL.size() == 0) {
|
||||
ALL.addAll(ServiceLoader.load(layer, DataStoreActionProvider.class).stream()
|
||||
.map(p -> (DataStoreActionProvider<?>) p.get())
|
||||
.filter(provider -> {
|
||||
try {
|
||||
return provider.isActive();
|
||||
} catch (Throwable e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toList());
|
||||
}
|
||||
}
|
||||
|
||||
Class<T> getApplicableClass();
|
||||
|
||||
default boolean isMajor() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isActive() throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean isApplicable(T o) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
default void applyToRegion(T store, Region region) {
|
||||
}
|
||||
|
||||
ObservableValue<String> getName(T store);
|
||||
|
||||
String getIcon(T store);
|
||||
|
||||
default void execute(T store) throws Exception {
|
||||
}
|
||||
|
||||
default boolean showIfDisabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import io.xpipe.core.util.SecretValue;
|
|||
import io.xpipe.extension.event.TrackEvent;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
|
@ -91,6 +92,18 @@ public class ScriptHelper {
|
|||
} "$@"
|
||||
""";
|
||||
|
||||
public static String unquote(String input) {
|
||||
if (input.startsWith("\"") && input.endsWith("\"")) {
|
||||
return input.substring(1, input.length() - 1);
|
||||
}
|
||||
|
||||
if (input.startsWith("'") && input.endsWith("'")) {
|
||||
return input.substring(1, input.length() - 1);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String constructOpenWithInitScriptCommand(
|
||||
ShellProcessControl processControl, List<String> init, String toExecuteInShell) {
|
||||
ShellType t = processControl.getShellType();
|
||||
|
@ -98,6 +111,20 @@ public class ScriptHelper {
|
|||
return t.getNormalOpenCommand();
|
||||
}
|
||||
|
||||
if (init.size() == 0) {
|
||||
var cmd = unquote(toExecuteInShell);
|
||||
|
||||
// Check for special case of the command to be executed just being another shell script
|
||||
if (cmd.endsWith(".sh") || cmd.endsWith(".bat")) {
|
||||
return t.executeCommandWithShell(cmd);
|
||||
}
|
||||
|
||||
// Check for special case of the command being a shell command
|
||||
if (Arrays.stream(ShellTypes.getAllShellTypes()).anyMatch(shellType -> cmd.equals(shellType.getNormalOpenCommand()))) {
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
|
||||
String nl = t.getNewLine().getNewLineString();
|
||||
var content = String.join(nl, init) + nl;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import io.xpipe.core.util.ProxyFunction;
|
||||
import io.xpipe.extension.DataSourceProvider;
|
||||
import io.xpipe.extension.DataStoreActionProvider;
|
||||
import io.xpipe.extension.DataSourceTarget;
|
||||
import io.xpipe.extension.prefs.PrefsProvider;
|
||||
import io.xpipe.extension.util.ActionProvider;
|
||||
|
@ -45,7 +44,6 @@ open module io.xpipe.extension {
|
|||
|
||||
uses DataSourceProvider;
|
||||
uses DataSourceTarget;
|
||||
uses DataStoreActionProvider;
|
||||
uses io.xpipe.extension.I18n;
|
||||
uses io.xpipe.extension.event.EventHandler;
|
||||
uses io.xpipe.extension.prefs.PrefsProvider;
|
||||
|
|
Loading…
Add table
Reference in a new issue