Improve detection for initial launch

This commit is contained in:
crschnick 2023-05-04 13:37:13 +00:00
parent 4152d6e1db
commit e9af3d5bc7
9 changed files with 55 additions and 31 deletions

View file

@ -3,6 +3,7 @@ package io.xpipe.app.comp.storage.store;
import atlantafx.base.theme.Styles; import atlantafx.base.theme.Styles;
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.util.BindingsHelper; import io.xpipe.app.fxcomps.util.BindingsHelper;
@ -29,13 +30,17 @@ public class StoreEntryListComp extends SimpleComp {
@Override @Override
protected Region createSimple() { protected Region createSimple() {
var initialCount = StoreViewState.get().getAllEntries().size();
var showIntro = Bindings.createBooleanBinding(() -> {
return initialCount == StoreViewState.get().getAllEntries().size() && AppState.get().isInitialLaunch();
}, StoreViewState.get().getAllEntries());
var map = new LinkedHashMap<Comp<?>, ObservableBooleanValue>(); var map = new LinkedHashMap<Comp<?>, ObservableBooleanValue>();
map.put( map.put(
createList(), createList(),
BindingsHelper.persist( BindingsHelper.persist(
Bindings.not(Bindings.isEmpty(StoreViewState.get().getShownEntries())))); Bindings.not(Bindings.isEmpty(StoreViewState.get().getShownEntries()))));
map.put(new StoreIntroComp(), StoreViewState.get().emptyProperty()); map.put(new StoreIntroComp(), showIntro);
map.put( map.put(
new StoreNotFoundComp(), new StoreNotFoundComp(),
BindingsHelper.persist(Bindings.and( BindingsHelper.persist(Bindings.and(

View file

@ -6,6 +6,7 @@ import io.xpipe.app.fxcomps.SimpleComp;
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;
@ -70,8 +71,9 @@ 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.CENTER); sp.setAlignment(Pos.BOTTOM_CENTER);
sp.setPickOnBounds(false); sp.setPickOnBounds(false);
sp.setPadding(new Insets(0, 0, 40, 0));
return sp; return sp;
} }
} }

View file

@ -7,9 +7,7 @@ import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.StorageListener; import io.xpipe.app.storage.StorageListener;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
@ -29,10 +27,6 @@ public class StoreViewState {
private final ObservableList<StoreEntryWrapper> shownEntries = private final ObservableList<StoreEntryWrapper> shownEntries =
FXCollections.observableList(new CopyOnWriteArrayList<>()); FXCollections.observableList(new CopyOnWriteArrayList<>());
private final ObservableBooleanValue empty = Bindings.createBooleanBinding(() -> {
return allEntries.stream().allMatch(storeEntryWrapper -> !storeEntryWrapper.getEntry().getConfiguration().isRenameable());
}, allEntries);
private StoreViewState() { private StoreViewState() {
try { try {
addStorageGroupListeners(); addStorageGroupListeners();
@ -107,12 +101,4 @@ public class StoreViewState {
public ObservableList<StoreEntryWrapper> getShownEntries() { public ObservableList<StoreEntryWrapper> getShownEntries() {
return shownEntries; return shownEntries;
} }
public boolean isEmpty() {
return empty.get();
}
public ObservableBooleanValue emptyProperty() {
return empty;
}
} }

View file

@ -9,7 +9,6 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
public class AppCache { public class AppCache {
@ -18,12 +17,6 @@ public class AppCache {
return Optional.ofNullable(get(key, type, () -> null)); return Optional.ofNullable(get(key, type, () -> null));
} }
public static UUID getCachedUserId() {
var id = get("userId", UUID.class, UUID::randomUUID);
update("userId", id);
return id;
}
private static Path getBasePath() { private static Path getBasePath() {
return AppProperties.get().getDataDir().resolve("cache"); return AppProperties.get().getDataDir().resolve("cache");
} }
@ -68,7 +61,7 @@ public class AppCache {
FileUtils.deleteQuietly(path.toFile()); FileUtils.deleteQuietly(path.toFile());
} }
} }
return notPresent.get(); return notPresent != null ? notPresent.get() : null;
} }
public static <T> void update(String key, T val) { public static <T> void update(String key, T val) {

View file

@ -0,0 +1,38 @@
package io.xpipe.app.core;
import lombok.Value;
import java.util.UUID;
@Value
public class AppState {
private static AppState INSTANCE;
UUID userId;
boolean initialLaunch;
public AppState() {
UUID id = AppCache.get("userId", UUID.class, null);
if (id == null) {
initialLaunch = AppCache.getIfPresent("lastBuild", String.class).isEmpty();
userId = UUID.randomUUID();
AppCache.update("userId", userId);
} else {
userId = id;
initialLaunch = false;
}
}
public static void init() {
if (INSTANCE != null) {
return;
}
INSTANCE = new AppState();
}
public static AppState get() {
return INSTANCE;
}
}

View file

@ -1,9 +1,6 @@
package io.xpipe.app.core.mode; package io.xpipe.app.core.mode;
import io.xpipe.app.core.App; import io.xpipe.app.core.*;
import io.xpipe.app.core.AppChecks;
import io.xpipe.app.core.AppLogs;
import io.xpipe.app.core.AppProperties;
import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.ErrorHandler; import io.xpipe.app.issue.ErrorHandler;
import io.xpipe.app.issue.TrackEvent; import io.xpipe.app.issue.TrackEvent;
@ -87,6 +84,7 @@ public abstract class OperationMode {
TrackEvent.info("mode", "Initial setup"); TrackEvent.info("mode", "Initial setup");
AppProperties.init(); AppProperties.init();
AppState.init();
XPipeSession.init(AppProperties.get().getBuildUuid()); XPipeSession.init(AppProperties.get().getBuildUuid());
AppChecks.checkDirectoryPermissions(); AppChecks.checkDirectoryPermissions();
AppLogs.init(); AppLogs.init();

View file

@ -3,8 +3,8 @@ package io.xpipe.app.issue;
import io.sentry.*; import io.sentry.*;
import io.sentry.protocol.SentryId; import io.sentry.protocol.SentryId;
import io.sentry.protocol.User; import io.sentry.protocol.User;
import io.xpipe.app.core.AppCache;
import io.xpipe.app.core.AppProperties; import io.xpipe.app.core.AppProperties;
import io.xpipe.app.core.AppState;
import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.update.XPipeDistributionType; import io.xpipe.app.update.XPipeDistributionType;
@ -28,6 +28,7 @@ public class SentryErrorHandler implements ErrorHandler {
// Assume that this object is wrapped by a synchronous error handler // Assume that this object is wrapped by a synchronous error handler
if (!init) { if (!init) {
AppProperties.init(); AppProperties.init();
AppState.init();
if (AppProperties.get().getSentryUrl() != null) { if (AppProperties.get().getSentryUrl() != null) {
Sentry.init(options -> { Sentry.init(options -> {
options.setDsn(AppProperties.get().getSentryUrl()); options.setDsn(AppProperties.get().getSentryUrl());
@ -110,7 +111,7 @@ public class SentryErrorHandler implements ErrorHandler {
} }
var user = new User(); var user = new User();
user.setId(AppCache.getCachedUserId().toString()); user.setId(AppState.get().getUserId().toString());
s.setUser(user); s.setUser(user);
} }

View file

@ -53,6 +53,7 @@ public class TerminalErrorHandler implements ErrorHandler {
try { try {
AppProperties.init(); AppProperties.init();
AppState.init();
AppExtensionManager.init(false); AppExtensionManager.init(false);
AppI18n.init(); AppI18n.init();
AppStyle.init(); AppStyle.init();

View file

@ -16,6 +16,6 @@ storeIntroTitle=Adding Connections
storeIntroDescription=Connect to remote systems, databases, and more. storeIntroDescription=Connect to 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=You can quickly search for available remote connections automatically.\nAlternatively, you can also of course add them manually.
detectConnections=Detect 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 X-Pipe, check out the documentation: storeDocumentation=In case you prefer a more structured approach to\nfamiliarizing yourself with X-Pipe, check out the documentation: