Many small fixes [release]

This commit is contained in:
crschnick 2023-03-05 11:39:38 +00:00
parent c936e37509
commit b7fa352ae5
25 changed files with 164 additions and 85 deletions

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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();

View file

@ -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");

View file

@ -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);

View file

@ -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();

View file

@ -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 -> {

View file

@ -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);

View file

@ -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();
}

View file

@ -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();

View file

@ -45,5 +45,5 @@ public abstract class ScanProvider {
return ALL;
}
public abstract ScanOperation create(DataStore store);
public abstract ScanOperation create(DataStore store, boolean automatic);
}

View file

@ -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);

View file

@ -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);
}
});

View file

@ -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);

View file

@ -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();

View file

@ -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);

View 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));
}
}

View 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);
}

View file

@ -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) {

View file

@ -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);

View file

@ -43,6 +43,6 @@
}
.loading-comp {
-fx-background-color: #FFFFFFAA;
-fx-background-color: #0002;
}

View file

@ -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);

View file

@ -37,7 +37,7 @@ public class ShellDialects {
@Override
public boolean prioritizeLoading() {
return false;
return true;
}
}

View file

@ -1 +1 @@
0.5.5
0.5.6