mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Fix file browser connection list not updating
This commit is contained in:
parent
758f721690
commit
c1886cc9cd
9 changed files with 89 additions and 91 deletions
|
@ -1,21 +1,21 @@
|
|||
package io.xpipe.app.browser;
|
||||
|
||||
import io.xpipe.app.comp.storage.store.StoreEntryFlatMiniSection;
|
||||
import io.xpipe.app.comp.storage.store.StoreEntryWrapper;
|
||||
import io.xpipe.app.comp.base.ListBoxViewComp;
|
||||
import io.xpipe.app.comp.storage.store.StoreEntryFlatMiniSectionComp;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
import io.xpipe.app.fxcomps.augment.DragPseudoClassAugment;
|
||||
import io.xpipe.app.fxcomps.augment.GrowAugment;
|
||||
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.input.DragEvent;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
|
@ -33,39 +33,29 @@ final class BookmarkList extends SimpleComp {
|
|||
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var map = StoreEntryFlatMiniSection.createMap();
|
||||
var list = new VBox();
|
||||
for (Map.Entry<StoreEntryWrapper, Region> e : map.entrySet()) {
|
||||
if (!(e.getKey().getEntry().getStore() instanceof ShellStore)) {
|
||||
continue;
|
||||
}
|
||||
var observableList = BindingsHelper.filteredContentBinding(StoreEntryFlatMiniSectionComp.ALL, e -> e.getEntry().getStore() instanceof ShellStore);
|
||||
var list = new ListBoxViewComp<>(observableList, observableList, e -> {
|
||||
return Comp.of(() -> {
|
||||
var button = new Button(null, e.createRegion());
|
||||
button.setOnAction(event -> {
|
||||
var fileSystem = ((ShellStore) e.getEntry().getStore());
|
||||
model.openFileSystem(fileSystem);
|
||||
event.consume();
|
||||
});
|
||||
GrowAugment.create(true, false).augment(new SimpleCompStructure<>(button));
|
||||
DragPseudoClassAugment.create().augment(new SimpleCompStructure<>(button));
|
||||
|
||||
var button = new Button(null, e.getValue());
|
||||
button.setOnAction(event -> {
|
||||
var fileSystem = ((ShellStore) e.getKey().getEntry().getStore());
|
||||
model.openFileSystem(fileSystem);
|
||||
event.consume();
|
||||
button.addEventHandler(
|
||||
DragEvent.DRAG_OVER,
|
||||
mouseEvent -> handleHoverTimer(e.getEntry().getStore(), mouseEvent));
|
||||
button.addEventHandler(
|
||||
DragEvent.DRAG_EXITED,
|
||||
mouseEvent -> activeTask = null);
|
||||
|
||||
return button;
|
||||
});
|
||||
button.prefWidthProperty().bind(list.widthProperty());
|
||||
DragPseudoClassAugment.create().augment(new SimpleCompStructure<>(button));
|
||||
|
||||
button.addEventHandler(
|
||||
DragEvent.DRAG_OVER,
|
||||
mouseEvent -> handleHoverTimer(e.getKey().getEntry().getStore(), mouseEvent));
|
||||
button.addEventHandler(
|
||||
DragEvent.DRAG_EXITED,
|
||||
mouseEvent -> activeTask = null);
|
||||
|
||||
list.getChildren().add(button);
|
||||
}
|
||||
list.setFillWidth(true);
|
||||
list.getStyleClass().add("bookmark-list");
|
||||
|
||||
var sp = new ScrollPane(list);
|
||||
sp.setFitToWidth(true);
|
||||
sp.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||
|
||||
return sp;
|
||||
}).styleClass("bookmark-list").createRegion();
|
||||
return list;
|
||||
}
|
||||
|
||||
private void handleHoverTimer(DataStore store, DragEvent event) {
|
||||
|
|
|
@ -109,7 +109,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
|
|||
show(null, null, null, filter, e -> {
|
||||
try {
|
||||
DataStorage.get().addStoreEntry(e);
|
||||
ScanAlert.show(e.getStore(), true);
|
||||
ScanAlert.showAsync(e.getStore(), true);
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).handle();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import io.xpipe.app.fxcomps.SimpleComp;
|
|||
import io.xpipe.app.fxcomps.impl.PrettyImageComp;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
@ -12,27 +15,34 @@ import javafx.scene.layout.Region;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class StoreEntryFlatMiniSection extends SimpleComp {
|
||||
public class StoreEntryFlatMiniSectionComp extends SimpleComp {
|
||||
|
||||
public static final ObservableList<StoreEntryFlatMiniSectionComp> ALL = FXCollections.observableArrayList();
|
||||
|
||||
static {
|
||||
var topLevel = StoreSection.createTopLevels();
|
||||
|
||||
topLevel.addListener((ListChangeListener<? super StoreSection>) c -> {
|
||||
ALL.clear();
|
||||
var depth = 0;
|
||||
for (StoreSection v : topLevel) {
|
||||
System.out.println(v.getWrapper().getEntry().getName() + " " + v.getChildren().size());
|
||||
add(depth, v);
|
||||
}
|
||||
});
|
||||
|
||||
public static Map<StoreEntryWrapper, Region> createMap() {
|
||||
var map = new LinkedHashMap<StoreEntryWrapper, Region>();
|
||||
var topLevel = StoreViewSection.createTopLevels();
|
||||
var depth = 0;
|
||||
for (StoreViewSection v : topLevel) {
|
||||
add(depth, v, map);
|
||||
for (StoreSection v : topLevel) {
|
||||
add(depth, v);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static void add(int depth, StoreViewSection section, Map<StoreEntryWrapper, Region> map) {
|
||||
map.put(section.getWrapper(), new StoreEntryFlatMiniSection(depth, section.getWrapper().getEntry()).createRegion());
|
||||
for (StoreViewSection child : section.getChildren()) {
|
||||
add(depth + 1, child, map);
|
||||
private static void add(int depth, StoreSection section) {
|
||||
ALL.add(new StoreEntryFlatMiniSectionComp(depth, section.getWrapper().getEntry()));
|
||||
for (StoreSection child : section.getChildren()) {
|
||||
add(depth + 1, child);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,14 +15,14 @@ import java.util.LinkedHashMap;
|
|||
public class StoreEntryListComp extends SimpleComp {
|
||||
|
||||
private Comp<?> createList() {
|
||||
var topLevel = StoreViewSection.createTopLevels();
|
||||
var topLevel = StoreSection.createTopLevels();
|
||||
var filtered = BindingsHelper.filteredContentBinding(
|
||||
topLevel,
|
||||
StoreViewState.get()
|
||||
.getFilterString()
|
||||
.map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
|
||||
var content = new ListBoxViewComp<>(filtered, topLevel, (StoreViewSection e) -> {
|
||||
return new StoreEntrySection(e, true);
|
||||
var content = new ListBoxViewComp<>(filtered, topLevel, (StoreSection e) -> {
|
||||
return new StoreEntrySection(e);
|
||||
});
|
||||
return content.styleClass("store-list-comp").styleClass(Styles.STRIPED);
|
||||
}
|
||||
|
|
|
@ -16,12 +16,10 @@ import java.util.List;
|
|||
|
||||
public class StoreEntrySection extends Comp<CompStructure<VBox>> {
|
||||
|
||||
private final StoreViewSection section;
|
||||
private final boolean top;
|
||||
private final StoreSection section;
|
||||
|
||||
public StoreEntrySection(StoreViewSection section, boolean top) {
|
||||
public StoreEntrySection(StoreSection section) {
|
||||
this.section = section;
|
||||
this.top = top;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,8 +47,8 @@ public class StoreEntrySection extends Comp<CompStructure<VBox>> {
|
|||
StoreViewState.get()
|
||||
.getFilterString()
|
||||
.map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
|
||||
var content = new ListBoxViewComp<>(shown, all, (StoreViewSection e) -> {
|
||||
return new StoreEntrySection(e, false).apply(GrowAugment.create(true, false));
|
||||
var content = new ListBoxViewComp<>(shown, all, (StoreSection e) -> {
|
||||
return new StoreEntrySection(e).apply(GrowAugment.create(true, false));
|
||||
})
|
||||
.apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS))
|
||||
.apply(struc -> struc.get().backgroundProperty().set(Background.fill(Color.color(0, 0, 0, 0.01))));
|
||||
|
|
|
@ -35,7 +35,7 @@ public class StoreIntroComp extends SimpleComp {
|
|||
});
|
||||
|
||||
var scanButton = new Button(AppI18n.get("detectConnections"), new FontIcon("mdi2m-magnify"));
|
||||
scanButton.setOnAction(event -> ScanAlert.show(new LocalStore(), false));
|
||||
scanButton.setOnAction(event -> ScanAlert.showAsync(new LocalStore(), false));
|
||||
var scanPane = new StackPane(scanButton);
|
||||
scanPane.setAlignment(Pos.CENTER);
|
||||
|
||||
|
|
|
@ -12,42 +12,42 @@ import java.time.Instant;
|
|||
import java.util.Comparator;
|
||||
|
||||
@Value
|
||||
public class StoreViewSection implements StorageFilter.Filterable {
|
||||
public class StoreSection implements StorageFilter.Filterable {
|
||||
|
||||
StoreEntryWrapper wrapper;
|
||||
ObservableList<StoreViewSection> children;
|
||||
ObservableList<StoreSection> children;
|
||||
|
||||
private static final Comparator<StoreViewSection> COMPARATOR = Comparator.<StoreViewSection, Instant>comparing(
|
||||
private static final Comparator<StoreSection> COMPARATOR = Comparator.<StoreSection, Instant>comparing(
|
||||
o -> o.wrapper.getEntry().getState().equals(DataStoreEntry.State.COMPLETE_AND_VALID)
|
||||
? o.wrapper.getEntry().getLastAccess()
|
||||
: Instant.EPOCH).reversed()
|
||||
.thenComparing(
|
||||
storeEntrySection -> storeEntrySection.wrapper.getEntry().getName());
|
||||
|
||||
public static ObservableList<StoreViewSection> createTopLevels() {
|
||||
public static ObservableList<StoreSection> createTopLevels() {
|
||||
var topLevel = BindingsHelper.mappedContentBinding(StoreViewState.get().getAllEntries(), storeEntryWrapper -> create(storeEntryWrapper));
|
||||
var filtered =
|
||||
BindingsHelper.filteredContentBinding(StoreViewState.get().getAllEntries(), storeEntryWrapper -> {
|
||||
if (!storeEntryWrapper.getEntry().getState().isUsable()) {
|
||||
BindingsHelper.filteredContentBinding(topLevel, section -> {
|
||||
if (!section.getWrapper().getEntry().getState().isUsable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var parent = storeEntryWrapper
|
||||
var parent = section.getWrapper()
|
||||
.getEntry()
|
||||
.getProvider()
|
||||
.getParent(storeEntryWrapper.getEntry().getStore());
|
||||
.getParent(section.getWrapper().getEntry().getStore());
|
||||
return parent == null
|
||||
|| (DataStorage.get().getStoreEntryIfPresent(parent).isEmpty());
|
||||
});
|
||||
var topLevel = BindingsHelper.mappedContentBinding(filtered, storeEntryWrapper -> create(storeEntryWrapper));
|
||||
var ordered = BindingsHelper.orderedContentBinding(
|
||||
topLevel,
|
||||
filtered,
|
||||
COMPARATOR);
|
||||
return ordered;
|
||||
}
|
||||
|
||||
public static StoreViewSection create(StoreEntryWrapper e) {
|
||||
private static StoreSection create(StoreEntryWrapper e) {
|
||||
if (!e.getEntry().getState().isUsable()) {
|
||||
return new StoreViewSection(e, FXCollections.observableArrayList());
|
||||
return new StoreSection(e, FXCollections.observableArrayList());
|
||||
}
|
||||
|
||||
var filtered = BindingsHelper.filteredContentBinding(
|
||||
|
@ -62,7 +62,7 @@ public class StoreViewSection implements StorageFilter.Filterable {
|
|||
var ordered = BindingsHelper.orderedContentBinding(
|
||||
children,
|
||||
COMPARATOR);
|
||||
return new StoreViewSection(e, ordered);
|
||||
return new StoreSection(e, ordered);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,7 +1,6 @@
|
|||
package io.xpipe.app.fxcomps.impl;
|
||||
|
||||
import io.xpipe.app.comp.storage.store.StoreEntryFlatMiniSection;
|
||||
import io.xpipe.app.comp.storage.store.StoreEntryWrapper;
|
||||
import io.xpipe.app.comp.storage.store.StoreEntryFlatMiniSectionComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.DataStoreProviders;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
|
@ -19,7 +18,6 @@ import javafx.scene.control.Label;
|
|||
import javafx.scene.layout.Region;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
@ -82,25 +80,25 @@ public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Region createSimple() {
|
||||
var map = StoreEntryFlatMiniSection.createMap();
|
||||
var list = StoreEntryFlatMiniSectionComp.ALL;
|
||||
var comboBox = new CustomComboBoxBuilder<T>(
|
||||
selected,
|
||||
t -> map.entrySet().stream()
|
||||
.filter(e -> t.equals(e.getKey().getEntry().getStore()))
|
||||
t -> list.stream()
|
||||
.filter(e -> t.equals(e.getEntry().getStore()))
|
||||
.findFirst()
|
||||
.orElseThrow()
|
||||
.getValue(),
|
||||
.createRegion(),
|
||||
new Label(AppI18n.get("none")),
|
||||
n -> true);
|
||||
comboBox.setSelectedDisplay(t -> createGraphic(t));
|
||||
comboBox.setUnknownNode(t -> createGraphic(t));
|
||||
|
||||
for (Map.Entry<StoreEntryWrapper, Region> e : map.entrySet()) {
|
||||
if (e.getKey().getEntry().getStore() == self) {
|
||||
for (var e : list) {
|
||||
if (e.getEntry().getStore() == self) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var s = e.getKey().getEntry().getStore();
|
||||
var s = e.getEntry().getStore();
|
||||
if (!storeClass.isAssignableFrom(s.getClass()) || !applicableCheck.test((T) s)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -109,7 +107,7 @@ public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
|
|||
continue;
|
||||
}
|
||||
|
||||
comboBox.add((T) e.getKey().getEntry().getStore());
|
||||
comboBox.add((T) e.getEntry().getStore());
|
||||
}
|
||||
|
||||
ComboBox<Node> cb = comboBox.build();
|
||||
|
|
|
@ -20,12 +20,14 @@ import java.util.List;
|
|||
|
||||
public class ScanAlert {
|
||||
|
||||
public static void show(DataStore store, boolean automatic) {
|
||||
if (store instanceof ShellStore) {
|
||||
showForShellStore(store.asNeeded(), automatic);
|
||||
} else {
|
||||
showForOtherStore(store, automatic);
|
||||
}
|
||||
public static void showAsync(DataStore store, boolean automatic) {
|
||||
ThreadHelper.runAsync(() -> {
|
||||
if (store instanceof ShellStore) {
|
||||
showForShellStore(store.asNeeded(), automatic);
|
||||
} else {
|
||||
showForOtherStore(store, automatic);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void showForOtherStore(DataStore store, boolean automatic) {
|
||||
|
|
Loading…
Reference in a new issue