Rework [stage]

This commit is contained in:
crschnick
2026-01-31 23:06:04 +00:00
parent bcd715e35a
commit e7280e2ef5
9 changed files with 185 additions and 15 deletions

View File

@@ -20,13 +20,13 @@ public interface ExternalSpiceClient extends PrefsValue {
return switch (OsType.ofLocal()) {
case OsType.Linux ignored -> {
yield new VirtViewerSpiceClient.Linux();
yield new RemoteViewerSpiceClient.Linux();
}
case OsType.MacOs ignored -> {
yield new VirtViewerSpiceClient.MacOs();
yield new RemoteViewerSpiceClient.MacOs();
}
case OsType.Windows ignored -> {
yield new VirtViewerSpiceClient.Windows();
yield new RemoteViewerSpiceClient.Windows();
}
};
}
@@ -44,13 +44,13 @@ public interface ExternalSpiceClient extends PrefsValue {
var l = new ArrayList<Class<?>>();
switch (OsType.ofLocal()) {
case OsType.Linux ignored -> {
l.add(VirtViewerSpiceClient.Linux.class);
l.add(RemoteViewerSpiceClient.Linux.class);
}
case OsType.MacOs ignored -> {
l.add(VirtViewerSpiceClient.MacOs.class);
l.add(RemoteViewerSpiceClient.MacOs.class);
}
case OsType.Windows ignored -> {
l.add(VirtViewerSpiceClient.Windows.class);
l.add(RemoteViewerSpiceClient.Windows.class);
}
}
l.add(CustomSpiceClient.class);

View File

@@ -14,7 +14,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
public abstract class VirtViewerSpiceClient implements ExternalSpiceClient {
public abstract class RemoteViewerSpiceClient implements ExternalSpiceClient {
protected CommandBuilder createBuilder(SpiceLaunchConfig configuration) {
var builder = CommandBuilder.of().addFile(configuration.getFile());
@@ -28,8 +28,8 @@ public abstract class VirtViewerSpiceClient implements ExternalSpiceClient {
@Builder
@Jacksonized
@JsonTypeName("virtViewer")
public static class Windows extends VirtViewerSpiceClient implements ExternalApplicationType.WindowsType {
@JsonTypeName("remoteViewer")
public static class Windows extends RemoteViewerSpiceClient implements ExternalApplicationType.WindowsType {
@Override
public boolean detach() {
@@ -68,8 +68,8 @@ public abstract class VirtViewerSpiceClient implements ExternalSpiceClient {
@Builder
@Jacksonized
@JsonTypeName("virtViewer")
public static class Linux extends VirtViewerSpiceClient implements ExternalApplicationType.LinuxApplication {
@JsonTypeName("remoteViewer")
public static class Linux extends RemoteViewerSpiceClient implements ExternalApplicationType.LinuxApplication {
@Override
public void launch(SpiceLaunchConfig configuration) throws Exception {
@@ -95,8 +95,8 @@ public abstract class VirtViewerSpiceClient implements ExternalSpiceClient {
@Builder
@Jacksonized
@JsonTypeName("virtViewer")
public static class MacOs extends VirtViewerSpiceClient implements ExternalApplicationType.PathApplication {
@JsonTypeName("remoteViewer")
public static class MacOs extends RemoteViewerSpiceClient implements ExternalApplicationType.PathApplication {
@Override
public void launch(SpiceLaunchConfig configuration) throws Exception {

View File

@@ -208,6 +208,7 @@ public class TerminalDockHubManager {
public void refreshDockStatus() {
dockModel.clearDeadTerminals();
dockModel.updateCustomBounds();
var running = dockModel.isRunning();
if (!running) {

View File

@@ -44,6 +44,10 @@ public class TerminalDockView {
return terminalInstances.stream().noneMatch(terminal -> terminal.isActive());
}
public synchronized void updateCustomBounds() {
terminalInstances.forEach(terminal -> terminal.updateBoundsState());
}
public synchronized void trackTerminal(ControllableTerminalSession terminal, boolean dock) {
if (!terminalInstances.add(terminal)) {
return;
@@ -64,6 +68,11 @@ public class TerminalDockView {
terminal.updatePosition(windowBoundsFunction.apply(viewBounds));
},
Duration.ofMillis(100));
GlobalTimer.delay(
() -> {
terminal.updatePosition(windowBoundsFunction.apply(viewBounds));
},
Duration.ofMillis(1000));
}
}
}

View File

@@ -35,17 +35,20 @@ public interface ExternalVncClient {
case OsType.Linux ignored -> {
l.add(RemminaVncClient.class);
l.add(TigerVncClient.Linux.class);
l.add(RemoteViewerVncClient.Linux.class);
l.add(RealVncClient.Linux.class);
}
case OsType.MacOs ignored -> {
l.add(ScreenSharingVncClient.class);
l.add(TigerVncClient.MacOs.class);
l.add(RemoteViewerVncClient.MacOs.class);
l.add(RealVncClient.MacOs.class);
}
case OsType.Windows ignored -> {
l.add(TigerVncClient.Windows.class);
l.add(RealVncClient.Windows.class);
l.add(TightVncClient.class);
l.add(RemoteViewerVncClient.Windows.class);
l.add(RealVncClient.Windows.class);
}
}
l.add(CustomVncClient.class);

View File

@@ -0,0 +1,153 @@
package io.xpipe.app.vnc;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.app.core.AppLocalTemp;
import io.xpipe.app.core.AppSystemInfo;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.prefs.ExternalApplicationType;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.app.process.OsFileSystem;
import io.xpipe.app.spice.ExternalSpiceClient;
import io.xpipe.app.spice.SpiceLaunchConfig;
import io.xpipe.app.util.RdpConfig;
import lombok.Builder;
import lombok.extern.jackson.Jacksonized;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
public abstract class RemoteViewerVncClient implements ExternalVncClient {
protected CommandBuilder createBuilder(VncLaunchConfig configuration) throws Exception {
var vv = """
[virt-viewer]
type=vnc
host=%s
port=%s
title=%s
""".formatted(configuration.getHost(), configuration.getPort(), configuration.getTitle());
var user = configuration.retrieveUsername();
if (user.isPresent()) {
vv += "username=" + user.get() + "\n";
}
var pass = configuration.retrievePassword();
if (pass.isPresent()) {
vv += "password=" + pass.get().getSecretValue() + "\n";
}
var file = writeVncConfigFile(configuration.getTitle(), vv);
var builder = CommandBuilder.of().addFile(file);
return builder;
}
private Path writeVncConfigFile(String title, String content) throws Exception {
var name = OsFileSystem.ofLocal().makeFileSystemCompatible(title);
var file = AppLocalTemp.getLocalTempDataDirectory("vnc").resolve(name + ".vv");
Files.createDirectories(file.getParent());
Files.writeString(file, content);
return file;
}
@Override
public String getWebsite() {
return "https://virt-manager.org";
}
@Override
public boolean supportsPasswords() {
return true;
}
@Builder
@Jacksonized
@JsonTypeName("remoteViewer")
public static class Windows extends RemoteViewerVncClient implements ExternalApplicationType.WindowsType {
@Override
public boolean detach() {
return false;
}
@Override
public String getExecutable() {
return "remote-viewer.exe";
}
@Override
public Optional<Path> determineInstallation() {
try (var stream = Files.list(AppSystemInfo.ofWindows().getProgramFiles())) {
var l = stream.toList();
var found = l.stream()
.filter(path -> path.toString().contains("VirtViewer"))
.findFirst();
if (found.isEmpty()) {
return Optional.empty();
}
return Optional.ofNullable(found.get().resolve("bin", "remote-viewer.exe"));
} catch (IOException e) {
ErrorEventFactory.fromThrowable(e).handle();
return Optional.empty();
}
}
@Override
public void launch(VncLaunchConfig configuration) throws Exception {
var builder = createBuilder(configuration);
launch(builder);
}
}
@Builder
@Jacksonized
@JsonTypeName("remoteViewer")
public static class Linux extends RemoteViewerVncClient implements ExternalApplicationType.LinuxApplication {
@Override
public void launch(VncLaunchConfig configuration) throws Exception {
var builder = createBuilder(configuration);
launch(builder);
}
@Override
public String getExecutable() {
return "remote-viewer";
}
@Override
public boolean detach() {
return true;
}
@Override
public String getFlatpakId() {
return "org.virt_manager.virt-viewer";
}
}
@Builder
@Jacksonized
@JsonTypeName("remoteViewer")
public static class MacOs extends RemoteViewerVncClient implements ExternalApplicationType.PathApplication {
@Override
public void launch(VncLaunchConfig configuration) throws Exception {
var builder = createBuilder(configuration);
launch(builder);
}
@Override
public String getExecutable() {
return "remote-viewer";
}
@Override
public boolean detach() {
return true;
}
}
}

View File

@@ -49,10 +49,13 @@ The scripting system has been completely reworked with the goal of becoming simp
- Add support to automatically wait in terminal until serial port is connected
- Creating a new category will now automatically focus the text field to rename it
- Add support for Yakuake terminal
- Add support for virt-viewer as a VNC client
## Fixes
- Fix various performance issues
- Fix docker refresh action taking very long when compose projects were available
- Fix automatic use gateway setting detection for VMs
- Fix various entries like SSH connections or SSH config entries sometimes disappearing on restart
- Fix SSH config write, e.g. for vscode SSH, not properly passing all configured options
- Fix SSH config identity detection not working for patterns in host entries

View File

@@ -157,3 +157,4 @@ ed25519Sk=ED25519 (FIDO2)
westonEditor=Weston Editor
passbolt=Passbolt
yakuake=Yakuake
remoteViewer=Virt viewer

View File

@@ -1 +1 @@
21.0-4
21.0-5