This commit is contained in:
crschnick 2025-03-05 19:18:52 +00:00
parent fec34c2f70
commit 7337eaf8c3
122 changed files with 624 additions and 486 deletions

View file

@ -15,9 +15,10 @@ public class CategoryAddExchangeImpl extends CategoryAddExchange {
throw new BeaconClientException("Parent category with id " + msg.getParent() + " does not exist");
}
var found = DataStorage.get().getStoreCategories().stream().filter(
dataStoreCategory -> msg.getParent().equals(dataStoreCategory.getParentCategory()) &&
msg.getName().equals(dataStoreCategory.getName())).findAny();
var found = DataStorage.get().getStoreCategories().stream()
.filter(dataStoreCategory -> msg.getParent().equals(dataStoreCategory.getParentCategory())
&& msg.getName().equals(dataStoreCategory.getName()))
.findAny();
if (found.isPresent()) {
return Response.builder().category(found.get().getUuid()).build();
}

View file

@ -2,10 +2,10 @@ package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.app.util.FixedSizeInputStream;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.api.FsReadExchange;
import io.xpipe.app.ext.ConnectionFileSystem;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;

View file

@ -2,8 +2,8 @@ package io.xpipe.app.beacon.impl;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BlobManager;
import io.xpipe.beacon.api.FsWriteExchange;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.beacon.api.FsWriteExchange;
import com.sun.net.httpserver.HttpExchange;
import lombok.SneakyThrows;

View file

@ -7,7 +7,6 @@ import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.util.FileReference;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.util.FailableFunction;

View file

@ -10,7 +10,6 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.util.FailableFunction;

View file

@ -4,7 +4,6 @@ import io.xpipe.app.browser.icon.BrowserIconDirectoryType;
import io.xpipe.app.browser.icon.BrowserIconFileType;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import lombok.Getter;

View file

@ -8,7 +8,6 @@ import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileInfo;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;

View file

@ -294,7 +294,8 @@ public class BrowserFileListCompEntry {
return;
}
model.getFileSystemModel().cdAsync(item.getRawFileEntry().getPath().toString());
model.getFileSystemModel()
.cdAsync(item.getRawFileEntry().getPath().toString());
}
};
DROP_TIMER.schedule(activeTask, 1200);

View file

