Rework shell terminal command handling and clipboards

This commit is contained in:
crschnick 2023-12-19 14:55:50 +00:00
parent 2af59af190
commit 4daa183dad
8 changed files with 57 additions and 59 deletions

View file

@ -28,10 +28,6 @@ import javafx.css.PseudoClass;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.input.MouseButton; import javafx.scene.input.MouseButton;
import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.ColumnConstraints;
@ -39,16 +35,13 @@ import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
public abstract class StoreEntryComp extends SimpleComp { public abstract class StoreEntryComp extends SimpleComp {
public static StoreEntryComp create( public static StoreEntryComp create(
StoreEntryWrapper entry, boolean showIcon, Comp<?> content, boolean preferLarge) { StoreEntryWrapper entry, Comp<?> content, boolean preferLarge) {
if (!preferLarge) { if (!preferLarge) {
return new DenseStoreEntryComp(entry, true, content); return new DenseStoreEntryComp(entry, true, content);
} else { } else {
@ -331,10 +324,8 @@ public abstract class StoreEntryComp extends SimpleComp {
l.textProperty().bind(AppI18n.observable("base.copyShareLink")); l.textProperty().bind(AppI18n.observable("base.copyShareLink"));
l.setOnAction(event -> { l.setOnAction(event -> {
ThreadHelper.runFailableAsync(() -> { ThreadHelper.runFailableAsync(() -> {
var selection = new StringSelection(url);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
AppActionLinkDetector.setLastDetectedAction(url); AppActionLinkDetector.setLastDetectedAction(url);
clipboard.setContents(selection, selection); ClipboardHelper.copyUrl(url);
}); });
}); });
menu.getItems().add(l); menu.getItems().add(l);

View file

@ -16,6 +16,7 @@ import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority; import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -108,15 +109,17 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
return; return;
} }
struc.get().getStyleClass().removeIf(s -> Arrays.stream(DataStoreColor.values()) var newList = new ArrayList<>(struc.get().getStyleClass());
newList.removeIf(s -> Arrays.stream(DataStoreColor.values())
.anyMatch(dataStoreColor -> dataStoreColor.getId().equals(s))); .anyMatch(dataStoreColor -> dataStoreColor.getId().equals(s)));
struc.get().getStyleClass().remove("none"); newList.remove("none");
struc.get().getStyleClass().add("color-box"); newList.add("color-box");
if (val != null) { if (val != null) {
struc.get().getStyleClass().add(val.getId()); newList.add(val.getId());
} else { } else {
struc.get().getStyleClass().add("none"); newList.add("none");
} }
struc.get().getStyleClass().setAll(newList);
})) }))
.apply(struc -> { .apply(struc -> {
struc.get().pseudoClassStateChanged(ROOT, topLevel); struc.get().pseudoClassStateChanged(ROOT, topLevel);

View file

@ -57,7 +57,7 @@ public interface DataStoreProvider {
} }
default Comp<?> customEntryComp(StoreSection s, boolean preferLarge) { default Comp<?> customEntryComp(StoreSection s, boolean preferLarge) {
return StoreEntryComp.create(s.getWrapper(),true, null, preferLarge); return StoreEntryComp.create(s.getWrapper(), null, preferLarge);
} }
default Comp<?> customSectionComp(StoreSection section, boolean topLevel) { default Comp<?> customSectionComp(StoreSection section, boolean topLevel) {

View file

@ -4,6 +4,7 @@ import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.util.ClipboardHelper;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -14,10 +15,6 @@ import javafx.scene.paint.Color;
import org.fxmisc.richtext.InlineCssTextArea; import org.fxmisc.richtext.InlineCssTextArea;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
public class CodeSnippetComp extends Comp<CompStructure<?>> { public class CodeSnippetComp extends Comp<CompStructure<?>> {
private final ObservableValue<Boolean> showLineNumbers; private final ObservableValue<Boolean> showLineNumbers;
@ -67,9 +64,7 @@ public class CodeSnippetComp extends Comp<CompStructure<?>> {
var button = new Button(); var button = new Button();
button.setGraphic(new FontIcon("mdoal-content_copy")); button.setGraphic(new FontIcon("mdoal-content_copy"));
button.setOnAction(e -> { button.setOnAction(e -> {
var string = new StringSelection(value.getValue().getRawString()); ClipboardHelper.copyText(value.getValue().getRawString());
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(string, string);
}); });
button.getStyleClass().add("copy"); button.getStyleClass().add("copy");
button.getStyleClass().add("button-comp"); button.getStyleClass().add("button-comp");

View file

@ -0,0 +1,24 @@
package io.xpipe.app.util;
import io.xpipe.app.fxcomps.util.PlatformThread;
import javafx.scene.input.Clipboard;
import javafx.scene.input.DataFormat;
import java.util.Map;
public class ClipboardHelper {
public static void copyText(String s) {
PlatformThread.runLaterIfNeeded(() -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
clipboard.setContent(Map.of(DataFormat.PLAIN_TEXT, s));
});
}
public static void copyUrl(String s) {
PlatformThread.runLaterIfNeeded(() -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
clipboard.setContent(Map.of(DataFormat.PLAIN_TEXT, s, DataFormat.URL, s));
});
}
}

View file

@ -172,22 +172,26 @@ public interface ShellControl extends ProcessControl {
FailableSupplier<SecretValue> getElevationPassword(); FailableSupplier<SecretValue> getElevationPassword();
default ShellControl subShell(@NonNull ShellDialect type) { default ShellControl subShell(@NonNull ShellDialect type) {
return subShell(p -> type.getOpenCommand(), (sc, command) -> command != null ? command : type.getLoginOpenCommand()) return subShell(p -> type.getOpenCommand(), (sc) -> type.getLoginOpenCommand())
.elevationPassword(getElevationPassword()); .elevationPassword(getElevationPassword());
} }
interface TerminalOpenFunction { interface TerminalOpenFunction {
String prepare(ShellControl sc, String command) throws Exception; String prepareWithoutInitCommand(ShellControl sc) throws Exception;
default String prepareWithInitCommand(ShellControl sc, @NonNull String command) throws Exception {
return command;
}
} }
default ShellControl identicalSubShell() { default ShellControl identicalSubShell() {
return subShell(p -> p.getShellDialect().getOpenCommand(), (sc, command) -> command) return subShell(p -> p.getShellDialect().getOpenCommand(), (sc) -> sc.getShellDialect().getOpenCommand())
.elevationPassword(getElevationPassword()); .elevationPassword(getElevationPassword());
} }
default ShellControl subShell(@NonNull String command) { default ShellControl subShell(@NonNull String command) {
return subShell(processControl -> command, (sc, command1) -> command1); return subShell(processControl -> command, (sc) -> command);
} }
default ShellControl enforcedDialect(ShellDialect type) throws Exception { default ShellControl enforcedDialect(ShellDialect type) throws Exception {

View file

@ -5,15 +5,12 @@ import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.ActionProvider; import io.xpipe.app.ext.ActionProvider;
import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.DataStoreEntryRef; import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.ClipboardHelper;
import io.xpipe.app.util.SecretHelper; import io.xpipe.app.util.SecretHelper;
import io.xpipe.core.store.DataStore; import io.xpipe.core.store.DataStore;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import lombok.Value; import lombok.Value;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
public class ShareStoreAction implements ActionProvider { public class ShareStoreAction implements ActionProvider {
@Value @Value
@ -33,11 +30,9 @@ public class ShareStoreAction implements ActionProvider {
@Override @Override
public void execute() { public void execute() {
var string = create(store.getStore()); var url = create(store.getStore());
var selection = new StringSelection(string); AppActionLinkDetector.setLastDetectedAction(url);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); ClipboardHelper.copyUrl(url);
AppActionLinkDetector.setLastDetectedAction(string);
clipboard.setContents(selection, selection);
} }
} }

View file

@ -6,15 +6,13 @@ import io.xpipe.app.browser.action.BranchAction;
import io.xpipe.app.browser.action.BrowserAction; import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.action.BrowserActionFormatter; import io.xpipe.app.browser.action.BrowserActionFormatter;
import io.xpipe.app.browser.action.LeafAction; import io.xpipe.app.browser.action.LeafAction;
import io.xpipe.core.store.FileNames; import io.xpipe.app.util.ClipboardHelper;
import io.xpipe.core.store.FileKind; import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyCombination;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -60,9 +58,7 @@ public class CopyPathAction implements BrowserAction, BranchAction {
var s = entries.stream() var s = entries.stream()
.map(entry -> entry.getRawFileEntry().getPath()) .map(entry -> entry.getRawFileEntry().getPath())
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
var selection = new StringSelection(s); ClipboardHelper.copyText(s);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
} }
}, },
new LeafAction() { new LeafAction() {
@ -94,9 +90,7 @@ public class CopyPathAction implements BrowserAction, BranchAction {
var s = entries.stream() var s = entries.stream()
.map(entry -> entry.getRawFileEntry().getPath()) .map(entry -> entry.getRawFileEntry().getPath())
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
var selection = new StringSelection(s); ClipboardHelper.copyText(s);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
} }
}, },
new LeafAction() { new LeafAction() {
@ -124,9 +118,7 @@ public class CopyPathAction implements BrowserAction, BranchAction {
var s = entries.stream() var s = entries.stream()
.map(entry -> "\"" + entry.getRawFileEntry().getPath() + "\"") .map(entry -> "\"" + entry.getRawFileEntry().getPath() + "\"")
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
var selection = new StringSelection(s); ClipboardHelper.copyText(s);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
} }
}, },
new LeafAction() { new LeafAction() {
@ -156,9 +148,7 @@ public class CopyPathAction implements BrowserAction, BranchAction {
.map(entry -> FileNames.getFileName( .map(entry -> FileNames.getFileName(
entry.getRawFileEntry().getPath())) entry.getRawFileEntry().getPath()))
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
var selection = new StringSelection(s); ClipboardHelper.copyText(s);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
} }
}, },
new LeafAction() { new LeafAction() {
@ -200,9 +190,7 @@ public class CopyPathAction implements BrowserAction, BranchAction {
.map(entry -> FileNames.getFileName( .map(entry -> FileNames.getFileName(
entry.getRawFileEntry().getPath())) entry.getRawFileEntry().getPath()))
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
var selection = new StringSelection(s); ClipboardHelper.copyText(s);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
} }
}, },
new LeafAction() { new LeafAction() {
@ -235,9 +223,7 @@ public class CopyPathAction implements BrowserAction, BranchAction {
+ FileNames.getFileName( + FileNames.getFileName(
entry.getRawFileEntry().getPath()) + "\"") entry.getRawFileEntry().getPath()) + "\"")
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
var selection = new StringSelection(s); ClipboardHelper.copyText(s);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
} }
}); });
} }