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 d058ce31..90e7239d 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 @@ final class BrowserFileListComp extends SimpleComp { 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 8ad2b828..49a648a7 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 @@ public class BrowserTransferComp extends SimpleComp { }); 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 bcbd3144..3b58c970 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 class FileSystemHelper { 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 @@ public class FileSystemHelper { 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 cdebc3f5..16c3d12b 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.prefs.AppPrefs; 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 class LoadingOverlayComp extends Comp> { 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 40328f3f..fbcc51d7 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 @@ public abstract class StoreEntryComp extends SimpleComp { }); 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 805cfbe3..8a03b5c6 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 @@ public class StoreEntryListStatusComp extends SimpleComp { }); alphabetical.accessibleTextKey("sortAlphabetical"); alphabetical.apply(new FancyTooltipAugment<>("sortAlphabetical")); - alphabetical.shortcut(new KeyCodeCombination(KeyCode.P, KeyCombination.SHORTCUT_DOWN)); return alphabetical; } @@ -204,7 +203,6 @@ public class StoreEntryListStatusComp extends SimpleComp { }); 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 cbcd5a31..8c7a68d6 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 class AppWindowHelper { 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 class AppWindowHelper { 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 ee17d03c..710992dd 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 @@ import java.util.List; 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 e98841dd..f53d2f51 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 863ad4f1..fe6589bc 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 class ScriptHelper { .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 a2c50e43..9abb1a11 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 00000000..2c52cfde --- /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 df3e0e35..4e57e276 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 2a967fe2..c781f36f 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 class ConnectionFileSystem implements FileSystem { try (var pc = shellControl .getShellDialect() .createFileExistsCommand(shellControl, file) - .complex() .start()) { return pc.discardAndCheckExit(); } @@ -124,7 +123,6 @@ public class ConnectionFileSystem implements FileSystem { 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 79f21826..491c5a23 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 interface FileSystem extends Closeable, AutoCloseable { 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 00000000..ef9e6380 --- /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 b8a25766..f19943a8 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 @@ public abstract class ScriptStore extends JacksonizedValue implements DataStore, var fileName = scriptStore.get().getName().toLowerCase(Locale.ROOT).replaceAll(" ", "_"); var scriptFile = FileNames.join(targetDir, fileName + "." + d.getScriptFileEnding()); d.createScriptTextFileWriteCommand(proc, content, scriptFile).execute(); - - var chmod = d.getScriptPermissionsCommand(scriptFile); - if (chmod != null) { - proc.executeSimpleBooleanCommand(chmod); - } } d.createTextFileWriteCommand(proc, String.valueOf(hash), hashFile).execute(); diff --git a/version b/version index 3511591d..5849151f 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.7.4 \ No newline at end of file +1.7.5 \ No newline at end of file