mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Many small fixes [release]
This commit is contained in:
parent
c936e37509
commit
b7fa352ae5
25 changed files with 164 additions and 85 deletions
|
@ -1,14 +1,14 @@
|
|||
package io.xpipe.app.browser;
|
||||
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
import io.xpipe.core.util.XPipeTempDirectory;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.input.Dragboard;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.Value;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FileBrowserClipboard {
|
||||
|
||||
|
@ -18,7 +18,6 @@ public class FileBrowserClipboard {
|
|||
List<FileSystem.FileEntry> entries;
|
||||
}
|
||||
|
||||
public static Map<UUID, List<FileSystem.FileEntry>> CLIPBOARD = new HashMap<>();
|
||||
public static Instance currentCopyClipboard;
|
||||
public static Instance currentDragClipboard;
|
||||
|
||||
|
@ -26,17 +25,15 @@ public class FileBrowserClipboard {
|
|||
public static ClipboardContent startDrag(List<FileSystem.FileEntry> selected) {
|
||||
var content = new ClipboardContent();
|
||||
var idea = UUID.randomUUID();
|
||||
var file = XPipeTempDirectory.getLocal().resolve(idea.toString());
|
||||
Files.createFile(file);
|
||||
currentDragClipboard = new Instance(idea, selected);
|
||||
content.putFiles(List.of(file.toFile()));
|
||||
content.putString(idea.toString());
|
||||
return content;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static void startCopy(List<FileSystem.FileEntry> selected) {
|
||||
var idea = UUID.randomUUID();
|
||||
currentCopyClipboard = new Instance(idea, new ArrayList<>(selected));
|
||||
var id = UUID.randomUUID();
|
||||
currentCopyClipboard = new Instance(id, new ArrayList<>(selected));
|
||||
}
|
||||
|
||||
public static Instance retrieveCopy() {
|
||||
|
@ -45,15 +42,19 @@ public class FileBrowserClipboard {
|
|||
}
|
||||
|
||||
public static Instance retrieveDrag(Dragboard dragboard) {
|
||||
if (dragboard.getFiles().size() != 1) {
|
||||
if (dragboard.getString() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var idea = UUID.fromString(dragboard.getFiles().get(0).toPath().getFileName().toString());
|
||||
if (idea.equals(currentDragClipboard.uuid)) {
|
||||
var current = currentDragClipboard;
|
||||
currentDragClipboard = null;
|
||||
return current;
|
||||
try {
|
||||
var idea = UUID.fromString(dragboard.getString());
|
||||
if (idea.equals(currentDragClipboard.uuid)) {
|
||||
var current = currentDragClipboard;
|
||||
currentDragClipboard = null;
|
||||
return current;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -4,7 +4,11 @@ package io.xpipe.app.browser;
|
|||
|
||||
import io.xpipe.app.comp.source.GuiDsCreatorMultiStep;
|
||||
import io.xpipe.app.ext.DataSourceProvider;
|
||||
import io.xpipe.app.util.*;
|
||||
import io.xpipe.app.util.FileOpener;
|
||||
import io.xpipe.app.util.ScriptHelper;
|
||||
import io.xpipe.app.util.TerminalHelper;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.impl.FileNames;
|
||||
import io.xpipe.core.impl.FileStore;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
|
@ -13,10 +17,11 @@ import javafx.beans.property.Property;
|
|||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.SeparatorMenuItem;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.util.List;
|
||||
|
||||
final class FileContextMenu extends ContextMenu {
|
||||
|
@ -73,8 +78,7 @@ final class FileContextMenu extends ContextMenu {
|
|||
var execute = new MenuItem("Run in terminal");
|
||||
execute.setOnAction(event -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
ShellControl pc =
|
||||
model.getFileSystem().getShell().orElseThrow();
|
||||
ShellControl pc = model.getFileSystem().getShell().orElseThrow();
|
||||
pc.executeBooleanSimpleCommand(pc.getShellDialect().getMakeExecutableCommand(entry.getPath()));
|
||||
var cmd = pc.command("\"" + entry.getPath() + "\"").prepareTerminalOpen();
|
||||
TerminalHelper.open(FilenameUtils.getBaseName(entry.getPath()), cmd);
|
||||
|
@ -86,8 +90,7 @@ final class FileContextMenu extends ContextMenu {
|
|||
var executeInBackground = new MenuItem("Run in background");
|
||||
executeInBackground.setOnAction(event -> {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
ShellControl pc =
|
||||
model.getFileSystem().getShell().orElseThrow();
|
||||
ShellControl pc = model.getFileSystem().getShell().orElseThrow();
|
||||
pc.executeBooleanSimpleCommand(pc.getShellDialect().getMakeExecutableCommand(entry.getPath()));
|
||||
var cmd = ScriptHelper.createDetachCommand(pc, "\"" + entry.getPath() + "\"");
|
||||
pc.executeBooleanSimpleCommand(cmd);
|
||||
|
@ -112,30 +115,48 @@ final class FileContextMenu extends ContextMenu {
|
|||
GuiDsCreatorMultiStep.showForStore(DataSourceProvider.Category.STREAM, store, null);
|
||||
event.consume();
|
||||
});
|
||||
getItems().add(pipe);
|
||||
// getItems().add(pipe);
|
||||
|
||||
var edit = new MenuItem("Edit");
|
||||
edit.setOnAction(event -> {
|
||||
FileOpener.openInTextEditor(entry);
|
||||
ThreadHelper.runAsync(() -> FileOpener.openInTextEditor(entry));
|
||||
event.consume();
|
||||
});
|
||||
getItems().add(edit);
|
||||
}
|
||||
|
||||
var cut = new MenuItem("Delete");
|
||||
cut.setOnAction(event -> {
|
||||
getItems().add(new SeparatorMenuItem());
|
||||
|
||||
var copyName = new MenuItem("Copy name");
|
||||
copyName.setOnAction(event -> {
|
||||
var selection = new StringSelection(FileNames.getFileName(entry.getPath()));
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
clipboard.setContents(selection, selection);
|
||||
event.consume();
|
||||
});
|
||||
getItems().add(copyName);
|
||||
|
||||
var copyPath = new MenuItem("Copy full path");
|
||||
copyPath.setOnAction(event -> {
|
||||
var selection = new StringSelection(entry.getPath());
|
||||
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
clipboard.setContents(selection, selection);
|
||||
event.consume();
|
||||
});
|
||||
getItems().add(copyPath);
|
||||
|
||||
var delete = new MenuItem("Delete");
|
||||
delete.setOnAction(event -> {
|
||||
event.consume();
|
||||
model.deleteAsync(entry.getPath());
|
||||
});
|
||||
cut.setAccelerator(new KeyCodeCombination(KeyCode.DELETE));
|
||||
|
||||
var rename = new MenuItem("Rename");
|
||||
rename.setOnAction(event -> {
|
||||
event.consume();
|
||||
editing.setValue(entry.getPath());
|
||||
});
|
||||
rename.setAccelerator(new KeyCodeCombination(KeyCode.F2));
|
||||
|
||||
getItems().addAll(new SeparatorMenuItem(), cut, rename);
|
||||
getItems().addAll(new SeparatorMenuItem(), rename, delete);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@ public class FileSystemHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Handle special case when file system creation has failed
|
||||
if (model.getFileSystem() == null) {
|
||||
return path;
|
||||
}
|
||||
|
||||
var shell = model.getFileSystem().getShell();
|
||||
if (shell.isEmpty()) {
|
||||
return path;
|
||||
|
|
|
@ -13,6 +13,7 @@ import io.xpipe.core.store.FileSystemStore;
|
|||
import io.xpipe.core.store.ShellStore;
|
||||
import javafx.beans.property.*;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
@ -40,13 +41,14 @@ final class OpenFileSystemModel {
|
|||
fileList = new FileListModel(this);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void refresh() {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
cdSync(currentPath.get());
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshInternal() {
|
||||
private void refreshInternal() throws Exception {
|
||||
cdSync(currentPath.get());
|
||||
}
|
||||
|
||||
|
@ -68,7 +70,13 @@ final class OpenFileSystemModel {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
private void cdSync(String path) {
|
||||
private void cdSync(String path) throws Exception {
|
||||
if (fileSystem == null) {
|
||||
var fs = store.getValue().createFileSystem();
|
||||
fs.open();
|
||||
this.fileSystem = fs;
|
||||
}
|
||||
|
||||
path = FileSystemHelper.normalizeDirectoryPath(this, path);
|
||||
|
||||
navigateToSync(path);
|
||||
|
@ -99,6 +107,10 @@ final class OpenFileSystemModel {
|
|||
public void dropLocalFilesIntoAsync(FileSystem.FileEntry entry, List<Path> files) {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
if (fileSystem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileSystemHelper.dropLocalFilesInto(entry, files);
|
||||
refreshInternal();
|
||||
});
|
||||
|
@ -109,6 +121,10 @@ final class OpenFileSystemModel {
|
|||
FileSystem.FileEntry target, List<FileSystem.FileEntry> files, boolean explicitCopy) {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
if (fileSystem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileSystemHelper.dropFilesInto(target, files, explicitCopy);
|
||||
refreshInternal();
|
||||
});
|
||||
|
@ -122,6 +138,10 @@ final class OpenFileSystemModel {
|
|||
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
if (fileSystem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fileSystem.mkdirs(path);
|
||||
refreshInternal();
|
||||
});
|
||||
|
@ -135,6 +155,10 @@ final class OpenFileSystemModel {
|
|||
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
if (fileSystem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fileSystem.touch(path);
|
||||
refreshInternal();
|
||||
});
|
||||
|
@ -144,6 +168,10 @@ final class OpenFileSystemModel {
|
|||
public void deleteAsync(String path) {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
if (fileSystem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
fileSystem.delete(path);
|
||||
refreshInternal();
|
||||
});
|
||||
|
@ -164,12 +192,6 @@ final class OpenFileSystemModel {
|
|||
store = null;
|
||||
}
|
||||
|
||||
public void switchFileSystem(FileSystemStore fileSystem) throws Exception {
|
||||
BusyProperty.execute(busy, () -> {
|
||||
switchSync(fileSystem);
|
||||
});
|
||||
}
|
||||
|
||||
private void switchSync(FileSystemStore fileSystem) throws Exception {
|
||||
closeSync();
|
||||
this.store.setValue(fileSystem);
|
||||
|
@ -198,6 +220,10 @@ final class OpenFileSystemModel {
|
|||
|
||||
public void openTerminalAsync(String directory) {
|
||||
ThreadHelper.runFailableAsync(() -> {
|
||||
if (fileSystem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BusyProperty.execute(busy, () -> {
|
||||
if (store.getValue() instanceof ShellStore s) {
|
||||
var connection = ((ConnectionFileSystem) fileSystem).getShellControl();
|
||||
|
|
|
@ -8,7 +8,7 @@ import io.xpipe.app.util.DynamicOptionsBuilder;
|
|||
import io.xpipe.app.util.Hyperlinks;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.control.SplitPane;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
@ -62,10 +62,10 @@ public class AboutTabComp extends Comp<CompStructure<?>> {
|
|||
.styleClass("information");
|
||||
|
||||
return Comp.derive(box, boxS -> {
|
||||
var bp = new BorderPane();
|
||||
bp.setLeft(boxS);
|
||||
var bp = new SplitPane();
|
||||
bp.getItems().add(boxS);
|
||||
var deps = createThirdPartyDeps();
|
||||
bp.setRight(createThirdPartyDeps());
|
||||
bp.getItems().add(createThirdPartyDeps());
|
||||
deps.prefWidthProperty().bind(bp.widthProperty().divide(2));
|
||||
boxS.prefWidthProperty().bind(bp.widthProperty().divide(2));
|
||||
bp.getStyleClass().add("about-tab");
|
||||
|
|
|
@ -28,7 +28,7 @@ public class ThirdPartyDependencyListComp extends Comp<CompStructure<?>> {
|
|||
var sp = new StackPane(link, licenseName);
|
||||
StackPane.setAlignment(licenseName, Pos.CENTER_RIGHT);
|
||||
StackPane.setAlignment(link, Pos.CENTER_LEFT);
|
||||
sp.prefWidthProperty().bind(tp.widthProperty().subtract(40));
|
||||
sp.prefWidthProperty().bind(tp.widthProperty().subtract(65));
|
||||
tp.setGraphic(sp);
|
||||
|
||||
var text = new TextArea();
|
||||
|
@ -36,7 +36,7 @@ public class ThirdPartyDependencyListComp extends Comp<CompStructure<?>> {
|
|||
text.setText(t.licenseText());
|
||||
text.setWrapText(true);
|
||||
text.setPrefHeight(300);
|
||||
text.prefWidthProperty().bind(tp.widthProperty());
|
||||
text.maxWidthProperty().bind(tp.widthProperty());
|
||||
AppFont.setSize(text, -4);
|
||||
tp.setContent(text);
|
||||
AppFont.verySmall(tp);
|
||||
|
|
|
@ -47,8 +47,9 @@ public class IntegratedTextAreaComp extends SimpleComp {
|
|||
}
|
||||
|
||||
private Region createOpenButton(Region container) {
|
||||
var name = identifier + (fileType != null ? "." + fileType : "");
|
||||
var button = new IconButtonComp("mdal-edit", () -> FileOpener
|
||||
.openString(identifier, fileType, this, value.getValue(), (s) -> {
|
||||
.openString(name, this, value.getValue(), (s) -> {
|
||||
Platform.runLater(() -> value.setValue(s));
|
||||
}))
|
||||
.createRegion();
|
||||
|
|
|
@ -93,7 +93,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
|
|||
e.applyChanges(newE);
|
||||
if (!DataStorage.get().getStoreEntries().contains(e)) {
|
||||
DataStorage.get().addStoreEntry(e);
|
||||
ScanAlert.showIfNeeded(e.getStore());
|
||||
ScanAlert.showIfNeeded(e.getStore(), true);
|
||||
}
|
||||
DataStorage.get().refresh();
|
||||
});
|
||||
|
@ -104,7 +104,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
|
|||
show(null, null, null, filter, e -> {
|
||||
try {
|
||||
DataStorage.get().addStoreEntry(e);
|
||||
ScanAlert.showIfNeeded(e.getStore());
|
||||
ScanAlert.showIfNeeded(e.getStore(), true);
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
}
|
||||
|
@ -183,6 +183,9 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
|
|||
public CompStructure<? extends Region> createBase() {
|
||||
var layout = new BorderPane();
|
||||
var providerChoice = new DsStoreProviderChoiceComp(filter, provider);
|
||||
if (provider.getValue() != null) {
|
||||
providerChoice.apply(struc -> struc.get().setDisable(true));
|
||||
}
|
||||
providerChoice.apply(GrowAugment.create(true, false));
|
||||
|
||||
SimpleChangeListener.apply(provider, n -> {
|
||||
|
|
|
@ -35,7 +35,7 @@ public class StoreIntroComp extends SimpleComp {
|
|||
});
|
||||
|
||||
var scanButton = new Button(AppI18n.get("detectConnections"), new FontIcon("mdi2m-magnify"));
|
||||
scanButton.setOnAction(event -> ScanAlert.showIfNeeded(new LocalStore()));
|
||||
scanButton.setOnAction(event -> ScanAlert.showIfNeeded(new LocalStore(), false));
|
||||
var scanPane = new StackPane(scanButton);
|
||||
scanPane.setAlignment(Pos.CENTER);
|
||||
|
||||
|
|
|
@ -15,21 +15,21 @@ import java.util.function.BiConsumer;
|
|||
|
||||
import static java.nio.file.StandardWatchEventKinds.*;
|
||||
|
||||
public class FileWatchManager {
|
||||
public class AppFileWatcher {
|
||||
|
||||
private static FileWatchManager INSTANCE;
|
||||
private static AppFileWatcher INSTANCE;
|
||||
|
||||
private final Set<WatchedDirectory> watchedDirectories = new CopyOnWriteArraySet<>();
|
||||
private WatchService watchService;
|
||||
private Thread watcherThread;
|
||||
private boolean active;
|
||||
|
||||
public static FileWatchManager getInstance() {
|
||||
public static AppFileWatcher getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
INSTANCE = new FileWatchManager();
|
||||
INSTANCE = new AppFileWatcher();
|
||||
INSTANCE.startWatcher();
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ public class FileWatchManager {
|
|||
while (active) {
|
||||
WatchKey key;
|
||||
try {
|
||||
key = FileWatchManager.this.watchService.poll(10, TimeUnit.MILLISECONDS);
|
||||
key = AppFileWatcher.this.watchService.poll(10, TimeUnit.MILLISECONDS);
|
||||
if (key == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public class FileWatchManager {
|
|||
}
|
||||
|
||||
try {
|
||||
dir.register(FileWatchManager.this.watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
|
||||
dir.register(AppFileWatcher.this.watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
|
||||
Files.list(dir).filter(Files::isDirectory).forEach(this::createRecursiveWatchers);
|
||||
} catch (IOException e) {
|
||||
ErrorEvent.fromThrowable(e).omit().handle();
|
||||
|
@ -158,7 +158,7 @@ public class FileWatchManager {
|
|||
// Add new watcher for directory
|
||||
if (ev.kind().equals(ENTRY_CREATE) && Files.isDirectory(file)) {
|
||||
try {
|
||||
file.register(FileWatchManager.this.watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
|
||||
file.register(AppFileWatcher.this.watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
|
||||
} catch (IOException e) {
|
||||
ErrorEvent.fromThrowable(e).omit().handle();
|
||||
}
|
|
@ -39,7 +39,7 @@ public class BaseMode extends OperationMode {
|
|||
AppCharsets.init();
|
||||
AppCharsetter.init();
|
||||
DataStorage.init();
|
||||
FileWatchManager.init();
|
||||
AppFileWatcher.init();
|
||||
FileBridge.init();
|
||||
AppSocketServer.init();
|
||||
AppUpdater.init();
|
||||
|
|
|
@ -45,5 +45,5 @@ public abstract class ScanProvider {
|
|||
return ALL;
|
||||
}
|
||||
|
||||
public abstract ScanOperation create(DataStore store);
|
||||
public abstract ScanOperation create(DataStore store, boolean automatic);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.app.fxcomps.impl;
|
|||
|
||||
import atlantafx.base.controls.Popover;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import io.xpipe.app.comp.base.MarkdownComp;
|
||||
import io.xpipe.app.core.AppFont;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
|
@ -90,6 +91,8 @@ public class OptionsComp extends Comp<CompStructure<Pane>> {
|
|||
AppFont.small(popover.getContentNode());
|
||||
|
||||
var descriptionHover = new Button("... ?");
|
||||
descriptionHover.getStyleClass().add(Styles.BUTTON_OUTLINED);
|
||||
descriptionHover.getStyleClass().add(Styles.ACCENT);
|
||||
descriptionHover.setPadding(new Insets(0, 6, 0, 6));
|
||||
descriptionHover.getStyleClass().add("long-description");
|
||||
AppFont.header(descriptionHover);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.app.fxcomps.impl;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.CompStructure;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
|
@ -55,14 +56,14 @@ public class ToggleGroupComp<T> extends Comp<CompStructure<HBox>> {
|
|||
}
|
||||
|
||||
if (box.getChildren().size() > 0) {
|
||||
box.getChildren().get(0).getStyleClass().add("first");
|
||||
box.getChildren().get(0).getStyleClass().add(Styles.LEFT_PILL);
|
||||
for (int i = 1; i < box.getChildren().size() - 1; i++) {
|
||||
box.getChildren().get(i).getStyleClass().add("center");
|
||||
box.getChildren().get(i).getStyleClass().add(Styles.CENTER_PILL);
|
||||
}
|
||||
box.getChildren()
|
||||
.get(box.getChildren().size() - 1)
|
||||
.getStyleClass()
|
||||
.add("last");
|
||||
.add(Styles.RIGHT_PILL);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ public class UserReportComp extends SimpleComp {
|
|||
.apply(struc -> struc.get().getStyleClass().addAll(BUTTON_OUTLINED, ACCENT))
|
||||
.createRegion();
|
||||
var spacer = new Region();
|
||||
var buttons = new HBox(dataPolicyButton, spacer, sendButton);
|
||||
var buttons = new HBox(spacer, sendButton);
|
||||
buttons.setAlignment(Pos.CENTER);
|
||||
buttons.getStyleClass().add("buttons");
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
|
|
|
@ -13,7 +13,7 @@ public class ApplicationHelper {
|
|||
public static void executeLocalApplication(String s) throws Exception {
|
||||
var args = ShellDialects.getPlatformDefault().executeCommandListWithShell(s);
|
||||
TrackEvent.withDebug("proc", "Executing local application")
|
||||
.elements(args)
|
||||
.tag("command", s)
|
||||
.handle();
|
||||
try (var c = LocalStore.getShell().command(s).start()) {
|
||||
c.discardOrThrow();
|
||||
|
@ -21,9 +21,8 @@ public class ApplicationHelper {
|
|||
}
|
||||
|
||||
public static void executeLocalApplication(List<String> s) throws Exception {
|
||||
var args = ShellDialects.getPlatformDefault().executeCommandListWithShell(s);
|
||||
TrackEvent.withDebug("proc", "Executing local application")
|
||||
.elements(args)
|
||||
.elements(s)
|
||||
.handle();
|
||||
try (var c = LocalStore.getShell().command(s).start()) {
|
||||
c.discardOrThrow();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.core.FileWatchManager;
|
||||
import io.xpipe.app.core.AppFileWatcher;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
|
@ -51,7 +51,7 @@ public class FileBridge {
|
|||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
FileWatchManager.getInstance().startWatchersInDirectories(List.of(TEMP), (changed, kind) -> {
|
||||
AppFileWatcher.getInstance().startWatchersInDirectories(List.of(TEMP), (changed, kind) -> {
|
||||
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
|
||||
event("Editor entry file " + changed.toString() + " has been removed");
|
||||
INSTANCE.removeForFile(changed);
|
||||
|
@ -121,7 +121,7 @@ public class FileBridge {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
public void openString(String keyName, String fileType, Object key, String input, Consumer<String> output, Consumer<String> consumer) {
|
||||
public void openString(String keyName, Object key, String input, Consumer<String> output, Consumer<String> consumer) {
|
||||
if (input == null) {
|
||||
input = "";
|
||||
}
|
||||
|
@ -129,7 +129,6 @@ public class FileBridge {
|
|||
String s = input;
|
||||
openIO(
|
||||
keyName,
|
||||
fileType,
|
||||
key,
|
||||
() -> new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)),
|
||||
() -> new ByteArrayOutputStream(s.length()) {
|
||||
|
@ -144,7 +143,6 @@ public class FileBridge {
|
|||
|
||||
public void openIO(
|
||||
String keyName,
|
||||
String fileType,
|
||||
Object key,
|
||||
FailableSupplier<InputStream, Exception> input,
|
||||
FailableSupplier<OutputStream, Exception> output,
|
||||
|
@ -155,9 +153,7 @@ public class FileBridge {
|
|||
return;
|
||||
}
|
||||
|
||||
var name = keyName + " - " + UUID.randomUUID().toString().substring(0, 6) + "."
|
||||
+ (fileType != null ? fileType : "txt");
|
||||
Path file = TEMP.resolve(name);
|
||||
Path file = TEMP.resolve(UUID.randomUUID().toString().substring(0, 6)).resolve(keyName);
|
||||
try {
|
||||
FileUtils.forceMkdirParent(file.toFile());
|
||||
try (var out = Files.newOutputStream(file);
|
||||
|
|
|
@ -6,7 +6,6 @@ import io.xpipe.core.impl.FileNames;
|
|||
import io.xpipe.core.impl.LocalStore;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -23,7 +22,6 @@ public class FileOpener {
|
|||
FileBridge.get()
|
||||
.openIO(
|
||||
FileNames.getFileName(file),
|
||||
FilenameUtils.getExtension(file),
|
||||
file,
|
||||
() -> {
|
||||
return entry.getFileSystem().openInput(file);
|
||||
|
@ -42,7 +40,6 @@ public class FileOpener {
|
|||
FileBridge.get()
|
||||
.openIO(
|
||||
FileNames.getFileName(file),
|
||||
FilenameUtils.getExtension(file),
|
||||
file,
|
||||
() -> {
|
||||
return entry.getFileSystem().openInput(file);
|
||||
|
@ -67,7 +64,7 @@ public class FileOpener {
|
|||
public static void openInDefaultApplication(String file) {
|
||||
try (var pc = LocalStore.getShell().start()) {
|
||||
if (pc.getOsType().equals(OsType.WINDOWS)) {
|
||||
pc.executeSimpleCommand("\"" + file + "\"");
|
||||
pc.executeSimpleCommand("start \"\" \"" + file + "\"");
|
||||
} else if (pc.getOsType().equals(OsType.LINUX)) {
|
||||
pc.executeSimpleCommand("xdg-open \"" + file + "\"");
|
||||
} else {
|
||||
|
@ -78,7 +75,7 @@ public class FileOpener {
|
|||
}
|
||||
}
|
||||
|
||||
public static void openString(String keyName, String fileType, Object key, String input, Consumer<String> output) {
|
||||
FileBridge.get().openString(keyName, fileType, key, input, output, file -> openInTextEditor(file));
|
||||
public static void openString(String keyName,Object key, String input, Consumer<String> output) {
|
||||
FileBridge.get().openString(keyName, key, input, output, file -> openInTextEditor(file));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.xpipe.app.fxcomps.Comp;
|
|||
import io.xpipe.app.fxcomps.impl.*;
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.Region;
|
||||
|
@ -12,6 +13,7 @@ import net.synedra.validatorfx.Check;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class OptionsBuilder {
|
||||
|
@ -80,7 +82,18 @@ public class OptionsBuilder {
|
|||
props.add(prop);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OptionsBuilder addToggle(Property<Boolean> prop) {
|
||||
var comp = new ToggleGroupComp<>(
|
||||
prop,
|
||||
new SimpleObjectProperty<>(Map.of(
|
||||
Boolean.TRUE,
|
||||
AppI18n.observable("app.yes"),
|
||||
Boolean.FALSE,
|
||||
AppI18n.observable("app.no"))));
|
||||
pushComp(comp);
|
||||
props.add(prop);
|
||||
return this;
|
||||
}
|
||||
public OptionsBuilder addString(Property<String> prop) {
|
||||
return addString(prop, false);
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ import java.util.List;
|
|||
|
||||
public class ScanAlert {
|
||||
|
||||
public static void showIfNeeded(DataStore store) {
|
||||
public static void showIfNeeded(DataStore store, boolean automatic) {
|
||||
var providers = ScanProvider.getAll();
|
||||
var applicable = providers.stream()
|
||||
.map(scanProvider -> scanProvider.create(store))
|
||||
.map(scanProvider -> scanProvider.create(store, automatic))
|
||||
.filter(scanOperation -> scanOperation != null)
|
||||
.toList();
|
||||
if (applicable.size() == 0) {
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
}
|
||||
|
||||
.error-report .buttons {
|
||||
-fx-border-color:-color-accent-fg;
|
||||
-fx-border-width: 0.1em 0 0 0;
|
||||
-fx-border-color: -color-neutral-emphasis;
|
||||
-fx-border-width: 1px 0 0 0;
|
||||
-fx-padding: 1.0em 1.5em 1em 1.5em;
|
||||
-fx-background-color: -color-neutral-muted;
|
||||
-fx-effect: dropshadow(three-pass-box, #333, 6, 0, 0, -1);
|
||||
|
|
|
@ -43,6 +43,6 @@
|
|||
}
|
||||
|
||||
.loading-comp {
|
||||
-fx-background-color: #FFFFFFAA;
|
||||
-fx-background-color: #0002;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,19 @@ public class FileNames {
|
|||
return components.get(components.size() - 1);
|
||||
}
|
||||
|
||||
public static String getExtension(String file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var name = FileNames.getFileName(file);
|
||||
var split = file.split("\\.");
|
||||
if (split.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return split[split.length - 1];
|
||||
}
|
||||
|
||||
public static String join(String... parts) {
|
||||
var joined = String.join("/", parts);
|
||||
return normalize(joined);
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ShellDialects {
|
|||
|
||||
@Override
|
||||
public boolean prioritizeLoading() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
version
2
version
|
@ -1 +1 @@
|
|||
0.5.5
|
||||
0.5.6
|
Loading…
Reference in a new issue