From e8b44cd2dd585ace7e3cdcd15dd1b57607bb2f07 Mon Sep 17 00:00:00 2001 From: crschnick Date: Sun, 2 Jun 2024 14:14:01 +0000 Subject: [PATCH] Merge branch 'refresh-fixes' into release-10.0 --- .../app/ext/DataStorageExtensionProvider.java | 31 ++++++++++++ .../io/xpipe/app/storage/DataStorage.java | 37 ++++++-------- .../io/xpipe/app/storage/DataStoreEntry.java | 45 ++--------------- .../io/xpipe/app/storage/StandardStorage.java | 17 +++++-- app/src/main/java/module-info.java | 3 ++ .../script/ScriptDataStorageProvider.java | 50 +++++++++++++++++++ .../script/SimpleScriptStoreProvider.java | 44 ---------------- ext/base/src/main/java/module-info.java | 3 ++ 8 files changed, 121 insertions(+), 109 deletions(-) create mode 100644 app/src/main/java/io/xpipe/app/ext/DataStorageExtensionProvider.java create mode 100644 ext/base/src/main/java/io/xpipe/ext/base/script/ScriptDataStorageProvider.java diff --git a/app/src/main/java/io/xpipe/app/ext/DataStorageExtensionProvider.java b/app/src/main/java/io/xpipe/app/ext/DataStorageExtensionProvider.java new file mode 100644 index 000000000..946726769 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/ext/DataStorageExtensionProvider.java @@ -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 ALL; + + public static List 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()); + } + } +} diff --git a/app/src/main/java/io/xpipe/app/storage/DataStorage.java b/app/src/main/java/io/xpipe/app/storage/DataStorage.java index c68ee24f6..62fa86aac 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStorage.java @@ -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(); } diff --git a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java index 0b705df86..55f41f039 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java @@ -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 diff --git a/app/src/main/java/io/xpipe/app/storage/StandardStorage.java b/app/src/main/java/io/xpipe/app/storage/StandardStorage.java index 34958fbaa..1a64ee96a 100644 --- a/app/src/main/java/io/xpipe/app/storage/StandardStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/StandardStorage.java @@ -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 diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index 35756c470..a5a0f64f5 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -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, diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptDataStorageProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptDataStorageProvider.java new file mode 100644 index 000000000..d1fe28e4f --- /dev/null +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptDataStorageProvider.java @@ -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()); + } + } + } +} diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStoreProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStoreProvider.java index 808f3b187..976a523d4 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStoreProvider.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/SimpleScriptStoreProvider.java @@ -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 informationString(StoreEntryWrapper wrapper) { SimpleScriptStore scriptStore = wrapper.getEntry().getStore().asNeeded(); diff --git a/ext/base/src/main/java/module-info.java b/ext/base/src/main/java/module-info.java index a3d6095fd..734506315 100644 --- a/ext/base/src/main/java/module-info.java +++ b/ext/base/src/main/java/module-info.java @@ -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; }