More browser improvements

This commit is contained in:
crschnick 2023-02-24 22:16:27 +00:00
parent 01a3177843
commit e0b34ff480
11 changed files with 150 additions and 25 deletions

View file

@ -0,0 +1,89 @@
package io.xpipe.app.browser;
import atlantafx.base.theme.Styles;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.augment.GrowAugment;
import io.xpipe.app.fxcomps.impl.TextFieldComp;
import io.xpipe.app.fxcomps.util.Shortcuts;
import io.xpipe.app.fxcomps.util.SimpleChangeListener;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import org.kordamp.ikonli.javafx.FontIcon;
public class FileFilterComp extends SimpleComp {
private final Property<String> filterString;
public FileFilterComp(Property<String> filterString) {
this.filterString = filterString;
}
@Override
protected Region createSimple() {
var expanded = new SimpleBooleanProperty();
var text = new TextFieldComp(filterString, false).createRegion();
text.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue && filterString.getValue() == null) {
expanded.set(false);
return;
}
if (newValue) {
expanded.set(true);
}
});
filterString.addListener((observable, oldValue, newValue) -> {
if (newValue == null && !text.isFocused()) {
expanded.set(false);
}
});
text.setMinWidth(0);
Styles.toggleStyleClass(text, Styles.LEFT_PILL);
SimpleChangeListener.apply(filterString, val -> {
if (val == null) {
text.getStyleClass().remove(Styles.SUCCESS);
} else {
text.getStyleClass().add(Styles.SUCCESS);
}
});
var fi = new FontIcon("mdi2m-magnify");
var button = new Button();
GrowAugment.create(false, true).augment(new SimpleCompStructure<>(button));
Shortcuts.addShortcut(button, new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN));
button.setGraphic(fi);
button.setOnAction(event -> {
if (expanded.get() && filterString.getValue() == null) {
expanded.set(false);
return;
}
text.requestFocus();
event.consume();
});
SimpleChangeListener.apply(expanded, val -> {
if (val) {
text.setPrefWidth(250);
button.getStyleClass().add(Styles.RIGHT_PILL);
button.getStyleClass().remove(Styles.FLAT);
} else {
text.setPrefWidth(0);
button.getStyleClass().remove(Styles.RIGHT_PILL);
button.getStyleClass().add(Styles.FLAT);
}
});
var box = new HBox(text, button);
box.setFillHeight(true);
return box;
}
}

View file

