From d67085d57d2a32030af83af95a31144de46fcafd Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 20 Mar 2025 16:41:30 +0100 Subject: [PATCH] doodles --- .../org/cryptomator/common/vaults/Vault.java | 2 +- .../event/FileSystemEventBucket.java | 29 --- .../event/FileSystemEventRegistry.java | 203 +++++------------- .../ui/eventview/EventListCellController.java | 34 +-- .../ui/eventview/EventListCellFactory.java | 13 +- .../ui/eventview/EventViewController.java | 65 +++--- .../ui/fxapp/EventsUpdateCheck.java | 62 ++++++ .../cryptomator/ui/fxapp/FxApplication.java | 1 + .../ui/mainwindow/VaultListController.java | 8 - 9 files changed, 176 insertions(+), 241 deletions(-) delete mode 100644 src/main/java/org/cryptomator/event/FileSystemEventBucket.java create mode 100644 src/main/java/org/cryptomator/ui/fxapp/EventsUpdateCheck.java diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java index 0bf2128c5..a48c5d0ac 100644 --- a/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -259,7 +259,7 @@ public class Vault { private void consumeVaultEvent(FilesystemEvent e) { - fileSystemEventRegistry.enque(this, e); + fileSystemEventRegistry.enqueue(this, e); } // ****************************************************************************** diff --git a/src/main/java/org/cryptomator/event/FileSystemEventBucket.java b/src/main/java/org/cryptomator/event/FileSystemEventBucket.java deleted file mode 100644 index c7b0bc577..000000000 --- a/src/main/java/org/cryptomator/event/FileSystemEventBucket.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cryptomator.event; - -import org.cryptomator.common.vaults.Vault; -import org.cryptomator.cryptofs.event.FilesystemEvent; - -public record FileSystemEventBucket(Vault vault, FilesystemEvent mostRecent, int count) implements Comparable { - - @Override - public boolean equals(Object other) { - if (other instanceof FileSystemEventBucket(Vault v2, FilesystemEvent e2, _)) { - return vault.equals(v2) && mostRecent.getClass().equals(e2.getClass()); - } - return false; - } - - @Override - public int compareTo(FileSystemEventBucket other) { - var timeResult = mostRecent.getTimestamp().compareTo(other.mostRecent().getTimestamp()); - if (timeResult != 0) { - return timeResult; - } - var vaultIdResult = vault.getId().compareTo(other.vault.getId()); - if (vaultIdResult != 0) { - return vaultIdResult; - } - return this.mostRecent.getClass().getName().compareTo(other.mostRecent.getClass().getName()); - } - -} diff --git a/src/main/java/org/cryptomator/event/FileSystemEventRegistry.java b/src/main/java/org/cryptomator/event/FileSystemEventRegistry.java index ffd79276e..cacfc6053 100644 --- a/src/main/java/org/cryptomator/event/FileSystemEventRegistry.java +++ b/src/main/java/org/cryptomator/event/FileSystemEventRegistry.java @@ -7,61 +7,51 @@ import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent; import org.cryptomator.cryptofs.event.ConflictResolvedEvent; import org.cryptomator.cryptofs.event.DecryptionFailedEvent; import org.cryptomator.cryptofs.event.FilesystemEvent; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; import javax.inject.Singleton; -import javafx.application.Platform; -import javafx.collections.FXCollections; -import javafx.collections.MapChangeListener; -import javafx.collections.ObservableMap; import java.nio.file.Path; -import java.util.List; -import java.util.TreeSet; +import java.time.Instant; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +/** + * Angenommen: + * Datenstruktur die + * 1. Thread-Safe ist + * ?? + * + * + * + * + * 1. Wenn ein Set verwendet wird, dann können wir nach Timestamp sortieren, aber wir können einen Eintrag nur durch entfernen und hinzufügen updaten + * 2. Wenn eine Map verwendet wird, dann können wir Einträge updaten. Aber + * + */ +//TODO: Rename to aggregator +//TODO: lru cache @Singleton public class FileSystemEventRegistry { private static final int MAX_MAP_SIZE = 400; - public record Key(Vault vault, Path idPath, Class c) {} + public record Key(Vault vault, Path idPath, Class c) {}; public record Value(FilesystemEvent mostRecentEvent, int count) {} - /** - * Queue of elements to be inserted into the map - */ - private final ConcurrentMap queue; - /** - * Least-recently-used cache. - */ - private final TreeSet lruCache; - /** - * Actual map - */ - private final ObservableMap map; - - private final ScheduledExecutorService scheduler; - - private final AtomicBoolean queueHasElements; + private final ConcurrentHashMap map; + private final AtomicBoolean hasUpdates; @Inject public FileSystemEventRegistry(ScheduledExecutorService scheduledExecutorService) { - this.queue = new ConcurrentHashMap<>(); - this.lruCache = new TreeSet<>(this::compareKeys); - this.map = FXCollections.observableHashMap(); - this.scheduler = scheduledExecutorService; - this.queueHasElements = new AtomicBoolean(false); - scheduler.scheduleWithFixedDelay(() -> { - if (queueHasElements.get()) { - flush(); - } - }, 1000, 1000, TimeUnit.MILLISECONDS); + this.map = new ConcurrentHashMap<>(); + this.hasUpdates = new AtomicBoolean(false); } /** @@ -70,9 +60,9 @@ public class FileSystemEventRegistry { * @param v Vault where the event occurred * @param e Actual {@link FilesystemEvent} */ - public synchronized void enque(Vault v, FilesystemEvent e) { + public synchronized void enqueue(Vault v, FilesystemEvent e) { var key = computeKey(v, e); - queue.compute(key, (k, val) -> { + map.compute(key, (k, val) -> { if (val == null) { return new Value(e, 1); } else { @@ -80,45 +70,21 @@ public class FileSystemEventRegistry { } }); - queueHasElements.set(true); - } - - - /** - * Lists all entries in this map as {@link FileSystemEventBucket}. The list is sorted ascending by the timestamp of event occurral (and more if it is the same timestamp). - * Must be executed on the JavaFX application thread - * - * @return a list of vault events, mainly sorted ascending by the event timestamp - * @implNote Method is not synchronized, because it is only executed if executed by JavaFX application thread - */ - public List listAll() { - if (!Platform.isFxApplicationThread()) { - throw new IllegalStateException("Listing map entries must be performed on JavaFX application thread"); - } - return lruCache.stream().map(key -> { - var value = map.get(key); - return new FileSystemEventBucket(key.vault(), value.mostRecentEvent(), value.count()); - }).toList(); + hasUpdates.set(true); } /** * Removes an event from the map. *

* To identify the event, a similar event (in the sense of map key) is given. - * Must be executed on the JavaFX application thread * - * @param v Vault where the event occurred - * @param similar A similar {@link FilesystemEvent} (same class, same idPath) * @return the removed {@link Value} * @implNote Method is not synchronized, because it is only executed if executed by JavaFX application thread */ - public Value remove(Vault v, FilesystemEvent similar) { - if (!Platform.isFxApplicationThread()) { - throw new IllegalStateException("Map removal must be performed on JavaFX application thread"); - } - var key = computeKey(v, similar); - lruCache.remove(key); - return map.remove(key); + public Value remove(Key key) { + var result = map.remove(key); + hasUpdates.set(true); + return result; } /** @@ -129,93 +95,8 @@ public class FileSystemEventRegistry { * @implNote Method is not synchronized, because it is only executed if executed by JavaFX application thread */ public void clear() { - if (!Platform.isFxApplicationThread()) { - throw new IllegalStateException("Map removal must be performed on JavaFX application thread"); - } - lruCache.clear(); map.clear(); - } - - /** - * Flushes all changes from the queue into the map - */ - private synchronized void flush() { - //Lock queue - var latch = new CountDownLatch(1); - Platform.runLater(() -> { - queue.forEach(this::updateMap); - queue.clear(); - latch.countDown(); - }); - try { - latch.await(); - queueHasElements.set(false); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - /** - * Updates a single map entry - * - * @param k Key of the entry to update - * @param v Value of the entry to update - * @implNote Method is not synchronized, because it is only called on the (one-and-only) JavaFX application thread - */ - private void updateMap(Key k, Value v) { - var entry = map.get(k); - if (entry == null) { - if (map.size() == MAX_MAP_SIZE) { - var toRemove = lruCache.first(); - lruCache.remove(toRemove); - map.remove(toRemove); - } - map.put(k, v); - lruCache.add(k); - } else { - lruCache.remove(k); - map.put(k, new Value(v.mostRecentEvent, entry.count + v.count)); - lruCache.add(k); //correct, because cache-sorting uses the map in comparsionMethod - } - } - - /* Observability */ - - public void addListener(MapChangeListener mapChangeListener) { - map.addListener(mapChangeListener); - } - - public void removeListener(MapChangeListener mapChangeListener) { - map.removeListener(mapChangeListener); - } - - - /* Internal stuff */ - - /** - * Comparsion method for the lru cache. During comparsion the map is accessed. - * First the entries are compared by the event timestamp, then vaultId, then identifying path and lastly by class name. - * - * @param left a {@link Key} object - * @param right another {@link Key} object, compared to {@code left} - * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. - */ - private int compareKeys(Key left, Key right) { - var t1 = map.get(left).mostRecentEvent.getTimestamp(); - var t2 = map.get(right).mostRecentEvent.getTimestamp(); - var timeComparsion = t1.compareTo(t2); - if (timeComparsion != 0) { - return timeComparsion; - } - var vaultIdComparsion = left.vault.getId().compareTo(right.vault.getId()); - if (vaultIdComparsion != 0) { - return vaultIdComparsion; - } - var pathComparsion = left.idPath.compareTo(right.idPath); - if (pathComparsion != 0) { - return pathComparsion; - } - return left.c.getName().compareTo(right.c.getName()); + hasUpdates.set(true); } /** @@ -236,4 +117,20 @@ public class FileSystemEventRegistry { return new Key(v, p, event.getClass()); } + public boolean hasUpdates() { + return hasUpdates.get(); + } + + /** + * Clones the map entries into a set. + *

+ * The set is first cleared, then all map entries are added in one bulk operation. Sets the updates status of the event registry. + * + * @param targetCollection + */ + public void cloneTo(Collection> targetCollection) { + targetCollection.clear(); + targetCollection.addAll(map.entrySet()); + hasUpdates.set(false); + } } diff --git a/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java b/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java index 4a278cb4b..d5c404348 100644 --- a/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java +++ b/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java @@ -9,7 +9,6 @@ import org.cryptomator.cryptofs.event.BrokenFileNodeEvent; import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent; import org.cryptomator.cryptofs.event.ConflictResolvedEvent; import org.cryptomator.cryptofs.event.DecryptionFailedEvent; -import org.cryptomator.event.FileSystemEventBucket; import org.cryptomator.integrations.revealpath.RevealFailedException; import org.cryptomator.integrations.revealpath.RevealPathService; import org.cryptomator.ui.common.FxController; @@ -41,6 +40,7 @@ import java.nio.file.Path; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; +import java.util.Map; import java.util.Optional; import java.util.ResourceBundle; import java.util.function.Function; @@ -55,7 +55,7 @@ public class EventListCellController implements FxController { @Nullable private final RevealPathService revealService; private final ResourceBundle resourceBundle; - private final ObjectProperty event; + private final ObjectProperty> eventEntry; private final StringProperty eventMessage; private final StringProperty eventDescription; private final ObjectProperty eventIcon; @@ -81,14 +81,14 @@ public class EventListCellController implements FxController { this.fileSystemEventRegistry = fileSystemEventRegistry; this.revealService = revealService.orElseGet(() -> null); this.resourceBundle = resourceBundle; - this.event = new SimpleObjectProperty<>(null); + this.eventEntry = new SimpleObjectProperty<>(null); this.eventMessage = new SimpleStringProperty(); this.eventDescription = new SimpleStringProperty(); this.eventIcon = new SimpleObjectProperty<>(); - this.eventCount = ObservableUtil.mapWithDefault(event, e -> e.count() == 1? "" : "("+ e.count() +")", ""); - this.vaultUnlocked = ObservableUtil.mapWithDefault(event.flatMap(e -> e.vault().unlockedProperty()), Function.identity(), false); - this.readableTime = ObservableUtil.mapWithDefault(event, e -> LOCAL_TIME_FORMATTER.format(e.mostRecent().getTimestamp()), ""); - this.readableDate = ObservableUtil.mapWithDefault(event, e -> LOCAL_DATE_FORMATTER.format(e.mostRecent().getTimestamp()), ""); + this.eventCount = ObservableUtil.mapWithDefault(eventEntry, e -> e.getValue().count() == 1? "" : "("+ e.getValue().count() +")", ""); + this.vaultUnlocked = ObservableUtil.mapWithDefault(eventEntry.flatMap(e -> e.getKey().vault().unlockedProperty()), Function.identity(), false); + this.readableTime = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_TIME_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), ""); + this.readableDate = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_DATE_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), ""); this.message = Bindings.createStringBinding(this::selectMessage, vaultUnlocked, eventMessage); this.description = Bindings.createStringBinding(this::selectDescription, vaultUnlocked, eventDescription); this.icon = Bindings.createObjectBinding(this::selectIcon, vaultUnlocked, eventIcon); @@ -108,13 +108,13 @@ public class EventListCellController implements FxController { return vaultUnlocked.getValue() && (eventActionsMenu.isShowing() || root.isHover()); } - public void setEvent(@NotNull FileSystemEventBucket item) { - event.set(item); + public void setEventEntry(@NotNull Map.Entry item) { + eventEntry.set(item); eventActionsMenu.hide(); eventActionsMenu.getItems().clear(); - eventTooltip.setText(item.vault().getDisplayName()); - addAction("generic.action.dismiss", () -> fileSystemEventRegistry.remove(item.vault(),item.mostRecent())); - switch (item.mostRecent()) { + eventTooltip.setText(item.getKey().vault().getDisplayName()); + addAction("generic.action.dismiss", () -> fileSystemEventRegistry.remove(item.getKey())); + switch (item.getValue().mostRecentEvent()) { case ConflictResolvedEvent fse -> this.adjustToConflictResolvedEvent(fse); case ConflictResolutionFailedEvent fse -> this.adjustToConflictEvent(fse); case DecryptionFailedEvent fse -> this.adjustToDecryptionFailedEvent(fse); @@ -209,16 +209,18 @@ public class EventListCellController implements FxController { private String selectDescription() { if (vaultUnlocked.getValue()) { return eventDescription.getValue(); - } else { - var e = event.getValue(); + } else if (eventEntry.getValue() != null) { + var e = eventEntry.getValue().getKey(); return resourceBundle.getString("eventView.entry.vaultLocked.description").formatted(e != null ? e.vault().getDisplayName() : ""); + } else { + return ""; } } @FXML public void toggleEventActionsMenu() { - var e = event.get(); + var e = eventEntry.get(); if (e != null) { if (eventActionsMenu.isShowing()) { eventActionsMenu.hide(); @@ -232,7 +234,7 @@ public class EventListCellController implements FxController { if (!(p instanceof CryptoPath)) { throw new IllegalArgumentException("Path " + p + " is not a vault path"); } - var v = event.getValue().vault(); + var v = eventEntry.getValue().getKey().vault(); if (!v.isUnlocked()) { return Path.of(System.getProperty("user.home")); } diff --git a/src/main/java/org/cryptomator/ui/eventview/EventListCellFactory.java b/src/main/java/org/cryptomator/ui/eventview/EventListCellFactory.java index 3a84fcde8..405e5f307 100644 --- a/src/main/java/org/cryptomator/ui/eventview/EventListCellFactory.java +++ b/src/main/java/org/cryptomator/ui/eventview/EventListCellFactory.java @@ -1,6 +1,6 @@ package org.cryptomator.ui.eventview; -import org.cryptomator.event.FileSystemEventBucket; +import org.cryptomator.event.FileSystemEventRegistry; import org.cryptomator.ui.common.FxmlLoaderFactory; import javax.inject.Inject; @@ -12,9 +12,10 @@ import javafx.scene.control.ListView; import javafx.util.Callback; import java.io.IOException; import java.io.UncheckedIOException; +import java.util.Map; @EventViewScoped -public class EventListCellFactory implements Callback, ListCell> { +public class EventListCellFactory implements Callback>, ListCell>> { private static final String FXML_PATH = "/fxml/eventview_cell.fxml"; @@ -27,7 +28,7 @@ public class EventListCellFactory implements Callback call(ListView eventListView) { + public ListCell> call(ListView> eventListView) { try { FXMLLoader fxmlLoader = fxmlLoaders.load(FXML_PATH); return new Cell(fxmlLoader.getRoot(), fxmlLoader.getController()); @@ -36,7 +37,7 @@ public class EventListCellFactory implements Callback { + private static class Cell extends ListCell> { private final Parent root; private final EventListCellController controller; @@ -47,7 +48,7 @@ public class EventListCellFactory implements Callback item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { @@ -57,7 +58,7 @@ public class EventListCellFactory implements Callback eventList; - private final FilteredList filteredEventList; + private final FilteredList> filteredEventList; private final ObservableList vaults; - private final SortedList reversedEventList; + private final SortedList> sortedEventList; private final ObservableList choiceBoxEntries; private final ResourceBundle resourceBundle; private final EventListCellFactory cellFactory; @@ -35,20 +32,44 @@ public class EventViewController implements FxController { @FXML ChoiceBox vaultFilterChoiceBox; @FXML - ListView eventListView; + ListView> eventListView; @Inject - public EventViewController(FileSystemEventRegistry fileSystemEventRegistry, ObservableList vaults, ResourceBundle resourceBundle, EventListCellFactory cellFactory) { - this.fileSystemEventRegistry = fileSystemEventRegistry; - this.eventList = FXCollections.observableArrayList(); - this.filteredEventList = eventList.filtered(_ -> true); + public EventViewController(EventsUpdateCheck eventsUpdateCheck, ObservableList vaults, ResourceBundle resourceBundle, EventListCellFactory cellFactory) { + this.filteredEventList = eventsUpdateCheck.getList().filtered(_ -> true); this.vaults = vaults; - this.reversedEventList = new SortedList<>(filteredEventList, Comparator.reverseOrder()); + this.sortedEventList = new SortedList<>(filteredEventList, this::compareBuckets); this.choiceBoxEntries = FXCollections.observableArrayList(); this.resourceBundle = resourceBundle; this.cellFactory = cellFactory; } + /** + * Comparsion method for the lru cache. During comparsion the map is accessed. + * First the entries are compared by the event timestamp, then vaultId, then identifying path and lastly by class name. + * + * @param left a {@link FileSystemEventRegistry.Key} object + * @param right another {@link FileSystemEventRegistry.Key} object, compared to {@code left} + * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. + */ + private int compareBuckets(Map.Entry left, Map.Entry right) { + var t1 = left.getValue().mostRecentEvent().getTimestamp(); + var t2 = right.getValue().mostRecentEvent().getTimestamp(); + var timeComparison = t1.compareTo(t2); + if (timeComparison != 0) { + return -timeComparison; //we need the reverse timesorting + } + var vaultIdComparsion = left.getKey().vault().getId().compareTo(right.getKey().vault().getId()); + if (vaultIdComparsion != 0) { + return vaultIdComparsion; + } + var pathComparsion = left.getKey().idPath().compareTo(right.getKey().idPath()); + if (pathComparsion != 0) { + return pathComparsion; + } + return left.getKey().c().getName().compareTo(right.getKey().c().getName()); + } + @FXML public void initialize() { choiceBoxEntries.add(null); @@ -60,37 +81,25 @@ public class EventViewController implements FxController { } }); - eventList.addAll(fileSystemEventRegistry.listAll()); - fileSystemEventRegistry.addListener((MapChangeListener) this::updateList); eventListView.setCellFactory(cellFactory); - eventListView.setItems(reversedEventList); + eventListView.setItems(sortedEventList); vaultFilterChoiceBox.setItems(choiceBoxEntries); vaultFilterChoiceBox.valueProperty().addListener(this::applyVaultFilter); vaultFilterChoiceBox.setConverter(new VaultConverter(resourceBundle)); } - private void updateList(MapChangeListener.Change change) { - var vault = change.getKey().vault(); - if (change.wasRemoved()) { - eventList.remove(new FileSystemEventBucket(vault, change.getValueRemoved().mostRecentEvent(), 0)); - } - if (change.wasAdded()) { - eventList.addLast(new FileSystemEventBucket(vault, change.getValueAdded().mostRecentEvent(), change.getValueAdded().count())); - } - } - private void applyVaultFilter(ObservableValue v, Vault oldV, Vault newV) { if (newV == null) { filteredEventList.setPredicate(_ -> true); } else { - filteredEventList.setPredicate(e -> e.vault().equals(newV)); + filteredEventList.setPredicate(e -> e.getKey().vault().equals(newV)); } } @FXML void clearEvents() { - fileSystemEventRegistry.clear(); + //fileSystemEventRegistry.clear(); } private static class VaultConverter extends StringConverter { diff --git a/src/main/java/org/cryptomator/ui/fxapp/EventsUpdateCheck.java b/src/main/java/org/cryptomator/ui/fxapp/EventsUpdateCheck.java new file mode 100644 index 000000000..a02316699 --- /dev/null +++ b/src/main/java/org/cryptomator/ui/fxapp/EventsUpdateCheck.java @@ -0,0 +1,62 @@ +package org.cryptomator.ui.fxapp; + +import org.cryptomator.event.FileSystemEventRegistry; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import javafx.application.Platform; +import javafx.beans.property.BooleanProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +@FxApplicationScoped +public class EventsUpdateCheck { + + private final ObservableList> events; + private final FileSystemEventRegistry eventRegistry; + private final ScheduledFuture scheduledTask; + private final BooleanProperty unreadEvents; + + @Inject + public EventsUpdateCheck(FileSystemEventRegistry eventRegistry, ScheduledExecutorService scheduler, @Named("unreadEventsAvailable") BooleanProperty unreadEvents) { + this.events = FXCollections.observableArrayList(); + this.eventRegistry = eventRegistry; + this.unreadEvents = unreadEvents; + this.scheduledTask = scheduler.scheduleWithFixedDelay(() -> { + if (eventRegistry.hasUpdates()) { + flush(); + } + }, 1000, 1000, TimeUnit.MILLISECONDS); + //TODO: allow the task to be canceled (to enable ui actions, e.g. when the contextMenu is open, the list should not be updated + } + + public ObservableList> getList() { + return events; + } + + /** + * Clones the registry into the observable list + */ + private void flush() { + var latch = new CountDownLatch(1); + Platform.runLater(() -> { + eventRegistry.cloneTo(events); + unreadEvents.setValue(true); + latch.countDown(); + }); + try { + latch.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + + +} diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index fd480033c..78c288768 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -43,6 +43,7 @@ public class FxApplication { this.autoUnlocker = autoUnlocker; } + //TODO: eventUpdater muss hier starten public void start() { LOG.trace("FxApplication.start()"); applicationStyle.initialize(); diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java index 165c14a25..684e8540e 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java @@ -69,7 +69,6 @@ public class VaultListController implements FxController { private final VaultListCellFactory cellFactory; private final AddVaultWizardComponent.Builder addVaultWizard; private final BooleanBinding emptyVaultList; - private final FileSystemEventRegistry fileSystemEventRegistry; private final BooleanProperty newEventsPresent; private final VaultListManager vaultListManager; private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty(); @@ -97,7 +96,6 @@ public class VaultListController implements FxController { FxApplicationWindows appWindows, // Settings settings, // Dialogs dialogs, // - FileSystemEventRegistry fileSystemEventRegistry, // @Named("unreadEventsAvailable") BooleanProperty unreadEvents) { this.mainWindow = mainWindow; this.vaults = vaults; @@ -111,13 +109,7 @@ public class VaultListController implements FxController { this.dialogs = dialogs; this.emptyVaultList = Bindings.isEmpty(vaults); - this.fileSystemEventRegistry = fileSystemEventRegistry; this.newEventsPresent = unreadEvents; - fileSystemEventRegistry.addListener((MapChangeListener) change -> { - if (change.wasAdded()) { - newEventsPresent.setValue(true); - } - }); selectedVault.addListener(this::selectedVaultDidChange); cellSize = settings.compactMode.map(compact -> compact ? 30.0 : 60.0);