Small fixes [release]

This commit is contained in:
crschnick 2023-07-06 06:38:48 +00:00
parent 447ec12023
commit f464c2c1ac
19 changed files with 62 additions and 42 deletions

View file

@ -31,6 +31,7 @@ public class LoadingOverlayComp extends Comp<CompStructure<StackPane>> {
var loadingBg = new StackPane(loading); var loadingBg = new StackPane(loading);
loadingBg.getStyleClass().add("loading-comp"); loadingBg.getStyleClass().add("loading-comp");
loadingBg.getStyleClass().add("modal-pane");
loadingBg.setVisible(showLoading.getValue()); loadingBg.setVisible(showLoading.getValue());

View file

@ -2,7 +2,6 @@ package io.xpipe.app.comp.storage.store;
import io.xpipe.app.comp.base.ListBoxViewComp; import io.xpipe.app.comp.base.ListBoxViewComp;
import io.xpipe.app.comp.base.MultiContentComp; import io.xpipe.app.comp.base.MultiContentComp;
import io.xpipe.app.core.AppState;
import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.HorizontalComp; import io.xpipe.app.fxcomps.impl.HorizontalComp;
@ -33,11 +32,10 @@ public class StoreEntryListComp extends SimpleComp {
@Override @Override
protected Region createSimple() { protected Region createSimple() {
var initialCount = StoreViewState.get().getAllEntries().size(); var initialCount = 1;
var showIntro = Bindings.createBooleanBinding( var showIntro = Bindings.createBooleanBinding(
() -> { () -> {
return initialCount == StoreViewState.get().getAllEntries().size() return initialCount == StoreViewState.get().getAllEntries().size();
&& AppState.get().isInitialLaunch();
}, },
StoreViewState.get().getAllEntries()); StoreViewState.get().getAllEntries());
var map = new LinkedHashMap<Comp<?>, ObservableBooleanValue>(); var map = new LinkedHashMap<Comp<?>, ObservableBooleanValue>();

View file

@ -206,7 +206,7 @@ public class StoreEntryWrapper implements StorageFilter.Filterable {
@Override @Override
public boolean shouldShow(String filter) { public boolean shouldShow(String filter) {
return getName().toLowerCase().contains(filter.toLowerCase()) return filter == null || getName().toLowerCase().contains(filter.toLowerCase())
|| (summary.get() != null && summary.get().toLowerCase().contains(filter.toLowerCase())) || (summary.get() != null && summary.get().toLowerCase().contains(filter.toLowerCase()))
|| (information.get() != null && information.get().toLowerCase().contains(filter.toLowerCase())); || (information.get() != null && information.get().toLowerCase().contains(filter.toLowerCase()));
} }

View file

@ -7,7 +7,6 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.Hyperlinks; import io.xpipe.app.util.Hyperlinks;
import io.xpipe.app.util.ScanAlert; import io.xpipe.app.util.ScanAlert;
import io.xpipe.core.impl.LocalStore; import io.xpipe.core.impl.LocalStore;
import javafx.geometry.Insets;
import javafx.geometry.Orientation; import javafx.geometry.Orientation;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -29,7 +28,7 @@ public class StoreIntroComp extends SimpleComp {
var introDesc = new Label(AppI18n.get("storeIntroDescription")); var introDesc = new Label(AppI18n.get("storeIntroDescription"));
var mfi = new FontIcon("mdi2m-magnify"); var mfi = new FontIcon("mdi2p-playlist-plus");
var machine = new Label(AppI18n.get("storeMachineDescription"), mfi); var machine = new Label(AppI18n.get("storeMachineDescription"), mfi);
machine.heightProperty().addListener((c, o, n) -> { machine.heightProperty().addListener((c, o, n) -> {
mfi.iconSizeProperty().set(n.intValue()); mfi.iconSizeProperty().set(n.intValue());
@ -67,9 +66,8 @@ public class StoreIntroComp extends SimpleComp {
v.getStyleClass().add("intro"); v.getStyleClass().add("intro");
var sp = new StackPane(v); var sp = new StackPane(v);
sp.setAlignment(Pos.BOTTOM_CENTER); sp.setAlignment(Pos.CENTER);
sp.setPickOnBounds(false); sp.setPickOnBounds(false);
sp.setPadding(new Insets(0, 0, 40, 0));
return sp; return sp;
} }
} }

View file

@ -123,7 +123,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
e -> { e -> {
try { try {
DataStorage.get().addStoreEntry(e); DataStorage.get().addStoreEntry(e);
if (e.getProvider().shouldHaveSubShells()) { if (e.getProvider().shouldHaveChildren()) {
ScanAlert.showAsync(e); ScanAlert.showAsync(e);
} }
} catch (Exception ex) { } catch (Exception ex) {

View file

@ -20,7 +20,7 @@ public class AppActionLinkDetector {
return content != null ? content.toString() : null; return content != null ? content.toString() : null;
} }
private static void handle(String content, boolean showAlert) { public static void handle(String content, boolean showAlert) {
var detected = LauncherInput.of(content); var detected = LauncherInput.of(content);
if (detected.size() == 0) { if (detected.size() == 0) {
return; return;

View file

@ -46,7 +46,7 @@ public interface DataStoreProvider {
return true; return true;
} }
default boolean shouldHaveSubShells() { default boolean shouldHaveChildren() {
return canHaveSubShells(); return canHaveSubShells();
} }

View file

@ -1,9 +1,10 @@
package io.xpipe.app.fxcomps.impl; package io.xpipe.app.fxcomps.impl;
import io.xpipe.app.core.AppActionLinkDetector;
import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.fxcomps.util.SimpleChangeListener; import io.xpipe.app.fxcomps.util.SimpleChangeListener;
import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.scene.Node; import javafx.scene.Node;
@ -14,6 +15,8 @@ import lombok.Builder;
import lombok.Value; import lombok.Value;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
import java.util.Objects;
public class FilterComp extends Comp<FilterComp.Structure> { public class FilterComp extends Comp<FilterComp.Structure> {
private final Property<String> filterText; private final Property<String> filterText;
@ -31,9 +34,20 @@ public class FilterComp extends Comp<FilterComp.Structure> {
filter.setAccessibleText("Filter"); filter.setAccessibleText("Filter");
SimpleChangeListener.apply(filterText, val -> { SimpleChangeListener.apply(filterText, val -> {
PlatformThread.runLaterIfNeeded(() -> filter.setText(val)); Platform.runLater(() -> {
if (!Objects.equals(filter.getText(), val)) {
filter.setText(val);
}
});
}); });
filter.textProperty().addListener((observable, oldValue, newValue) -> { filter.textProperty().addListener((observable, oldValue, newValue) -> {
// Handle pasted xpipe URLs
if (newValue != null && newValue.startsWith("xpipe://")) {
AppActionLinkDetector.handle(newValue, false);
filter.setText(null);
return;
}
filterText.setValue(newValue); filterText.setValue(newValue);
}); });

View file

@ -139,7 +139,7 @@ public class BindingsHelper {
ObservableList<V> l2, ObservableValue<Predicate<V>> predicate) { ObservableList<V> l2, ObservableValue<Predicate<V>> predicate) {
ObservableList<V> l1 = FXCollections.observableList(new ArrayList<>()); ObservableList<V> l1 = FXCollections.observableList(new ArrayList<>());
Runnable runnable = () -> { Runnable runnable = () -> {
setContent(l1, l2.stream().filter(predicate.getValue()).toList()); setContent(l1, predicate.getValue() != null ? l2.stream().filter(predicate.getValue()).toList() : l2);
}; };
runnable.run(); runnable.run();
l2.addListener((ListChangeListener<? super V>) c -> { l2.addListener((ListChangeListener<? super V>) c -> {

View file

@ -19,6 +19,7 @@ import io.xpipe.app.fxcomps.util.SimpleChangeListener;
import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.LockChangeAlert; import io.xpipe.app.util.LockChangeAlert;
import io.xpipe.app.util.LockedSecretValue; import io.xpipe.app.util.LockedSecretValue;
import io.xpipe.core.util.ModuleHelper;
import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.SecretValue;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.*; import javafx.beans.property.*;
@ -35,6 +36,10 @@ import java.util.*;
public class AppPrefs { public class AppPrefs {
public boolean isDevelopmentEnvironment() {
return developerMode().getValue() && !ModuleHelper.isImage();
}
private static ObservableBooleanValue bindDeveloperTrue(ObservableBooleanValue o) { private static ObservableBooleanValue bindDeveloperTrue(ObservableBooleanValue o) {
return Bindings.createBooleanBinding( return Bindings.createBooleanBinding(
() -> { () -> {
@ -588,7 +593,7 @@ public class AppPrefs {
developerShowHiddenProviders)), developerShowHiddenProviders)),
Category.of("troubleshoot", Group.of(troubleshoot)))); Category.of("troubleshoot", Group.of(troubleshoot))));
categories.get(categories.size() - 1).setVisibilityProperty(VisibilityProperty.of(developerMode())); categories.get(categories.size() - 2).setVisibilityProperty(VisibilityProperty.of(developerMode()));
var handler = new PrefsHandlerImpl(categories); var handler = new PrefsHandlerImpl(categories);
PrefsProvider.getAll().forEach(prov -> prov.addPrefs(handler)); PrefsProvider.getAll().forEach(prov -> prov.addPrefs(handler));

View file

@ -182,6 +182,7 @@ public class DataStoreEntry extends StorageElement {
public void setExpanded(boolean expanded) { public void setExpanded(boolean expanded) {
this.dirty = true; this.dirty = true;
this.expanded = expanded; this.expanded = expanded;
listeners.forEach(l -> l.onUpdate());
} }
public DataStore getStore() { public DataStore getStore() {

View file

@ -94,9 +94,8 @@ public class StandardStorage extends DataStorage {
storeEntries.add(entry); storeEntries.add(entry);
} catch (Exception e) { } catch (Exception e) {
// We only keep invalid entries in developer mode as there's no point in keeping them in // We only keep invalid entries in developer mode as there's no point in keeping them in production.
// production. if (AppPrefs.get().isDevelopmentEnvironment()) {
if (AppPrefs.get().developerMode().getValue()) {
directoriesToKeep.add(path); directoriesToKeep.add(path);
} }
ErrorEvent.fromThrowable(e).omitted(true).build().handle(); ErrorEvent.fromThrowable(e).omitted(true).build().handle();
@ -107,7 +106,7 @@ public class StandardStorage extends DataStorage {
storeEntries.forEach(dataStoreEntry -> dataStoreEntry.simpleRefresh()); storeEntries.forEach(dataStoreEntry -> dataStoreEntry.simpleRefresh());
// Remove even incomplete stores when in production // Remove even incomplete stores when in production
if (!AppPrefs.get().developerMode().getValue()) { if (!AppPrefs.get().isDevelopmentEnvironment()) {
storeEntries.removeIf(entry -> { storeEntries.removeIf(entry -> {
return !entry.getState().isUsable(); return !entry.getState().isUsable();
}); });

View file

@ -11,8 +11,7 @@ public class DesktopShortcuts {
private static void createWindowsShortcut(String target, String name) throws Exception { private static void createWindowsShortcut(String target, String name) throws Exception {
var icon = XPipeInstallation.getLocalDefaultInstallationIcon(); var icon = XPipeInstallation.getLocalDefaultInstallationIcon();
var shortcutTarget = XPipeInstallation.getCurrentInstallationBasePath() var shortcutTarget = XPipeInstallation.getLocalDefaultCliExecutable();
.resolve(XPipeInstallation.getRelativeCliExecutablePath(OsType.WINDOWS));
var content = String.format( var content = String.format(
""" """
set "TARGET=%s" set "TARGET=%s"
@ -26,8 +25,7 @@ public class DesktopShortcuts {
} }
private static void createLinuxShortcut(String target, String name) throws Exception { private static void createLinuxShortcut(String target, String name) throws Exception {
var exec = XPipeInstallation.getCurrentInstallationBasePath() var exec = XPipeInstallation.getLocalDefaultCliExecutable();
.resolve(XPipeInstallation.getRelativeCliExecutablePath(OsType.LINUX));
var icon = XPipeInstallation.getLocalDefaultInstallationIcon(); var icon = XPipeInstallation.getLocalDefaultInstallationIcon();
var content = String.format( var content = String.format(
""" """
@ -47,8 +45,7 @@ public class DesktopShortcuts {
} }
private static void createMacOSShortcut(String target, String name) throws Exception { private static void createMacOSShortcut(String target, String name) throws Exception {
var exec = XPipeInstallation.getCurrentInstallationBasePath() var exec = XPipeInstallation.getLocalDefaultCliExecutable();
.resolve(XPipeInstallation.getRelativeCliExecutablePath(OsType.MACOS));
var icon = XPipeInstallation.getLocalDefaultInstallationIcon(); var icon = XPipeInstallation.getLocalDefaultInstallationIcon();
var base = System.getProperty("user.home") + "/Desktop/" + name + ".app"; var base = System.getProperty("user.home") + "/Desktop/" + name + ".app";
var content = String.format( var content = String.format(

View file

@ -40,7 +40,7 @@ public class ScanAlert {
} }
private static void showForOtherStore(DataStoreEntry entry) { private static void showForOtherStore(DataStoreEntry entry) {
showIfNeeded(() -> { show(entry, () -> {
var providers = ScanProvider.getAll(); var providers = ScanProvider.getAll();
var applicable = providers.stream() var applicable = providers.stream()
.map(scanProvider -> scanProvider.create(entry.getStore())) .map(scanProvider -> scanProvider.create(entry.getStore()))
@ -51,7 +51,7 @@ public class ScanAlert {
} }
private static void showForShellStore(DataStoreEntry entry) { private static void showForShellStore(DataStoreEntry entry) {
showIfNeeded(() -> { show(entry, () -> {
try (var sc = ((ShellStore) entry.getStore()).control().start()) { try (var sc = ((ShellStore) entry.getStore()).control().start()) {
var providers = ScanProvider.getAll(); var providers = ScanProvider.getAll();
var applicable = new ArrayList<ScanProvider.ScanOperation>(); var applicable = new ArrayList<ScanProvider.ScanOperation>();
@ -69,7 +69,7 @@ public class ScanAlert {
}); });
} }
private static void showIfNeeded(Supplier<List<ScanProvider.ScanOperation>> applicable) { private static void show(DataStoreEntry entry, Supplier<List<ScanProvider.ScanOperation>> applicable) {
var busy = new SimpleBooleanProperty(); var busy = new SimpleBooleanProperty();
var selected = new SimpleListProperty<ScanProvider.ScanOperation>(FXCollections.observableArrayList()); var selected = new SimpleListProperty<ScanProvider.ScanOperation>(FXCollections.observableArrayList());
AppWindowHelper.showAlert( AppWindowHelper.showAlert(
@ -104,6 +104,8 @@ public class ScanAlert {
} }
} }
entry.setExpanded(true);
Platform.runLater(() -> { Platform.runLater(() -> {
alert.setResult(ButtonType.OK); alert.setResult(ButtonType.OK);
alert.close(); alert.close();

View file

@ -12,10 +12,10 @@ dataSourceIntroStructure=Structure data sources contain some form of object stru
dataSourceIntroText=Text data sources contain readable text that can\ncome in a variety of different encodings and simple formats. dataSourceIntroText=Text data sources contain readable text that can\ncome in a variety of different encodings and simple formats.
dataSourceIntroBinary=Binary data sources contain binary data. They\ncan be used when the data should be handled and preserved byte by byte. dataSourceIntroBinary=Binary data sources contain binary data. They\ncan be used when the data should be handled and preserved byte by byte.
dataSourceIntroCollection=Collection data sources contain multiple sub data sources. \nExamples are zip files or file system directories. dataSourceIntroCollection=Collection data sources contain multiple sub data sources. \nExamples are zip files or file system directories.
storeIntroTitle=Adding Connections storeIntroTitle=Shell Connection Hub
storeIntroDescription=Connect to remote systems, databases, and more. storeIntroDescription=Connect to shells, remote systems, databases, and more.
storeStreamDescription=Stream connections produce raw byte data\nthat can be used to construct data sources from. storeStreamDescription=Stream connections produce raw byte data\nthat can be used to construct data sources from.
storeMachineDescription=You can quickly search for available remote connections automatically.\nAlternatively, you can also of course add them manually. storeMachineDescription=To start off, here you can quickly detect available\nconnections automatically and choose which ones to add.
detectConnections=Search for connections detectConnections=Search for connections
storeDatabaseDescription=Database connections allow you to connect to\na database server and interact with its contained data. storeDatabaseDescription=Database connections allow you to connect to\na database server and interact with its contained data.
storeDocumentation=In case you prefer a more structured approach to\nfamiliarizing yourself with XPipe, check out the documentation: storeDocumentation=In case you prefer a more structured approach to\nfamiliarizing yourself with XPipe, check out the documentation:

View file

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

View file

@ -177,6 +177,11 @@ public class XPipeInstallation {
} }
} }
public static String getLocalDefaultCliExecutable() {
Path path = ModuleHelper.isImage() ? getCurrentInstallationBasePath() : Path.of(getLocalDefaultInstallationBasePath(true));
return path.resolve(getRelativeCliExecutablePath(OsType.getLocal())).toString();
}
public static Path getLocalDefaultInstallationIcon() { public static Path getLocalDefaultInstallationIcon() {
Path path = getCurrentInstallationBasePath(); Path path = getCurrentInstallationBasePath();

View file

@ -5,7 +5,7 @@ import io.xpipe.app.ext.ActionProvider;
import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.DesktopShortcuts; import io.xpipe.app.util.DesktopShortcuts;
import io.xpipe.core.store.ShellStore; import io.xpipe.core.store.LaunchableStore;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import lombok.Value; import lombok.Value;
@ -29,30 +29,30 @@ public class LaunchShortcutAction implements ActionProvider {
@Override @Override
public DataStoreCallSite<?> getDataStoreCallSite() { public DataStoreCallSite<?> getDataStoreCallSite() {
return new DataStoreCallSite<ShellStore>() { return new DataStoreCallSite<LaunchableStore>() {
@Override @Override
public Action createAction(ShellStore store) { public Action createAction(LaunchableStore store) {
return new Action(DataStorage.get().getStoreEntry(store)); return new Action(DataStorage.get().getStoreEntry(store));
} }
@Override @Override
public Class<ShellStore> getApplicableClass() { public Class<LaunchableStore> getApplicableClass() {
return ShellStore.class; return LaunchableStore.class;
} }
@Override @Override
public ObservableValue<String> getName(ShellStore store) { public ObservableValue<String> getName(LaunchableStore store) {
return AppI18n.observable("createShortcut"); return AppI18n.observable("createShortcut");
} }
@Override @Override
public String getIcon(ShellStore store) { public String getIcon(LaunchableStore store) {
return "mdi2c-code-greater-than"; return "mdi2c-code-greater-than";
} }
@Override @Override
public boolean isMajor(ShellStore o) { public boolean isMajor(LaunchableStore o) {
return false; return false;
} }
}; };

View file

@ -34,7 +34,7 @@ public class ScanAction implements ActionProvider {
@Override @Override
public boolean isMajor(ShellStore o) { public boolean isMajor(ShellStore o) {
return DataStoreProviders.byStore(o).shouldHaveSubShells(); return DataStoreProviders.byStore(o).shouldHaveChildren();
} }
@Override @Override