@ -5,7 +5,6 @@ import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
@ -66,7 +65,10 @@ public final class BrowserFileListModel {
List<BrowserEntry> filtered = fileSystemModel.getFilter().getValue() != null
? all.getValue().stream()
.filter(entry -> {
var name = entry.getRawFileEntry().getPath().getFileName().toLowerCase(Locale.ROOT);
var name = entry.getRawFileEntry()
.getPath()
.getFileName()
.toLowerCase(Locale.ROOT);
var filterString =
fileSystemModel.getFilter().getValue().toLowerCase(Locale.ROOT);
return name.contains(filterString);

View file

@ -1,16 +1,15 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.core.window.AppWindowHelper;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.FileBridge;
import io.xpipe.app.util.FileOpener;
import io.xpipe.core.process.ElevationFunction;
import io.xpipe.core.process.OsType;
import io.xpipe.app.ext.ConnectionFileSystem;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileInfo;
import io.xpipe.core.store.FileNames;
import java.io.FilterOutputStream;
import java.io.IOException;

View file

@ -1,6 +1,7 @@
package io.xpipe.app.browser.file;
import io.xpipe.core.store.FilePath;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.IntegerProperty;

View file

@ -1,7 +1,6 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.core.AppCache;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.util.JacksonMapper;

View file

@ -10,8 +10,8 @@ import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.util.InputHelper;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.core.store.FilePath;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.control.Button;

View file

@ -299,7 +299,10 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
}
// Handle commands typed into navigation bar
if (customInput && !evaluatedPath.isBlank() && !FileNames.isAbsolute(evaluatedPath) && fileSystem.getShell().isPresent()) {
if (customInput
&& !evaluatedPath.isBlank()
&& !FileNames.isAbsolute(evaluatedPath)
&& fileSystem.getShell().isPresent()) {
var directory = currentPath.get();
var name = adjustedPath + " - " + entry.get().getName();
ThreadHelper.runFailableAsync(() -> {

View file

@ -223,8 +223,7 @@ public class BrowserFileTransferOperation {
if (matcher.matches()) {
try {
var number = Integer.parseInt(matcher.group(2));
var newFile =
target.getParent().join(matcher.group(1) + " (" + (number + 1) + ")." + matcher.group(3));
var newFile = target.getParent().join(matcher.group(1) + " (" + (number + 1) + ")." + matcher.group(3));
return newFile;
} catch (NumberFormatException ignored) {
}

View file

@ -1,6 +1,7 @@
package io.xpipe.app.browser.file;
import io.xpipe.core.store.FilePath;
import javafx.collections.ObservableList;
import lombok.AllArgsConstructor;

View file

@ -169,7 +169,9 @@ public class BrowserHistoryTabComp extends SimpleComp {
var name = Bindings.createStringBinding(
() -> {
var n = e.getPath();
return AppPrefs.get().censorMode().get() ? "*".repeat(n.toString().length()) : n.toString();
return AppPrefs.get().censorMode().get()
? "*".repeat(n.toString().length())
: n.toString();
},
AppPrefs.get().censorMode());
return new ButtonComp(name, () -> {

View file

@ -11,7 +11,6 @@ import io.xpipe.app.comp.base.TooltipAugment;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FilePath;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;

View file

@ -3,7 +3,6 @@ package io.xpipe.app.browser.icon;
import io.xpipe.app.resources.AppResources;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import lombok.Getter;
@ -38,7 +37,8 @@ public abstract class BrowserIconDirectoryType {
@Override
public boolean matches(FileEntry entry) {
return entry.getPath().toString().equals("/") || entry.getPath().toString().matches("\\w:\\\\");
return entry.getPath().toString().equals("/")
|| entry.getPath().toString().matches("\\w:\\\\");
}
@Override

View file

@ -3,7 +3,6 @@ package io.xpipe.app.browser.icon;
import io.xpipe.app.resources.AppResources;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import lombok.Getter;

View file

@ -6,12 +6,11 @@ import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.value.ObservableIntegerValue;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.OverrunStyle;
import lombok.AllArgsConstructor;
import java.util.function.Function;
@ -28,15 +27,17 @@ public class CountComp extends Comp<CompStructure<Label>> {
var label = new Label();
label.setTextOverrun(OverrunStyle.CLIP);
label.setAlignment(Pos.CENTER);
var binding = Bindings.createStringBinding(() -> {
if (sub.get() == all.get()) {
return transformation.apply(all.get() + "");
} else {
return transformation.apply(sub.get() + "/" + all.get());
}
}, sub, all);
label.textProperty()
.bind(PlatformThread.sync(binding));
var binding = Bindings.createStringBinding(
() -> {
if (sub.get() == all.get()) {
return transformation.apply(all.get() + "");
} else {
return transformation.apply(sub.get() + "/" + all.get());
}
},
sub,
all);
label.textProperty().bind(PlatformThread.sync(binding));
label.getStyleClass().add("count-comp");
return new SimpleCompStructure<>(label);
}

View file

@ -5,10 +5,10 @@ import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.FileOpener;
import io.xpipe.core.process.ShellScript;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.store.StatefulDataStore;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
@ -27,24 +27,27 @@ import java.nio.file.Files;
public class IntegratedTextAreaComp extends Comp<IntegratedTextAreaComp.Structure> {
public static IntegratedTextAreaComp script(ObservableValue<DataStoreEntryRef<ShellStore>> host, Property<ShellScript> value) {
var string = new SimpleStringProperty(value.getValue() != null ? value.getValue().getValue() : null);
public static IntegratedTextAreaComp script(
ObservableValue<DataStoreEntryRef<ShellStore>> host, Property<ShellScript> value) {
var string = new SimpleStringProperty(
value.getValue() != null ? value.getValue().getValue() : null);
string.addListener((observable, oldValue, newValue) -> {
value.setValue(newValue != null ? new ShellScript(newValue) : null);
});
var i = new IntegratedTextAreaComp(
string,
false,
"script",
Bindings.createStringBinding(
() -> {
return host.getValue() != null && host.getValue().getStore() instanceof StatefulDataStore<?> sd &&
sd.getState() instanceof ShellStoreState sss && sss.getShellDialect() != null
? sss.getShellDialect()
.getScriptFileEnding()
: "sh";
},
host));
string,
false,
"script",
Bindings.createStringBinding(
() -> {
return host.getValue() != null
&& host.getValue().getStore() instanceof StatefulDataStore<?> sd
&& sd.getState() instanceof ShellStoreState sss
&& sss.getShellDialect() != null
? sss.getShellDialect().getScriptFileEnding()
: "sh";
},
host));
i.minHeight(60);
i.prefHeight(60);
i.maxHeight(60);

View file

@ -91,7 +91,8 @@ public class ListSelectorComp<T> extends SimpleComp {
if (showAllSelector.get()) {
var allSelector = new CheckBox(null);
allSelector.setSelected(currentVals.stream().filter(t -> !disable.test(t)).count() == selected.size());
allSelector.setSelected(
currentVals.stream().filter(t -> !disable.test(t)).count() == selected.size());
allSelector.selectedProperty().addListener((observable, oldValue, newValue) -> {
cbs.forEach(checkBox -> {
if (checkBox.isDisabled()) {

View file

@ -5,16 +5,17 @@ import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.util.PlatformThread;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.ObservableList;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.skin.VirtualFlow;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import lombok.Setter;
import java.util.ArrayList;
@ -55,7 +56,6 @@ public class ListVirtualViewComp<T> extends Comp<CompStructure<ScrollPane>> {
vbox.getStyleClass().add("list-box-content");
vbox.setFocusTraversable(false);
var scroll = new ScrollPane(vbox);
if (scrollBar) {
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);

View file

@ -21,7 +21,6 @@ import javafx.scene.control.ButtonBar;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
@ -47,7 +46,8 @@ public class ModalOverlayComp extends SimpleComp {
var bgRegion = background.createRegion();
var modal = new ModalPane();
modal.setInTransitionFactory(null);
modal.setOutTransitionFactory(OsType.getLocal() == OsType.LINUX ? null : node -> Animations.fadeOut(node, Duration.millis(50)));
modal.setOutTransitionFactory(
OsType.getLocal() == OsType.LINUX ? null : node -> Animations.fadeOut(node, Duration.millis(50)));
modal.focusedProperty().addListener((observable, oldValue, newValue) -> {
var c = modal.getContent();
if (newValue && c != null) {
@ -228,13 +228,14 @@ public class ModalOverlayComp extends SimpleComp {
var busy = mocc.busy();
if (busy != null) {
var loading = LoadingOverlayComp.noProgress(Comp.of(() -> modalBox), busy);
// loading.apply(struc -> {
// var bg = struc.get().getChildren().getFirst();
// struc.get().getChildren().get(1).addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
// bg.fireEvent(event);
// event.consume();
// });
// });
// loading.apply(struc -> {
// var bg = struc.get().getChildren().getFirst();
// struc.get().getChildren().get(1).addEventFilter(MouseEvent.MOUSE_PRESSED, event ->
// {
// bg.fireEvent(event);
// event.consume();
// });
// });
return loading.createRegion();
}
}

View file

@ -12,7 +12,6 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreCategory;
import io.xpipe.app.util.ClipboardHelper;
import io.xpipe.app.util.ContextMenuHelper;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.util.LabelGraphic;
import javafx.beans.binding.Bindings;
@ -118,7 +117,10 @@ public class StoreCategoryComp extends SimpleComp {
}))
.styleClass("status-button");
var count = new CountComp(category.getShownContainedEntriesCount(), category.getAllContainedEntriesCount(), string -> "(" + string + ")");
var count = new CountComp(
category.getShownContainedEntriesCount(),
category.getAllContainedEntriesCount(),
string -> "(" + string + ")");
count.visible(Bindings.notEqual(0, category.getShownContainedEntriesCount()));
var showStatus = hover.or(new SimpleBooleanProperty(DataStorage.get().supportsSharing()))
@ -134,7 +136,8 @@ public class StoreCategoryComp extends SimpleComp {
statusButton.hide(showStatus.not())));
h.padding(new Insets(0, 10, 0, (category.getDepth() * 10)));
var categoryButton = new ButtonComp(null, new SimpleObjectProperty<>(new LabelGraphic.CompGraphic(h)), category::select)
var categoryButton = new ButtonComp(
null, new SimpleObjectProperty<>(new LabelGraphic.CompGraphic(h)), category::select)
.focusTraversable()
.styleClass("category-button")
.apply(struc -> hover.bind(struc.get().hoverProperty()))

View file

@ -10,7 +10,6 @@ import io.xpipe.app.util.PlatformThread;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ObservableNumberValue;
import javafx.beans.value.ObservableStringValue;
import javafx.collections.FXCollections;
@ -185,17 +184,22 @@ public class StoreCategoryWrapper {
.equals(storeCategoryWrapper.getCategory().getParentCategory()))
.toList());
var direct = directContainedEntries.getList().size();
var sub = children.getList().stream().mapToInt(value -> value.allContainedEntriesCount.get()).sum();
var sub = children.getList().stream()
.mapToInt(value -> value.allContainedEntriesCount.get())
.sum();
allContainedEntriesCount.setValue(direct + sub);
var directFiltered = directContainedEntries.getList().stream().filter(storeEntryWrapper ->
storeEntryWrapper.matchesFilter(StoreViewState.get().getFilterString().getValue())).count();
var subFiltered = children.getList().stream().mapToInt(value -> value.shownContainedEntriesCount.get()).sum();
var directFiltered = directContainedEntries.getList().stream()
.filter(storeEntryWrapper -> storeEntryWrapper.matchesFilter(
StoreViewState.get().getFilterString().getValue()))
.count();
var subFiltered = children.getList().stream()
.mapToInt(value -> value.shownContainedEntriesCount.get())
.sum();
shownContainedEntriesCount.setValue(directFiltered + subFiltered);
Optional.ofNullable(getParent()).ifPresent(storeCategoryWrapper -> {
storeCategoryWrapper.update();
});
}
private String translatedName(String original) {

View file

@ -449,8 +449,13 @@ public class StoreCreationComp extends DialogComp {
private Region createStoreProperties(Comp<?> comp, Validator propVal) {
var p = provider.getValue();
var nameKey = p == null || p.getCreationCategory() == null || p.getCreationCategory().getCategory().equals(DataStorage.ALL_CONNECTIONS_CATEGORY_UUID) ?
"connection" : p.getCreationCategory().getCategory().equals(DataStorage.ALL_SCRIPTS_CATEGORY_UUID) ? "script" : "identity";
var nameKey = p == null
|| p.getCreationCategory() == null
|| p.getCreationCategory().getCategory().equals(DataStorage.ALL_CONNECTIONS_CATEGORY_UUID)
? "connection"
: p.getCreationCategory().getCategory().equals(DataStorage.ALL_SCRIPTS_CATEGORY_UUID)
? "script"
: "identity";
return new OptionsBuilder()
.addComp(comp, store)
.name(nameKey + "Name")

View file

@ -8,7 +8,6 @@ import io.xpipe.app.storage.DataColor;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreCategory;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.DataStore;
@ -16,7 +15,6 @@ import io.xpipe.core.store.SingletonSessionStore;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ObservableStringValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
@ -186,7 +184,7 @@ public class StoreEntryWrapper {
validity.setValue(entry.getValidity());
expanded.setValue(entry.isExpanded());
persistentState.setValue(entry.getStorePersistentState());
// The property values are only registered as changed once they are queried
// If we use information bindings that depend on some of these properties
// but use the store methods to retrieve data instead of the wrapper properties,

View file

@ -1,31 +1,26 @@
package io.xpipe.app.comp.store;
import atlantafx.base.theme.Styles;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.icon.SystemIcon;
import io.xpipe.app.icon.SystemIconCache;
import io.xpipe.app.icon.SystemIconManager;
import io.xpipe.app.resources.AppImages;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.LabelGraphic;
import io.xpipe.app.util.ThreadHelper;
import javafx.application.Platform;
import javafx.beans.property.*;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.Region;
import atlantafx.base.theme.Tweaks;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import atlantafx.base.theme.Styles;
import atlantafx.base.theme.Tweaks;
import java.util.*;
import static atlantafx.base.theme.Styles.TEXT_SMALL;
@ -40,7 +35,8 @@ public class StoreIconChoiceComp extends SimpleComp {
private final Runnable doubleClick;
public StoreIconChoiceComp(
Runnable reshow, Property<SystemIcon> selected,
Runnable reshow,
Property<SystemIcon> selected,
Set<SystemIcon> icons,
int columns,
SimpleStringProperty filter,
@ -83,17 +79,23 @@ public class StoreIconChoiceComp extends SimpleComp {
table.getStyleClass().add("icon-browser");
var busy = new SimpleBooleanProperty(false);
var refreshButton = new ButtonComp(AppI18n.observable("refreshIcons"), new SimpleObjectProperty<>(new LabelGraphic.IconGraphic("mdi2r-refresh")), () -> {
ThreadHelper.runFailableAsync(() -> {
try (var ignored = new BooleanScope(busy).start()) {
SystemIconManager.reload();
}
reshow.run();
});
});
var refreshButton = new ButtonComp(
AppI18n.observable("refreshIcons"),
new SimpleObjectProperty<>(new LabelGraphic.IconGraphic("mdi2r-refresh")),
() -> {
ThreadHelper.runFailableAsync(() -> {
try (var ignored = new BooleanScope(busy).start()) {
SystemIconManager.reload();
}
reshow.run();
});
});
refreshButton.disable(busy);
var text = new LabelComp(AppI18n.observable("refreshIconsDescription", SystemIconManager.getSources().values().stream()
.mapToInt(value -> value.getIcons().size()).sum()));
var text = new LabelComp(AppI18n.observable(
"refreshIconsDescription",
SystemIconManager.getSources().values().stream()
.mapToInt(value -> value.getIcons().size())
.sum()));
text.apply(struc -> {
struc.get().setWrapText(true);
struc.get().setTextAlignment(TextAlignment.CENTER);
@ -109,7 +111,9 @@ public class StoreIconChoiceComp extends SimpleComp {
private void updateData(TableView<List<SystemIcon>> table, String filterString) {
var displayedIcons = filterString == null || filterString.isBlank() || filterString.length() < 2
? icons.stream().sorted(Comparator.<SystemIcon, String>comparing(systemIcon -> systemIcon.getId())).toList()
? icons.stream()
.sorted(Comparator.<SystemIcon, String>comparing(systemIcon -> systemIcon.getId()))
.toList()
: icons.stream()
.filter(icon -> containsString(icon.getId(), filterString))
.toList();

View file

@ -5,7 +5,6 @@ import io.xpipe.app.icon.SystemIcon;
import io.xpipe.app.icon.SystemIconManager;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.Hyperlinks;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
@ -38,21 +37,27 @@ public class StoreIconChoiceDialog {
var filter = new FilterComp(filterText).grow(true, false);
filter.focusOnShow();
var github = new ButtonComp(null, new FontIcon("mdomz-settings"), () -> {
overlay.close();
AppPrefs.get().selectCategory("icons");
overlay.close();
AppPrefs.get().selectCategory("icons");
})
.grow(false, true);
var modal = ModalOverlay.of(
"chooseCustomIcon",
new StoreIconChoiceComp(() -> {
var showing = overlay.isShowing();
overlay.close();
if (showing) {
Platform.runLater(() -> overlay.show());
}
}, selected, SystemIconManager.getIcons(), 5, filterText, () -> {
finish();
})
new StoreIconChoiceComp(
() -> {
var showing = overlay.isShowing();
overlay.close();
if (showing) {
Platform.runLater(() -> overlay.show());
}
},
selected,
SystemIconManager.getIcons(),
5,
filterText,
() -> {
finish();
})
.prefWidth(600));
modal.addButtonBarComp(github);
modal.addButtonBarComp(filter);
@ -72,7 +77,12 @@ public class StoreIconChoiceDialog {
}
private void finish() {
entry.setIcon(selected.get() != null ? selected.getValue().getSource().getId() + "/" + selected.getValue().getId() : null, true);
entry.setIcon(
selected.get() != null
? selected.getValue().getSource().getId() + "/"
+ selected.getValue().getId()
: null,
true);
overlay.close();
}
}

View file

@ -85,9 +85,8 @@ public class StoreSection {
}
});
var comp = explicitOrderComp;
var mappedSortMode = BindingsHelper.flatMap(
category,
storeCategoryWrapper -> storeCategoryWrapper.getSortMode());
var mappedSortMode =
BindingsHelper.flatMap(category, storeCategoryWrapper -> storeCategoryWrapper.getSortMode());
return list.sorted(
(o1, o2) -> {
var r = comp.compare(o1, o2);
@ -114,7 +113,8 @@ public class StoreSection {
ObservableIntegerValue updateObservable) {
var topLevel = all.filtered(
section -> {
return DataStorage.get().isRootEntry(section.getEntry(), category.getValue().getCategory());
return DataStorage.get()
.isRootEntry(section.getEntry(), category.getValue().getCategory());
},
category,
updateObservable);
@ -200,7 +200,10 @@ public class StoreSection {
// If this entry is already shown as root due to a different category than parent, don't
// show it
// again here
!DataStorage.get().isRootEntry(section.getWrapper().getEntry(), category.getValue().getCategory());
!DataStorage.get()
.isRootEntry(
section.getWrapper().getEntry(),
category.getValue().getCategory());
},
category,
filterString,

View file

@ -7,34 +7,20 @@ import io.xpipe.app.prefs.SupportedLocale;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.PlatformState;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.core.util.XPipeInstallation;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import lombok.Value;
import org.apache.commons.io.FilenameUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
public class AppI18n {
private static AppI18n INSTANCE;
private final Property<AppI18nData> currentLanguage = new SimpleObjectProperty<>();
private final ObservableValue<SupportedLocale> currentLocale = BindingsHelper.map(currentLanguage,appI18nData -> appI18nData.getLocale());
private final ObservableValue<SupportedLocale> currentLocale =
BindingsHelper.map(currentLanguage, appI18nData -> appI18nData.getLocale());
private final Map<String, ObservableValue<String>> observableCache = new HashMap<>();
private AppI18nData english;
@ -71,9 +57,11 @@ public class AppI18n {
// Don't cache vars
if (vars.length > 0) {
var binding = Bindings.createStringBinding(() -> {
return getLocalised(key, vars);
}, currentLanguage);
var binding = Bindings.createStringBinding(
() -> {
return getLocalised(key, vars);
},
currentLanguage);
return binding;
}
@ -82,9 +70,11 @@ public class AppI18n {
return found;
}
var binding = Bindings.createStringBinding(() -> {
return getLocalised(key, vars);
}, currentLanguage);
var binding = Bindings.createStringBinding(
() -> {
return getLocalised(key, vars);
},
currentLanguage);
observableCache.put(key, binding);
return binding;
}

View file

@ -4,6 +4,7 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.SupportedLocale;
import io.xpipe.core.util.XPipeInstallation;
import lombok.Value;
import org.apache.commons.io.FilenameUtils;
@ -123,5 +124,4 @@ public class AppI18nData {
var ending = "_" + l.toLanguageTag();
return name.endsWith(ending);
}
}

View file

@ -4,7 +4,6 @@ import io.xpipe.app.browser.BrowserFullSessionComp;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.store.StoreLayoutComp;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.prefs.AppPrefsComp;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.LabelGraphic;

View file

@ -6,8 +6,8 @@ import io.xpipe.app.ext.ActionProvider;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.core.store.FilePath;
import lombok.Value;
import java.net.URI;

View file

@ -2,7 +2,6 @@ package io.xpipe.app.core.window;
import io.xpipe.app.comp.base.AppLayoutComp;
import io.xpipe.app.comp.base.AppMainWindowContentComp;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.*;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.issue.ErrorEvent;

View file

@ -141,7 +141,12 @@ public interface ActionProvider {
};
}
static <T extends DataStore> LeafDataStoreCallSite<T> simple(boolean major, String nameKey, String icon, Class<T> applicableClass, FailableConsumer<DataStoreEntryRef<T>, Exception> action) {
static <T extends DataStore> LeafDataStoreCallSite<T> simple(
boolean major,
String nameKey,
String icon,
Class<T> applicableClass,
FailableConsumer<DataStoreEntryRef<T>, Exception> action) {
return new LeafDataStoreCallSite<T>() {
@Override
public boolean isMajor(DataStoreEntryRef<T> o) {

View file

@ -3,11 +3,11 @@ package io.xpipe.app.ext;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.ShellControl;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.store.FileSystem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import java.io.InputStream;
@ -29,8 +29,10 @@ public class ConnectionFileSystem implements FileSystem {
@Override
public long getFileSize(FilePath file) throws Exception {
return Long.parseLong(
shellControl.getShellDialect().queryFileSize(shellControl, file.toString()).readStdoutOrThrow());
return Long.parseLong(shellControl
.getShellDialect()
.queryFileSize(shellControl, file.toString())
.readStdoutOrThrow());
}
@Override
@ -69,7 +71,8 @@ public class ConnectionFileSystem implements FileSystem {
@Override
public OutputStream openOutput(FilePath file, long totalBytes) throws Exception {
var cmd = shellControl.getShellDialect().createStreamFileWriteCommand(shellControl, file.toString(), totalBytes);
var cmd =
shellControl.getShellDialect().createStreamFileWriteCommand(shellControl, file.toString(), totalBytes);
cmd.setExitTimeout(Duration.ofMillis(Long.MAX_VALUE));
return cmd.startExternalStdin();
}
@ -167,7 +170,11 @@ public class ConnectionFileSystem implements FileSystem {
@Override
public List<FilePath> listRoots() throws Exception {
return shellControl.getShellDialect().listRoots(shellControl).map(s -> FilePath.of(s)).toList();
return shellControl
.getShellDialect()
.listRoots(shellControl)
.map(s -> FilePath.of(s))
.toList();
}
@Override

View file

@ -42,9 +42,7 @@ public class DataStoreProviders {
throw new IllegalStateException("Not initialized");
}
return ALL.stream()
.filter(d -> d.getId().equalsIgnoreCase(id))
.findAny();
return ALL.stream().filter(d -> d.getId().equalsIgnoreCase(id)).findAny();
}
@SuppressWarnings("unchecked")

View file

@ -1,15 +1,14 @@
package io.xpipe.app.icon;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.issue.ErrorEvent;
import com.github.weisj.jsvg.SVGDocument;
import com.github.weisj.jsvg.SVGRenderingHints;
import com.github.weisj.jsvg.attributes.ViewBox;
import com.github.weisj.jsvg.parser.SVGLoader;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.resources.AppImages;
import lombok.Getter;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
@ -18,11 +17,13 @@ import java.nio.file.*;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
import javax.imageio.ImageIO;
public class SystemIconCache {
private static final Path DIRECTORY = AppProperties.get().getDataDir().resolve("cache").resolve("icons").resolve("raster");
private static final int[] sizes = new int[]{16, 24, 40, 80};
private static final Path DIRECTORY =
AppProperties.get().getDataDir().resolve("cache").resolve("icons").resolve("raster");
private static final int[] sizes = new int[] {16, 24, 40, 80};
@Getter
private static boolean built = false;
@ -49,11 +50,11 @@ public class SystemIconCache {
Files.createDirectories(target);
for (var icon : e.getValue().getIcons()) {
if (refreshChecksum(icon.getFile(),target,icon.getName(), icon.isDark())) {
if (refreshChecksum(icon.getFile(), target, icon.getName(), icon.isDark())) {
continue;
}
rasterizeSizes(icon.getFile(),target,icon.getName(), icon.isDark());
rasterizeSizes(icon.getFile(), target, icon.getName(), icon.isDark());
}
}
} catch (Exception e) {
@ -110,6 +111,6 @@ public class SystemIconCache {
g.dispose();
var out = dir.resolve(name + "-" + px + (dark ? "-dark" : "") + ".png");
ImageIO.write(image,"png", out.toFile());
ImageIO.write(image, "png", out.toFile());
}
}

View file

@ -12,7 +12,8 @@ import java.util.*;
public class SystemIconManager {
private static final Path DIRECTORY = AppProperties.get().getDataDir().resolve("cache").resolve("icons").resolve("pool");
private static final Path DIRECTORY =
AppProperties.get().getDataDir().resolve("cache").resolve("icons").resolve("pool");
private static final Map<SystemIconSource, SystemIconSourceData> LOADED = new HashMap<>();
private static final Set<SystemIcon> ICONS = new HashSet<>();
@ -20,8 +21,14 @@ public class SystemIconManager {
public static List<SystemIconSource> getEffectiveSources() {
var prefs = AppPrefs.get().getIconSources().getValue();
var all = new ArrayList<SystemIconSource>();
all.add(SystemIconSource.Directory.builder().path(DataStorage.get().getIconsDir()).id("custom").build());
all.add(SystemIconSource.GitRepository.builder().remote("https://github.com/selfhst/icons").id("selfhst").build());
all.add(SystemIconSource.Directory.builder()
.path(DataStorage.get().getIconsDir())
.id("custom")
.build());
all.add(SystemIconSource.GitRepository.builder()
.remote("https://github.com/selfhst/icons")
.id("selfhst")
.build());
for (var pref : prefs) {
if (!all.contains(pref)) {
all.add(pref);
@ -53,7 +60,7 @@ public class SystemIconManager {
LOADED.clear();
for (var source : getEffectiveSources()) {
LOADED.put(source,SystemIconSourceData.of(source));
LOADED.put(source, SystemIconSourceData.of(source));
}
ICONS.clear();
@ -88,6 +95,10 @@ public class SystemIconManager {
}
public static Path getPoolPath() {
return AppProperties.get().getDataDir().resolve("cache").resolve("icons").resolve("pool");
return AppProperties.get()
.getDataDir()
.resolve("cache")
.resolve("icons")
.resolve("pool");
}
}

View file

@ -1,14 +1,15 @@
package io.xpipe.app.icon;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.util.DesktopHelper;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.Builder;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
@ -16,11 +17,10 @@ import lombok.extern.jackson.Jacksonized;
import java.nio.file.Files;
import java.nio.file.Path;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = SystemIconSource.Directory.class),
@JsonSubTypes.Type(value = SystemIconSource.GitRepository.class)
@JsonSubTypes.Type(value = SystemIconSource.Directory.class),
@JsonSubTypes.Type(value = SystemIconSource.GitRepository.class)
})
public interface SystemIconSource {
@ -28,7 +28,7 @@ public interface SystemIconSource {
@Builder
@Jacksonized
@JsonTypeName("directory")
static class Directory implements SystemIconSource{
static class Directory implements SystemIconSource {
Path path;
String id;
@ -69,19 +69,26 @@ public interface SystemIconSource {
@Builder
@Jacksonized
@JsonTypeName("git")
static class GitRepository implements SystemIconSource{
static class GitRepository implements SystemIconSource {
String remote;
String id;
@Override
public void refresh() throws Exception {
try (var sc = ProcessControlProvider.get().createLocalProcessControl(true).start()) {
try (var sc =
ProcessControlProvider.get().createLocalProcessControl(true).start()) {
var dir = SystemIconManager.getPoolPath().resolve(id);
if (!Files.exists(dir)) {
sc.command(CommandBuilder.of().add("git", "clone").addQuoted(remote).addFile(dir.toString())).execute();
sc.command(CommandBuilder.of()
.add("git", "clone")
.addQuoted(remote)
.addFile(dir.toString()))
.execute();
} else {
sc.command(CommandBuilder.of().add("git", "pull")).withWorkingDirectory(FilePath.of(dir)).execute();
sc.command(CommandBuilder.of().add("git", "pull"))
.withWorkingDirectory(FilePath.of(dir))
.execute();
}
}
}

View file

@ -1,15 +1,14 @@
package io.xpipe.app.icon;
import io.xpipe.app.issue.ErrorEvent;
import lombok.Value;
import org.apache.commons.io.FilenameUtils;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;

View file

@ -3,7 +3,6 @@ package io.xpipe.app.issue;
import io.xpipe.app.core.AppLogs;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.util.Deobfuscator;
import java.nio.file.Path;

View file

@ -78,8 +78,9 @@ public class TerminalErrorHandler extends GuiErrorHandlerBase implements ErrorHa
try {
var rel = XPipeDistributionType.get().getUpdateHandler().refreshUpdateCheck(false, false);
if (rel != null && rel.isUpdate()) {
var updateModal =
ModalOverlay.of("updateAvailableTitle", AppDialog.dialogText(AppI18n.get("updateAvailableContent", rel.getVersion())));
var updateModal = ModalOverlay.of(
"updateAvailableTitle",
AppDialog.dialogText(AppI18n.get("updateAvailableContent", rel.getVersion())));
updateModal.addButton(
new ModalButton("checkOutUpdate", () -> Hyperlinks.open(rel.getReleaseUrl()), false, true));
updateModal.addButton(new ModalButton("ignore", null, true, false));

View file

@ -1,6 +1,5 @@
package io.xpipe.app.prefs;
import com.fasterxml.jackson.core.type.TypeReference;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.core.*;
import io.xpipe.app.core.mode.OperationMode;
@ -21,6 +20,7 @@ import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableStringValue;
import javafx.beans.value.ObservableValue;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.SimpleType;
import com.fasterxml.jackson.databind.type.TypeFactory;
@ -84,9 +84,11 @@ public class AppPrefs {
.key("iconSources")
.valueType(TypeFactory.defaultInstance().constructType(new TypeReference<List<SystemIconSource>>() {}))
.build());
public final ObservableValue<List<SystemIconSource>> getIconSources() {
return iconSources;
}
public final BooleanProperty disableCertutilUse =
mapLocal(new SimpleBooleanProperty(false), "disableCertutilUse", Boolean.class, false);
public final BooleanProperty useLocalFallbackShell =
@ -99,8 +101,11 @@ public class AppPrefs {
mapVaultShared(new SimpleBooleanProperty(false), "dontCachePasswords", Boolean.class, false);
public final BooleanProperty denyTempScriptCreation =
mapVaultShared(new SimpleBooleanProperty(false), "denyTempScriptCreation", Boolean.class, false);
final Property<ExternalPasswordManager> passwordManager =
mapVaultShared(new SimpleObjectProperty<>(ExternalPasswordManager.NONE), "passwordManager", ExternalPasswordManager.class, false);
final Property<ExternalPasswordManager> passwordManager = mapVaultShared(
new SimpleObjectProperty<>(ExternalPasswordManager.NONE),
"passwordManager",
ExternalPasswordManager.class,
false);
final StringProperty passwordManagerCommand =
mapLocal(new SimpleStringProperty(""), "passwordManagerCommand", String.class, false);
final ObjectProperty<StartupBehaviour> startupBehaviour = mapLocal(

View file

@ -1,9 +1,5 @@
package io.xpipe.app.prefs;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.util.TokenBuffer;
import io.xpipe.app.ext.PrefsChoiceValue;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
@ -13,9 +9,9 @@ import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.util.TokenBuffer;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;

View file

@ -64,13 +64,14 @@ public interface ExternalEditorType extends PrefsChoiceValue {
@Override
protected Optional<Path> determineInstallation() {
var found =
WindowsRegistry.local().readStringValueIfPresent(WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Notepad++", null);
var found = WindowsRegistry.local()
.readStringValueIfPresent(WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Notepad++", null);
// Check 32 bit install
if (found.isEmpty()) {
found = WindowsRegistry.local()
.readStringValueIfPresent(WindowsRegistry.HKEY_LOCAL_MACHINE, "WOW6432Node\\SOFTWARE\\Notepad++", null);
.readStringValueIfPresent(
WindowsRegistry.HKEY_LOCAL_MACHINE, "WOW6432Node\\SOFTWARE\\Notepad++", null);
}
return found.map(p -> p + "\\notepad++.exe").map(Path::of);
}

View file

@ -83,7 +83,8 @@ public interface ExternalRdpClientType extends PrefsChoiceValue {
protected Optional<Path> determineInstallation() {
try {
var r = WindowsRegistry.local()
.readStringValueIfPresent(WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\rdm\\DefaultIcon");
.readStringValueIfPresent(
WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\rdm\\DefaultIcon");
return r.map(Path::of);
} catch (Exception e) {
ErrorEvent.fromThrowable(e).omit().handle();

View file

@ -3,26 +3,19 @@ package io.xpipe.app.prefs;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.ext.PrefsChoiceValue;
import io.xpipe.app.icon.SystemIcon;
import io.xpipe.app.icon.SystemIconCache;
import io.xpipe.app.icon.SystemIconManager;
import io.xpipe.app.icon.SystemIconSource;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStorageUserHandler;
import io.xpipe.app.util.*;
import io.xpipe.core.store.FilePath;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.TextField;
import org.kordamp.ikonli.javafx.FontIcon;
import java.nio.file.Path;
import java.util.ArrayList;
@ -41,10 +34,7 @@ public class IconsCategory extends AppPrefsCategory {
var prefs = AppPrefs.get();
return new OptionsBuilder()
.addTitle("customIcons")
.sub(new OptionsBuilder()
.nameAndDescription("iconSources")
.addComp(createOverview())
)
.sub(new OptionsBuilder().nameAndDescription("iconSources").addComp(createOverview()))
.buildComp();
}
@ -67,58 +57,81 @@ public class IconsCategory extends AppPrefsCategory {
refreshButton.disable(PlatformThread.sync(busy.or(Bindings.isEmpty(sources))));
refreshButton.grow(true, false);
var addGitButton = new TileButtonComp("addGitIconSource", "addGitIconSourceDescription", "mdi2a-access-point-plus", e -> {
var remote = new SimpleStringProperty();
var modal = ModalOverlay.of(
"repositoryUrl",
Comp.of(() -> {
var creationName = new TextField();
creationName.textProperty().bindBidirectional(remote);
return creationName;
})
.prefWidth(350));
modal.withDefaultButtons(() -> {
if (remote.get() == null || remote.get().isBlank()) {
return;
}
var addGitButton =
new TileButtonComp("addGitIconSource", "addGitIconSourceDescription", "mdi2a-access-point-plus", e -> {
var remote = new SimpleStringProperty();
var modal = ModalOverlay.of(
"repositoryUrl",
Comp.of(() -> {
var creationName = new TextField();
creationName.textProperty().bindBidirectional(remote);
return creationName;
})
.prefWidth(350));
modal.withDefaultButtons(() -> {
if (remote.get() == null || remote.get().isBlank()) {
return;
}
var source = SystemIconSource.GitRepository.builder().remote(remote.get()).id(UUID.randomUUID().toString()).build();
if (!sources.contains(source)) {
sources.add(source);
var nl = new ArrayList<>(AppPrefs.get().getIconSources().getValue());
nl.add(source);
AppPrefs.get().iconSources.setValue(nl);
}
});
modal.show();
e.consume();
});
var source = SystemIconSource.GitRepository.builder()
.remote(remote.get())
.id(UUID.randomUUID().toString())
.build();
if (!sources.contains(source)) {
sources.add(source);
var nl = new ArrayList<>(
AppPrefs.get().getIconSources().getValue());
nl.add(source);
AppPrefs.get().iconSources.setValue(nl);
}
});
modal.show();
e.consume();
});
addGitButton.grow(true, false);
var addDirectoryButton = new TileButtonComp("addDirectoryIconSource", "addDirectoryIconSourceDescription", "mdi2f-folder-plus", e -> {
var dir = new SimpleObjectProperty<FilePath>();
var modal = ModalOverlay.of(
"iconDirectory",
new ContextualFileReferenceChoiceComp(new SimpleObjectProperty<>(DataStorage.get().local().ref()),dir,null,List.of()).prefWidth(350));
modal.withDefaultButtons(() -> {
if (dir.get() == null) {
return;
}
var addDirectoryButton = new TileButtonComp(
"addDirectoryIconSource", "addDirectoryIconSourceDescription", "mdi2f-folder-plus", e -> {
var dir = new SimpleObjectProperty<FilePath>();
var modal = ModalOverlay.of(
"iconDirectory",
new ContextualFileReferenceChoiceComp(
new SimpleObjectProperty<>(
DataStorage.get().local().ref()),
dir,
null,
List.of())
.prefWidth(350));
modal.withDefaultButtons(() -> {
if (dir.get() == null) {
return;
}
var source = SystemIconSource.Directory.builder().path(Path.of(dir.get().toString())).id(UUID.randomUUID().toString()).build();
if (!sources.contains(source)) {
sources.add(source);
var nl = new ArrayList<>(AppPrefs.get().getIconSources().getValue());
nl.add(source);
AppPrefs.get().iconSources.setValue(nl);
}
});
modal.show();
e.consume();
});
var source = SystemIconSource.Directory.builder()
.path(Path.of(dir.get().toString()))
.id(UUID.randomUUID().toString())
.build();
if (!sources.contains(source)) {
sources.add(source);
var nl = new ArrayList<>(
AppPrefs.get().getIconSources().getValue());
nl.add(source);
AppPrefs.get().iconSources.setValue(nl);
}
});
modal.show();
e.consume();
});
addDirectoryButton.grow(true, false);
var vbox = new VerticalComp(List.of(Comp.vspacer(10), box, Comp.separator(), refreshButton, Comp.separator(), addDirectoryButton, addGitButton));
var vbox = new VerticalComp(List.of(
Comp.vspacer(10),
box,
Comp.separator(),
refreshButton,
Comp.separator(),
addDirectoryButton,
addGitButton));
vbox.spacing(10);
return vbox;
}
@ -141,7 +154,10 @@ public class IconsCategory extends AppPrefsCategory {
}
var tile = new TileButtonComp(
new SimpleStringProperty(AppPrefs.get().getIconSources().getValue().contains(source) ? source.getDisplayName() : source.getId()),
new SimpleStringProperty(
AppPrefs.get().getIconSources().getValue().contains(source)
? source.getDisplayName()
: source.getId()),
new SimpleStringProperty(source.getDescription()),
new SimpleObjectProperty<>(source.getIcon()),
actionEvent -> {

View file

@ -36,7 +36,11 @@ public class PasswordManagerCategory extends AppPrefsCategory {
private static class Choice {
public static Choice ofOther(ExternalPasswordManager externalPasswordManager) {
return new Choice(externalPasswordManager.getId(), null, externalPasswordManager.getDocsLink(),externalPasswordManager);
return new Choice(
externalPasswordManager.getId(),
null,
externalPasswordManager.getDocsLink(),
externalPasswordManager);
}
String id;

View file

@ -14,7 +14,6 @@ import java.util.Locale;
@AllArgsConstructor
@Getter
public enum SupportedLocale implements PrefsChoiceValue {
ENGLISH(Locale.ENGLISH, "en", false),
GERMAN(Locale.GERMAN, "de", false),
DUTCH(Locale.of("nl"), "nl", false),
@ -38,7 +37,8 @@ public enum SupportedLocale implements PrefsChoiceValue {
public static SupportedLocale getInitial() {
var s = Locale.getDefault();
return Arrays.stream(values())
.filter(supportedLocale -> supportedLocale.isSetDefault() && supportedLocale.getLocale().getLanguage().equals(s.getLanguage()))
.filter(supportedLocale -> supportedLocale.isSetDefault()
&& supportedLocale.getLocale().getLanguage().equals(s.getLanguage()))
.findFirst()
.orElse(getEnglish());
}

View file

@ -72,7 +72,6 @@ public class AppImages {
TrackEvent.trace("Loaded images in " + module + ":" + dir + " in " + elapsed.toMillis() + " ms");
}
public static void loadRasterImages(Path directory, String prefix) throws IOException {
if (!Files.isDirectory(directory)) {
return;

View file

@ -2,16 +2,13 @@ package io.xpipe.app.storage;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.Value;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.regex.Matcher;
@ -26,7 +23,9 @@ public class ContextualFileReference {
private static FilePath getDataDir() {
if (DataStorage.get() == null) {
return lastDataDir != null ? lastDataDir : FilePath.of(AppPrefs.DEFAULT_STORAGE_DIR.resolve("data")).toUnix();
return lastDataDir != null
? lastDataDir
: FilePath.of(AppPrefs.DEFAULT_STORAGE_DIR.resolve("data")).toUnix();
}
return lastDataDir = FilePath.of(DataStorage.get().getDataDir()).toUnix();
@ -65,7 +64,8 @@ public class ContextualFileReference {
}
public FilePath toAbsoluteFilePath(ShellControl sc) {
return FilePath.of(path.replaceAll("/", Matcher.quoteReplacement(sc != null ? sc.getOsType().getFileSystemSeparator() : "/")));
return FilePath.of(path.replaceAll(
"/", Matcher.quoteReplacement(sc != null ? sc.getOsType().getFileSystemSeparator() : "/")));
}
public boolean isInDataDirectory() {

View file

@ -444,7 +444,9 @@ public abstract class DataStorage {
try {
List<? extends DataStoreEntryRef<? extends FixedChildStore>> l = h.listChildren();
if (l != null) {
newChildren = l.stream().filter(dataStoreEntryRef -> dataStoreEntryRef != null && dataStoreEntryRef.get() != null).toList();
newChildren = l.stream()
.filter(dataStoreEntryRef -> dataStoreEntryRef != null && dataStoreEntryRef.get() != null)
.toList();
} else {
newChildren = null;
}
@ -490,24 +492,31 @@ public abstract class DataStorage {
.filter(oc -> oc.getStore() instanceof FixedChildStore)
.filter(oc -> getFixedChildId(oc).isPresent())
.noneMatch(oc -> {
return getFixedChildId(oc).getAsInt()
== nid.getAsInt();
return getFixedChildId(oc).getAsInt() == nid.getAsInt();
});
})
.toList();
var toUpdate = new ArrayList<>(oldChildren.stream().map(oc -> {
var oid = getFixedChildId(oc);
if (oid.isEmpty()) {
return new Pair<DataStoreEntry, DataStoreEntryRef<? extends FixedChildStore>>(oc, null);
}
var toUpdate = new ArrayList<>(oldChildren.stream()
.map(oc -> {
var oid = getFixedChildId(oc);
if (oid.isEmpty()) {
return new Pair<DataStoreEntry, DataStoreEntryRef<? extends FixedChildStore>>(oc, null);
}
var found = newChildren.stream().filter(nc -> getFixedChildId(nc.get()).isPresent()).filter(nc -> getFixedChildId(nc.get()).getAsInt() ==
oid.getAsInt()).findFirst().orElse(null);
return new Pair<DataStoreEntry, DataStoreEntryRef<? extends FixedChildStore>>(oc, found);
}).filter(en -> en.getValue() != null).toList());
var found = newChildren.stream()
.filter(nc -> getFixedChildId(nc.get()).isPresent())
.filter(nc -> getFixedChildId(nc.get()).getAsInt() == oid.getAsInt())
.findFirst()
.orElse(null);
return new Pair<DataStoreEntry, DataStoreEntryRef<? extends FixedChildStore>>(oc, found);
})
.filter(en -> en.getValue() != null)
.toList());
toUpdate.removeIf(pair -> {
return pair.getKey().getStorePersistentState().equals(pair.getValue().get().getStorePersistentState());
return pair.getKey()
.getStorePersistentState()
.equals(pair.getValue().get().getStorePersistentState());
});
if (toRemove.isEmpty() && toAdd.isEmpty() && toUpdate.isEmpty()) {
@ -794,7 +803,8 @@ public abstract class DataStorage {
return true;
}
var parentCat = getStoreCategoryIfPresent(parent.get().getCategoryUuid()).orElseThrow();
var parentCat =
getStoreCategoryIfPresent(parent.get().getCategoryUuid()).orElseThrow();
var parentCatHierarchy = getCategoryParentHierarchy(parentCat);
var cat = getStoreCategoryIfPresent(entry.getCategoryUuid()).orElseThrow();
var catHierarchy = getCategoryParentHierarchy(cat);

View file

@ -41,10 +41,10 @@ public class StandardStorage extends DataStorage {
@Getter
private boolean disposed;
private boolean saveQueued;
private final ReentrantLock busyIo = new ReentrantLock();
StandardStorage() {
this.dataStorageSyncHandler = DataStorageSyncHandler.getInstance();
this.dataStorageUserHandler = DataStorageUserHandler.getInstance();

View file

@ -26,7 +26,8 @@ public class MobaXTermTerminalType extends ExternalTerminalType.WindowsType {
protected Optional<Path> determineInstallation() {
try {
var r = WindowsRegistry.local()
.readStringValueIfPresent(WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\mobaxterm\\DefaultIcon");
.readStringValueIfPresent(
WindowsRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\mobaxterm\\DefaultIcon");
return r.map(Path::of);
} catch (Exception e) {
ErrorEvent.fromThrowable(e).omit().handle();

View file

@ -47,7 +47,8 @@ public class TerminalLauncher {
open(null, title, null, cc, request, true);
}
public static void open(DataStoreEntry entry, String title, FilePath directory, ProcessControl cc) throws Exception {
public static void open(DataStoreEntry entry, String title, FilePath directory, ProcessControl cc)
throws Exception {
open(entry, title, directory, cc, UUID.randomUUID(), true);
}

View file

@ -41,14 +41,20 @@ public interface WaveTerminalType extends ExternalTerminalType, TrackableTermina
default void launch(TerminalLaunchConfiguration configuration) throws Exception {
try (var sc = LocalShell.getShell().start()) {
var wsh = CommandSupport.findProgram(sc, "wsh");
var env = sc.command(sc.getShellDialect().getPrintEnvironmentVariableCommand("WAVETERM_JWT")).readStdoutOrThrow();
var env = sc.command(sc.getShellDialect().getPrintEnvironmentVariableCommand("WAVETERM_JWT"))
.readStdoutOrThrow();
if (wsh.isEmpty() || env.isEmpty()) {
var inPath = CommandSupport.findProgram(sc, "xpipe").isPresent();
var msg = """
var msg =
"""
The Wave integration requires XPipe to be launched from Wave itself to have access to its environment variables. Otherwise, XPipe does not have access to the token to control Wave.
You can do this by running the command "%s" in a local terminal block inside Wave.
""".formatted(inPath ? "xpipe open" : XPipeInstallation.getLocalDefaultCliExecutable() + " open");
"""
.formatted(
inPath
? "xpipe open"
: XPipeInstallation.getLocalDefaultCliExecutable() + " open");
throw ErrorEvent.expected(new IllegalStateException(msg));
}

View file

@ -63,7 +63,8 @@ public interface WezTerminalType extends ExternalTerminalType, TrackableTerminal
"http://wezfurlong.org/wezterm");
if (foundKey.isPresent()) {
var installKey = WindowsRegistry.local()
.readStringValueIfPresent(foundKey.get().getHkey(), foundKey.get().getKey(), "InstallLocation");
.readStringValueIfPresent(
foundKey.get().getHkey(), foundKey.get().getKey(), "InstallLocation");
if (installKey.isPresent()) {
return installKey.map(p -> p + "\\wezterm-gui.exe").map(Path::of);
}

View file

@ -147,7 +147,9 @@ public enum XPipeDistributionType {
}
}
var yumRepo = sc.command(CommandBuilder.of().add("test", "-f").addFile("/etc/yum.repos.d/rpm.xpipe.io.repo")).executeAndCheck();
var yumRepo = sc.command(
CommandBuilder.of().add("test", "-f").addFile("/etc/yum.repos.d/rpm.xpipe.io.repo"))
.executeAndCheck();
if (yumRepo) {
return RPM_REPO;
}

View file

@ -52,9 +52,11 @@ public class DesktopHelper {
case OsType.Windows windows -> {
// Explorer does not support single quotes, so use normal quotes
if (kind == FileKind.DIRECTORY) {
sc.command(CommandBuilder.of().add("explorer").addQuoted(path.toString())).execute();
sc.command(CommandBuilder.of().add("explorer").addQuoted(path.toString()))
.execute();
} else {
sc.command(CommandBuilder.of().add("explorer", "/select,\"" + path.toString() + "\"")).execute();
sc.command(CommandBuilder.of().add("explorer", "/select,\"" + path.toString() + "\""))
.execute();
}
}
case OsType.Linux linux -> {
@ -77,7 +79,11 @@ public class DesktopHelper {
.execute();
}
case OsType.MacOs macOs -> {
sc.command(CommandBuilder.of().add("open").addIf(kind == FileKind.DIRECTORY, "-R").addFile(path)).execute();
sc.command(CommandBuilder.of()
.add("open")
.addIf(kind == FileKind.DIRECTORY, "-R")
.addFile(path))
.execute();
}
case OsType.Bsd bsd -> {}
case OsType.Solaris solaris -> {}

View file

@ -70,7 +70,9 @@ public final class HumanReadableFormat {
// not this week
if (getWeekNumber(x) != getWeekNumber(now)) {
return DAY_MONTH.withLocale(AppI18n.activeLanguage().getValue().getLocale()).format(x);
return DAY_MONTH
.withLocale(AppI18n.activeLanguage().getValue().getLocale())
.format(x);
}
// not today
@ -80,14 +82,19 @@ public final class HumanReadableFormat {
return AppI18n.get("yesterday");
}
if (xDay != nowDay) {
return DAY_OF_WEEK.withLocale(AppI18n.activeLanguage().getValue().getLocale()).format(x);
return DAY_OF_WEEK
.withLocale(AppI18n.activeLanguage().getValue().getLocale())
.format(x);
}
return HOUR_MINUTE.withLocale(AppI18n.activeLanguage().getValue().getLocale()).format(x);
return HOUR_MINUTE
.withLocale(AppI18n.activeLanguage().getValue().getLocale())
.format(x);
}
private static int getWeekNumber(LocalDateTime date) {
return date.get(WeekFields.of(AppI18n.activeLanguage().getValue().getLocale()).weekOfYear());
return date.get(
WeekFields.of(AppI18n.activeLanguage().getValue().getLocale()).weekOfYear());
}
public static String duration(Duration duration) {

View file

@ -22,8 +22,8 @@ public class RdpConfig {
Map<String, TypedValue> content;
public static RdpConfig parseFile(FilePath file) throws Exception {
try (var in = new BufferedReader(
StreamCharset.detectedReader(new BufferedInputStream(Files.newInputStream(Path.of(file.toString())))))) {
try (var in = new BufferedReader(StreamCharset.detectedReader(
new BufferedInputStream(Files.newInputStream(Path.of(file.toString())))))) {
var content = in.lines().collect(Collectors.joining("\n"));
return parseContent(content);
} catch (NoSuchFileException e) {

View file

@ -1,6 +1,5 @@
package io.xpipe.app.util;
import io.xpipe.app.comp.base.LoadingOverlayComp;
import io.xpipe.app.comp.base.ModalButton;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.ext.ScanProvider;

View file

@ -15,7 +15,6 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import javafx.application.Platform;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.layout.Region;
@ -23,7 +22,6 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import static javafx.scene.layout.Priority.ALWAYS;
@ -33,7 +31,8 @@ class ScanDialogComp extends ModalOverlayContentComp {
private final DataStoreEntryRef<ShellStore> initialStore;
private final ScanDialogAction action;
private final ObjectProperty<DataStoreEntryRef<ShellStore>> entry;
private final ObservableList<ScanProvider.ScanOpportunity> available = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
private final ObservableList<ScanProvider.ScanOpportunity> available =
FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
private final ListProperty<ScanProvider.ScanOpportunity> selected =
new SimpleListProperty<>(FXCollections.synchronizedObservableList(FXCollections.observableArrayList()));
private final BooleanProperty busy = new SimpleBooleanProperty();
@ -131,7 +130,8 @@ class ScanDialogComp extends ModalOverlayContentComp {
.disable(busy.or(new SimpleBooleanProperty(initialStore != null))))
.name("scanAlertHeader")
.description("scanAlertHeaderDescription")
.addComp(LoadingOverlayComp.noProgress(Comp.of(() -> stackPane), busy).vgrow())
.addComp(LoadingOverlayComp.noProgress(Comp.of(() -> stackPane), busy)
.vgrow())
.buildComp()
.prefWidth(500)
.prefHeight(680)

View file

@ -36,7 +36,8 @@ public class SecretManager {
List<SecretQueryFormatter> formatters,
CountDown countDown,
boolean interactive) {
var p = new SecretQueryProgress(request, storeId, suppliers, fallback, filters, formatters, countDown, interactive);
var p = new SecretQueryProgress(
request, storeId, suppliers, fallback, filters, formatters, countDown, interactive);
progress.add(p);
return p;
}

View file

@ -1,7 +1,5 @@
package io.xpipe.app.util;
import io.xpipe.core.util.SecretValue;
import java.util.Optional;
public interface SecretQueryFormatter {

View file

@ -31,7 +31,8 @@ public class SecretQueryProgress {
@NonNull UUID storeId,
@NonNull List<SecretQuery> suppliers,
@NonNull SecretQuery fallback,
@NonNull List<SecretQueryFilter> filters, List<SecretQueryFormatter> formatters,
@NonNull List<SecretQueryFilter> filters,
List<SecretQueryFormatter> formatters,
@NonNull CountDown countDown,
boolean interactive) {
this.requestId = requestId;

View file

@ -2,7 +2,6 @@ package io.xpipe.app.util;
import io.xpipe.app.comp.store.StoreSection;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellEnvironmentStoreState;
import io.xpipe.core.process.ShellStoreState;

View file

@ -5,7 +5,6 @@ import io.xpipe.app.core.AppProperties;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.util.XPipeInstallation;

View file

@ -9,7 +9,8 @@ import java.util.List;
public class Validators {
public static <T extends DataStore> void isType(DataStoreEntryRef<? extends T> ref, Class<T> c) throws ValidationException {
public static <T extends DataStore> void isType(DataStoreEntryRef<? extends T> ref, Class<T> c)
throws ValidationException {
if (ref != null && !c.isAssignableFrom(ref.getStore().getClass())) {
throw new ValidationException("Value must be an instance of " + c.getSimpleName());
}

View file

@ -180,13 +180,14 @@ public abstract class WindowsRegistry {
@Override
public List<String> listSubKeys(int hkey, String key) throws Exception {
var prefix = hkey(hkey) + "\\" + key;
var command = CommandBuilder.of()
.add("reg", "query")
.addQuoted(prefix);
var command = CommandBuilder.of().add("reg", "query").addQuoted(prefix);
var out = shellControl.command(command).readStdoutOrThrow();
return out.lines().filter(s -> {
return s.contains(prefix + "\\");
}).map(s -> s.replace(prefix + "\\", "")).toList();
return out.lines()
.filter(s -> {
return s.contains(prefix + "\\");
})
.map(s -> s.replace(prefix + "\\", ""))
.toList();
}
@Override

View file

@ -1,8 +1,8 @@
package io.xpipe.beacon.api;
import io.xpipe.beacon.BeaconInterface;
import io.xpipe.core.store.FilePath;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

View file

@ -1,8 +1,8 @@
package io.xpipe.beacon.api;
import io.xpipe.beacon.BeaconInterface;
import io.xpipe.core.store.FilePath;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

View file

@ -1,6 +1,5 @@
package io.xpipe.core.process;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import java.util.ArrayList;
@ -58,11 +57,7 @@ public interface OsType {
@Override
public List<FilePath> determineInterestingPaths(ShellControl pc) throws Exception {
var home = pc.view().userHome();
return List.of(
home,
home.join("Documents"),
home.join("Downloads"),
home.join("Desktop"));
return List.of(home, home.join("Documents"), home.join("Downloads"), home.join("Desktop"));
}
@Override
@ -180,8 +175,7 @@ public interface OsType {
FilePath.of("/Library"),
FilePath.of("/System"),
FilePath.of("/etc"),
FilePath.of("/tmp")
);
FilePath.of("/tmp"));
return list;
}

View file

@ -46,9 +46,7 @@ public class ShellView {
}
public boolean directoryExists(FilePath path) throws Exception {
return getDialect()
.directoryExists(shellControl, path.toString())
.executeAndCheck();
return getDialect().directoryExists(shellControl, path.toString()).executeAndCheck();
}
public String user() throws Exception {
@ -91,6 +89,8 @@ public class ShellView {
}
public String environmentVariable(String name) throws Exception {
return shellControl.command(shellControl.getShellDialect().getPrintEnvironmentVariableCommand(name)).readStdoutOrThrow();
return shellControl
.command(shellControl.getShellDialect().getPrintEnvironmentVariableCommand(name))
.readStdoutOrThrow();
}
}

View file

@ -25,11 +25,11 @@ public final class FilePath {
public static FilePath of(String path) {
return path != null ? new FilePath(path) : null;
}
public static FilePath of(Path path) {
return path != null ? new FilePath(path.toString()) : null;
}
@NonNull
private final String value;

View file

@ -78,8 +78,7 @@ public class CoreJacksonModule extends SimpleModule {
public static class ShellScriptSerializer extends JsonSerializer<ShellScript> {
@Override
public void serialize(ShellScript value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(ShellScript value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.getValue());
}
}

View file

@ -10,8 +10,8 @@ import io.xpipe.core.process.CommandControl;
import io.xpipe.core.process.ElevationFunction;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.store.FilePath;
import javafx.beans.value.ObservableValue;
import lombok.Value;

View file

@ -78,8 +78,10 @@ public class ChgrpAction implements BrowserBranchAction {
.executeSimpleCommand(CommandBuilder.of()
.add("chgrp", option)
.addFiles(entries.stream()
.map(browserEntry ->
browserEntry.getRawFileEntry().getPath().toString())
.map(browserEntry -> browserEntry
.getRawFileEntry()
.getPath()
.toString())
.toList()));
}
}
@ -106,8 +108,10 @@ public class ChgrpAction implements BrowserBranchAction {
CommandBuilder.of()
.add("chgrp", group.getValue())
.addFiles(entries.stream()
.map(browserEntry ->
browserEntry.getRawFileEntry().getPath().toString())
.map(browserEntry -> browserEntry
.getRawFileEntry()
.getPath()
.toString())
.toList()),
false);
});

View file

@ -77,8 +77,10 @@ public class ChmodAction implements BrowserBranchAction {
.executeSimpleCommand(CommandBuilder.of()
.add("chmod", option)
.addFiles(entries.stream()
.map(browserEntry ->
browserEntry.getRawFileEntry().getPath().toString())
.map(browserEntry -> browserEntry
.getRawFileEntry()
.getPath()
.toString())
.toList()));
}
}
@ -104,8 +106,10 @@ public class ChmodAction implements BrowserBranchAction {
CommandBuilder.of()
.add("chmod", permissions.getValue())
.addFiles(entries.stream()
.map(browserEntry ->
browserEntry.getRawFileEntry().getPath().toString())
.map(browserEntry -> browserEntry
.getRawFileEntry()
.getPath()
.toString())
.toList()),
false);
});

View file

@ -77,8 +77,10 @@ public class ChownAction implements BrowserBranchAction {
.executeSimpleCommand(CommandBuilder.of()
.add("chown", option)
.addFiles(entries.stream()
.map(browserEntry ->
browserEntry.getRawFileEntry().getPath().toString())
.map(browserEntry -> browserEntry
.getRawFileEntry()
.getPath()
.toString())
.toList()));
}
}
@ -104,8 +106,10 @@ public class ChownAction implements BrowserBranchAction {
CommandBuilder.of()
.add("chown", user.getValue())
.addFiles(entries.stream()
.map(browserEntry ->
browserEntry.getRawFileEntry().getPath().toString())
.map(browserEntry -> browserEntry
.getRawFileEntry()
.getPath()
.toString())
.toList()),
false);
});

View file

@ -9,7 +9,6 @@ import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.util.ClipboardHelper;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
@ -51,7 +50,11 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
if (entries.size() == 1) {
return new SimpleObjectProperty<>(BrowserActionFormatter.centerEllipsis(
entries.getFirst().getRawFileEntry().getPath().toString(), 50));
entries.getFirst()
.getRawFileEntry()
.getPath()
.toString(),
50));
}
return AppI18n.observable("absolutePaths");
@ -71,7 +74,11 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
if (entries.size() == 1) {
return new SimpleObjectProperty<>(BrowserActionFormatter.centerEllipsis(
entries.getFirst().getRawFileEntry().getPath().toString(), 50));
entries.getFirst()
.getRawFileEntry()
.getPath()
.toString(),
50));
}
return AppI18n.observable("absoluteLinkPaths");
@ -104,7 +111,11 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
if (entries.size() == 1) {
return new SimpleObjectProperty<>("\""
+ BrowserActionFormatter.centerEllipsis(
entries.getFirst().getRawFileEntry().getPath().toString(), 50)
entries.getFirst()
.getRawFileEntry()
.getPath()
.toString(),
50)
+ "\"");
}
@ -113,9 +124,10 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
@Override
public boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return entries.stream()
.anyMatch(entry ->
entry.getRawFileEntry().getPath().toString().contains(" "));
return entries.stream().anyMatch(entry -> entry.getRawFileEntry()
.getPath()
.toString()
.contains(" "));
}
@Override
@ -138,7 +150,10 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
if (entries.size() == 1) {
return new SimpleObjectProperty<>(BrowserActionFormatter.centerEllipsis(
entries.getFirst().getRawFileEntry().getPath().getFileName(),
entries.getFirst()
.getRawFileEntry()
.getPath()
.getFileName(),
50));
}
@ -159,7 +174,10 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
if (entries.size() == 1) {
return new SimpleObjectProperty<>(BrowserActionFormatter.centerEllipsis(
entries.getFirst().getRawFileEntry().getPath().getFileName(),
entries.getFirst()
.getRawFileEntry()
.getPath()
.getFileName(),
50));
}
@ -176,7 +194,8 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
.equals(browserEntry
.getRawFileEntry()
.resolved()
.getPath().getFileName()));
.getPath()
.getFileName()));
}
@Override
@ -198,9 +217,11 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
if (entries.size() == 1) {
return new SimpleObjectProperty<>("\""
+ BrowserActionFormatter.centerEllipsis(entries.getFirst()
+ BrowserActionFormatter.centerEllipsis(
entries.getFirst()
.getRawFileEntry()
.getPath().getFileName(),
.getPath()
.getFileName(),
50)
+ "\"");
}
@ -210,15 +231,17 @@ public class CopyPathAction implements BrowserAction, BrowserBranchAction {
@Override
public boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return entries.stream().anyMatch(entry -> entry.getRawFileEntry().getPath().getFileName()
return entries.stream().anyMatch(entry -> entry.getRawFileEntry()
.getPath()
.getFileName()
.contains(" "));
}
@Override
public void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
var s = entries.stream()
.map(entry -> "\""
+ entry.getRawFileEntry().getPath().getFileName() + "\"")
.map(entry ->
"\"" + entry.getRawFileEntry().getPath().getFileName() + "\"")
.collect(Collectors.joining("\n"));
ClipboardHelper.copyText(s);
}

View file

@ -5,7 +5,6 @@ import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.core.AppI18n;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;

View file

@ -5,7 +5,6 @@ import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.browser.icon.BrowserIconFileType;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.store.FileNames;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
@ -36,6 +35,8 @@ public class JavapAction extends ToFileCommandAction implements FileTypeAction,
@Override
protected CommandBuilder createCommand(BrowserFileSystemTabModel model, BrowserEntry entry) {
return CommandBuilder.of().add("javap", "-c", "-p").addFile(entry.getRawFileEntry().getPath());
return CommandBuilder.of()
.add("javap", "-c", "-p")
.addFile(entry.getRawFileEntry().getPath());
}
}

View file

@ -1,6 +1,5 @@
package io.xpipe.ext.base.browser;
import atlantafx.base.layout.ModalBox;
import io.xpipe.app.browser.action.BrowserBranchAction;
import io.xpipe.app.browser.action.BrowserLeafAction;
import io.xpipe.app.browser.file.BrowserEntry;
@ -9,7 +8,6 @@ import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.process.CommandBuilder;
@ -19,7 +17,6 @@ import io.xpipe.core.process.ShellControl;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@ -95,9 +92,10 @@ public abstract class MultiExecuteSelectionAction implements BrowserBranchAction
if (out.length() > 10000) {
var counter = new AtomicInteger();
var start = out.lines().filter(s -> {
counter.incrementAndGet();
return true;
var start = out.lines()
.filter(s -> {
counter.incrementAndGet();
return true;
})
.limit(100)
.collect(Collectors.joining("\n"));
@ -114,16 +112,19 @@ public abstract class MultiExecuteSelectionAction implements BrowserBranchAction
}
String finalOut = out;
var modal = ModalOverlay.of("commandOutput", Comp.of(() -> {
var text = new TextArea(finalOut);
text.setWrapText(true);
text.setEditable(false);
text.setPrefRowCount(Math.max(8,( int) finalOut.lines().count()));
AppFont.medium(text);
var sp = new StackPane(text);
return sp;
})
.prefWidth(650));
var modal = ModalOverlay.of(
"commandOutput",
Comp.of(() -> {
var text = new TextArea(finalOut);
text.setWrapText(true);
text.setEditable(false);
text.setPrefRowCount(Math.max(8, (int)
finalOut.lines().count()));
AppFont.medium(text);
var sp = new StackPane(text);
return sp;
})
.prefWidth(650));
modal.show();
},
true);

View file

@ -11,8 +11,8 @@ import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FilePath;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;

View file

@ -9,8 +9,6 @@ import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import javafx.beans.value.ObservableValue;
import javafx.scene.input.KeyCode;

View file

@ -6,8 +6,8 @@ import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FilePath;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.input.KeyCode;

View file

@ -76,9 +76,12 @@ public abstract class BaseCompressAction implements BrowserAction, BrowserBranch
@Override
public boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
var ext = List.of("zip", "tar", "tar.gz", "tgz", "7z", "rar", "xar");
if (entries.stream().anyMatch(browserEntry -> ext.stream()
.anyMatch(s ->
browserEntry.getRawFileEntry().getPath().toString().toLowerCase().endsWith("." + s)))) {
if (entries.stream().anyMatch(browserEntry -> ext.stream().anyMatch(s -> browserEntry
.getRawFileEntry()
.getPath()
.toString()
.toLowerCase()
.endsWith("." + s)))) {
return false;
}
@ -172,14 +175,10 @@ public abstract class BaseCompressAction implements BrowserAction, BrowserBranch
() -> {
var sc = model.getFileSystem().getShell().orElseThrow();
if (ShellDialects.isPowershell(sc)) {
sc.command(command)
.withWorkingDirectory(base)
.execute();
sc.command(command).withWorkingDirectory(base).execute();
} else {
try (var sub = sc.subShell(ShellDialects.POWERSHELL)) {
sub.command(command)
.withWorkingDirectory(base)
.execute();
sub.command(command).withWorkingDirectory(base).execute();
}
}
},
@ -205,9 +204,7 @@ public abstract class BaseCompressAction implements BrowserAction, BrowserBranch
var target = base.join(fileName);
var command = CommandBuilder.of().add("zip", "-r", "-");
for (BrowserEntry entry : entries) {
var rel = entry.getRawFileEntry().getPath()
.relativize(base)
.toUnix();
var rel = entry.getRawFileEntry().getPath().relativize(base).toUnix();
if (directory) {
command.add(".");
} else {

View file

@ -9,8 +9,8 @@ import io.xpipe.app.browser.icon.BrowserIcons;
import io.xpipe.app.core.AppI18n;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.store.FilePath;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
@ -69,19 +69,27 @@ public class BaseUntarAction implements BrowserApplicationPathAction, BrowserLea
@Override
public ObservableValue<String> getName(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
var sep = model.getFileSystem().getShell().orElseThrow().getOsType().getFileSystemSeparator();
var dir = entries.size() > 1 ? "[...]" : getTarget(entries.getFirst().getRawFileEntry().getPath()).getFileName() + sep;
var dir = entries.size() > 1
? "[...]"
: getTarget(entries.getFirst().getRawFileEntry().getPath()).getFileName() + sep;
return toDirectory ? AppI18n.observable("untarDirectory", dir) : AppI18n.observable("untarHere");
}
private FilePath getTarget(FilePath name) {
return FilePath.of(name.toString().replaceAll("\\.tar$", "").replaceAll("\\.tar.gz$", "").replaceAll("\\.tgz$", ""));
return FilePath.of(name.toString()
.replaceAll("\\.tar$", "")
.replaceAll("\\.tar.gz$", "")
.replaceAll("\\.tgz$", ""));
}
@Override
public boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
if (gz) {
return entries.stream()
.allMatch(entry -> entry.getRawFileEntry().getPath().toString().endsWith(".tar.gz")
.allMatch(entry -> entry.getRawFileEntry()
.getPath()
.toString()
.endsWith(".tar.gz")
|| entry.getRawFileEntry().getPath().toString().endsWith(".tgz"));
}

View file

@ -57,7 +57,9 @@ public abstract class BaseUnzipUnixAction extends ExecuteApplicationAction {
@Override
public ObservableValue<String> getName(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
var sep = model.getFileSystem().getShell().orElseThrow().getOsType().getFileSystemSeparator();
var dir = entries.size() > 1 ? "[...]" : getTarget(entries.getFirst().getRawFileEntry().getPath()).getFileName() + sep;
var dir = entries.size() > 1
? "[...]"
: getTarget(entries.getFirst().getRawFileEntry().getPath()).getFileName() + sep;
return toDirectory ? AppI18n.observable("unzipDirectory", dir) : AppI18n.observable("unzipHere");
}
@ -68,7 +70,8 @@ public abstract class BaseUnzipUnixAction extends ExecuteApplicationAction {
@Override
public boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return entries.stream()
.allMatch(entry -> entry.getRawFileEntry().getPath().toString().endsWith(".zip"))
.allMatch(entry ->
entry.getRawFileEntry().getPath().toString().endsWith(".zip"))
&& !model.getFileSystem().getShell().orElseThrow().getOsType().equals(OsType.WINDOWS);
}
}

View file

@ -10,8 +10,8 @@ import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellControl;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.store.FilePath;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
@ -70,7 +70,9 @@ public abstract class BaseUnzipWindowsAction implements BrowserLeafAction {
@Override
public ObservableValue<String> getName(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
var sep = model.getFileSystem().getShell().orElseThrow().getOsType().getFileSystemSeparator();
var dir = entries.size() > 1 ? "[...]" : getTarget(entries.getFirst().getRawFileEntry().getPath()).getFileName() + sep;
var dir = entries.size() > 1
? "[...]"
: getTarget(entries.getFirst().getRawFileEntry().getPath()).getFileName() + sep;
return toDirectory ? AppI18n.observable("unzipDirectory", dir) : AppI18n.observable("unzipHere");
}
@ -81,7 +83,8 @@ public abstract class BaseUnzipWindowsAction implements BrowserLeafAction {
@Override
public boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return entries.stream()
.allMatch(entry -> entry.getRawFileEntry().getPath().toString().endsWith(".zip"))
.allMatch(entry ->
entry.getRawFileEntry().getPath().toString().endsWith(".zip"))
&& model.getFileSystem().getShell().orElseThrow().getOsType().equals(OsType.WINDOWS);
}
}

View file

@ -109,8 +109,8 @@ public class DesktopApplicationStoreProvider implements DataStoreProvider {
return DesktopApplicationStore.builder().build();
}
@Override
public String getId() {
@Override
public String getId() {
return "desktopApplication";
}

View file

@ -11,7 +11,6 @@ import io.xpipe.app.comp.store.StoreEntryWrapper;
import io.xpipe.app.comp.store.StoreViewState;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.DataStoreCreationCategory;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.DataStoreEntryRef;

View file

@ -71,14 +71,17 @@ public class LocalIdentityStoreProvider extends IdentityStoreProvider {
return AppI18n.get("localIdentity");
}
@Override
public String getId() {
@Override
public String getId() {
return "localIdentity";
}
@Override
public DataStore defaultStore() {
return LocalIdentityStore.builder().password(EncryptedValue.of(new SecretRetrievalStrategy.None())).sshIdentity(EncryptedValue.of(new SshIdentityStrategy.None())).build();
return LocalIdentityStore.builder()
.password(EncryptedValue.of(new SecretRetrievalStrategy.None()))
.sshIdentity(EncryptedValue.of(new SshIdentityStrategy.None()))
.build();
}
@Override

View file

@ -173,8 +173,9 @@ public interface SshIdentityStrategy {
if (s.startsWith("~")) {
s = s.resolveTildeHome(parent.getOsType().getUserHomeDirectory(parent));
}
var resolved =
parent.getShellDialect().evaluateExpression(parent, s.toString()).readStdoutOrThrow();
var resolved = parent.getShellDialect()
.evaluateExpression(parent, s.toString())
.readStdoutOrThrow();
if (!parent.getShellDialect()
.createFileExistsCommand(parent, resolved)
.executeAndCheck()) {
@ -216,8 +217,9 @@ public interface SshIdentityStrategy {
if (s.startsWith("~")) {
s = s.resolveTildeHome(sc.getOsType().getUserHomeDirectory(sc));
}
var resolved =
sc.getShellDialect().evaluateExpression(sc, s.toString()).readStdoutOrThrow();
var resolved = sc.getShellDialect()
.evaluateExpression(sc, s.toString())
.readStdoutOrThrow();
return sc.getShellDialect().fileArgument(resolved);
})
.add("-oIdentitiesOnly=yes");

View file

@ -7,8 +7,8 @@ import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.storage.ContextualFileReference;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.*;
import io.xpipe.core.store.FilePath;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;

Some files were not shown because too many files have changed in this diff Show more