mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-07-08 11:30:42 +00:00
Rework
This commit is contained in:
@@ -12,6 +12,7 @@ import io.xpipe.app.hub.comp.StoreChoiceComp;
|
||||
import io.xpipe.app.hub.comp.StoreViewState;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.platform.*;
|
||||
import io.xpipe.app.process.LocalShell;
|
||||
import io.xpipe.app.process.ShellScript;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
@@ -22,6 +23,7 @@ import io.xpipe.app.util.OsType;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
@@ -333,9 +335,11 @@ public class TerminalCategory extends AppPrefsCategory {
|
||||
var choice = choiceBuilder.build().buildComp();
|
||||
choice.maxWidth(600);
|
||||
|
||||
var testCounter = new SimpleIntegerProperty();
|
||||
var testDisabled = new SimpleBooleanProperty();
|
||||
var test = new ButtonComp(AppI18n.observable("test"), new FontIcon("mdi2p-play"), () -> {
|
||||
testDisabled.set(true);
|
||||
testCounter.set(testCounter.getValue() + 1);
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
try {
|
||||
var term = AppPrefs.get().terminalType().getValue();
|
||||
@@ -382,6 +386,9 @@ public class TerminalCategory extends AppPrefsCategory {
|
||||
.documentationLink(DocumentationLink.TERMINAL_MULTIPLEXER)
|
||||
.addComp(choice);
|
||||
if (OsType.ofLocal() == OsType.WINDOWS) {
|
||||
options.disable(Bindings.createBooleanBinding(() -> {
|
||||
return prefs.terminalProxy() == null && !TerminalMultiplexerManager.isAvailableOnWindows();
|
||||
}, prefs.terminalProxy(), testCounter));
|
||||
options.disable(BindingsHelper.map(prefs.terminalProxy(), uuid -> uuid == null));
|
||||
}
|
||||
options.addComp(test).hide(prefs.terminalMultiplexer.isNull());
|
||||
|
||||
@@ -1,19 +1,38 @@
|
||||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.prefs.ExternalApplicationHelper;
|
||||
import io.xpipe.app.process.*;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.util.OsType;
|
||||
import io.xpipe.app.webtop.WebtopApp;
|
||||
import lombok.Builder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
@Builder
|
||||
@Jacksonized
|
||||
@JsonTypeName("screen")
|
||||
public class ScreenTerminalMultiplexer implements TerminalMultiplexer {
|
||||
|
||||
@Override
|
||||
public boolean requiresUnixEnvironment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() throws Exception {
|
||||
if (OsType.ofLocal() == OsType.WINDOWS) {
|
||||
var p = TerminalProxyManager.getProxy();
|
||||
return p.isPresent() && p.get().view().findProgram("screen").isPresent();
|
||||
} else {
|
||||
return LocalShell.getShell().view().findProgram("screen").isPresent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebtopApp getRequiredWebtopApp() {
|
||||
return null;
|
||||
|
||||
@@ -239,6 +239,10 @@ public class TerminalLauncher {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OsType.ofLocal() == OsType.WINDOWS && multiplexer.get().requiresUnixEnvironment() && TerminalProxyManager.getProxy().isEmpty()) {
|
||||
throw ErrorEventFactory.expected(new IllegalStateException("Terminal multiplexer is only supported with a WSL terminal environment on Windows"));
|
||||
}
|
||||
|
||||
var control = TerminalProxyManager.getProxy().orElse(LocalShell.getShell());
|
||||
|
||||
// Throw if not supported
|
||||
|
||||
@@ -49,6 +49,10 @@ public interface TerminalMultiplexer {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean requiresUnixEnvironment();
|
||||
|
||||
boolean isSupported() throws Exception;
|
||||
|
||||
WebtopApp getRequiredWebtopApp();
|
||||
|
||||
boolean supportsSplitView();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.process.LocalShell;
|
||||
import io.xpipe.app.update.AppDistributionType;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.app.util.OsType;
|
||||
|
||||
@@ -11,6 +14,7 @@ public class TerminalMultiplexerManager {
|
||||
private static final Map<UUID, TerminalMultiplexer> connectionHubRequests = new HashMap<>();
|
||||
private static UUID pendingMultiplexerLaunch;
|
||||
private static UUID runningMultiplexerContainer;
|
||||
private static Boolean availableOnWindows;
|
||||
|
||||
public static void registerMultiplexerContainerLaunch(UUID uuid) {
|
||||
pendingMultiplexerLaunch = uuid;
|
||||
@@ -42,6 +46,19 @@ public class TerminalMultiplexerManager {
|
||||
TerminalView.get().addListener(listener);
|
||||
}
|
||||
|
||||
public static boolean isAvailableOnWindows() {
|
||||
if (availableOnWindows != null) {
|
||||
return availableOnWindows;
|
||||
}
|
||||
|
||||
try {
|
||||
return (availableOnWindows = LocalShell.getShell().view().findProgram("zellij").isPresent());
|
||||
} catch (Exception e) {
|
||||
ErrorEventFactory.fromThrowable(e).handle();
|
||||
return (availableOnWindows = false);
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<TerminalMultiplexer> getEffectiveMultiplexer() {
|
||||
var multiplexer = AppPrefs.get().terminalMultiplexer().getValue();
|
||||
if (multiplexer == null) {
|
||||
@@ -53,9 +70,20 @@ public class TerminalMultiplexerManager {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// Don't apply multiplexer on webtop if it is not installed yet
|
||||
if (AppDistributionType.get() == AppDistributionType.WEBTOP) {
|
||||
try {
|
||||
if (!multiplexer.isSupported()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorEventFactory.fromThrowable(e).handle();
|
||||
}
|
||||
}
|
||||
|
||||
if (OsType.ofLocal() == OsType.WINDOWS) {
|
||||
var hasProxy = AppPrefs.get().terminalProxy().getValue() != null;
|
||||
if (!hasProxy) {
|
||||
if (!hasProxy && multiplexer.requiresUnixEnvironment()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.xpipe.app.process.ShellControl;
|
||||
import io.xpipe.app.process.ShellScript;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.util.OsType;
|
||||
import io.xpipe.app.webtop.WebtopApp;
|
||||
import lombok.Builder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
@@ -19,6 +20,20 @@ import java.util.List;
|
||||
@JsonTypeName("tmux")
|
||||
public class TmuxTerminalMultiplexer implements TerminalMultiplexer {
|
||||
|
||||
@Override
|
||||
public boolean requiresUnixEnvironment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() throws Exception {
|
||||
if (OsType.ofLocal() == OsType.WINDOWS) {
|
||||
var p = TerminalProxyManager.getProxy();
|
||||
return p.isPresent() && p.get().view().findProgram("tmux").isPresent();
|
||||
} else {
|
||||
return LocalShell.getShell().view().findProgram("tmux").isPresent();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public WebtopApp getRequiredWebtopApp() {
|
||||
return WebtopApp.TMUX;
|
||||
|
||||
@@ -20,6 +20,22 @@ import java.util.List;
|
||||
@JsonTypeName("zellij")
|
||||
public class ZellijTerminalMultiplexer implements TerminalMultiplexer {
|
||||
|
||||
@Override
|
||||
public boolean requiresUnixEnvironment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() throws Exception {
|
||||
if (OsType.ofLocal() == OsType.WINDOWS) {
|
||||
var p = TerminalProxyManager.getProxy();
|
||||
if (p.isPresent() && p.get().view().findProgram("zellij").isPresent()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return LocalShell.getShell().view().findProgram("zellij").isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebtopApp getRequiredWebtopApp() {
|
||||
return WebtopApp.ZELLIJ;
|
||||
|
||||
Generated
+5
@@ -2236,3 +2236,8 @@ configureWebtop=Configure webtop
|
||||
#context: verb
|
||||
transfer=Transfer
|
||||
rebuild=Rebuild
|
||||
webtop.displayName=XPipe Webtop
|
||||
webtop.displayDescription=Access and manage a webtop environment remotely
|
||||
webtopHost=Host
|
||||
webtopHostDescription=The container the webtop environment is running on
|
||||
|
||||
|
||||
Reference in New Issue
Block a user