mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-09-02 18:51:01 +12:00
Polish various features
This commit is contained in:
parent
c0abdf968a
commit
6263b791cf
12 changed files with 181 additions and 161 deletions
|
@ -25,19 +25,15 @@ public class StoreEntrySection implements StorageFilter.Filterable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObservableList<StoreEntrySection> createTopLevels() {
|
public static ObservableList<StoreEntrySection> createTopLevels() {
|
||||||
var topLevel = BindingsHelper.mappedContentBinding(
|
var filtered = BindingsHelper.filteredContentBinding(
|
||||||
StoreViewState.get()
|
StoreViewState.get().getAllEntries(),
|
||||||
.getAllEntries()
|
storeEntryWrapper -> !storeEntryWrapper.getEntry().getState().isUsable()
|
||||||
.filtered(storeEntryWrapper ->
|
|| storeEntryWrapper
|
||||||
!storeEntryWrapper.getEntry().getState().isUsable()
|
.getEntry()
|
||||||
|| storeEntryWrapper
|
.getProvider()
|
||||||
.getEntry()
|
.getParent(storeEntryWrapper.getEntry().getStore())
|
||||||
.getProvider()
|
== null);
|
||||||
.getParent(storeEntryWrapper
|
var topLevel = BindingsHelper.mappedContentBinding(filtered, storeEntryWrapper -> create(storeEntryWrapper));
|
||||||
.getEntry()
|
|
||||||
.getStore())
|
|
||||||
== null),
|
|
||||||
storeEntryWrapper -> create(storeEntryWrapper));
|
|
||||||
var ordered = BindingsHelper.orderedContentBinding(
|
var ordered = BindingsHelper.orderedContentBinding(
|
||||||
topLevel,
|
topLevel,
|
||||||
Comparator.<StoreEntrySection, Instant>comparing(storeEntrySection ->
|
Comparator.<StoreEntrySection, Instant>comparing(storeEntrySection ->
|
||||||
|
@ -51,16 +47,15 @@ public class StoreEntrySection implements StorageFilter.Filterable {
|
||||||
return new StoreEntrySection(e, FXCollections.observableArrayList());
|
return new StoreEntrySection(e, FXCollections.observableArrayList());
|
||||||
}
|
}
|
||||||
|
|
||||||
var children = BindingsHelper.mappedContentBinding(
|
var filtered = BindingsHelper.filteredContentBinding(
|
||||||
StoreViewState.get()
|
StoreViewState.get().getAllEntries(),
|
||||||
.getAllEntries()
|
other -> other.getEntry().getState().isUsable()
|
||||||
.filtered(other -> other.getEntry().getState().isUsable()
|
&& e.getEntry()
|
||||||
&& e.getEntry()
|
.getStore()
|
||||||
.getStore()
|
.equals(other.getEntry()
|
||||||
.equals(other.getEntry()
|
.getProvider()
|
||||||
.getProvider()
|
.getParent(other.getEntry().getStore())));
|
||||||
.getParent(other.getEntry().getStore()))),
|
var children = BindingsHelper.mappedContentBinding(filtered, entry1 -> create(entry1));
|
||||||
entry1 -> create(entry1));
|
|
||||||
var ordered = BindingsHelper.orderedContentBinding(
|
var ordered = BindingsHelper.orderedContentBinding(
|
||||||
children,
|
children,
|
||||||
Comparator.<StoreEntrySection, Instant>comparing(storeEntrySection ->
|
Comparator.<StoreEntrySection, Instant>comparing(storeEntrySection ->
|
||||||
|
@ -94,7 +89,9 @@ public class StoreEntrySection implements StorageFilter.Filterable {
|
||||||
storeEntrySection.entry.lastAccessProperty().getValue()));
|
storeEntrySection.entry.lastAccessProperty().getValue()));
|
||||||
var shown = BindingsHelper.filteredContentBinding(
|
var shown = BindingsHelper.filteredContentBinding(
|
||||||
all,
|
all,
|
||||||
StoreViewState.get().getFilterString().map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
|
StoreViewState.get()
|
||||||
|
.getFilterString()
|
||||||
|
.map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
|
||||||
var content = new ListBoxViewComp<>(shown, all, (StoreEntrySection e) -> {
|
var content = new ListBoxViewComp<>(shown, all, (StoreEntrySection e) -> {
|
||||||
return e.comp(false).apply(GrowAugment.create(true, false));
|
return e.comp(false).apply(GrowAugment.create(true, false));
|
||||||
})
|
})
|
||||||
|
|
|
@ -80,12 +80,12 @@ public class App extends Application {
|
||||||
appWindow.show();
|
appWindow.show();
|
||||||
|
|
||||||
// For demo purposes
|
// For demo purposes
|
||||||
if (true) {
|
// if (true) {
|
||||||
stage.setX(310);
|
// stage.setX(310);
|
||||||
stage.setY(178);
|
// stage.setY(178);
|
||||||
stage.setWidth(1300);
|
// stage.setWidth(1300);
|
||||||
stage.setHeight(730);
|
// stage.setHeight(730);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void focus() {
|
public void focus() {
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class AppGreetings {
|
||||||
label.setGraphic(cb);
|
label.setGraphic(cb);
|
||||||
AppFont.medium(label);
|
AppFont.medium(label);
|
||||||
label.setPadding(new Insets(40, 0, 10, 0));
|
label.setPadding(new Insets(40, 0, 10, 0));
|
||||||
|
label.setOnMouseClicked(event -> accepted.set(!accepted.get()));
|
||||||
return label;
|
return label;
|
||||||
})
|
})
|
||||||
.createRegion();
|
.createRegion();
|
||||||
|
|
|
@ -54,28 +54,23 @@ public abstract class ExternalApplicationType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LinuxPathApplication extends ExternalApplicationType {
|
public static abstract class PathApplication extends ExternalApplicationType {
|
||||||
|
|
||||||
protected final String command;
|
protected final String executable;
|
||||||
|
|
||||||
public LinuxPathApplication(String id, String command) {
|
public PathApplication(String id, String executable) {
|
||||||
super(id);
|
super(id);
|
||||||
this.command = command;
|
this.executable = executable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAvailable() {
|
public boolean isAvailable() {
|
||||||
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
||||||
return pc.executeBooleanSimpleCommand(pc.getShellType().getWhichCommand(command));
|
return pc.executeBooleanSimpleCommand(pc.getShellType().getWhichCommand(executable));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ErrorEvent.fromThrowable(e).omit().handle();
|
ErrorEvent.fromThrowable(e).omit().handle();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelectable() {
|
|
||||||
return OsType.getLocal().equals(OsType.LINUX);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class WindowsFullPathType extends ExternalApplicationType {
|
public abstract static class WindowsFullPathType extends ExternalApplicationType {
|
||||||
|
|
|
@ -109,7 +109,7 @@ public interface ExternalEditorType extends PrefsChoiceValue {
|
||||||
public void launch(Path file) throws Exception;
|
public void launch(Path file) throws Exception;
|
||||||
|
|
||||||
|
|
||||||
public static class LinuxPathType extends ExternalApplicationType.LinuxPathApplication implements ExternalEditorType {
|
public static class LinuxPathType extends ExternalApplicationType.PathApplication implements ExternalEditorType {
|
||||||
|
|
||||||
public LinuxPathType(String id, String command) {
|
public LinuxPathType(String id, String command) {
|
||||||
super(id, command);
|
super(id, command);
|
||||||
|
@ -117,9 +117,14 @@ public interface ExternalEditorType extends PrefsChoiceValue {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch(Path file) throws IOException {
|
public void launch(Path file) throws IOException {
|
||||||
var list = ShellTypes.getPlatformDefault().executeCommandListWithShell(command + " \"" + file + "\"");
|
var list = ShellTypes.getPlatformDefault().executeCommandListWithShell(executable + " \"" + file + "\"");
|
||||||
new ProcessBuilder(list).start();
|
new ProcessBuilder(list).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelectable() {
|
||||||
|
return OsType.getLocal().equals(OsType.LINUX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class WindowsFullPathType extends ExternalApplicationType.WindowsFullPathType implements ExternalEditorType {
|
public abstract static class WindowsFullPathType extends ExternalApplicationType.WindowsFullPathType implements ExternalEditorType {
|
||||||
|
@ -174,7 +179,7 @@ public interface ExternalEditorType extends PrefsChoiceValue {
|
||||||
var env = System.getenv("VISUAL");
|
var env = System.getenv("VISUAL");
|
||||||
if (env != null) {
|
if (env != null) {
|
||||||
var found = LINUX_EDITORS.stream()
|
var found = LINUX_EDITORS.stream()
|
||||||
.filter(externalEditorType -> externalEditorType.command.equalsIgnoreCase(env))
|
.filter(externalEditorType -> externalEditorType.executable.equalsIgnoreCase(env))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
if (found == null) {
|
if (found == null) {
|
||||||
|
|
|
@ -69,6 +69,14 @@ recentlyUsed=Recently used
|
||||||
programmingLanguages=Programming languages
|
programmingLanguages=Programming languages
|
||||||
applications=Applications
|
applications=Applications
|
||||||
addMore=Add more
|
addMore=Add more
|
||||||
|
vscode=Visual Studio Code
|
||||||
|
kate=Kate
|
||||||
|
gedit=GEdit
|
||||||
|
leafpad=Leafpad
|
||||||
|
mousepad=Mousepad
|
||||||
|
pluma=Pluma
|
||||||
|
textEdit=Text Edit
|
||||||
|
sublime=Sublime Text
|
||||||
newTable=new_table
|
newTable=new_table
|
||||||
unknown=Unknown
|
unknown=Unknown
|
||||||
editRaw=Edit Raw
|
editRaw=Edit Raw
|
||||||
|
|
|
@ -46,15 +46,10 @@ specific information we send, please visit https://xpipe.io/privacy_policy. You
|
||||||
1. **Automatic Software Updates.** The Software communicates with its server (and sends information described at the URL
|
1. **Automatic Software Updates.** The Software communicates with its server (and sends information described at the URL
|
||||||
above) to determine whether there are any patches, bug fixes, updates, upgrades or other modifications to improve the
|
above) to determine whether there are any patches, bug fixes, updates, upgrades or other modifications to improve the
|
||||||
Software. You agree that the Software may automatically install any such improvements to the Software on your
|
Software. You agree that the Software may automatically install any such improvements to the Software on your
|
||||||
computer without providing any further notice or receiving any additional consent. This feature may not be disabled.
|
computer without providing any further notice or receiving any additional consent. This feature may be disabled.
|
||||||
If you do not want to receive automatic updates, you must uninstall the Software.
|
|
||||||
2. **Error Reports.** In order to help us improve the Software, when the Software encounters certain errors, it will
|
2. **Error Reports.** In order to help us improve the Software, when the Software encounters certain errors, it will
|
||||||
automatically send some information to its server about the error (as described at the URL above). This feature may
|
automatically send some information to its server about the error (as described at the URL above). This feature may
|
||||||
not be disabled. If you do not want to send error reports to its server, you must uninstall the Software.
|
be disabled.
|
||||||
3. **Anonymized Usage Data.** X-Pipe collects anonymized data about your usage of the Software to help us make it more
|
|
||||||
awesome. Approximately once a day the Software sends such data (as described in more detail at the URL above) to its
|
|
||||||
server. If you do not want to send anonymized usage data to the server, you may opt out by changing your settings in
|
|
||||||
the Preferences view.
|
|
||||||
|
|
||||||
### Open-Source Notices
|
### Open-Source Notices
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
## Welcome to X-Pipe!
|
## Welcome to X-Pipe!
|
||||||
|
|
||||||
X-Pipe (short for eXtended Pipe) is a tool that enables a fast and an efficient data transfer/exchange between
|
Thank you for trying out the X-Pipe Alpha.
|
||||||
all types of producers and consumers of data, e.g. different file types,
|
You can overview the development status, report issues, and more at the following places:
|
||||||
applications, programming languages, databases, technologies, and more.
|
|
||||||
|
|
||||||
It is currently in early development and this build is an alpha version.
|
#### [GitHub Repository](https://github.com/xpipe-io/xpipe/)
|
||||||
A lot of features are incomplete or bugged.
|
|
||||||
You can overview and contribute to the development here:
|
|
||||||
|
|
||||||
#### [Issue Tracker](https://github.com/xpipe-io/xpipe/issues)
|
|
||||||
|
|
||||||
#### [Discord Server](https://discord.gg/8y89vS8cRb)
|
#### [Discord Server](https://discord.gg/8y89vS8cRb)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.ext.proc;
|
package io.xpipe.ext.proc;
|
||||||
|
|
||||||
|
import io.xpipe.app.prefs.ExternalApplicationType;
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.process.OsType;
|
||||||
import io.xpipe.core.process.ShellProcessControl;
|
import io.xpipe.core.process.ShellProcessControl;
|
||||||
import io.xpipe.core.store.ShellStore;
|
import io.xpipe.core.store.ShellStore;
|
||||||
|
@ -7,18 +8,12 @@ import io.xpipe.extension.event.ErrorEvent;
|
||||||
import io.xpipe.extension.prefs.PrefsChoiceValue;
|
import io.xpipe.extension.prefs.PrefsChoiceValue;
|
||||||
import io.xpipe.extension.prefs.PrefsProvider;
|
import io.xpipe.extension.prefs.PrefsProvider;
|
||||||
import io.xpipe.extension.util.ApplicationHelper;
|
import io.xpipe.extension.util.ApplicationHelper;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
public interface ExternalTerminalType extends PrefsChoiceValue {
|
||||||
@AllArgsConstructor
|
|
||||||
public abstract class TerminalType implements PrefsChoiceValue {
|
|
||||||
|
|
||||||
public static final TerminalType CMD = new SimpleType("proc.cmd", "cmd", "cmd.exe") {
|
public static final ExternalTerminalType CMD = new SimpleType("proc.cmd", "cmd", "cmd.exe") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String toCommand(String name, String command) {
|
protected String toCommand(String name, String command) {
|
||||||
|
@ -31,7 +26,7 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TerminalType POWERSHELL = new SimpleType("proc.powershell", "powershell", "PowerShell") {
|
public static final ExternalTerminalType POWERSHELL = new SimpleType("proc.powershell", "powershell", "PowerShell") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String toCommand(String name, String command) {
|
protected String toCommand(String name, String command) {
|
||||||
|
@ -44,7 +39,7 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TerminalType WINDOWS_TERMINAL =
|
public static final ExternalTerminalType WINDOWS_TERMINAL =
|
||||||
new SimpleType("proc.windowsTerminal", "wt.exe", "Windows Terminal") {
|
new SimpleType("proc.windowsTerminal", "wt.exe", "Windows Terminal") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,7 +53,7 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TerminalType GNOME_TERMINAL =
|
public static final ExternalTerminalType GNOME_TERMINAL =
|
||||||
new SimpleType("proc.gnomeTerminal", "gnome-terminal", "Gnome Terminal") {
|
new SimpleType("proc.gnomeTerminal", "gnome-terminal", "Gnome Terminal") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,7 +67,7 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TerminalType KONSOLE = new SimpleType("proc.konsole", "konsole", "Konsole") {
|
public static final ExternalTerminalType KONSOLE = new SimpleType("proc.konsole", "konsole", "Konsole") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String toCommand(String name, String command) {
|
protected String toCommand(String name, String command) {
|
||||||
|
@ -85,7 +80,7 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TerminalType XFCE = new SimpleType("proc.xfce", "xfce4-terminal", "Xfce") {
|
public static final ExternalTerminalType XFCE = new SimpleType("proc.xfce", "xfce4-terminal", "Xfce") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String toCommand(String name, String command) {
|
protected String toCommand(String name, String command) {
|
||||||
|
@ -98,38 +93,15 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final TerminalType MACOS_TERMINAL = new MacType("proc.macosTerminal", "Terminal");
|
public static final ExternalTerminalType MACOS_TERMINAL = new MacOsType();
|
||||||
|
|
||||||
public static final TerminalType ITERM2 = new ITerm2Type();
|
public static final ExternalTerminalType ITERM2 = new ITerm2Type();
|
||||||
|
|
||||||
public static final TerminalType WARP = new WarpType();
|
public static final ExternalTerminalType WARP = new WarpType();
|
||||||
|
|
||||||
public static final TerminalType CUSTOM = new TerminalType("app.custom") {
|
public static final ExternalTerminalType CUSTOM = new CustomType();
|
||||||
|
|
||||||
@Override
|
public static final List<ExternalTerminalType> ALL = List.of(
|
||||||
public void launch(String name, String command) throws Exception {
|
|
||||||
var custom =
|
|
||||||
PrefsProvider.get(ProcPrefs.class).customTerminalCommand().getValue();
|
|
||||||
if (custom == null || custom.trim().isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var format = custom.contains("$cmd") ? custom : custom + " $cmd";
|
|
||||||
ShellStore.local().create().executeSimpleCommand(format.replace("$cmd", command));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelectable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final List<TerminalType> ALL = List.of(
|
|
||||||
WINDOWS_TERMINAL,
|
WINDOWS_TERMINAL,
|
||||||
POWERSHELL,
|
POWERSHELL,
|
||||||
CMD,
|
CMD,
|
||||||
|
@ -144,42 +116,60 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
.filter(terminalType -> terminalType.isSelectable())
|
.filter(terminalType -> terminalType.isSelectable())
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
public static TerminalType getDefault() {
|
public static ExternalTerminalType getDefault() {
|
||||||
return ALL.stream()
|
return ALL.stream()
|
||||||
.filter(terminalType -> terminalType.isAvailable())
|
.filter(terminalType -> terminalType.isAvailable())
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
public abstract void launch(String name, String command) throws Exception;
|
public abstract void launch(String name, String command) throws Exception;
|
||||||
|
|
||||||
public abstract boolean isSelectable();
|
static class MacOsType extends ExternalApplicationType.MacApplication implements ExternalTerminalType {
|
||||||
|
|
||||||
public abstract boolean isAvailable();
|
public MacOsType() {
|
||||||
|
super("proc.macosTerminal", "Terminal");
|
||||||
|
}
|
||||||
|
|
||||||
static class MacType extends TerminalType {
|
@Override
|
||||||
|
public void launch(String name, String command) throws Exception {
|
||||||
|
var custom =
|
||||||
|
PrefsProvider.get(ProcPrefs.class).customTerminalCommand().getValue();
|
||||||
|
if (custom == null || custom.trim().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
private final String terminalName;
|
var format = custom.contains("$cmd") ? custom : custom + " $cmd";
|
||||||
|
try (var pc = ShellStore.local().create().start()) {
|
||||||
|
var toExecute = format.replace("$cmd", command);
|
||||||
|
if (pc.getOsType().equals(OsType.WINDOWS)) {
|
||||||
|
toExecute = "start \"" + name + "\" " + toExecute;
|
||||||
|
} else {
|
||||||
|
toExecute = "nohup " + toExecute + " </dev/null &>/dev/null & disown";
|
||||||
|
}
|
||||||
|
pc.executeSimpleCommand(toExecute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MacType(String id, String terminalName) {
|
static class CustomType extends ExternalApplicationType implements ExternalTerminalType {
|
||||||
super(id);
|
|
||||||
this.terminalName = terminalName;
|
public CustomType() {
|
||||||
|
super("proc.custom");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch(String name, String command) throws Exception {
|
public void launch(String name, String command) throws Exception {
|
||||||
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
||||||
var suffix = command.equals(pc.getShellType().getNormalOpenCommand()) ? "\"\"" : "\"" + command + "\"";
|
var suffix = command.equals(pc.getShellType().getNormalOpenCommand()) ? "\"\"" : "\"" + command + "\"";
|
||||||
var cmd = "osascript -e 'tell app \"" + terminalName + "\" to do script " + suffix + "'";
|
var cmd = "osascript -e 'tell app \"" + "Terminal" + "\" to do script " + suffix + "'";
|
||||||
pc.executeSimpleCommand(cmd);
|
pc.executeSimpleCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSelectable() {
|
public boolean isSelectable() {
|
||||||
return OsType.getLocal().equals(OsType.MAC);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -188,10 +178,10 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ITerm2Type extends TerminalType {
|
static class ITerm2Type extends ExternalApplicationType.MacApplication implements ExternalTerminalType {
|
||||||
|
|
||||||
public ITerm2Type() {
|
public ITerm2Type() {
|
||||||
super("proc.iterm2");
|
super("proc.iterm2", "iTerm2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -200,7 +190,6 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
var cmd = String.format(
|
var cmd = String.format(
|
||||||
"""
|
"""
|
||||||
osascript - "$@" <<EOF
|
osascript - "$@" <<EOF
|
||||||
on run argv
|
|
||||||
tell application "iTerm"
|
tell application "iTerm"
|
||||||
activate
|
activate
|
||||||
set new_term to (create window with profile "Default" command "%s")
|
set new_term to (create window with profile "Default" command "%s")
|
||||||
|
@ -211,22 +200,12 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
pc.executeSimpleCommand(cmd);
|
pc.executeSimpleCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelectable() {
|
|
||||||
return OsType.getLocal().equals(OsType.MAC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable() {
|
|
||||||
return Files.exists(Path.of("/Applications/iTerm2.app"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class WarpType extends TerminalType {
|
static class WarpType extends ExternalApplicationType.MacApplication implements ExternalTerminalType {
|
||||||
|
|
||||||
public WarpType() {
|
public WarpType() {
|
||||||
super("proc.warp");
|
super("proc.warp", "Warp");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -234,41 +213,30 @@ public abstract class TerminalType implements PrefsChoiceValue {
|
||||||
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
try (ShellProcessControl pc = ShellStore.local().create().start()) {
|
||||||
var cmd = String.format(
|
var cmd = String.format(
|
||||||
"""
|
"""
|
||||||
osascript - "$@" <<EOF
|
osascript - "$@" <<EOF
|
||||||
tell application "Warp" to activate'
|
tell application "Warp" to activate
|
||||||
sudo osascript -e 'tell application "System Events" to tell process "Warp" to keystroke "t" using command down'
|
tell application "System Events" to tell process "Warp" to keystroke "t" using command down
|
||||||
sleep 1
|
delay 1
|
||||||
sudo osascript -e 'tell application "System Events"
|
tell application "System Events"
|
||||||
tell process "Warp"
|
tell process "Warp"
|
||||||
keystroke "%s"
|
keystroke "%s"
|
||||||
key code 36
|
key code 36
|
||||||
end tell
|
end tell
|
||||||
end tell
|
end tell
|
||||||
EOF""",
|
EOF
|
||||||
|
""",
|
||||||
command);
|
command);
|
||||||
pc.executeSimpleCommand(cmd);
|
pc.executeSimpleCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelectable() {
|
|
||||||
return OsType.getLocal().equals(OsType.MAC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable() {
|
|
||||||
return Files.exists(Path.of("/Applications/iTerm2.app"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class SimpleType extends TerminalType {
|
public abstract static class SimpleType extends ExternalApplicationType.PathApplication implements ExternalTerminalType {
|
||||||
|
|
||||||
private final String executable;
|
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
|
|
||||||
public SimpleType(String id, String executable, String displayName) {
|
public SimpleType(String id, String executable, String displayName) {
|
||||||
super(id);
|
super(id, executable);
|
||||||
this.executable = executable;
|
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ public class ProcPrefs extends PrefsProvider {
|
||||||
return enableCaching;
|
return enableCaching;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ObjectProperty<TerminalType> terminalType = new SimpleObjectProperty<>();
|
private final ObjectProperty<ExternalTerminalType> terminalType = new SimpleObjectProperty<>();
|
||||||
private final SimpleListProperty<TerminalType> terminalTypeList = new SimpleListProperty<>(
|
private final SimpleListProperty<ExternalTerminalType> terminalTypeList = new SimpleListProperty<>(
|
||||||
FXCollections.observableArrayList(PrefsChoiceValue.getSupported(TerminalType.class)));
|
FXCollections.observableArrayList(PrefsChoiceValue.getSupported(ExternalTerminalType.class)));
|
||||||
private final SingleSelectionField<TerminalType> terminalTypeControl = Field.ofSingleSelectionType(
|
private final SingleSelectionField<ExternalTerminalType> terminalTypeControl = Field.ofSingleSelectionType(
|
||||||
terminalTypeList, terminalType)
|
terminalTypeList, terminalType)
|
||||||
.render(() -> new TranslatableComboBoxControl<>());
|
.render(() -> new TranslatableComboBoxControl<>());
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ public class ProcPrefs extends PrefsProvider {
|
||||||
private final StringProperty customTerminalCommand = new SimpleStringProperty("");
|
private final StringProperty customTerminalCommand = new SimpleStringProperty("");
|
||||||
private final StringField customTerminalCommandControl = editable(
|
private final StringField customTerminalCommandControl = editable(
|
||||||
StringField.ofStringType(customTerminalCommand).render(() -> new SimpleTextControl()),
|
StringField.ofStringType(customTerminalCommand).render(() -> new SimpleTextControl()),
|
||||||
terminalType.isEqualTo(TerminalType.CUSTOM));
|
terminalType.isEqualTo(ExternalTerminalType.CUSTOM));
|
||||||
|
|
||||||
public ObservableValue<TerminalType> terminalType() {
|
public ObservableValue<ExternalTerminalType> terminalType() {
|
||||||
return terminalType;
|
return terminalType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,19 +53,19 @@ public class ProcPrefs extends PrefsProvider {
|
||||||
List.of("integrations"),
|
List.of("integrations"),
|
||||||
"proc.terminal",
|
"proc.terminal",
|
||||||
Setting.of("app.defaultProgram", terminalTypeControl, terminalType),
|
Setting.of("app.defaultProgram", terminalTypeControl, terminalType),
|
||||||
TerminalType.class);
|
ExternalTerminalType.class);
|
||||||
handler.addSetting(
|
handler.addSetting(
|
||||||
List.of("integrations"),
|
List.of("integrations"),
|
||||||
"proc.terminal",
|
"proc.terminal",
|
||||||
Setting.of("proc.customTerminalCommand", customTerminalCommandControl, customTerminalCommand)
|
Setting.of("proc.customTerminalCommand", customTerminalCommandControl, customTerminalCommand)
|
||||||
.applyVisibility(VisibilityProperty.of(terminalType.isEqualTo(TerminalType.CUSTOM))),
|
.applyVisibility(VisibilityProperty.of(terminalType.isEqualTo(ExternalTerminalType.CUSTOM))),
|
||||||
String.class);
|
String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
if (terminalType.get() == null) {
|
if (terminalType.get() == null) {
|
||||||
terminalType.set(TerminalType.getDefault());
|
terminalType.set(ExternalTerminalType.getDefault());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,3 +89,6 @@ key=Key
|
||||||
installConnector=Install Connector
|
installConnector=Install Connector
|
||||||
konsole=Konsole
|
konsole=Konsole
|
||||||
xfce=Xfce
|
xfce=Xfce
|
||||||
|
macosTerminal=Terminal
|
||||||
|
iterm2=iTerm2
|
||||||
|
warp=Warp
|
|
@ -1,10 +1,14 @@
|
||||||
package io.xpipe.extension.fxcomps.util;
|
package io.xpipe.extension.fxcomps.util;
|
||||||
|
|
||||||
|
import io.xpipe.extension.util.ThreadHelper;
|
||||||
import javafx.beans.binding.Binding;
|
import javafx.beans.binding.Binding;
|
||||||
|
import javafx.beans.binding.ListBinding;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -14,6 +18,37 @@ import java.util.function.Predicate;
|
||||||
|
|
||||||
public class BindingsHelper {
|
public class BindingsHelper {
|
||||||
|
|
||||||
|
private static final Set<ReferenceEntry> REFERENCES = Collections.newSetFromMap(new ConcurrentHashMap<ReferenceEntry, Boolean>());
|
||||||
|
|
||||||
|
@Value
|
||||||
|
private static class ReferenceEntry {
|
||||||
|
|
||||||
|
WeakReference<?> source;
|
||||||
|
Object target;
|
||||||
|
|
||||||
|
public boolean canGc() {
|
||||||
|
return source.get() == null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
ThreadHelper.create("referenceGC", true, () -> {
|
||||||
|
while (true) {
|
||||||
|
for (ReferenceEntry reference : REFERENCES) {
|
||||||
|
if (reference.canGc()) {
|
||||||
|
REFERENCES.remove(reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ThreadHelper.sleep(1000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void linkPersistently(Object source, Object target) {
|
||||||
|
REFERENCES.add(new ReferenceEntry(new WeakReference<>(source), target));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Proper cleanup. Maybe with a separate thread?
|
TODO: Proper cleanup. Maybe with a separate thread?
|
||||||
*/
|
*/
|
||||||
|
@ -30,6 +65,17 @@ public class BindingsHelper {
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T extends ListBinding<?>> T persist(T binding) {
|
||||||
|
var dependencies = new HashSet<javafx.beans.Observable>();
|
||||||
|
while (dependencies.addAll(binding.getDependencies().stream()
|
||||||
|
.map(o -> (javafx.beans.Observable) o)
|
||||||
|
.toList())) {
|
||||||
|
}
|
||||||
|
dependencies.add(binding);
|
||||||
|
BINDINGS.put(new WeakReference<>(binding), dependencies);
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> void bindContent(ObservableList<T> l1, ObservableList<? extends T> l2) {
|
public static <T> void bindContent(ObservableList<T> l1, ObservableList<? extends T> l2) {
|
||||||
setContent(l1, l2);
|
setContent(l1, l2);
|
||||||
l2.addListener((ListChangeListener<? super T>) c -> {
|
l2.addListener((ListChangeListener<? super T>) c -> {
|
||||||
|
@ -56,6 +102,7 @@ public class BindingsHelper {
|
||||||
l2.addListener((ListChangeListener<? super V>) c -> {
|
l2.addListener((ListChangeListener<? super V>) c -> {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
});
|
});
|
||||||
|
linkPersistently(l2, l1);
|
||||||
return l1;
|
return l1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +115,14 @@ public class BindingsHelper {
|
||||||
l2.addListener((ListChangeListener<? super V>) c -> {
|
l2.addListener((ListChangeListener<? super V>) c -> {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
});
|
});
|
||||||
|
linkPersistently(l2, l1);
|
||||||
return l1;
|
return l1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <V> ObservableList<V> filteredContentBinding(ObservableList<V> l2,Predicate<V> predicate) {
|
||||||
|
return filteredContentBinding(l2, new SimpleObjectProperty<>(predicate));
|
||||||
|
}
|
||||||
|
|
||||||
public static <V> ObservableList<V> filteredContentBinding(ObservableList<V> l2, ObservableValue<Predicate<V>> predicate) {
|
public static <V> ObservableList<V> filteredContentBinding(ObservableList<V> l2, ObservableValue<Predicate<V>> predicate) {
|
||||||
ObservableList<V> l1 = FXCollections.observableList(new ArrayList<>());
|
ObservableList<V> l1 = FXCollections.observableList(new ArrayList<>());
|
||||||
Runnable runnable = () -> {
|
Runnable runnable = () -> {
|
||||||
|
@ -83,6 +135,7 @@ public class BindingsHelper {
|
||||||
predicate.addListener((c,o,n) -> {
|
predicate.addListener((c,o,n) -> {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
});
|
});
|
||||||
|
linkPersistently(l2, l1);
|
||||||
return l1;
|
return l1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue