diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java index d058ce311..90e7239d3 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java @@ -403,6 +403,10 @@ private void borderScroll(TableView tableView, DragEvent event) { VirtualFlow flow = (VirtualFlow) skin.getChildren().get(1); ScrollBar vbar = (ScrollBar) flow.getChildrenUnmodifiable().get(2); + if (!vbar.isVisible()) { + return; + } + double proximity = 100; Bounds tableBounds = tableView.localToScene(tableView.getBoundsInParent()); double dragY = event.getSceneY(); diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java index 8ad2b8285..49a648a7f 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java @@ -80,7 +80,7 @@ protected Region createSimple() { }); var listBox = new VerticalComp(List.of(list, dragNotice)).padding(new Insets(10, 10, 5, 10)); - var stack = new LoadingOverlayComp( + var stack = LoadingOverlayComp.noProgress( new StackComp(List.of(backgroundStack, listBox, clearPane)) .apply(DragOverPseudoClassAugment.create()) .apply(struc -> { diff --git a/app/src/main/java/io/xpipe/app/browser/FileSystemHelper.java b/app/src/main/java/io/xpipe/app/browser/FileSystemHelper.java index bcbd31448..3b58c9700 100644 --- a/app/src/main/java/io/xpipe/app/browser/FileSystemHelper.java +++ b/app/src/main/java/io/xpipe/app/browser/FileSystemHelper.java @@ -104,7 +104,12 @@ public static void validateDirectoryPath(OpenFileSystemModel model, String path) throw ErrorEvent.unreportable(new IllegalArgumentException(String.format("Directory %s does not exist", path))); } - model.getFileSystem().directoryAccessible(path); + try { + model.getFileSystem().directoryAccessible(path); + } catch (Exception ex) { + ErrorEvent.unreportable(ex); + throw ex; + } } private static FileSystem localFileSystem; @@ -229,7 +234,7 @@ private static void dropFileAcrossFileSystems(FileSystem.FileEntry target, FileS if (sourceFile.getKind() == FileKind.DIRECTORY) { target.getFileSystem().mkdirs(targetFile); - } else { + } else if (sourceFile.getKind() == FileKind.FILE) { try (var in = sourceFile.getFileSystem().openInput(sourceFile.getPath()); var out = target.getFileSystem().openOutput(targetFile)) { in.transferTo(out); diff --git a/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java b/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java index cdebc3f5a..16c3d12ba 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/LoadingOverlayComp.java @@ -9,18 +9,25 @@ import io.xpipe.app.util.ThreadHelper; import javafx.application.Platform; import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.layout.StackPane; public class LoadingOverlayComp extends Comp> { + public static LoadingOverlayComp noProgress(Comp comp, ObservableValue loading) { + return new LoadingOverlayComp(comp, loading, new SimpleDoubleProperty(-1)); + } + private final Comp comp; private final ObservableValue showLoading; + private final ObservableValue progress; - public LoadingOverlayComp(Comp comp, ObservableValue loading) { + public LoadingOverlayComp(Comp comp, ObservableValue loading, ObservableValue progress) { this.comp = comp; this.showLoading = PlatformThread.sync(loading); + this.progress = PlatformThread.sync(progress); } @Override @@ -29,7 +36,7 @@ public CompStructure createBase() { var r = compStruc.get(); var loading = new RingProgressIndicator(0, false); - loading.setProgress(-1); + loading.progressProperty().bind(progress); loading.visibleProperty().bind(Bindings.not(AppPrefs.get().performanceMode())); var loadingOverlay = new StackPane(loading); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java index 40328f3fe..fbcc51d77 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java @@ -103,7 +103,7 @@ protected final Region createSimple() { }); new ContextMenuAugment<>(() -> this.createContextMenu()).augment(new SimpleCompStructure<>(button)); - var loading = new LoadingOverlayComp( + var loading = LoadingOverlayComp.noProgress( Comp.of(() -> button), BindingsHelper.persist( wrapper.getInRefresh().and(wrapper.getObserving().not()))); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java index 805cfbe3b..8a03b5c68 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java @@ -164,7 +164,6 @@ private Comp createAlphabeticalSortButton() { }); alphabetical.accessibleTextKey("sortAlphabetical"); alphabetical.apply(new FancyTooltipAugment<>("sortAlphabetical")); - alphabetical.shortcut(new KeyCodeCombination(KeyCode.P, KeyCombination.SHORTCUT_DOWN)); return alphabetical; } @@ -204,7 +203,6 @@ private Comp createDateSortButton() { }); date.accessibleTextKey("sortLastUsed"); date.apply(new FancyTooltipAugment<>("sortLastUsed")); - date.shortcut(new KeyCodeCombination(KeyCode.L, KeyCombination.SHORTCUT_DOWN)); return date; } diff --git a/app/src/main/java/io/xpipe/app/core/AppWindowHelper.java b/app/src/main/java/io/xpipe/app/core/AppWindowHelper.java index cbcd5a31d..8c7a68d6b 100644 --- a/app/src/main/java/io/xpipe/app/core/AppWindowHelper.java +++ b/app/src/main/java/io/xpipe/app/core/AppWindowHelper.java @@ -161,7 +161,7 @@ public static void setupStylesheets(Scene scene) { public static void setupContent( Stage stage, Function> contentFunc, boolean bindSize, ObservableValue loading) { var baseComp = contentFunc.apply(stage); - var content = loading != null ? new LoadingOverlayComp(baseComp, loading) : baseComp; + var content = loading != null ? LoadingOverlayComp.noProgress(baseComp, loading) : baseComp; var contentR = content.createRegion(); AppFont.small(contentR); var scene = new Scene(bindSize ? new Pane(contentR) : contentR, -1, -1, false); @@ -175,7 +175,7 @@ public static void setupContent( scene.addEventHandler(KeyEvent.KEY_PRESSED, event -> { if (AppProperties.get().isDeveloperMode() && event.getCode().equals(KeyCode.F6)) { var newBaseComp = contentFunc.apply(stage); - var newComp = loading != null ? new LoadingOverlayComp(newBaseComp, loading) : newBaseComp; + var newComp = loading != null ? LoadingOverlayComp.noProgress(newBaseComp, loading) : newBaseComp; var newR = newComp.createRegion(); AppFont.medium(newR); scene.setRoot(bindSize ? new Pane(newR) : newR); diff --git a/app/src/main/java/io/xpipe/app/prefs/AboutComp.java b/app/src/main/java/io/xpipe/app/prefs/AboutComp.java index ee17d03c3..710992dd2 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AboutComp.java +++ b/app/src/main/java/io/xpipe/app/prefs/AboutComp.java @@ -16,10 +16,6 @@ public class AboutComp extends Comp> { - private Region createDepsList() { - return new ThirdPartyDependencyListComp().createRegion(); - } - private Comp createLinks() { return new OptionsBuilder() .addComp( diff --git a/app/src/main/java/io/xpipe/app/prefs/PropertiesComp.java b/app/src/main/java/io/xpipe/app/prefs/PropertiesComp.java index e98841dd9..f53d2f517 100644 --- a/app/src/main/java/io/xpipe/app/prefs/PropertiesComp.java +++ b/app/src/main/java/io/xpipe/app/prefs/PropertiesComp.java @@ -1,13 +1,12 @@ package io.xpipe.app.prefs; -import atlantafx.base.controls.Tile; -import io.xpipe.app.core.*; +import io.xpipe.app.core.AppI18n; +import io.xpipe.app.core.AppProperties; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.impl.LabelComp; +import io.xpipe.app.util.JfxHelper; import io.xpipe.app.util.OptionsBuilder; -import javafx.scene.control.Label; -import javafx.scene.image.ImageView; import javafx.scene.layout.Region; public class PropertiesComp extends SimpleComp { @@ -15,19 +14,13 @@ public class PropertiesComp extends SimpleComp { @Override protected Region createSimple() { var title = Comp.of(() -> { - var image = new ImageView(AppImages.image("logo/logo_48x48.png")); - image.setPreserveRatio(true); - image.setSmooth(true); - image.setFitHeight(40); - var label = new Label(AppI18n.get("xPipeClient"), image); - label.getStyleClass().add("header"); - AppFont.setSize(label, 5); - return new Tile(AppI18n.get("xPipeClient"), "Version " + AppProperties.get().getVersion() + " (" - + AppProperties.get().getArch() + ")", image); + return JfxHelper.createNamedEntry(AppI18n.get("xPipeClient"), "Version " + AppProperties.get().getVersion() + " (" + + AppProperties.get().getArch() + ")", "logo/logo_48x48.png"); }); var section = new OptionsBuilder() .addComp(title, null) + .addComp(Comp.vspacer(10)) .name("build") .addComp( new LabelComp(AppProperties.get().getBuild()), diff --git a/app/src/main/java/io/xpipe/app/util/ScriptHelper.java b/app/src/main/java/io/xpipe/app/util/ScriptHelper.java index 863ad4f10..fe6589bc7 100644 --- a/app/src/main/java/io/xpipe/app/util/ScriptHelper.java +++ b/app/src/main/java/io/xpipe/app/util/ScriptHelper.java @@ -125,10 +125,6 @@ public static String createExecScript(ShellDialect type, ShellControl processCon .getShellDialect() .createScriptTextFileWriteCommand(processControl, content, file) .execute(); - var e = processControl.getShellDialect().getScriptPermissionsCommand(file); - if (e != null) { - processControl.executeSimpleCommand(e, "Failed to set script permissions of " + file); - } return file; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/browser.css b/app/src/main/resources/io/xpipe/app/resources/style/browser.css index a2c50e431..9abb1a11c 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/browser.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/browser.css @@ -231,7 +231,7 @@ } .browser .table-view:drag-into-current .table-row-cell { - -fx-opacity: 0.8; + -fx-opacity: 0.65; } .browser .table-row-cell:file:hover,.table-row-cell:folder:hover { diff --git a/core/src/main/java/io/xpipe/core/process/BufferedProcessInputStream.java b/core/src/main/java/io/xpipe/core/process/BufferedProcessInputStream.java new file mode 100644 index 000000000..2c52cfde1 --- /dev/null +++ b/core/src/main/java/io/xpipe/core/process/BufferedProcessInputStream.java @@ -0,0 +1,15 @@ +package io.xpipe.core.process; + +import java.io.BufferedInputStream; +import java.io.InputStream; + +public class BufferedProcessInputStream extends BufferedInputStream { + + public BufferedProcessInputStream(InputStream in, int size) { + super(in, size); + } + + public int bufferedAvailable() { + return count - pos; + } +} diff --git a/core/src/main/java/io/xpipe/core/process/ShellControl.java b/core/src/main/java/io/xpipe/core/process/ShellControl.java index df3e0e35d..4e57e276e 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellControl.java +++ b/core/src/main/java/io/xpipe/core/process/ShellControl.java @@ -21,6 +21,10 @@ public interface ShellControl extends ProcessControl { ShellDialect getTargetTerminalShellDialect(); + BufferedProcessInputStream getStdout(); + + BufferedProcessInputStream getStderr(); + default boolean hasLocalSystemAccess() { return getSystemId().equals(XPipeSystemId.getLocal()); } diff --git a/core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java b/core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java index 2a967fe20..c781f36f4 100644 --- a/core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java +++ b/core/src/main/java/io/xpipe/core/store/ConnectionFileSystem.java @@ -84,7 +84,6 @@ public boolean fileExists(String file) throws Exception { try (var pc = shellControl .getShellDialect() .createFileExistsCommand(shellControl, file) - .complex() .start()) { return pc.discardAndCheckExit(); } @@ -124,7 +123,6 @@ public void move(String file, String newFile) throws Exception { public void mkdirs(String file) throws Exception { try (var pc = shellControl .command(proc -> proc.getShellDialect().getMkdirsCommand(file)) - .complex() .start()) { pc.discardOrThrow(); } diff --git a/core/src/main/java/io/xpipe/core/store/FileSystem.java b/core/src/main/java/io/xpipe/core/store/FileSystem.java index 79f21826f..491c5a23a 100644 --- a/core/src/main/java/io/xpipe/core/store/FileSystem.java +++ b/core/src/main/java/io/xpipe/core/store/FileSystem.java @@ -115,7 +115,10 @@ public FileEntry resolved() { Stream listFiles(String file) throws Exception; default List listFilesRecursively(String file) throws Exception { - var base = listFiles(file).toList(); + List base; + try (var filesStream = listFiles(file)) { + base = filesStream.toList(); + } return base.stream() .flatMap(fileEntry -> { if (fileEntry.getKind() != FileKind.DIRECTORY) { diff --git a/dist/changelogs/1.7.5.md b/dist/changelogs/1.7.5.md new file mode 100644 index 000000000..ef9e63803 --- /dev/null +++ b/dist/changelogs/1.7.5.md @@ -0,0 +1,14 @@ +## Changes in 1.7.5 + +- Implement some more performance improvements +- Fix file browser transfer freezing up when trying to copy/move nested directories +- Fix file browser transfer failing when trying to copy symbolic links +- Fix file browser jittering when dragging and dropping files +- Fix performance regression when transferring large files + +## Previous changes in 1.7 + +- [1.7.4](https://github.com/xpipe-io/xpipe/releases/tag/1.7.4) +- [1.7.3](https://github.com/xpipe-io/xpipe/releases/tag/1.7.3) +- [1.7.2](https://github.com/xpipe-io/xpipe/releases/tag/1.7.2) +- [1.7.1](https://github.com/xpipe-io/xpipe/releases/tag/1.7.1) diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java index b8a257666..f19943a8a 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptStore.java @@ -99,11 +99,6 @@ private static String initScriptsDirectory(ShellControl proc, List