mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-10-06 13:03:29 +13:00
Merge branch 'refresh-fixes' into release-10.0
This commit is contained in:
parent
56e30ce222
commit
e8b44cd2dd
8 changed files with 121 additions and 109 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue