mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-09-19 22:01:12 +00:00
Small browser fixes [release]
This commit is contained in:
parent
4bb7627488
commit
1f9d5ab2e6
|
@ -17,10 +17,14 @@ import javafx.beans.property.*;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
|
import javafx.geometry.Bounds;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.control.skin.TableViewSkin;
|
||||||
|
import javafx.scene.control.skin.VirtualFlow;
|
||||||
|
import javafx.scene.input.DragEvent;
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
|
@ -29,6 +33,7 @@ import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static io.xpipe.app.util.HumanReadableFormat.byteCount;
|
import static io.xpipe.app.util.HumanReadableFormat.byteCount;
|
||||||
import static javafx.scene.control.TableColumn.SortType.ASCENDING;
|
import static javafx.scene.control.TableColumn.SortType.ASCENDING;
|
||||||
|
@ -125,7 +130,7 @@ final class FileListComp extends AnchorPane {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var emptyEntry = new FileListEntry(table, null, fileList);
|
var emptyEntry = new FileListCompEntry(table, null, fileList);
|
||||||
table.setOnDragOver(event -> {
|
table.setOnDragOver(event -> {
|
||||||
emptyEntry.onDragOver(event);
|
emptyEntry.onDragOver(event);
|
||||||
});
|
});
|
||||||
|
@ -145,7 +150,7 @@ final class FileListComp extends AnchorPane {
|
||||||
table.setRowFactory(param -> {
|
table.setRowFactory(param -> {
|
||||||
TableRow<FileSystem.FileEntry> row = new TableRow<>();
|
TableRow<FileSystem.FileEntry> row = new TableRow<>();
|
||||||
var listEntry = Bindings.createObjectBinding(
|
var listEntry = Bindings.createObjectBinding(
|
||||||
() -> new FileListEntry(row, row.getItem(), fileList), row.itemProperty());
|
() -> new FileListCompEntry(row, row.getItem(), fileList), row.itemProperty());
|
||||||
|
|
||||||
row.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
row.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if (newValue && listEntry.get().isSynthetic()) {
|
if (newValue && listEntry.get().isSynthetic()) {
|
||||||
|
@ -180,6 +185,7 @@ final class FileListComp extends AnchorPane {
|
||||||
listEntry.get().onDragEntered(event);
|
listEntry.get().onDragEntered(event);
|
||||||
});
|
});
|
||||||
row.setOnDragOver(event -> {
|
row.setOnDragOver(event -> {
|
||||||
|
borderScroll(table, event);
|
||||||
listEntry.get().onDragOver(event);
|
listEntry.get().onDragOver(event);
|
||||||
});
|
});
|
||||||
row.setOnDragDetected(event -> {
|
row.setOnDragDetected(event -> {
|
||||||
|
@ -195,6 +201,7 @@ final class FileListComp extends AnchorPane {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var lastDir = new SimpleObjectProperty<FileSystem.FileEntry>();
|
||||||
SimpleChangeListener.apply(fileList.getShown(), (newValue) -> {
|
SimpleChangeListener.apply(fileList.getShown(), (newValue) -> {
|
||||||
PlatformThread.runLaterIfNeeded(() -> {
|
PlatformThread.runLaterIfNeeded(() -> {
|
||||||
var newItems = new ArrayList<FileSystem.FileEntry>();
|
var newItems = new ArrayList<FileSystem.FileEntry>();
|
||||||
|
@ -204,16 +211,36 @@ final class FileListComp extends AnchorPane {
|
||||||
}
|
}
|
||||||
newItems.addAll(newValue);
|
newItems.addAll(newValue);
|
||||||
table.getItems().setAll(newItems);
|
table.getItems().setAll(newItems);
|
||||||
// if (newValue.size() > 0) {
|
|
||||||
// table.scrollTo(0);
|
var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory();
|
||||||
// }
|
if (!Objects.equals(lastDir.get(), currentDirectory)) {
|
||||||
|
table.scrollTo(0);
|
||||||
|
}
|
||||||
|
lastDir.setValue(currentDirectory);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
private void borderScroll(TableView<?> tableView, DragEvent event) {
|
||||||
|
TableViewSkin<?> skin = (TableViewSkin<?>) tableView.getSkin();
|
||||||
|
VirtualFlow<?> flow = (VirtualFlow<?>) skin.getChildren().get(1);
|
||||||
|
ScrollBar vbar = (ScrollBar) flow.getChildrenUnmodifiable().get(2);
|
||||||
|
|
||||||
|
double proximity = 100;
|
||||||
|
Bounds tableBounds = tableView.localToScene(tableView.getBoundsInParent());
|
||||||
|
double dragY = event.getSceneY();
|
||||||
|
double topYProximity = tableBounds.getMinY() + proximity;
|
||||||
|
double bottomYProximity = tableBounds.getMaxY() - proximity;
|
||||||
|
if (dragY < topYProximity) {
|
||||||
|
var scrollValue = Math.min(topYProximity - dragY, 100) / 10000.0;
|
||||||
|
vbar.setValue(vbar.getValue() - scrollValue);
|
||||||
|
} else if (dragY > bottomYProximity) {
|
||||||
|
var scrollValue = Math.min(dragY - bottomYProximity, 100) / 10000.0;
|
||||||
|
vbar.setValue(vbar.getValue() + scrollValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class FilenameCell extends TableCell<FileSystem.FileEntry, String> {
|
private class FilenameCell extends TableCell<FileSystem.FileEntry, String> {
|
||||||
|
|
||||||
|
@ -265,7 +292,11 @@ final class FileListComp extends AnchorPane {
|
||||||
|
|
||||||
pseudoClassStateChanged(FOLDER, isDirectory);
|
pseudoClassStateChanged(FOLDER, isDirectory);
|
||||||
|
|
||||||
var fileName = getTableRow().getItem().equals(fileList.getFileSystemModel().getCurrentParentDirectory()) ? ".." : FileNames.getFileName(fullPath);
|
var fileName = getTableRow()
|
||||||
|
.getItem()
|
||||||
|
.equals(fileList.getFileSystemModel().getCurrentParentDirectory())
|
||||||
|
? ".."
|
||||||
|
: FileNames.getFileName(fullPath);
|
||||||
var hidden = getTableRow().getItem().isHidden() || fileName.startsWith(".");
|
var hidden = getTableRow().getItem().isHidden() || fileName.startsWith(".");
|
||||||
getTableRow().pseudoClassStateChanged(HIDDEN, hidden);
|
getTableRow().pseudoClassStateChanged(HIDDEN, hidden);
|
||||||
text.set(fileName);
|
text.set(fileName);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class FileListEntry {
|
public class FileListCompEntry {
|
||||||
|
|
||||||
public static final Timer DROP_TIMER = new Timer("dnd", true);
|
public static final Timer DROP_TIMER = new Timer("dnd", true);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class FileListEntry {
|
||||||
private Point2D lastOver = new Point2D(-1, -1);
|
private Point2D lastOver = new Point2D(-1, -1);
|
||||||
private TimerTask activeTask;
|
private TimerTask activeTask;
|
||||||
|
|
||||||
public FileListEntry(Node row, FileSystem.FileEntry item, FileListModel model) {
|
public FileListCompEntry(Node row, FileSystem.FileEntry item, FileListModel model) {
|
||||||
this.row = row;
|
this.row = row;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
@ -47,6 +47,11 @@ public class FileListEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean acceptsDrop(DragEvent event) {
|
private boolean acceptsDrop(DragEvent event) {
|
||||||
|
// Accept drops from outside the app window
|
||||||
|
if (event.getGestureSource() == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (FileBrowserClipboard.currentDragClipboard == null) {
|
if (FileBrowserClipboard.currentDragClipboard == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
|
@ -7,11 +7,9 @@ import io.xpipe.app.core.mode.OperationMode;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.issue.ErrorEvent;
|
import io.xpipe.app.issue.ErrorEvent;
|
||||||
import io.xpipe.app.issue.UserReportComp;
|
import io.xpipe.app.issue.UserReportComp;
|
||||||
import io.xpipe.app.util.DesktopHelper;
|
import io.xpipe.app.util.*;
|
||||||
import io.xpipe.app.util.DynamicOptionsBuilder;
|
|
||||||
import io.xpipe.app.util.FileOpener;
|
|
||||||
import io.xpipe.app.util.ScriptHelper;
|
|
||||||
import io.xpipe.core.impl.FileNames;
|
import io.xpipe.core.impl.FileNames;
|
||||||
|
import io.xpipe.core.process.OsType;
|
||||||
import io.xpipe.core.store.ShellStore;
|
import io.xpipe.core.store.ShellStore;
|
||||||
import io.xpipe.core.util.XPipeInstallation;
|
import io.xpipe.core.util.XPipeInstallation;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
@ -35,9 +33,9 @@ public class BrowseDirectoryComp extends SimpleComp {
|
||||||
"logFile",
|
"logFile",
|
||||||
new ButtonComp(AppI18n.observable("openCurrentLogFile"), () -> {
|
new ButtonComp(AppI18n.observable("openCurrentLogFile"), () -> {
|
||||||
FileOpener.openInTextEditor(AppLogs.get()
|
FileOpener.openInTextEditor(AppLogs.get()
|
||||||
.getSessionLogsDirectory()
|
.getSessionLogsDirectory()
|
||||||
.resolve("xpipe.log")
|
.resolve("xpipe.log")
|
||||||
.toString());
|
.toString());
|
||||||
}),
|
}),
|
||||||
null)
|
null)
|
||||||
.addComp(
|
.addComp(
|
||||||
|
@ -45,8 +43,15 @@ public class BrowseDirectoryComp extends SimpleComp {
|
||||||
new ButtonComp(AppI18n.observable("launchDebugMode"), () -> {
|
new ButtonComp(AppI18n.observable("launchDebugMode"), () -> {
|
||||||
OperationMode.executeAfterShutdown(() -> {
|
OperationMode.executeAfterShutdown(() -> {
|
||||||
try (var sc = ShellStore.createLocal().create().start()) {
|
try (var sc = ShellStore.createLocal().create().start()) {
|
||||||
var script = FileNames.join(XPipeInstallation.getCurrentInstallationBasePath().toString(), XPipeInstallation.getDaemonDebugScriptPath(sc.getOsType()));
|
var script = FileNames.join(
|
||||||
sc.executeSimpleCommand(ScriptHelper.createDetachCommand(sc, script));
|
XPipeInstallation.getCurrentInstallationBasePath()
|
||||||
|
.toString(),
|
||||||
|
XPipeInstallation.getDaemonDebugScriptPath(sc.getOsType()));
|
||||||
|
if (sc.getOsType().equals(OsType.WINDOWS)) {
|
||||||
|
sc.executeSimpleCommand(ScriptHelper.createDetachCommand(sc, "\"" + script + "\""));
|
||||||
|
} else {
|
||||||
|
TerminalHelper.open("X-Pipe Debug", "\"" + script + "\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DesktopHelper.browsePath(AppLogs.get().getSessionLogsDirectory());
|
DesktopHelper.browsePath(AppLogs.get().getSessionLogsDirectory());
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
public abstract class TestModule<V> {
|
public abstract class TestModule<V> {
|
||||||
|
|
||||||
private static final Map<Class<?>, Map<String, ?>> values = new HashMap<>();
|
private static final Map<Class<?>, Map<String, ?>> values = new LinkedHashMap<>();
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public static <T> Map<String, T> get(Class<T> c, String... classes) {
|
public static <T> Map<String, T> get(Class<T> c, String... classes) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class ConnectionFileSystem implements FileSystem {
|
||||||
@Override
|
@Override
|
||||||
public boolean exists(String file) throws Exception {
|
public boolean exists(String file) throws Exception {
|
||||||
try (var pc = shellControl.command(proc -> proc.getShellDialect()
|
try (var pc = shellControl.command(proc -> proc.getShellDialect()
|
||||||
.getFileExistsCommand(proc.getOsType().normalizeFileName(file)))
|
.getFileExistsCommand(proc.getOsType().normalizeFileName(file))).complex()
|
||||||
.start()) {
|
.start()) {
|
||||||
return pc.discardAndCheckExit();
|
return pc.discardAndCheckExit();
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class ConnectionFileSystem implements FileSystem {
|
||||||
@Override
|
@Override
|
||||||
public void delete(String file) throws Exception {
|
public void delete(String file) throws Exception {
|
||||||
try (var pc = shellControl.command(proc -> proc.getShellDialect()
|
try (var pc = shellControl.command(proc -> proc.getShellDialect()
|
||||||
.getFileDeleteCommand(proc.getOsType().normalizeFileName(file)))
|
.getFileDeleteCommand(proc.getOsType().normalizeFileName(file))).complex()
|
||||||
.start()) {
|
.start()) {
|
||||||
pc.discardOrThrow();
|
pc.discardOrThrow();
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ public class ConnectionFileSystem implements FileSystem {
|
||||||
@Override
|
@Override
|
||||||
public boolean mkdirs(String file) throws Exception {
|
public boolean mkdirs(String file) throws Exception {
|
||||||
try (var pc = shellControl.command(proc -> proc.getShellDialect()
|
try (var pc = shellControl.command(proc -> proc.getShellDialect()
|
||||||
.getMkdirsCommand(proc.getOsType().normalizeFileName(file)))
|
.getMkdirsCommand(proc.getOsType().normalizeFileName(file))).complex()
|
||||||
.start()) {
|
.start()) {
|
||||||
return pc.discardAndCheckExit();
|
return pc.discardAndCheckExit();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue