Merge branch 'refresh-fixes' into release-10.0

This commit is contained in:
crschnick 2024-06-02 14:14:01 +00:00
parent 56e30ce222
commit e8b44cd2dd
8 changed files with 121 additions and 109 deletions

View file

@ -0,0 +1,31 @@
package io.xpipe.app.ext;
import io.xpipe.core.util.ModuleLayerLoader;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
public abstract class DataStorageExtensionProvider {
private static List<DataStorageExtensionProvider> ALL;
public static List<DataStorageExtensionProvider> getAll() {
return ALL;
}
public void storageInit() throws Exception {}
public static class Loader implements ModuleLayerLoader {
@Override
public void init(ModuleLayer layer) {
ALL = ServiceLoader.load(layer, DataStorageExtensionProvider.class).stream()
.map(ServiceLoader.Provider::get)
.sorted(Comparator.comparing(
scanProvider -> scanProvider.getClass().getName()))
.collect(Collectors.toList());
}
}
}

View file

@ -5,11 +5,12 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.*;
import io.xpipe.core.store.DataStore;
import io.xpipe.core.store.DataStoreId;
import io.xpipe.core.store.FixedChildStore;
import io.xpipe.core.store.LocalStore;
import io.xpipe.core.util.UuidHelper;
import javafx.util.Pair;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
@ -20,7 +21,6 @@ import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -260,16 +260,10 @@ public abstract class DataStorage {
return true;
}
protected void refreshValidities(boolean makeValid) {
var changed = new AtomicBoolean(false);
do {
changed.set(false);
storeEntries.keySet().forEach(dataStoreEntry -> {
if (makeValid ? dataStoreEntry.tryMakeValid() : dataStoreEntry.tryMakeInvalid()) {
changed.set(true);
}
});
} while (changed.get());
protected void refreshEntries() {
storeEntries.keySet().forEach(dataStoreEntry -> {
dataStoreEntry.refreshStore();
});
}
public void updateEntry(DataStoreEntry entry, DataStoreEntry newEntry) {
@ -299,8 +293,7 @@ public abstract class DataStorage {
var toAdd = Stream.concat(Stream.of(entry), children.stream()).toArray(DataStoreEntry[]::new);
listeners.forEach(storageListener -> storageListener.onStoreAdd(toAdd));
}
refreshValidities(true);
refreshEntries();
saveAsync();
}
@ -460,7 +453,7 @@ public abstract class DataStorage {
c.forEach(entry -> entry.finalizeEntry());
this.storeEntriesSet.removeAll(c);
this.listeners.forEach(l -> l.onStoreRemove(c.toArray(DataStoreEntry[]::new)));
refreshValidities(false);
refreshEntries();
saveAsync();
}
@ -479,7 +472,7 @@ public abstract class DataStorage {
toDelete.forEach(entry -> entry.finalizeEntry());
toDelete.forEach(this.storeEntriesSet::remove);
this.listeners.forEach(l -> l.onStoreRemove(toDelete.toArray(DataStoreEntry[]::new)));
refreshValidities(false);
refreshEntries();
saveAsync();
}
@ -534,7 +527,7 @@ public abstract class DataStorage {
this.listeners.forEach(l -> l.onStoreAdd(e));
e.initializeEntry();
refreshValidities(true);
e.refreshStore();
return e;
}
@ -568,11 +561,13 @@ public abstract class DataStorage {
p.setChildrenCache(null);
});
}
for (DataStoreEntry e : toAdd) {
e.refreshStore();
}
this.listeners.forEach(l -> l.onStoreAdd(toAdd.toArray(DataStoreEntry[]::new)));
for (DataStoreEntry e : toAdd) {
e.initializeEntry();
}
refreshValidities(true);
saveAsync();
}
@ -600,7 +595,7 @@ public abstract class DataStorage {
this.storeEntries.remove(store);
getDefaultDisplayParent(store).ifPresent(p -> p.setChildrenCache(null));
this.listeners.forEach(l -> l.onStoreRemove(store));
refreshValidities(false);
refreshEntries();
saveAsync();
}

View file

