Bug fixes [release]

This commit is contained in:
crschnick 2023-03-12 12:49:10 +00:00
parent eecafd3cf9
commit 9e3637a97b
14 changed files with 101 additions and 48 deletions

View file

@ -7,8 +7,10 @@ import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.PrettyImageComp; import io.xpipe.app.fxcomps.impl.PrettyImageComp;
import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.BusyProperty;
import io.xpipe.core.store.FileSystem; import io.xpipe.core.store.FileSystem;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.geometry.Insets; import javafx.geometry.Insets;
@ -94,8 +96,15 @@ public class FileBrowserComp extends SimpleComp {
}); });
tabs.getSelectionModel().select(model.getOpenFileSystems().indexOf(model.getSelected().getValue())); tabs.getSelectionModel().select(model.getOpenFileSystems().indexOf(model.getSelected().getValue()));
// Used for ignoring changes by the tabpane when new tabs are added. We want to perform the selections manually!
var modifying = new SimpleBooleanProperty();
// Handle selection from platform // Handle selection from platform
tabs.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> { tabs.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> {
if (modifying.get()) {
return;
}
if (newValue.intValue() == -1) { if (newValue.intValue() == -1) {
model.getSelected().setValue(null); model.getSelected().setValue(null);
return; return;
@ -104,31 +113,36 @@ public class FileBrowserComp extends SimpleComp {
model.getSelected().setValue(model.getOpenFileSystems().get(newValue.intValue())); model.getSelected().setValue(model.getOpenFileSystems().get(newValue.intValue()));
}); });
// Handle selection from model
model.getSelected().addListener((observable, oldValue, newValue) -> {
PlatformThread.runLaterIfNeeded(() -> {
tabs.getSelectionModel().select(model.getOpenFileSystems().indexOf(newValue));
});
});
model.getOpenFileSystems().addListener((ListChangeListener<? super OpenFileSystemModel>) c -> { model.getOpenFileSystems().addListener((ListChangeListener<? super OpenFileSystemModel>) c -> {
while (c.next()) { while (c.next()) {
for (var r : c.getRemoved()) { for (var r : c.getRemoved()) {
PlatformThread.runLaterIfNeeded(() -> { PlatformThread.runLaterIfNeeded(() -> {
var t = map.remove(r); try (var b = new BusyProperty(modifying)) {
tabs.getTabs().remove(t); var t = map.remove(r);
tabs.getTabs().remove(t);
}
}); });
} }
for (var a : c.getAddedSubList()) { for (var a : c.getAddedSubList()) {
PlatformThread.runLaterIfNeeded(() -> { PlatformThread.runLaterIfNeeded(() -> {
var t = createTab(tabs, a); try (var b = new BusyProperty(modifying)) {
map.put(a, t); var t = createTab(tabs, a);
tabs.getTabs().add(t); map.put(a, t);
tabs.getTabs().add(t);
}
}); });
} }
} }
}); });
model.getSelected().addListener((observable, oldValue, newValue) -> {
PlatformThread.runLaterIfNeeded(() -> {
tabs.getSelectionModel().select(model.getOpenFileSystems().indexOf(newValue));
});
});
tabs.getTabs().addListener((ListChangeListener<? super Tab>) c -> { tabs.getTabs().addListener((ListChangeListener<? super Tab>) c -> {
while (c.next()) { while (c.next()) {
for (var r : c.getRemoved()) { for (var r : c.getRemoved()) {
@ -198,7 +212,7 @@ public class FileBrowserComp extends SimpleComp {
.getDisplayIconFileName() .getDisplayIconFileName()
: null; : null;
}, },
PlatformThread.sync(model.getStore())); model.getStore());
var logo = new PrettyImageComp(image, 20, 20).createRegion(); var logo = new PrettyImageComp(image, 20, 20).createRegion();
var label = new Label(); var label = new Label();

View file

@ -83,13 +83,14 @@ public class FileBrowserModel {
return; return;
} }
var found = openFileSystems.stream() // Duplication protection (Not needed for now)
.filter(fileSystemModel -> fileSystemModel.getStore().getValue().equals(store)) // var found = openFileSystems.stream()
.findFirst(); // .filter(fileSystemModel -> fileSystemModel.getStore().getValue().equals(store))
if (found.isPresent()) { // .findFirst();
selected.setValue(found.get()); // if (found.isPresent()) {
return; // selected.setValue(found.get());
} // return;
// }
var model = new OpenFileSystemModel(this); var model = new OpenFileSystemModel(this);
openFileSystems.add(model); openFileSystems.add(model);

View file

@ -22,7 +22,7 @@ public class ThirdPartyDependencyListComp extends Comp<CompStructure<?>> {
tp.setPadding(Insets.EMPTY); tp.setPadding(Insets.EMPTY);
tp.setGraphic(link); tp.setGraphic(link);
tp.setAlignment(Pos.CENTER_LEFT); tp.setAlignment(Pos.CENTER_LEFT);
AppFont.medium(tp); AppFont.small(tp);
var licenseName = new Label("(" + t.licenseName() + ")"); var licenseName = new Label("(" + t.licenseName() + ")");
var sp = new StackPane(link, licenseName); var sp = new StackPane(link, licenseName);

View file

@ -1,7 +1,6 @@
package io.xpipe.app.comp.source.store; package io.xpipe.app.comp.source.store;
import io.xpipe.app.comp.base.InstallExtensionComp; import io.xpipe.app.comp.base.InstallExtensionComp;
import io.xpipe.app.comp.base.LoadingOverlayComp;
import io.xpipe.app.comp.base.MessageComp; import io.xpipe.app.comp.base.MessageComp;
import io.xpipe.app.comp.base.MultiStepComp; import io.xpipe.app.comp.base.MultiStepComp;
import io.xpipe.app.core.AppExtensionManager; import io.xpipe.app.core.AppExtensionManager;
@ -125,6 +124,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
Consumer<DataStoreEntry> con) { Consumer<DataStoreEntry> con) {
var prop = new SimpleObjectProperty<DataStoreProvider>(provider); var prop = new SimpleObjectProperty<DataStoreProvider>(provider);
var store = new SimpleObjectProperty<DataStore>(s); var store = new SimpleObjectProperty<DataStore>(s);
var loading = new SimpleBooleanProperty();
var name = "addConnection"; var name = "addConnection";
Platform.runLater(() -> { Platform.runLater(() -> {
var stage = AppWindowHelper.sideWindow( var stage = AppWindowHelper.sideWindow(
@ -137,6 +137,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
@Override @Override
protected List<Entry> setup() { protected List<Entry> setup() {
loading.bind(creator.busy);
return List.of(new Entry(AppI18n.observable("a"), creator)); return List.of(new Entry(AppI18n.observable("a"), creator));
} }
@ -150,7 +151,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
}; };
}, },
false, false,
null); loading);
stage.show(); stage.show();
}); });
} }
@ -226,7 +227,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
top.getStyleClass().add("top"); top.getStyleClass().add("top");
layout.setTop(top); layout.setTop(top);
// layout.getStyleClass().add("data-input-creation-step"); // layout.getStyleClass().add("data-input-creation-step");
return new LoadingOverlayComp(Comp.of(() -> layout), busy).createStructure(); return Comp.of(() -> layout).createStructure();
} }
@Override @Override
@ -281,8 +282,8 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
ThreadHelper.runAsync(() -> { ThreadHelper.runAsync(() -> {
try (var b = new BusyProperty(busy)) { try (var b = new BusyProperty(busy)) {
entry.getValue().setStore(input.getValue()); var e = DataStoreEntry.createNew(UUID.randomUUID(), entry.getValue().getName(), input.getValue());
entry.getValue().refresh(true); e.refresh(true);
finished.setValue(true); finished.setValue(true);
PlatformThread.runLaterIfNeeded(parent::next); PlatformThread.runLaterIfNeeded(parent::next);
} catch (Exception ex) { } catch (Exception ex) {

View file

@ -0,0 +1,30 @@
package io.xpipe.app.core;
import io.xpipe.app.Main;
import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class AppSplashScreen {
public static void show() {
var stage = new Stage();
stage.setWidth(500);
stage.setHeight(500);
stage.setResizable(false);
stage.initStyle(StageStyle.TRANSPARENT);
var content = new ImageView(Main.class.getResource("resources/img/loading.gif").toString());
var aa = Platform.isSupported(ConditionalFeature.SCENE3D)
? SceneAntialiasing.BALANCED
: SceneAntialiasing.DISABLED;
var scene = new Scene(new Pane(content), -1, -1, false, aa);
stage.setScene(scene);
stage.show();
}
}

View file

@ -14,7 +14,7 @@ public class EditStoreExchangeImpl extends EditStoreExchange
var s = getStoreEntryByName(msg.getName(), false); var s = getStoreEntryByName(msg.getName(), false);
var dialog = s.getProvider().dialogForStore(s.getStore()); var dialog = s.getProvider().dialogForStore(s.getStore());
var reference = DialogExchangeImpl.add(dialog, (DataStore newStore) -> { var reference = DialogExchangeImpl.add(dialog, (DataStore newStore) -> {
s.setStore(newStore); // s.setStore(newStore);
}); });
return Response.builder().dialog(reference).build(); return Response.builder().dialog(reference).build();
} }

View file

@ -38,7 +38,7 @@ public class PlatformThread {
} }
public static <T> ObservableValue<T> sync(ObservableValue<T> ov) { public static <T> ObservableValue<T> sync(ObservableValue<T> ov) {
return new ObservableValue<>() { ObservableValue<T> obs = new ObservableValue<>() {
private final Map<ChangeListener<? super T>, ChangeListener<? super T>> changeListenerMap = private final Map<ChangeListener<? super T>, ChangeListener<? super T>> changeListenerMap =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
@ -79,10 +79,12 @@ public class PlatformThread {
ov.removeListener(invListenerMap.getOrDefault(listener, listener)); ov.removeListener(invListenerMap.getOrDefault(listener, listener));
} }
}; };
BindingsHelper.linkPersistently(obs, ov);
return obs;
} }
public static <T> ObservableList<T> sync(ObservableList<T> ol) { public static <T> ObservableList<T> sync(ObservableList<T> ol) {
return new ObservableList<>() { ObservableList<T> obs = new ObservableList<>() {
private final Map<ListChangeListener<? super T>, ListChangeListener<? super T>> listChangeListenerMap = private final Map<ListChangeListener<? super T>, ListChangeListener<? super T>> listChangeListenerMap =
new ConcurrentHashMap<>(); new ConcurrentHashMap<>();
@ -263,6 +265,8 @@ public class PlatformThread {
ol.removeListener(invListenerMap.getOrDefault(listener, listener)); ol.removeListener(invListenerMap.getOrDefault(listener, listener));
} }
}; };
BindingsHelper.linkPersistently(obs, ol);
return obs;
} }
public static void runLaterIfNeeded(Runnable r) { public static void runLaterIfNeeded(Runnable r) {

View file

@ -58,15 +58,15 @@ public class DataStorageParser {
return Optional.empty(); return Optional.empty();
} }
var storeNode = entry.get().getResolvedNode(); var testNode = entry.get().getResolvedNode();
if (storeNode == null) { if (testNode == null) {
TrackEvent.withWarn("storage", "Encountered disabled store").tag("id", id); TrackEvent.withWarn("storage", "Encountered disabled store").tag("id", id);
return Optional.empty(); return Optional.empty();
} }
var newSeenIds = new HashSet<>(seenIds); var newSeenIds = new HashSet<>(seenIds);
newSeenIds.add(id); newSeenIds.add(id);
return Optional.of(replaceReferenceIds(storeNode, newSeenIds)); return Optional.of(replaceReferenceIds(entry.get().getStoreNode(), newSeenIds));
}); });
node = replaceReferenceIdsForType(node, "sourceId", id -> { node = replaceReferenceIdsForType(node, "sourceId", id -> {
@ -86,6 +86,10 @@ public class DataStorageParser {
var value = getReferenceIdFromNode(node, replacementKeyName).orElse(null); var value = getReferenceIdFromNode(node, replacementKeyName).orElse(null);
if (value != null) { if (value != null) {
var found = function.apply(value); var found = function.apply(value);
if (found.isEmpty() || found.get().isNull()) {
TrackEvent.withWarn("storage", "Encountered unknown reference").tag("id", value);
}
return found.orElseGet(NullNode::getInstance); return found.orElseGet(NullNode::getInstance);
} }

View file

@ -152,12 +152,6 @@ public class DataStoreEntry extends StorageElement {
return store; return store;
} }
public void setStore(DataStore store) {
var node = DataStorageWriter.storeToNode(store);
this.storeNode = node;
simpleRefresh();
}
public boolean matches(String filter) { public boolean matches(String filter) {
return getName().toLowerCase().contains(filter.toLowerCase()) return getName().toLowerCase().contains(filter.toLowerCase())
|| (!isDisabled() || (!isDisabled()
@ -204,7 +198,13 @@ public class DataStoreEntry extends StorageElement {
dirty = dirty || oldStore != null; dirty = dirty || oldStore != null;
listeners.forEach(l -> l.onUpdate()); listeners.forEach(l -> l.onUpdate());
} else { } else {
dirty = dirty || !Objects.equals(store, newStore); var newNode = DataStorageWriter.storeToNode(newStore);
var nodesEqual = Objects.equals(storeNode, newNode);
if (!nodesEqual) {
storeNode = newNode;
}
dirty = dirty || !nodesEqual;
store = newStore; store = newStore;
var complete = newStore.isComplete(); var complete = newStore.isComplete();

View file

@ -43,6 +43,8 @@ public class AppUpdater {
event("Was updated is " + hasUpdated); event("Was updated is " + hasUpdated);
if (hasUpdated) { if (hasUpdated) {
AppCache.clear("performedUpdate"); AppCache.clear("performedUpdate");
AppCache.clear("lastUpdateCheckResult");
AppCache.clear("downloadedUpdate");
event("Found information about recent update"); event("Found information about recent update");
} }
@ -217,9 +219,6 @@ public class AppUpdater {
} catch (Throwable ex) { } catch (Throwable ex) {
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
AppCache.clear("lastUpdateCheckResult");
AppCache.clear("downloadedUpdate");
var performedUpdate = new PerformedUpdate( var performedUpdate = new PerformedUpdate(
downloadedUpdate.getValue().getVersion(), downloadedUpdate.getValue().getVersion(),
downloadedUpdate.getValue().getBody(), downloadedUpdate.getValue().getBody(),

View file

@ -17,9 +17,9 @@ public class UpdateAvailableAlert {
} }
var update = AppWindowHelper.showBlockingAlert(alert -> { var update = AppWindowHelper.showBlockingAlert(alert -> {
alert.setTitle(AppI18n.get("updateReadyTitle")); alert.setTitle(AppI18n.get("updateReadyAlertTitle"));
alert.setHeaderText(AppI18n.get("updateReadyHeader")); alert.setHeaderText(AppI18n.get("updateReadyAlertHeader"));
alert.setContentText(AppI18n.get("updateReadyContent")); alert.setContentText(AppI18n.get("updateReadyAlertContent"));
alert.setAlertType(Alert.AlertType.INFORMATION); alert.setAlertType(Alert.AlertType.INFORMATION);
}) })
.map(buttonType -> buttonType.getButtonData().isDefaultButton()) .map(buttonType -> buttonType.getButtonData().isDefaultButton())

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

View file

@ -48,9 +48,9 @@ target=Target
data=Data data=Data
more=More more=More
pipeDataSource=Pipe Data Source pipeDataSource=Pipe Data Source
updateReadyTitle=Update Ready updateReadyAlertTitle=Update Ready
updateReadyHeader=An update is ready to be installed updateReadyAlertHeader=An update to version $VERSION$ is ready to be installed
updateReadyContent=This will install the new version. updateReadyAlertContent=This will install the new version and restart X-Pipe once the installation finished.
errorNoDetail=No error details are available errorNoDetail=No error details are available
updateAvailableTitle=Update Available updateAvailableTitle=Update Available
updateAvailableHeader=An X-Pipe update is available to install updateAvailableHeader=An X-Pipe update is available to install

View file

@ -1 +1 @@
0.5.10 0.5.11