From b255d521f69f9535ecb0887f34d2d33c2a3d2634 Mon Sep 17 00:00:00 2001 From: crschnick Date: Mon, 14 Jul 2025 00:10:30 +0000 Subject: [PATCH] Various --- .../app/browser/file/BrowserFileListNameCell.java | 5 +++-- .../io/xpipe/app/comp/base/LeftSplitPaneComp.java | 5 ++++- .../java/io/xpipe/app/ext/DataStoreProviders.java | 12 ++++++++---- app/src/main/java/io/xpipe/app/ext/Session.java | 6 +++++- app/src/main/java/io/xpipe/app/ext/ShellSession.java | 10 +++++++--- app/src/main/java/io/xpipe/app/ext/ShellStore.java | 1 + .../io/xpipe/app/hub/action/BatchStoreAction.java | 2 +- .../io/xpipe/app/hub/action/MultiStoreAction.java | 2 +- .../main/java/io/xpipe/app/process/ShellControl.java | 11 +++++++++++ .../io/xpipe/app/process/WrapperShellControl.java | 10 ++++++++++ .../java/io/xpipe/app/storage/DataStoreEntry.java | 4 ++-- .../io/xpipe/app/resources/theme/cupertinoDark.css | 2 +- .../resources/io/xpipe/app/resources/theme/dark.css | 2 +- 13 files changed, 55 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListNameCell.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListNameCell.java index a44f4fa9e..359ec8460 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListNameCell.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserFileListNameCell.java @@ -160,7 +160,8 @@ class BrowserFileListNameCell extends TableCell { text.addListener(listener); editing.addListener((observable, oldValue, newValue) -> { - if (getTableRow().getItem() != null && getTableRow().getItem().equals(newValue)) { + var item = getTableRow().getItem(); + if (item != null && item.equals(newValue)) { PlatformThread.runLaterIfNeeded(() -> { textField.setDisable(false); textField.requestFocus(); @@ -168,7 +169,7 @@ class BrowserFileListNameCell extends TableCell { var content = textField.getText(); if (content != null && !content.isEmpty()) { var name = FilePath.of(content); - var baseNameEnd = name.getBaseName().toString().length(); + var baseNameEnd = item.getRawFileEntry().getKind() == FileKind.DIRECTORY ? content.length() : name.getBaseName().toString().length(); textField.selectRange(0, baseNameEnd); } }); diff --git a/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java b/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java index a3c186da8..063e965c0 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/LeftSplitPaneComp.java @@ -77,7 +77,10 @@ public class LeftSplitPaneComp extends Comp { divs.getFirst().setPosition(d); r.layout(); Platform.runLater(() -> { - divs.getFirst().setPosition(oldPos / r.getWidth()); + // Div might be removed again since last time + if (divs.size() > 0) { + divs.getFirst().setPosition(oldPos / r.getWidth()); + } }); if (onDividerChange != null) { onDividerChange.accept(d); diff --git a/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java b/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java index 78414a7e9..bd4ab23b3 100644 --- a/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java +++ b/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java @@ -44,16 +44,20 @@ public class DataStoreProviders { return ALL.stream().filter(d -> d.getId().equalsIgnoreCase(id)).findAny(); } + @SuppressWarnings("unchecked") - public static T byStore(DataStore store) { + public static Optional byStoreIfPresent(DataStore store) { if (ALL == null) { throw new IllegalStateException("Not initialized"); } - return (T) ALL.stream() + return (Optional) ALL.stream() .filter(d -> d.getStoreClasses().contains(store.getClass())) - .findAny() - .orElseThrow(() -> new IllegalArgumentException("Unknown store class")); + .findAny(); + } + + public static T byStore(DataStore store) { + return DataStoreProviders.byStoreIfPresent(store).orElseThrow(() -> new IllegalArgumentException("Unknown store class")); } public static List getAll() { diff --git a/app/src/main/java/io/xpipe/app/ext/Session.java b/app/src/main/java/io/xpipe/app/ext/Session.java index b0b3c931a..48d432391 100644 --- a/app/src/main/java/io/xpipe/app/ext/Session.java +++ b/app/src/main/java/io/xpipe/app/ext/Session.java @@ -19,12 +19,16 @@ public abstract class Session implements AutoCloseable { } protected void startAliveListener() { - GlobalTimer.scheduleUntil(Duration.ofMillis(5000), false, () -> { + GlobalTimer.scheduleUntil(Duration.ofMillis(10000), false, () -> { if (!isRunning()) { return true; } ThreadHelper.runAsync(() -> { + if (!isRunning()) { + return; + } + try { var r = checkAlive(); if (r) { diff --git a/app/src/main/java/io/xpipe/app/ext/ShellSession.java b/app/src/main/java/io/xpipe/app/ext/ShellSession.java index 4d6c3c7c6..8eeaba791 100644 --- a/app/src/main/java/io/xpipe/app/ext/ShellSession.java +++ b/app/src/main/java/io/xpipe/app/ext/ShellSession.java @@ -28,9 +28,9 @@ public class ShellSession extends Session { try { shellControl.start(); - var supportsAliveCheck = - shellControl.getShellDialect().getDumbMode().supportsAnyPossibleInteraction(); - if (supportsAliveCheck) { + var shouldAliveCheck = !shellControl.isLocal(); + var supportsAliveCheck = shellControl.getShellDialect().getDumbMode().supportsAnyPossibleInteraction(); + if (shouldAliveCheck && supportsAliveCheck) { startAliveListener(); } } catch (Exception ex) { @@ -77,6 +77,10 @@ public class ShellSession extends Session { @Override public boolean checkAlive() throws Exception { + if (shellControl.isSubShellActive()) { + return true; + } + try { // Don't print it constantly return shellControl diff --git a/app/src/main/java/io/xpipe/app/ext/ShellStore.java b/app/src/main/java/io/xpipe/app/ext/ShellStore.java index e7db98fa0..b4de295bd 100644 --- a/app/src/main/java/io/xpipe/app/ext/ShellStore.java +++ b/app/src/main/java/io/xpipe/app/ext/ShellStore.java @@ -19,6 +19,7 @@ public interface ShellStore extends DataStore, FileSystemStore, ValidatableStore stopSessionIfNeeded(); } else { try { + existingSession.getShellControl().waitForSubShellExit(); existingSession.getShellControl().command(" echo xpipetest").execute(); return new StubShellControl(existingSession.getShellControl()); } catch (Exception e) { diff --git a/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java b/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java index fb735d7e6..032e88eb1 100644 --- a/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java +++ b/app/src/main/java/io/xpipe/app/hub/action/BatchStoreAction.java @@ -35,7 +35,7 @@ public final class BatchStoreAction extends SerializableAct @Override public String getShortcutName() { var names = actions.size() > 3 - ? actions.size() + "..." + ? actions.size() + " connections" : actions.stream() .map(a -> DataStorage.get() .getStoreEntryDisplayName(a.getRef().get())) diff --git a/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java b/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java index 61479063a..88d45a9d1 100644 --- a/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java +++ b/app/src/main/java/io/xpipe/app/hub/action/MultiStoreAction.java @@ -27,7 +27,7 @@ public abstract class MultiStoreAction extends Serializable @Override public String getShortcutName() { var names = refs.size() > 3 - ? refs.size() + "..." + ? refs.size() + " connections" : refs.stream() .map(ref -> DataStorage.get().getStoreEntryDisplayName(ref.get())) .collect(Collectors.joining(", ")); diff --git a/app/src/main/java/io/xpipe/app/process/ShellControl.java b/app/src/main/java/io/xpipe/app/process/ShellControl.java index 5dc8df9ee..ba5c98926 100644 --- a/app/src/main/java/io/xpipe/app/process/ShellControl.java +++ b/app/src/main/java/io/xpipe/app/process/ShellControl.java @@ -2,6 +2,7 @@ package io.xpipe.app.process; import io.xpipe.app.ext.DataStore; import io.xpipe.app.ext.StatefulDataStore; +import io.xpipe.app.util.ThreadHelper; import io.xpipe.core.FailableConsumer; import io.xpipe.core.FailableFunction; import io.xpipe.core.FilePath; @@ -33,6 +34,16 @@ public interface ShellControl extends ProcessControl { void write(byte[] b) throws IOException; + void setSubShellActive(boolean active); + + boolean isSubShellActive(); + + default void waitForSubShellExit() { + while (isSubShellActive()) { + ThreadHelper.sleep(10); + } + } + @Override LocalProcessInputStream getStdout(); diff --git a/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java b/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java index 4bec52650..86a6fac88 100644 --- a/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java +++ b/app/src/main/java/io/xpipe/app/process/WrapperShellControl.java @@ -246,6 +246,16 @@ public class WrapperShellControl implements ShellControl { parent.write(b); } + @Override + public void setSubShellActive(boolean active) { + parent.setSubShellActive(active); + } + + @Override + public boolean isSubShellActive() { + return parent.isSubShellActive(); + } + @Override public void close() throws Exception { parent.close(); diff --git a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java index c4410cddb..511682dac 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java @@ -112,8 +112,8 @@ public class DataStoreEntry extends StorageElement { this.categoryUuid = categoryUuid; this.store = store; this.storeNode = storeNode; - this.validity = validity; - this.provider = store != null ? DataStoreProviders.byStore(store) : null; + this.provider = store != null ? DataStoreProviders.byStoreIfPresent(store).orElse(null) : null; + this.validity = this.provider != null ? validity : Validity.LOAD_FAILED; this.storePersistentStateNode = storePersistentState; this.notes = notes; this.icon = icon; diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css b/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css index a5c08b275..29a880a7d 100644 --- a/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css +++ b/app/src/main/resources/io/xpipe/app/resources/theme/cupertinoDark.css @@ -1,4 +1,4 @@ -.root:windows { -color-bg-default-transparent: #1C1C1ED2; } +.root:windows { -color-bg-default-transparent: #1C1C1ED5; } .root:macos { -color-bg-default-transparent: #0d0d10D6; } diff --git a/app/src/main/resources/io/xpipe/app/resources/theme/dark.css b/app/src/main/resources/io/xpipe/app/resources/theme/dark.css index 42739597e..da6d1dd08 100644 --- a/app/src/main/resources/io/xpipe/app/resources/theme/dark.css +++ b/app/src/main/resources/io/xpipe/app/resources/theme/dark.css @@ -1,4 +1,4 @@ -.root:windows { -color-bg-default-transparent: #0d1117b8; } +.root:windows { -color-bg-default-transparent: #0d1117c3; } .root:macos { -color-bg-default-transparent: #080d13d3; }