@ -516,28 +516,23 @@ public class DataStoreEntry extends StorageElement {
}
}
public boolean tryMakeValid() {
public void refreshStore() {
if (validity == Validity.LOAD_FAILED) {
return false;
}
var complete = validity == Validity.COMPLETE;
if (complete) {
return false;
return;
}
var newStore = DataStorageParser.storeFromNode(storeNode);
if (newStore == null) {
store = null;
validity = Validity.LOAD_FAILED;
return true;
return;
}
var newComplete = newStore.isComplete();
if (!newComplete) {
validity = Validity.INCOMPLETE;
store = newStore;
return false;
return;
}
if (!newStore.equals(store)) {
@ -546,38 +541,6 @@ public class DataStoreEntry extends StorageElement {
validity = Validity.COMPLETE;
// Don't count this as modification as this is done always
notifyUpdate(false, false);
return true;
}
public boolean tryMakeInvalid() {
if (validity == Validity.LOAD_FAILED) {
return false;
}
if (validity == Validity.INCOMPLETE) {
return false;
}
var newStore = DataStorageParser.storeFromNode(storeNode);
if (newStore == null) {
store = null;
validity = Validity.LOAD_FAILED;
return true;
}
var newComplete = newStore.isComplete();
if (newComplete) {
validity = Validity.COMPLETE;
store = newStore;
return false;
}
if (!newStore.equals(store)) {
store = newStore;
}
validity = Validity.INCOMPLETE;
notifyUpdate(false, false);
return true;
}
@SneakyThrows

View file

@ -1,11 +1,11 @@
package io.xpipe.app.storage;
import io.xpipe.app.ext.DataStorageExtensionProvider;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.LocalStore;
import lombok.Getter;
import org.apache.commons.io.FileUtils;
@ -197,14 +197,15 @@ public class StandardStorage extends DataStorage {
local.setColor(DataStoreColor.BLUE);
}
refreshValidities(true);
callProviders();
refreshEntries();
storeEntriesSet.forEach(entry -> {
var syntheticParent = getSyntheticParent(entry);
syntheticParent.ifPresent(entry1 -> {
addStoreEntryIfNotPresent(entry1);
});
});
refreshValidities(true);
refreshEntries();
// Save to apply changes
if (!hasFixedLocal) {
@ -226,6 +227,16 @@ public class StandardStorage extends DataStorage {
this.gitStorageHandler.afterStorageLoad();
}
private void callProviders() {
DataStorageExtensionProvider.getAll().forEach(p -> {
try {
p.storageInit();
} catch (Exception e) {
ErrorEvent.fromThrowable(e).omit().handle();
}
});
}
public void save(boolean dispose) {
try {
// If another save operation is in progress, we have to wait on dispose

View file

@ -107,10 +107,13 @@ open module io.xpipe.app {
uses LicenseProvider;
uses io.xpipe.app.util.LicensedFeature;
uses io.xpipe.beacon.BeaconInterface;
uses DataStorageExtensionProvider;
provides Module with
AppJacksonModule;
provides ModuleLayerLoader with
DataStorageExtensionProvider.Loader,
MessageExchangeImpls.Loader,
DataStoreProviders.Loader,
ActionProvider.Loader,
PrefsProvider.Loader,

View file

@ -0,0 +1,50 @@
package io.xpipe.ext.base.script;
import io.xpipe.app.ext.DataStorageExtensionProvider;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class ScriptDataStorageProvider extends DataStorageExtensionProvider {
@Override
public void storageInit() {
DataStorage.get()
.addStoreEntryIfNotPresent(DataStoreEntry.createNew(
UUID.fromString("a9945ad2-db61-4304-97d7-5dc4330691a7"),
DataStorage.CUSTOM_SCRIPTS_CATEGORY_UUID,
"My scripts",
ScriptGroupStore.builder().build()));
for (PredefinedScriptGroup value : PredefinedScriptGroup.values()) {
ScriptGroupStore store = ScriptGroupStore.builder()
.description(value.getDescription())
.build();
var e = DataStorage.get()
.addStoreEntryIfNotPresent(DataStoreEntry.createNew(
UUID.nameUUIDFromBytes(("a " + value.getName()).getBytes(StandardCharsets.UTF_8)),
DataStorage.PREDEFINED_SCRIPTS_CATEGORY_UUID,
value.getName(),
store));
e.setStoreInternal(store, false);
e.setExpanded(value.isExpanded());
value.setEntry(e.ref());
}
for (PredefinedScriptStore value : PredefinedScriptStore.values()) {
var previous = DataStorage.get().getStoreEntryIfPresent(value.getUuid());
var store = value.getScriptStore().get();
if (previous.isPresent()) {
previous.get().setStoreInternal(store, false);
value.setEntry(previous.get().ref());
} else {
var e = DataStoreEntry.createNew(
value.getUuid(), DataStorage.PREDEFINED_SCRIPTS_CATEGORY_UUID, value.getName(), store);
DataStorage.get().addStoreEntryIfNotPresent(e);
value.setEntry(e.ref());
}
}
}
}

View file

@ -12,14 +12,12 @@ import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.impl.DataStoreChoiceComp;
import io.xpipe.app.fxcomps.impl.DataStoreListChoiceComp;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.MarkdownBuilder;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.core.process.ShellDialect;
import io.xpipe.core.store.DataStore;
import io.xpipe.core.util.Identifiers;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleListProperty;
@ -27,13 +25,10 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import lombok.SneakyThrows;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class SimpleScriptStoreProvider implements DataStoreProvider {
@ -201,45 +196,6 @@ public class SimpleScriptStoreProvider implements DataStoreProvider {
.buildDialog();
}
@Override
public void init() {
DataStorage.get()
.addStoreEntryIfNotPresent(DataStoreEntry.createNew(
UUID.fromString("a9945ad2-db61-4304-97d7-5dc4330691a7"),
DataStorage.CUSTOM_SCRIPTS_CATEGORY_UUID,
"My scripts",
ScriptGroupStore.builder().build()));
for (PredefinedScriptGroup value : PredefinedScriptGroup.values()) {
ScriptGroupStore store = ScriptGroupStore.builder()
.description(value.getDescription())
.build();
var e = DataStorage.get()
.addStoreEntryIfNotPresent(DataStoreEntry.createNew(
UUID.nameUUIDFromBytes(("a " + value.getName()).getBytes(StandardCharsets.UTF_8)),
DataStorage.PREDEFINED_SCRIPTS_CATEGORY_UUID,
value.getName(),
store));
e.setStoreInternal(store, false);
e.setExpanded(value.isExpanded());
value.setEntry(e.ref());
}
for (PredefinedScriptStore value : PredefinedScriptStore.values()) {
var previous = DataStorage.get().getStoreEntryIfPresent(value.getUuid());
var store = value.getScriptStore().get();
if (previous.isPresent()) {
previous.get().setStoreInternal(store, false);
value.setEntry(previous.get().ref());
} else {
var e = DataStoreEntry.createNew(
value.getUuid(), DataStorage.PREDEFINED_SCRIPTS_CATEGORY_UUID, value.getName(), store);
DataStorage.get().addStoreEntryIfNotPresent(e);
value.setEntry(e.ref());
}
}
}
@Override
public ObservableValue<String> informationString(StoreEntryWrapper wrapper) {
SimpleScriptStore scriptStore = wrapper.getEntry().getStore().asNeeded();

View file

@ -1,11 +1,13 @@
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.ext.ActionProvider;
import io.xpipe.app.ext.DataStorageExtensionProvider;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.ext.base.action.*;
import io.xpipe.ext.base.browser.*;
import io.xpipe.ext.base.desktop.DesktopApplicationStoreProvider;
import io.xpipe.ext.base.desktop.DesktopCommandStoreProvider;
import io.xpipe.ext.base.desktop.DesktopEnvironmentStoreProvider;
import io.xpipe.ext.base.script.ScriptDataStorageProvider;
import io.xpipe.ext.base.script.ScriptGroupStoreProvider;
import io.xpipe.ext.base.script.SimpleScriptStoreProvider;
import io.xpipe.ext.base.service.FixedServiceStoreProvider;
@ -79,4 +81,5 @@ open module io.xpipe.ext.base {
DesktopApplicationStoreProvider,
DesktopCommandStoreProvider,
ScriptGroupStoreProvider;
provides DataStorageExtensionProvider with ScriptDataStorageProvider;
}