@ -22,10 +22,7 @@ import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.*;
import java.io.File;
import java.time.Instant;
@ -83,6 +80,7 @@ final class FileListComp extends AnchorPane {
// ~
var table = new TableView<FileSystem.FileEntry>();
table.setPlaceholder(new Region());
table.getStyleClass().add(Styles.STRIPED);
table.getColumns().setAll(filenameCol, sizeCol, mtimeCol);
table.getSortOrder().add(filenameCol);

View file

@ -14,6 +14,7 @@ import lombok.Getter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
@Getter
@ -34,6 +35,10 @@ final class FileListModel {
public FileListModel(OpenFileSystemModel model) {
this.model = model;
model.getFilter().addListener((observable, oldValue, newValue) -> {
refreshShown();
});
}
public void setAll(List<FileSystem.FileEntry> newFiles) {
@ -47,11 +52,17 @@ final class FileListModel {
}
private void refreshShown() {
List<FileSystem.FileEntry> filtered = model.getFilter().getValue() != null ? all.getValue().stream().filter(entry -> {
var name = FileNames.getFileName(entry.getPath()).toLowerCase(Locale.ROOT);
var filterString = model.getFilter().getValue().toLowerCase(Locale.ROOT);
return name.contains(filterString);
}).toList() : all.getValue();
Comparator<FileSystem.FileEntry> tableComparator = comparatorProperty.getValue();
var comparator = tableComparator != null
? FILE_TYPE_COMPARATOR.thenComparing(tableComparator)
: FILE_TYPE_COMPARATOR;
var listCopy = new ArrayList<>(all.getValue());
var listCopy = new ArrayList<>(filtered);
listCopy.sort(comparator);
shown.setValue(listCopy);
}

View file

@ -8,7 +8,7 @@ import io.xpipe.core.store.ShellStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
public class FileSystemHelper {
@ -108,7 +108,7 @@ public class FileSystemHelper {
private static void dropFileAcrossFileSystems(FileSystem.FileEntry target, FileSystem.FileEntry source)
throws Exception {
var flatFiles = new HashMap<FileSystem.FileEntry, String>();
var flatFiles = new LinkedHashMap<FileSystem.FileEntry, String>();
// Prevent dropping directory into itself
if (source.getFileSystem().equals(target.getFileSystem())

View file

@ -57,12 +57,15 @@ public class OpenFileSystemComp extends SimpleComp {
creatingProperty.set(true);
});
var filter = new FileFilterComp(model.getFilter()).createRegion();
var topBar = new ToolBar();
topBar.getItems().setAll(
backBtn,
forthBtn,
new Spacer(10),
pathBar,
filter,
refreshBtn,
terminalBtn,
addBtn

View file

@ -25,6 +25,7 @@ final class OpenFileSystemModel {
private Property<FileSystemStore> store = new SimpleObjectProperty<>();
private FileSystem fileSystem;
private final Property<String> filter = new SimpleStringProperty();
private final FileListModel fileList;
private final ReadOnlyObjectWrapper<String> currentPath = new ReadOnlyObjectWrapper<>();
private final FileBrowserNavigationHistory history = new FileBrowserNavigationHistory();
@ -63,6 +64,7 @@ final class OpenFileSystemModel {
return false;
}
filter.setValue(null);
currentPath.set(path);
history.cd(path);
return true;

View file

@ -39,7 +39,7 @@ public class AppInstaller {
} else {
targetFile = FileNames.join(
s.getTemporaryDirectory(), localFile.getFileName().toString());
try (CommandProcessControl c = s.command(s.getShellDialect().getStreamFileWriteCommand(targetFile))
try (CommandProcessControl c = s.getShellDialect().getStreamFileWriteCommand(s, targetFile)
.start()) {
c.discardOut();
c.discardErr();

View file

@ -3,17 +3,22 @@ package io.xpipe.core.impl;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.store.*;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.MachineStore;
import io.xpipe.core.util.JacksonizedValue;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@JsonTypeName("local")
public class LocalStore extends JacksonizedValue implements FileSystemStore, MachineStore {
@ -25,7 +30,6 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
@Override
public FileSystem createFileSystem() {
if (true) return new ConnectionFileSystem(ShellStore.local().create());
return new FileSystem() {
@Override
public Optional<ShellProcessControl> getShell() {
@ -34,7 +38,7 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
@Override
public FileSystem open() throws Exception {
return this;
return this;
}
@Override
@ -44,17 +48,17 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
@Override
public void delete(String file) throws Exception {
Files.delete(Path.of(file));
}
@Override
public void copy(String file, String newFile) throws Exception {
Files.copy(Path.of(file), Path.of(newFile), StandardCopyOption.REPLACE_EXISTING);
}
@Override
public void move(String file, String newFile) throws Exception {
Files.move(Path.of(file), Path.of(newFile), StandardCopyOption.REPLACE_EXISTING);
}
@Override
@ -69,6 +73,11 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
@Override
public void touch(String file) throws Exception {
if (exists(file)) {
return;
}
Files.createFile(Path.of(file));
}
@Override
@ -78,12 +87,27 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
@Override
public Stream<FileEntry> listFiles(String file) throws Exception {
return null;
return Files.list(Path.of(file)).map(path -> {
try {
var date = Files.getLastModifiedTime(path);
var size = Files.isDirectory(path) ? 0 : Files.size(path);
return new FileEntry(
this,
path.toString(),
date.toInstant(),
Files.isDirectory(path),
Files.isHidden(path),
Files.isExecutable(path),
size);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
@Override
public List<String> listRoots() throws Exception {
return null;
return StreamSupport.stream(FileSystems.getDefault().getRootDirectories().spliterator(), false).map(path -> path.toString()).toList();
}
@Override
@ -99,9 +123,7 @@ public class LocalStore extends JacksonizedValue implements FileSystemStore, Mac
}
@Override
public void close() throws IOException {
}
public void close() throws IOException {}
};
}

View file

@ -93,7 +93,7 @@ public interface ShellDialect {
String getFileMoveCommand(String oldFile, String newFile);
String getStreamFileWriteCommand(String file);
CommandProcessControl getStreamFileWriteCommand(ShellProcessControl processControl, String file);
String getTextFileWriteCommand(String content, String file);

View file

@ -54,8 +54,8 @@ public class ConnectionFileSystem implements FileSystem {
@Override
public OutputStream openOutput(String file) throws Exception {
return shellProcessControl.command(proc -> proc.getShellDialect()
.getStreamFileWriteCommand(proc.getOsType().normalizeFileName(file)))
return shellProcessControl.getShellDialect()
.getStreamFileWriteCommand(shellProcessControl, shellProcessControl.getOsType().normalizeFileName(file))
.startExternalStdin();
}

View file

@ -73,7 +73,7 @@ public interface FileSystem extends Closeable, AutoCloseable {
}
try {
return listFilesRecursively(fileEntry.getPath());
return Stream.concat(Stream.of(fileEntry), listFilesRecursively(fileEntry.getPath()));
} catch (Exception e) {
throw new RuntimeException(e);
}