This commit is contained in:
crschnick 2024-05-01 17:16:19 +00:00
parent c7f6bcf7d7
commit 6408390535
41 changed files with 248 additions and 163 deletions

View file

@ -86,8 +86,7 @@ public final class BrowserBookmarkComp extends SimpleComp {
selectedCategory)
.styleClass(Styles.LEFT_PILL)
.minWidth(Region.USE_PREF_SIZE);
var filter =
new FilterComp(filterText).hgrow();
var filter = new FilterComp(filterText).hgrow();
var top = new HorizontalComp(List.of(category, filter))
.styleClass("categories")

View file

@ -1,6 +1,5 @@
package io.xpipe.app.browser;
import atlantafx.base.theme.Styles;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.base.ListBoxViewComp;
@ -32,6 +31,7 @@ import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import atlantafx.base.controls.Spacer;
import atlantafx.base.theme.Styles;
import java.util.List;
@ -139,7 +139,8 @@ public class BrowserWelcomeComp extends SimpleComp {
private Comp<?> entryButton(BrowserSavedState.Entry e, BooleanProperty disable) {
var entry = DataStorage.get().getStoreEntryIfPresent(e.getUuid());
var graphic = entry.get().getProvider().getDisplayIconFileName(entry.get().getStore());
var graphic =
entry.get().getProvider().getDisplayIconFileName(entry.get().getStore());
var view = PrettyImageHelper.ofFixedSize(graphic, 30, 24);
return new ButtonComp(
new SimpleStringProperty(DataStorage.get().getStoreDisplayName(entry.get())),

View file

@ -8,8 +8,10 @@ import io.xpipe.app.fxcomps.util.Shortcuts;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.app.util.ThreadHelper;
import javafx.scene.control.Button;
import javafx.scene.control.MenuItem;
import org.kordamp.ikonli.javafx.FontIcon;
import java.util.List;
@ -91,7 +93,8 @@ public interface LeafAction extends BrowserAction {
mi.setMnemonicParsing(false);
mi.setDisable(!isActive(model, selected));
if (getProFeatureId() != null && !LicenseProvider.get().getFeature(getProFeatureId()).isSupported()) {
if (getProFeatureId() != null
&& !LicenseProvider.get().getFeature(getProFeatureId()).isSupported()) {
mi.setDisable(true);
}

View file

@ -8,6 +8,7 @@ import io.xpipe.app.util.InputHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FileKind;
import io.xpipe.core.store.FileSystem;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Side;
@ -19,6 +20,7 @@ import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import lombok.Getter;
import java.util.ArrayList;

View file

@ -22,8 +22,10 @@ import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellOpenFunction;
import io.xpipe.core.store.*;
import io.xpipe.core.util.FailableConsumer;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import lombok.Getter;
import lombok.SneakyThrows;
@ -297,7 +299,8 @@ public final class OpenFileSystemModel extends BrowserSessionTab<FileSystemStore
loadFilesSync(path);
}
public void withFiles(String dir, FailableConsumer<Stream<FileSystem.FileEntry>, Exception> consumer) throws Exception {
public void withFiles(String dir, FailableConsumer<Stream<FileSystem.FileEntry>, Exception> consumer)
throws Exception {
BooleanScope.executeExclusive(busy, () -> {
if (dir != null) {
startIfNeeded();

View file

@ -6,11 +6,13 @@ import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.DataStore;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.scene.layout.Region;
import lombok.AllArgsConstructor;
import lombok.Setter;
@ -29,17 +31,29 @@ public class StoreToggleComp extends SimpleComp {
@Setter
private ObservableBooleanValue customVisibility = new SimpleBooleanProperty(true);
public static <T extends DataStore> StoreToggleComp simpleToggle(String nameKey, StoreSection section, Function<T, Boolean> initial, BiConsumer<T, Boolean> setter) {
return new StoreToggleComp(nameKey, section,new SimpleBooleanProperty(initial.apply(section.getWrapper().getEntry().getStore().asNeeded())),v -> {
setter.accept(section.getWrapper().getEntry().getStore().asNeeded(),v);
});
public static <T extends DataStore> StoreToggleComp simpleToggle(
String nameKey, StoreSection section, Function<T, Boolean> initial, BiConsumer<T, Boolean> setter) {
return new StoreToggleComp(
nameKey,
section,
new SimpleBooleanProperty(
initial.apply(section.getWrapper().getEntry().getStore().asNeeded())),
v -> {
setter.accept(section.getWrapper().getEntry().getStore().asNeeded(), v);
});
}
public static <T extends DataStore> StoreToggleComp childrenToggle(String nameKey, StoreSection section, Function<T, Boolean> initial, BiConsumer<T, Boolean> setter) {
return new StoreToggleComp(nameKey, section,new SimpleBooleanProperty(initial.apply(section.getWrapper().getEntry().getStore().asNeeded())),v -> {
setter.accept(section.getWrapper().getEntry().getStore().asNeeded(),v);
section.getWrapper().refreshChildren();
});
public static <T extends DataStore> StoreToggleComp childrenToggle(
String nameKey, StoreSection section, Function<T, Boolean> initial, BiConsumer<T, Boolean> setter) {
return new StoreToggleComp(
nameKey,
section,
new SimpleBooleanProperty(
initial.apply(section.getWrapper().getEntry().getStore().asNeeded())),
v -> {
setter.accept(section.getWrapper().getEntry().getStore().asNeeded(), v);
section.getWrapper().refreshChildren();
});
}
public StoreToggleComp(String nameKey, StoreSection section, boolean initial, Consumer<Boolean> onChange) {

View file

@ -5,10 +5,12 @@ import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.util.ScanAlert;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import org.kordamp.ikonli.javafx.FontIcon;
public class StoreCreationMenu {
@ -83,7 +85,9 @@ public class StoreCreationMenu {
category);
event.consume();
});
var providers = sub.stream().sorted((o1, o2) -> -o1.getModuleName().compareTo(o2.getModuleName())).toList();
var providers = sub.stream()
.sorted((o1, o2) -> -o1.getModuleName().compareTo(o2.getModuleName()))
.toList();
for (int i = 0; i < providers.size(); i++) {
var dataStoreProvider = providers.get(i);
if (i > 0 && !providers.get(i - 1).getModuleName().equals(dataStoreProvider.getModuleName())) {

View file

@ -116,9 +116,9 @@ public abstract class StoreEntryComp extends SimpleComp {
var loading = LoadingOverlayComp.noProgress(
Comp.of(() -> button),
wrapper.getEntry().getValidity().isUsable() ?
wrapper.getBusy().or(wrapper.getEntry().getProvider().busy(wrapper)):
wrapper.getBusy());
wrapper.getEntry().getValidity().isUsable()
? wrapper.getBusy().or(wrapper.getEntry().getProvider().busy(wrapper))
: wrapper.getBusy());
return loading.createRegion();
}

View file

@ -8,6 +8,7 @@ import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.util.ModuleHelper;
import io.xpipe.core.util.ModuleLayerLoader;
import io.xpipe.core.util.XPipeInstallation;
import lombok.Getter;
import lombok.Value;
@ -95,12 +96,16 @@ public class AppExtensionManager {
}
var iv = getLocalInstallVersion();
var installVersion = AppVersion.parse(iv).orElseThrow(() -> new IllegalArgumentException("Invalid installation version: " + iv));
var sv = !AppProperties.get().isImage() ? Files.readString(Path.of("version")).trim() : AppProperties.get().getVersion();
var sourceVersion = AppVersion.parse(sv).orElseThrow(() -> new IllegalArgumentException("Invalid source version: " + sv));
var installVersion = AppVersion.parse(iv)
.orElseThrow(() -> new IllegalArgumentException("Invalid installation version: " + iv));
var sv = !AppProperties.get().isImage()
? Files.readString(Path.of("version")).trim()
: AppProperties.get().getVersion();
var sourceVersion = AppVersion.parse(sv)
.orElseThrow(() -> new IllegalArgumentException("Invalid source version: " + sv));
if (!installVersion.equals(sourceVersion)) {
throw new IllegalStateException(
"Incompatible development version. Source: " + iv + ", Installation: " + sv + "\n\nPlease try to check out the matching release version in the repository.");
throw new IllegalStateException("Incompatible development version. Source: " + iv + ", Installation: "
+ sv + "\n\nPlease try to check out the matching release version in the repository.");
}
var extensions = XPipeInstallation.getLocalExtensionsDirectory(p);
@ -171,8 +176,8 @@ public class AppExtensionManager {
if (loadedExtensions.stream().anyMatch(extension -> dir.equals(extension.dir))
|| loadedExtensions.stream()
.anyMatch(extension ->
extension.id.equals(dir.getFileName().toString()))) {
.anyMatch(extension ->
extension.id.equals(dir.getFileName().toString()))) {
return Optional.empty();
}

View file

@ -55,7 +55,9 @@ public class AppProperties {
.orElse(UUID.randomUUID());
sentryUrl = System.getProperty("io.xpipe.app.sentryUrl");
arch = System.getProperty("io.xpipe.app.arch");
languages = Arrays.stream(System.getProperty("io.xpipe.app.languages").split(";")).sorted().toList();
languages = Arrays.stream(System.getProperty("io.xpipe.app.languages").split(";"))
.sorted()
.toList();
staging = XPipeInstallation.isStaging();
useVirtualThreads = Optional.ofNullable(System.getProperty("io.xpipe.app.useVirtualThreads"))
.map(Boolean::parseBoolean)

View file

@ -19,10 +19,11 @@ import io.xpipe.core.process.OsType;
import io.xpipe.core.util.FailableRunnable;
import io.xpipe.core.util.XPipeDaemonMode;
import io.xpipe.core.util.XPipeInstallation;
import javafx.application.Platform;
import lombok.Getter;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.desktop.AppReopenedEvent;
import java.awt.desktop.AppReopenedListener;
@ -30,6 +31,7 @@ import java.awt.desktop.SystemEventListener;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
public abstract class OperationMode {

View file

@ -1,18 +1,20 @@
package io.xpipe.app.fxcomps.impl;
import atlantafx.base.layout.InputGroup;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.util.ClipboardHelper;
import io.xpipe.core.util.InPlaceSecretValue;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import atlantafx.base.layout.InputGroup;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.kordamp.ikonli.javafx.FontIcon;
@ -27,6 +29,7 @@ public class SecretFieldComp extends Comp<SecretFieldComp.Structure> {
public static class Structure implements CompStructure<InputGroup> {
private final InputGroup inputGroup;
@Getter
private final TextField field;
@ -85,8 +88,11 @@ public class SecretFieldComp extends Comp<SecretFieldComp.Structure> {
HBox.setHgrow(text, Priority.ALWAYS);
var copyButton = new ButtonComp(null, new FontIcon("mdi2c-clipboard-multiple-outline"), () -> {
ClipboardHelper.copyPassword(value.getValue());
}).grow(false, true).tooltipKey("copyPassword").createRegion();
ClipboardHelper.copyPassword(value.getValue());
})
.grow(false, true)
.tooltipKey("copyPassword")
.createRegion();
var ig = new InputGroup(text);
ig.getStyleClass().add("secret-field-comp");

View file

@ -4,8 +4,8 @@ import io.xpipe.app.core.*;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.update.XPipeDistributionType;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.ThreadHelper;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;

View file

@ -1,7 +1,5 @@
package io.xpipe.app.issue;
import atlantafx.base.controls.Popover;
import atlantafx.base.controls.Spacer;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.base.ListSelectorComp;
import io.xpipe.app.comp.base.MarkdownComp;
@ -9,6 +7,7 @@ import io.xpipe.app.comp.base.TitledPaneComp;
import io.xpipe.app.core.*;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleStringProperty;
@ -23,6 +22,9 @@ import javafx.scene.control.TextField;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import atlantafx.base.controls.Popover;
import atlantafx.base.controls.Spacer;
import java.nio.file.Files;
import java.nio.file.Path;

View file

@ -139,21 +139,22 @@ public class AppPrefs {
private AppPrefs() {
this.categories = Stream.of(
new AboutCategory(),
new SystemCategory(),
new AppearanceCategory(),
new SyncCategory(),
new VaultCategory(),
new PasswordManagerCategory(),
new TerminalCategory(),
new EditorCategory(),
new RdpCategory(),
new SshCategory(),
new LocalShellCategory(),
new SecurityCategory(),
new TroubleshootCategory(),
new DeveloperCategory())
.filter(appPrefsCategory -> appPrefsCategory.show()).toList();
new AboutCategory(),
new SystemCategory(),
new AppearanceCategory(),
new SyncCategory(),
new VaultCategory(),
new PasswordManagerCategory(),
new TerminalCategory(),
new EditorCategory(),
new RdpCategory(),
new SshCategory(),
new LocalShellCategory(),
new SecurityCategory(),
new TroubleshootCategory(),
new DeveloperCategory())
.filter(appPrefsCategory -> appPrefsCategory.show())
.toList();
var selected = AppCache.get("selectedPrefsCategory", Integer.class, () -> 0);
if (selected == null) {
selected = 0;

View file

@ -46,7 +46,9 @@ public abstract class ExternalApplicationType implements PrefsChoiceValue {
public boolean isAvailable() {
try (ShellControl pc = LocalShell.getShell().start()) {
return pc.command(String.format(
"mdfind -name '%s' -onlyin /Applications -onlyin ~/Applications -onlyin /System/Applications", applicationName)).executeAndCheck();
"mdfind -name '%s' -onlyin /Applications -onlyin ~/Applications -onlyin /System/Applications",
applicationName))
.executeAndCheck();
} catch (Exception e) {
ErrorEvent.fromThrowable(e).handle();
return false;

View file

@ -5,8 +5,8 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.*;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.OsType;
import io.xpipe.core.util.SecretValue;
import lombok.Value;
import java.nio.file.Files;
@ -59,8 +59,8 @@ public interface ExternalRdpClientType extends PrefsChoiceValue {
private String encrypt(SecretValue password) throws Exception {
var ps = LocalShell.getLocalPowershell();
var cmd = ps.command(
"(\"" + password.getSecretValue() + "\" | ConvertTo-SecureString -AsPlainText -Force) | ConvertFrom-SecureString;");
var cmd = ps.command("(\"" + password.getSecretValue()
+ "\" | ConvertTo-SecureString -AsPlainText -Force) | ConvertFrom-SecureString;");
cmd.setSensitive();
return cmd.readStdoutOrThrow();
}

View file

@ -7,7 +7,9 @@ import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.*;
import io.xpipe.core.util.UuidHelper;
import javafx.util.Pair;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
@ -311,8 +313,8 @@ public abstract class DataStorage {
DataStoreCategory p = category;
if (share) {
while ((p = DataStorage.get()
.getStoreCategoryIfPresent(p.getParentCategory())
.orElse(null))
.getStoreCategoryIfPresent(p.getParentCategory())
.orElse(null))
!= null) {
p.setShare(true);
}
@ -428,7 +430,8 @@ public abstract class DataStorage {
// Children classes might not be the same, the same goes for state classes
// This can happen when there are multiple child classes and the ids got switched around
if (classMatch) {
DataStore merged = ((FixedChildStore) pair.getKey().getStore()).merge(pair.getValue().getStore().asNeeded());
DataStore merged = ((FixedChildStore) pair.getKey().getStore())
.merge(pair.getValue().getStore().asNeeded());
if (merged != pair.getKey().getStore()) {
pair.getKey().setStoreInternal(merged, false);
}
@ -781,9 +784,11 @@ public abstract class DataStorage {
public Optional<DataStoreEntry> getStoreEntryIfPresent(@NonNull DataStore store, boolean identityOnly) {
return storeEntriesSet.stream()
.filter(n -> n.getStore() == store
|| (!identityOnly && (n.getStore() != null
&& Objects.equals(store.getClass(), n.getStore().getClass())
&& store.equals(n.getStore()))))
|| (!identityOnly
&& (n.getStore() != null
&& Objects.equals(
store.getClass(), n.getStore().getClass())
&& store.equals(n.getStore()))))
.findFirst();
}

View file

@ -1,17 +1,18 @@
package io.xpipe.app.storage;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.core.store.*;
import io.xpipe.core.util.JacksonMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
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.ObjectNode;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.core.store.*;
import io.xpipe.core.util.JacksonMapper;
import lombok.*;
import lombok.experimental.NonFinal;
import org.apache.commons.io.FileUtils;

View file

@ -166,7 +166,8 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
}
@Override
public FailableFunction<LaunchConfiguration, String, Exception> remoteLaunchCommand(ShellDialect systemDialect) {
public FailableFunction<LaunchConfiguration, String, Exception> remoteLaunchCommand(
ShellDialect systemDialect) {
return launchConfiguration -> {
var toExecute = CommandBuilder.of()
.add(executable, "-v", "--title")
@ -608,7 +609,8 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
}
@Override
public FailableFunction<LaunchConfiguration, String, Exception> remoteLaunchCommand(ShellDialect systemDialect) {
public FailableFunction<LaunchConfiguration, String, Exception> remoteLaunchCommand(
ShellDialect systemDialect) {
return launchConfiguration -> {
var toExecute = CommandBuilder.of()
.add("open", "-a")
@ -806,7 +808,8 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
}
@Override
public FailableFunction<LaunchConfiguration, String, Exception> remoteLaunchCommand(ShellDialect systemDialect) {
public FailableFunction<LaunchConfiguration, String, Exception> remoteLaunchCommand(
ShellDialect systemDialect) {
return launchConfiguration -> {
var args = toCommand(launchConfiguration);
args.add(0, executable);

View file

@ -1,6 +1,5 @@
package io.xpipe.app.terminal;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.CommandSupport;
import io.xpipe.app.util.LocalShell;
@ -11,6 +10,8 @@ import io.xpipe.core.process.ShellControl;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.util.XPipeInstallation;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
public interface KittyTerminalType extends ExternalTerminalType {
ExternalTerminalType KITTY_LINUX = new Linux();

View file

@ -36,22 +36,22 @@ public interface TabbyTerminalType extends ExternalTerminalType {
@Override
default TerminalInitFunction additionalInitCommands() {
// return TerminalInitFunction.of(sc -> {
// if (sc.getShellDialect() == ShellDialects.ZSH) {
// return "export PS1=\"$PS1\\[\\e]1337;CurrentDir=\"'$(pwd)\\a\\]'";
// }
// if (sc.getShellDialect() == ShellDialects.BASH) {
// return "precmd () { echo -n \"\\x1b]1337;CurrentDir=$(pwd)\\x07\" }";
// }
// if (sc.getShellDialect() == ShellDialects.FISH) {
// return """
// function __tabby_working_directory_reporting --on-event fish_prompt
// echo -en "\\e]1337;CurrentDir=$PWD\\x7"
// end
// """;
// }
// return null;
// });
// return TerminalInitFunction.of(sc -> {
// if (sc.getShellDialect() == ShellDialects.ZSH) {
// return "export PS1=\"$PS1\\[\\e]1337;CurrentDir=\"'$(pwd)\\a\\]'";
// }
// if (sc.getShellDialect() == ShellDialects.BASH) {
// return "precmd () { echo -n \"\\x1b]1337;CurrentDir=$(pwd)\\x07\" }";
// }
// if (sc.getShellDialect() == ShellDialects.FISH) {
// return """
// function __tabby_working_directory_reporting --on-event fish_prompt
// echo -en "\\e]1337;CurrentDir=$PWD\\x7"
// end
// """;
// }
// return null;
// });
return TerminalInitFunction.none();
}

View file

@ -81,8 +81,11 @@ public interface WezTerminalType extends ExternalTerminalType {
@Override
public void launch(LaunchConfiguration configuration) throws Exception {
var path = LocalShell.getShell().command(String.format(
"mdfind -name '%s' -onlyin /Applications -onlyin ~/Applications -onlyin /System/Applications 2>/dev/null", applicationName)).readStdoutOrThrow();
var path = LocalShell.getShell()
.command(String.format(
"mdfind -name '%s' -onlyin /Applications -onlyin ~/Applications -onlyin /System/Applications 2>/dev/null",
applicationName))
.readStdoutOrThrow();
var c = CommandBuilder.of()
.addFile(Path.of(path)
.resolve("Contents")

View file

@ -2,6 +2,7 @@ package io.xpipe.app.util;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.core.util.SecretValue;
import javafx.animation.PauseTransition;
import javafx.scene.input.Clipboard;
import javafx.scene.input.DataFormat;
@ -21,9 +22,16 @@ public class ClipboardHelper {
PlatformThread.runLaterIfNeeded(() -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
Map<DataFormat, Object> previous = Stream.of(DataFormat.PLAIN_TEXT, DataFormat.URL, DataFormat.RTF, DataFormat.HTML, DataFormat.IMAGE, DataFormat.FILES)
.map(dataFormat -> new AbstractMap.SimpleEntry<>(dataFormat, clipboard.getContent(dataFormat))).filter(o -> o.getValue() != null)
.collect(HashMap::new, (m,v)->m.put(v.getKey(), v.getValue()), HashMap::putAll);
Map<DataFormat, Object> previous = Stream.of(
DataFormat.PLAIN_TEXT,
DataFormat.URL,
DataFormat.RTF,
DataFormat.HTML,
DataFormat.IMAGE,
DataFormat.FILES)
.map(dataFormat -> new AbstractMap.SimpleEntry<>(dataFormat, clipboard.getContent(dataFormat)))
.filter(o -> o.getValue() != null)
.collect(HashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), HashMap::putAll);
var withPassword = new HashMap<>(previous);
withPassword.put(DataFormat.PLAIN_TEXT, pass.getSecretValue());

View file

@ -8,6 +8,7 @@ import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.store.DataStore;
import io.xpipe.core.store.ShellStore;
import javafx.beans.value.ObservableValue;
import java.util.function.IntFunction;
@ -32,7 +33,8 @@ public class DataStoreFormatter {
return null;
}
if (s.getShellDialect() != null && !s.getShellDialect().getDumbMode().supportsAnyPossibleInteraction()) {
if (s.getShellDialect() != null
&& !s.getShellDialect().getDumbMode().supportsAnyPossibleInteraction()) {
if (s.getOsName() != null) {
return formattedOsName(s.getOsName());
}

View file

@ -29,34 +29,33 @@ public class DesktopHelper {
}
public static void browsePathRemote(ShellControl sc, String path, FileKind kind) throws Exception {
var d = sc.getShellDialect();
switch (sc.getOsType()) {
case OsType.Windows windows -> {
// Explorer does not support single quotes, so use normal quotes
if (kind == FileKind.DIRECTORY) {
sc.executeSimpleCommand("explorer " + d.quoteArgument(path));
} else {
sc.executeSimpleCommand("explorer /select," + d.quoteArgument(path));
}
}
case OsType.Linux linux -> {
var action = kind == FileKind.DIRECTORY ?
"org.freedesktop.FileManager1.ShowFolders" :
"org.freedesktop.FileManager1.ShowItems";
var dbus = String.format("""
dbus-send --session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 %s array:string:"file://%s" string:""
""", action, path);
sc.executeSimpleCommand(dbus);
}
case OsType.MacOs macOs -> {
sc.executeSimpleCommand(
"open " + (kind == FileKind.DIRECTORY ? "" : "-R ") + d.fileArgument(path));
}
case OsType.Bsd bsd -> {
}
case OsType.Solaris solaris -> {
var d = sc.getShellDialect();
switch (sc.getOsType()) {
case OsType.Windows windows -> {
// Explorer does not support single quotes, so use normal quotes
if (kind == FileKind.DIRECTORY) {
sc.executeSimpleCommand("explorer " + d.quoteArgument(path));
} else {
sc.executeSimpleCommand("explorer /select," + d.quoteArgument(path));
}
}
case OsType.Linux linux -> {
var action = kind == FileKind.DIRECTORY
? "org.freedesktop.FileManager1.ShowFolders"
: "org.freedesktop.FileManager1.ShowItems";
var dbus = String.format(
"""
dbus-send --session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 %s array:string:"file://%s" string:""
""",
action, path);
sc.executeSimpleCommand(dbus);
}
case OsType.MacOs macOs -> {
sc.executeSimpleCommand("open " + (kind == FileKind.DIRECTORY ? "" : "-R ") + d.fileArgument(path));
}
case OsType.Bsd bsd -> {}
case OsType.Solaris solaris -> {}
}
}
public static void browsePathLocal(Path file) {

View file

@ -32,7 +32,7 @@ public class TerminalLauncher {
title,
type.shouldClear()
&& AppPrefs.get().clearTerminalOnInit().get(),
TerminalInitFunction.none()),
TerminalInitFunction.none()),
true);
var config = new ExternalTerminalType.LaunchConfiguration(null, title, title, script, sc.getShellDialect());
type.launch(config);

View file

@ -1,11 +1,12 @@
package io.xpipe.app.util;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinReg;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.ShellControl;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinReg;
import java.util.Optional;
public class WindowsRegistry {
@ -56,7 +57,8 @@ public class WindowsRegistry {
}
}
public static Optional<String> findRemoteValuesRecursive(ShellControl shellControl, int hkey, String key, String valueName) throws Exception {
public static Optional<String> findRemoteValuesRecursive(
ShellControl shellControl, int hkey, String key, String valueName) throws Exception {
var command = CommandBuilder.of()
.add("reg", "query")
.addQuoted((hkey == HKEY_LOCAL_MACHINE ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER") + "\\" + key)

View file

@ -1,7 +1,6 @@
package io.xpipe.core.store;
public interface SingletonSessionStore<T extends Session>
extends ExpandedLifecycleStore, InternalCacheDataStore {
public interface SingletonSessionStore<T extends Session> extends ExpandedLifecycleStore, InternalCacheDataStore {
@Override
default void finalizeValidate() throws Exception {

View file

@ -21,7 +21,8 @@ public interface StatefulDataStore<T extends DataStoreState> extends DataStore {
@SuppressWarnings("unchecked")
default T getState() {
return (T) DataStateProvider.get().getState(this, this::createDefaultState).deepCopy();
return (T)
DataStateProvider.get().getState(this, this::createDefaultState).deepCopy();
}
default void setState(T val) {

View file

@ -1,6 +1,5 @@
package io.xpipe.core.util;
import com.fasterxml.jackson.databind.*;
import io.xpipe.core.dialog.BaseQueryElement;
import io.xpipe.core.dialog.BusyElement;
import io.xpipe.core.dialog.ChoiceElement;
@ -14,6 +13,7 @@ import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.module.SimpleModule;

View file

@ -8,8 +8,10 @@ import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.store.ShellStore;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import lombok.Value;
public class BrowseStoreAction implements ActionProvider {
@ -22,8 +24,8 @@ public class BrowseStoreAction implements ActionProvider {
public boolean isApplicable(DataStoreEntryRef<ShellStore> o) {
var state = o.get().getStorePersistentState();
if (state instanceof ShellStoreState shellStoreState) {
return shellStoreState.getShellDialect() == null ||
shellStoreState.getShellDialect().getDumbMode().supportsAnyPossibleInteraction();
return shellStoreState.getShellDialect() == null
|| shellStoreState.getShellDialect().getDumbMode().supportsAnyPossibleInteraction();
} else {
return true;
}

View file

@ -43,8 +43,9 @@ public class LaunchAction implements ActionProvider {
@Override
public boolean isApplicable(DataStoreEntryRef<DataStore> o) {
return o.get().getValidity().isUsable() && (o.getStore() instanceof LaunchableStore || o.get().getProvider().launchAction(o.get()) !=
null);
return o.get().getValidity().isUsable()
&& (o.getStore() instanceof LaunchableStore
|| o.get().getProvider().launchAction(o.get()) != null);
}
@Override
@ -75,8 +76,9 @@ public class LaunchAction implements ActionProvider {
@Override
public boolean isApplicable(DataStoreEntryRef<DataStore> o) {
return o.get().getValidity().isUsable() && (o.getStore() instanceof LaunchableStore || o.get().getProvider().launchAction(o.get()) !=
null);
return o.get().getValidity().isUsable()
&& (o.getStore() instanceof LaunchableStore
|| o.get().getProvider().launchAction(o.get()) != null);
}
};
}

View file

@ -7,7 +7,9 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.ScanAlert;
import io.xpipe.core.process.ShellStoreState;
import io.xpipe.core.store.ShellStore;
import javafx.beans.value.ObservableValue;
import lombok.Value;
public class ScanAction implements ActionProvider {
@ -39,8 +41,8 @@ public class ScanAction implements ActionProvider {
var state = o.get().getStorePersistentState();
if (state instanceof ShellStoreState shellStoreState) {
return shellStoreState.getShellDialect() == null ||
shellStoreState.getShellDialect().getDumbMode().supportsAnyPossibleInteraction();
return shellStoreState.getShellDialect() == null
|| shellStoreState.getShellDialect().getDumbMode().supportsAnyPossibleInteraction();
} else {
return true;
}

View file

@ -8,6 +8,7 @@ import io.xpipe.app.util.DesktopHelper;
import io.xpipe.app.util.LocalShell;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellControl;
import javafx.beans.value.ObservableValue;
import java.util.List;
@ -21,7 +22,8 @@ public class BrowseInNativeManagerAction implements LeafAction {
var e = entry.getRawFileEntry().getPath();
var localFile = sc.getLocalSystemAccess().translateToLocalSystemPath(e);
try (var local = LocalShell.getShell().start()) {
DesktopHelper.browsePathRemote(local,localFile, entry.getRawFileEntry().getKind());
DesktopHelper.browsePathRemote(
local, localFile, entry.getRawFileEntry().getKind());
}
}
}

View file

@ -9,6 +9,7 @@ import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.TerminalLauncher;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.ShellControl;
import javafx.beans.value.ObservableValue;
import java.util.List;

View file

@ -74,7 +74,8 @@ public class DesktopCommandStoreProvider implements DataStoreProvider {
entry,
env,
DesktopEnvironmentStore.class,
desktopStoreDataStoreEntryRef -> desktopStoreDataStoreEntryRef.getStore().supportsDesktopAccess(),
desktopStoreDataStoreEntryRef ->
desktopStoreDataStoreEntryRef.getStore().supportsDesktopAccess(),
StoreViewState.get().getAllConnectionsCategory()),
env)
.nonNull()

View file

@ -95,9 +95,9 @@ public class DesktopEnvironmentStore extends JacksonizedValue
: getMergedInitCommands(null));
var scriptFile = base.getStore().createScript(dialect, toExecute);
var launchScriptFile = base.getStore()
.createScript(dialect, dialect.prepareTerminalInitFileOpenCommand(dialect, null, scriptFile.toString()));
var launchConfig =
new ExternalTerminalType.LaunchConfiguration(null, name, name, launchScriptFile, dialect);
.createScript(
dialect, dialect.prepareTerminalInitFileOpenCommand(dialect, null, scriptFile.toString()));
var launchConfig = new ExternalTerminalType.LaunchConfiguration(null, name, name, launchScriptFile, dialect);
base.getStore().runDesktopScript(name, launchCommand.apply(launchConfig));
}

View file

@ -127,7 +127,9 @@ public class DesktopEnvironmentStoreProvider implements DataStoreProvider {
.nonNull()
.nameAndDescription("desktopTerminal")
.addComp(
ChoiceComp.ofTranslatable(terminal, ExternalTerminalType.getTypes(st.getUsedOsType(), true, false), true).maxWidth(2000),
ChoiceComp.ofTranslatable(
terminal, ExternalTerminalType.getTypes(st.getUsedOsType(), true, false), true)
.maxWidth(2000),
terminal)
.nonNull()
.nameAndDescription("desktopShellDialect")

View file

@ -29,17 +29,19 @@ public class ScriptGroupStoreProvider implements DataStoreProvider {
return new DenseStoreEntryComp(sec.getWrapper(), true, null);
}
var def = StoreToggleComp.<ScriptGroupStore>simpleToggle("base.isDefaultGroup", sec, s -> s.getState().isDefault(), (s, aBoolean) -> {
var state = s.getState();
state.setDefault(aBoolean);
s.setState(state);
});
var def = StoreToggleComp.<ScriptGroupStore>simpleToggle(
"base.isDefaultGroup", sec, s -> s.getState().isDefault(), (s, aBoolean) -> {
var state = s.getState();
state.setDefault(aBoolean);
s.setState(state);
});
var bring = StoreToggleComp.<ScriptGroupStore>simpleToggle("base.bringToShells", sec, s -> s.getState().isBringToShell(), (s, aBoolean) -> {
var state = s.getState();
state.setBringToShell(aBoolean);
s.setState(state);
});
var bring = StoreToggleComp.<ScriptGroupStore>simpleToggle(
"base.bringToShells", sec, s -> s.getState().isBringToShell(), (s, aBoolean) -> {
var state = s.getState();
state.setBringToShell(aBoolean);
s.setState(state);
});
var dropdown = new DropdownComp(List.of(def, bring));
return new DenseStoreEntryComp(sec.getWrapper(), true, dropdown);

View file

@ -54,17 +54,19 @@ public class SimpleScriptStoreProvider implements DataStoreProvider {
return new DenseStoreEntryComp(sec.getWrapper(), true, null);
}
var def = StoreToggleComp.<SimpleScriptStore>simpleToggle("base.isDefaultGroup", sec, s -> s.getState().isDefault(), (s, aBoolean) -> {
var state = s.getState();
state.setDefault(aBoolean);
s.setState(state);
});
var def = StoreToggleComp.<SimpleScriptStore>simpleToggle(
"base.isDefaultGroup", sec, s -> s.getState().isDefault(), (s, aBoolean) -> {
var state = s.getState();
state.setDefault(aBoolean);
s.setState(state);
});
var bring = StoreToggleComp.<SimpleScriptStore>simpleToggle("base.bringToShells", sec, s -> s.getState().isBringToShell(), (s, aBoolean) -> {
var state = s.getState();
state.setBringToShell(aBoolean);
s.setState(state);
});
var bring = StoreToggleComp.<SimpleScriptStore>simpleToggle(
"base.bringToShells", sec, s -> s.getState().isBringToShell(), (s, aBoolean) -> {
var state = s.getState();
state.setBringToShell(aBoolean);
s.setState(state);
});
SimpleScriptStore s = sec.getWrapper().getEntry().getStore().asNeeded();
var groupWrapper = StoreViewState.get().getEntryWrapper(s.getGroup().getEntry());
@ -136,7 +138,8 @@ public class SimpleScriptStoreProvider implements DataStoreProvider {
var group = new SimpleObjectProperty<>(st.getGroup());
Property<ShellDialect> dialect = new SimpleObjectProperty<>(st.getMinimumDialect());
var others = new SimpleListProperty<>(FXCollections.observableArrayList(new ArrayList<>(st.getEffectiveScripts())));
var others =
new SimpleListProperty<>(FXCollections.observableArrayList(new ArrayList<>(st.getEffectiveScripts())));
Property<String> commandProp = new SimpleObjectProperty<>(st.getCommands());
Comp<?> choice = (Comp<?>) Class.forName(
@ -268,9 +271,7 @@ public class SimpleScriptStoreProvider implements DataStoreProvider {
@Override
public DataStore defaultStore() {
return SimpleScriptStore.builder()
.scripts(List.of())
.build();
return SimpleScriptStore.builder().scripts(List.of()).build();
}
@Override