Merge branch 'develop' into feature/refactor-location-presets

This commit is contained in:
Sebastian Stenzel
2023-05-23 10:19:00 +02:00
3 changed files with 66 additions and 10 deletions

View File

@@ -1,30 +1,85 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.collections.ObservableList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Stream;
@FxApplicationScoped
public class AutoUnlocker {
private static final Logger LOG = LoggerFactory.getLogger(AutoUnlocker.class);
private final ObservableList<Vault> vaults;
private final FxApplicationWindows appWindows;
private final ScheduledExecutorService scheduler;
private ScheduledFuture<?> unlockMissingFuture;
private ScheduledFuture<?> timeoutFuture;
@Inject
public AutoUnlocker(ObservableList<Vault> vaults, FxApplicationWindows appWindows) {
public AutoUnlocker(ObservableList<Vault> vaults, FxApplicationWindows appWindows, ScheduledExecutorService scheduler) {
this.vaults = vaults;
this.appWindows = appWindows;
this.scheduler = scheduler;
}
public void unlock() {
vaults.stream().filter(Vault::isLocked) //
.filter(v -> v.getVaultSettings().unlockAfterStartup().get()) //
.<CompletionStage<Void>>reduce(CompletableFuture.completedFuture(null), //
(unlockFlow, v) -> unlockFlow.handle((voit, ex) -> appWindows.startUnlockWorkflow(v, null)).thenCompose(stage -> stage), //we don't care here about the exception, logged elsewhere
(unlockChain1, unlockChain2) -> unlockChain1.handle((voit, ex) -> unlockChain2).thenCompose(stage -> stage));
public void tryUnlockForTimespan(int timespan, TimeUnit timeUnit) {
// Unlock all available auto unlock vaults
Predicate<Vault> shouldAutoUnlock = v -> v.getVaultSettings().unlockAfterStartup().get();
unlockSequentially(vaults.stream().filter(shouldAutoUnlock)).thenRun(() -> startUnlockMissing(timespan, timeUnit));
}
private CompletionStage<Void> unlockSequentially(Stream<Vault> vaultStream) {
// this is an attempt to run all the unlock workflows sequentially, i.e. start the next workflow only after completing/failing the previous workflow.
return vaultStream.filter(Vault::isLocked).reduce(CompletableFuture.completedFuture(null),
(prevUnlock, nextVault) -> prevUnlock.thenCompose(unused -> appWindows.startUnlockWorkflow(nextVault, null)),
(prevUnlock, nextUnlock) -> nextUnlock.exceptionally(e -> null) // we don't care here about the exception, logged elsewhere
);
}
private void startUnlockMissing(int timespan, TimeUnit timeUnit) {
// Start a temporary service if there are missing auto unlock vaults
if (getMissingAutoUnlockVaults().findAny().isPresent()) {
LOG.info("Found MISSING vaults, starting periodic check");
unlockMissingFuture = scheduler.scheduleWithFixedDelay(this::unlockMissing, 0, 1, TimeUnit.SECONDS);
timeoutFuture = scheduler.schedule(this::timeout, timespan, timeUnit);
}
}
private void unlockMissing() {
List<Vault> missingAutoUnlockVaults = getMissingAutoUnlockVaults().toList();
missingAutoUnlockVaults.forEach(VaultListManager::redetermineVaultState);
unlockSequentially(missingAutoUnlockVaults.stream()).thenRun(this::stopUnlockMissing);
}
private void stopUnlockMissing() {
// Stop checking if there are no more missing vaults
if (getMissingAutoUnlockVaults().findAny().isEmpty()) {
LOG.info("No more MISSING vaults, stopping periodic check");
unlockMissingFuture.cancel(false);
timeoutFuture.cancel(false);
}
}
private void timeout() {
LOG.info("MISSING vaults periodic check timed out");
unlockMissingFuture.cancel(false);
}
private Stream<Vault> getMissingAutoUnlockVaults() {
return vaults.stream()
.filter(Vault::isMissing)
.filter(v -> v.getVaultSettings().unlockAfterStartup().get());
}
}

View File

@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import java.util.concurrent.TimeUnit;
@FxApplicationScoped
public class FxApplication {
@@ -68,7 +69,6 @@ public class FxApplication {
});
launchEventHandler.startHandlingLaunchEvents();
autoUnlocker.unlock();
autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES);
}
}

View File

@@ -12,6 +12,7 @@ import org.cryptomator.ui.preferences.PreferencesComponent;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import org.cryptomator.ui.quit.QuitComponent;
import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.unlock.UnlockWorkflow;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -114,7 +115,7 @@ public class FxApplicationWindows {
LOG.debug("Start unlock workflow for {}", vault.getDisplayName());
return unlockWorkflowFactory.create(vault, owner).unlockWorkflow();
}, Platform::runLater) //
.thenCompose(unlockWorkflow -> CompletableFuture.runAsync(unlockWorkflow, executor)) //
.thenAcceptAsync(UnlockWorkflow::run, executor)
.exceptionally(e -> {
showErrorWindow(e, owner == null ? primaryStage : owner, null);
return null;