mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-10-25 00:01:02 +00:00
Browser fixes [stage] [arm]
This commit is contained in:
1 parent
dd290ed7f3
commit
a3b9eaa9f7
13 files changed
+151
-62
No files matched your search
@@ -172,7 +172,7 @@ public final class McpTools {
|
||||
throw new BeaconClientException("Directory " + path + " does not exist");
|
||||
}
|
||||
|
||||
try (var stream = recursive ? fs.listFilesRecursively(fs, path) : fs.listFiles(fs, path)) {
|
||||
try (var stream = recursive ? fs.listFilesRecursively(fs, path).stream() : fs.listFiles(fs, path)) {
|
||||
var list = stream.toList();
|
||||
var builder = McpSchema.CallToolResult.builder();
|
||||
for (FileEntry e : list) {
|
||||
@@ -202,7 +202,7 @@ public final class McpTools {
|
||||
}
|
||||
|
||||
var regex = Pattern.compile(DataStorageQuery.toRegex(pattern));
|
||||
try (var stream = recursive ? fs.listFilesRecursively(fs, path) : fs.listFiles(fs, path)) {
|
||||
try (var stream = recursive ? fs.listFilesRecursively(fs, path).stream() : fs.listFiles(fs, path)) {
|
||||
var list = stream.toList();
|
||||
var builder = McpSchema.CallToolResult.builder();
|
||||
list.stream()
|
||||
|
||||
@@ -273,6 +273,14 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.isControlDown() || event.isShiftDown() || event.isAltDown() || event.isMetaDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typedSelection.get().isEmpty() && typed.equals(" ")) {
|
||||
return;
|
||||
}
|
||||
|
||||
var updated = typedSelection.get() + typed;
|
||||
var found = fileList.getShown().getValue().stream()
|
||||
.filter(browserEntry -> browserEntry.getFileName().toLowerCase().startsWith(updated.toLowerCase()))
|
||||
@@ -608,9 +616,14 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||
updateHandler.accept(null, null);
|
||||
fileList.getShown().addListener((observable, oldValue, newValue) -> {
|
||||
// Delay to prevent internal tableview exceptions when sorting
|
||||
Platform.runLater(() -> {
|
||||
var isSortChange = oldValue.size() == newValue.size() && new HashSet<>(oldValue).containsAll(newValue);
|
||||
if (isSortChange) {
|
||||
Platform.runLater(() -> {
|
||||
updateHandler.accept(oldValue, newValue);
|
||||
});
|
||||
} else {
|
||||
updateHandler.accept(oldValue, newValue);
|
||||
});
|
||||
}
|
||||
});
|
||||
fileList.getFileSystemModel().getCurrentPath().addListener((observable, oldValue, newValue) -> {
|
||||
if (oldValue == null) {
|
||||
|
||||
@@ -114,16 +114,16 @@ class BrowserFileListNameCell extends TableCell<BrowserEntry, String> {
|
||||
return;
|
||||
}
|
||||
|
||||
var selection = typedSelection.get() + " ";
|
||||
var found = fileList.getShown().getValue().stream()
|
||||
.filter(browserEntry ->
|
||||
browserEntry.getFileName().toLowerCase().startsWith(selection))
|
||||
.findFirst();
|
||||
// Ugly fix to prevent space from showing the menu when there is a file matching
|
||||
// Due to the table view input map, these events always get sent and consumed, not allowing us to
|
||||
// differentiate between these cases
|
||||
if (found.isPresent()) {
|
||||
return;
|
||||
if (!typedSelection.get().isEmpty()) {
|
||||
var selection = typedSelection.get() + " ";
|
||||
var found = fileList.getShown().getValue().stream().filter(
|
||||
browserEntry -> browserEntry.getFileName().toLowerCase().startsWith(selection)).findFirst();
|
||||
// Ugly fix to prevent space from showing the menu when there is a file matching
|
||||
// Due to the table view input map, these events always get sent and consumed, not allowing us to
|
||||
// differentiate between these cases
|
||||
if (found.isPresent()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var selected = fileList.getSelection();
|
||||
|
||||
@@ -9,11 +9,15 @@ import io.xpipe.app.comp.augment.ContextMenuAugment;
|
||||
import io.xpipe.app.comp.base.*;
|
||||
import io.xpipe.app.core.AppFontSizes;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.util.GlobalTimer;
|
||||
import io.xpipe.app.util.InputHelper;
|
||||
import io.xpipe.app.util.PlatformThread;
|
||||
import io.xpipe.core.FilePath;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.MenuButton;
|
||||
@@ -30,6 +34,7 @@ import javafx.scene.layout.VBox;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -220,13 +225,22 @@ public class BrowserFileSystemTabComp extends SimpleComp {
|
||||
});
|
||||
});
|
||||
|
||||
// Delay show to hide file list changes happening
|
||||
// Not perfect, but covers most of the cases of small directories
|
||||
var showOverview = new SimpleBooleanProperty(true);
|
||||
model.getCurrentPath().subscribe(path -> {
|
||||
GlobalTimer.delay(() -> {
|
||||
showOverview.setValue(path == null);
|
||||
}, Duration.ofMillis(250));
|
||||
});
|
||||
|
||||
var home = new BrowserOverviewComp(model).styleClass("browser-overview");
|
||||
var stack = new MultiContentComp(
|
||||
Map.of(
|
||||
home,
|
||||
model.getCurrentPath().isNull(),
|
||||
showOverview,
|
||||
fileList,
|
||||
model.getCurrentPath().isNull().not()),
|
||||
showOverview.not()),
|
||||
false);
|
||||
var r = stack.styleClass("browser-content-container").createRegion();
|
||||
r.focusedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
|
||||
@@ -30,6 +30,7 @@ import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import javafx.scene.control.SelectionMode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
@@ -37,10 +38,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -84,6 +82,11 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
|
||||
return;
|
||||
}
|
||||
|
||||
if (n.getTransferred() == 0) {
|
||||
progress.setValue(n);
|
||||
return;
|
||||
}
|
||||
|
||||
var changedHistory = false;
|
||||
if (progress.getValue() != null) {
|
||||
var last = progressesIntervalHistory.isEmpty()
|
||||
@@ -229,8 +232,23 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
|
||||
return;
|
||||
}
|
||||
|
||||
var all = new ArrayList<FileEntry>();
|
||||
all.addAll(entries);
|
||||
for (BrowserEntry browserEntry : fileList.getAll().getValue()) {
|
||||
var fe = browserEntry.getRawFileEntry();
|
||||
if (fe.getKind() == FileKind.LINK && entries.stream().anyMatch(o -> o.getPath().equals(fe.resolved().getPath()))) {
|
||||
all.add(fe);
|
||||
}
|
||||
}
|
||||
|
||||
for (FileEntry fileEntry : entries) {
|
||||
if (fileEntry.getKind() == FileKind.LINK) {
|
||||
all.add(fileEntry.resolved());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (var e : entries) {
|
||||
for (var e : all) {
|
||||
var refresh = fileSystem.getFileInfo(e.getPath());
|
||||
fileList.updateEntry(e.getPath(), refresh.orElse(null));
|
||||
}
|
||||
@@ -316,6 +334,11 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
currentPath.set(null);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
// Start shell in case we exited
|
||||
startIfNeeded();
|
||||
@@ -324,11 +347,6 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
|
||||
return Optional.ofNullable(cps);
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
currentPath.set(null);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// Fix common issues with paths
|
||||
var adjustedPath = BrowserFileSystemHelper.adjustPath(this, path);
|
||||
if (!Objects.equals(path, adjustedPath)) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -304,24 +305,45 @@ public class BrowserFileTransferOperation {
|
||||
flatFiles.put(source, directoryName);
|
||||
|
||||
var baseRelative = source.getPath().getParent().toDirectory();
|
||||
try (var stream = source.getFileSystem().listFilesRecursively(source.getFileSystem(), source.getPath())) {
|
||||
List<FileEntry> list = stream.toList();
|
||||
for (FileEntry fileEntry : list) {
|
||||
if (cancelled()) {
|
||||
return;
|
||||
}
|
||||
var list = new ArrayList<FileEntry>();
|
||||
source.getFileSystem().traverseFilesRecursively(source.getFileSystem(), source.getPath(), fileEntry -> {
|
||||
if (cancelled()) {
|
||||
progress.accept(BrowserTransferProgress.finished(source.getName() + " ...", totalSize.get()));
|
||||
return false;
|
||||
}
|
||||
|
||||
var rel = fileEntry
|
||||
.getPath()
|
||||
.relativize(baseRelative)
|
||||
.toUnix()
|
||||
.toString();
|
||||
flatFiles.put(fileEntry, rel);
|
||||
if (fileEntry.getKind() == FileKind.FILE) {
|
||||
// This one is up-to-date and does not need to be recalculated
|
||||
// If we don't have a size, it doesn't matter that much as the total size is only for display
|
||||
totalSize.addAndGet(fileEntry.getFileSizeLong().orElse(0));
|
||||
}
|
||||
var rel = fileEntry
|
||||
.getPath()
|
||||
.relativize(baseRelative)
|
||||
.toUnix()
|
||||
.toString();
|
||||
flatFiles.put(fileEntry, rel);
|
||||
if (fileEntry.getKind() == FileKind.FILE) {
|
||||
// This one is up-to-date and does not need to be recalculated
|
||||
// If we don't have a size, it doesn't matter that much as the total size is only for display
|
||||
totalSize.addAndGet(fileEntry.getFileSizeLong().orElse(0));
|
||||
progress.accept(new BrowserTransferProgress(source.getName() + " ...", 0, totalSize.get()));
|
||||
}
|
||||
list.add(fileEntry);
|
||||
return true;
|
||||
});
|
||||
|
||||
for (FileEntry fileEntry : list) {
|
||||
if (cancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rel = fileEntry
|
||||
.getPath()
|
||||
.relativize(baseRelative)
|
||||
.toUnix()
|
||||
.toString();
|
||||
flatFiles.put(fileEntry, rel);
|
||||
if (fileEntry.getKind() == FileKind.FILE) {
|
||||
// This one is up-to-date and does not need to be recalculated
|
||||
// If we don't have a size, it doesn't matter that much as the total size is only for display
|
||||
totalSize.addAndGet(fileEntry.getFileSizeLong().orElse(0));
|
||||
progress.accept(new BrowserTransferProgress(source.getName(), 0, totalSize.get()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -45,7 +45,7 @@ public class BrowserStatusBarComp extends SimpleComp {
|
||||
bar.apply(struc -> {
|
||||
struc.get().widthProperty().subscribe(value -> {
|
||||
var veryConstrained = value.doubleValue() < 600;
|
||||
var somewhatConstrained = value.doubleValue() < 750;
|
||||
var somewhatConstrained = value.doubleValue() < 710;
|
||||
struc.get().getChildren().get(2).setVisible(!somewhatConstrained);
|
||||
struc.get().getChildren().get(2).setManaged(!somewhatConstrained);
|
||||
struc.get().getChildren().get(4).setVisible(!veryConstrained);
|
||||
|
||||
@@ -7,8 +7,11 @@ import io.xpipe.core.FilePath;
|
||||
import java.io.Closeable;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface FileSystem extends Closeable, AutoCloseable {
|
||||
@@ -49,18 +52,29 @@ public interface FileSystem extends Closeable, AutoCloseable {
|
||||
|
||||
Stream<FileEntry> listFiles(FileSystem system, FilePath file) throws Exception;
|
||||
|
||||
default Stream<FileEntry> listFilesRecursively(FileSystem system, FilePath file) throws Exception {
|
||||
return listFiles(system, file).flatMap(fileEntry -> {
|
||||
if (fileEntry.getKind() != FileKind.DIRECTORY) {
|
||||
return Stream.of(fileEntry);
|
||||
default List<FileEntry> listFilesRecursively(FileSystem system, FilePath file) throws Exception {
|
||||
var all = new ArrayList<FileEntry>();
|
||||
traverseFilesRecursively(system, file, all::add);
|
||||
return all;
|
||||
}
|
||||
|
||||
default void traverseFilesRecursively(FileSystem system, FilePath file, Predicate<FileEntry> visitor) throws Exception {
|
||||
List<FileEntry> base;
|
||||
try (var filesStream = listFiles(system, file)) {
|
||||
base = filesStream.toList();
|
||||
}
|
||||
|
||||
for (FileEntry fileEntry : base) {
|
||||
if (!visitor.test(fileEntry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
return Stream.concat(Stream.of(fileEntry), listFilesRecursively(system, fileEntry.getPath()));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
if (fileEntry.getKind() != FileKind.DIRECTORY) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
traverseFilesRecursively(system, fileEntry.getPath(), visitor);
|
||||
}
|
||||
}
|
||||
|
||||
List<FilePath> listRoots() throws Exception;
|
||||
|
||||
@@ -40,6 +40,7 @@ public enum DocumentationLink {
|
||||
VNC("guide/vnc"),
|
||||
REAL_VNC("guide/vnc#realvnc-server"),
|
||||
SSH("guide/ssh"),
|
||||
SSH_GATEWAYS("guide/ssh#gateways-and-jump-servers"),
|
||||
SSH_HOST_KEYS("troubleshoot/ssh#no-matching-host-key-type-found"),
|
||||
SSH_KEX("troubleshoot/ssh#no-matching-key-exchange-method"),
|
||||
SSH_IPV6("troubleshoot/ssh#ipv6-issues"),
|
||||
|
||||
@@ -101,7 +101,7 @@ public class ShellTemp {
|
||||
"-Force"))
|
||||
.executeAndCheck();
|
||||
} else {
|
||||
sc.command(CommandBuilder.of().add("rm", "-f").add("\"" + prefix.toString() + "\"*"))
|
||||
sc.command(CommandBuilder.of().add("rm", "-f").add("\"" + prefix.toString() + "\"*").add("2>/dev/null"))
|
||||
.executeAndCheck();
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+13
-6
@@ -51,6 +51,19 @@ The fonts on macOS have been updated with the goal of better readability. If you
|
||||
- Add support to launch VsCode Insiders and Trae as well in the VsCode SSH launch menu
|
||||
- The custom SSH agent setting now works differently. To use the agent socket specified in the settings menu, you will now have to select the custom SSH agent for a connection. The default OpenSSH agent will no longer use this option
|
||||
|
||||
## File browser
|
||||
|
||||
- Files with trailing or leading spaces are now included in the file list
|
||||
- The initial transfer size calculation for large directories is now dynamically updated and shown
|
||||
- Fix execute action on Windows not being limited to certain file types
|
||||
- Fix refresh of single files failing on Windows systems
|
||||
- Fix execute action not showing confirmation dialog if enabled
|
||||
- Fix not supporting dollar signs in directory names
|
||||
- Fix conflict dialog being cut off
|
||||
- Fix file listing not working on Solaris systems
|
||||
- Fix renames not working in cmd
|
||||
- Fix script arguments not being passed with file selection
|
||||
|
||||
## Other
|
||||
|
||||
- Tailscale connections are now a top-level entry and can be synced via git
|
||||
@@ -72,13 +85,7 @@ The fonts on macOS have been updated with the goal of better readability. If you
|
||||
- Fix small parts of the UI moving a bit on hover
|
||||
- Fix Bitwarden integration in some cases requiring the master password every time
|
||||
- Fix restart button not working on Linux
|
||||
- Fix file browser execute action on Windows not being limited to certain file types
|
||||
- Fix file browser refresh of single files failing on Windows systems
|
||||
- Fix file browser execute action not showing confirmation dialog if enabled
|
||||
- Fix file browser not supporting dollar signs in directory names
|
||||
- Fix file browser conflict dialog being cut off
|
||||
- Fix license check becoming invalid if xpipe was left running for more than a week
|
||||
- Fix application freeze when having password manager identities while password manager was not running
|
||||
- Fix git vaultversion conflict not being solved automatically
|
||||
- Fix file listing in file browser not working on Solaris systems
|
||||
- Fix BSD and Solaris systems not being recognized correctly
|
||||
@@ -60,7 +60,7 @@ public class SimpleScriptStore extends ScriptStore implements SelfReferentialSto
|
||||
shellControl.getShellDialect().getNewLine().getNewLineString()));
|
||||
var targetType = shellControl.getOriginalShellDialect();
|
||||
var script = ScriptHelper.createExecScript(targetType, shellControl, fixedCommands);
|
||||
return targetType.sourceScriptCommand(shellControl, script.toString());
|
||||
return targetType.sourceScriptCommand(shellControl, script.toString()) + " " + targetType.getCatchAllVariable();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in new issue
Block a user