瀏覽代碼

Merge pull request #1935 from cryptomator/feature/lock-retry-loop

Handle exception when force-locking
Sebastian Stenzel 3 年之前
父節點
當前提交
0c47af2f15

+ 5 - 1
src/main/java/org/cryptomator/ui/common/UserInteractionLock.java

@@ -16,7 +16,11 @@ public class UserInteractionLock<E extends Enum> {
 	private volatile E state;
 
 	public UserInteractionLock(E initialValue) {
-		state = initialValue;
+		this.state = initialValue;
+	}
+
+	public synchronized void reset(E value) {
+		this.state = value;
 	}
 
 	public void interacted(E result) {

+ 11 - 1
src/main/java/org/cryptomator/ui/lock/LockForcedController.java

@@ -35,7 +35,13 @@ public class LockForcedController implements FxController {
 	}
 
 	@FXML
-	public void confirmForcedLock() {
+	public void retry() {
+		forceLockDecisionLock.interacted(LockModule.ForceLockDecision.RETRY);
+		window.close();
+	}
+
+	@FXML
+	public void force() {
 		forceLockDecisionLock.interacted(LockModule.ForceLockDecision.FORCE);
 		window.close();
 	}
@@ -54,4 +60,8 @@ public class LockForcedController implements FxController {
 		return vault.getDisplayName();
 	}
 
+	public boolean isForceSupported() {
+		return vault.supportsForcedUnmount();
+	}
+
 }

+ 1 - 0
src/main/java/org/cryptomator/ui/lock/LockModule.java

@@ -28,6 +28,7 @@ abstract class LockModule {
 
 	enum ForceLockDecision {
 		CANCEL,
+		RETRY,
 		FORCE;
 	}
 

+ 10 - 4
src/main/java/org/cryptomator/ui/lock/LockWorkflow.java

@@ -51,20 +51,26 @@ public class LockWorkflow extends Task<Void> {
 
 	@Override
 	protected Void call() throws Volume.VolumeException, InterruptedException, LockNotCompletedException {
+		lock(false);
+		return null;
+	}
+
+	private void lock(boolean forced) throws InterruptedException {
 		try {
-			vault.lock(false);
+			vault.lock(forced);
 		} catch (Volume.VolumeException | LockNotCompletedException e) {
-			LOG.debug("Regular lock of {} failed.", vault.getDisplayName(), e);
+			LOG.info("Locking {} failed (forced: {}).", vault.getDisplayName(), forced, e);
 			var decision = askUserForAction();
 			switch (decision) {
-				case FORCE -> vault.lock(true);
+				case RETRY -> lock(false);
+				case FORCE -> lock(true);
 				case CANCEL -> cancel(false);
 			}
 		}
-		return null;
 	}
 
 	private LockModule.ForceLockDecision askUserForAction() throws InterruptedException {
+		forceLockDecisionLock.reset(null);
 		// show forcedLock dialogue ...
 		Platform.runLater(() -> {
 			lockWindow.setScene(lockForcedScene.get());

+ 3 - 3
src/main/resources/fxml/lock_forced.fxml

@@ -33,11 +33,11 @@
 		</HBox>
 
 		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
-			<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
+			<ButtonBar buttonMinWidth="100" buttonOrder="+CIU">
 				<buttons>
 					<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" cancelButton="true" onAction="#cancel"/>
-					<!-- TODO: third button with retry? -->
-					<Button text="%lock.forced.confirmBtn" ButtonBar.buttonData="FINISH" onAction="#confirmForcedLock"/>
+					<Button text="%lock.forced.retryBtn" ButtonBar.buttonData="FINISH" onAction="#retry"/>
+					<Button text="%lock.forced.forceBtn" ButtonBar.buttonData="OTHER" onAction="#force" disable="${!controller.forceSupported}"/>
 				</buttons>
 			</ButtonBar>
 		</VBox>

+ 3 - 2
src/main/resources/i18n/strings.properties

@@ -118,9 +118,10 @@ unlock.error.invalidMountPoint.existing=Mount point "%s" already exists or paren
 
 # Lock
 ## Force
-lock.forced.heading=Graceful lock failed
+lock.forced.heading=Lock failed
 lock.forced.message=Locking "%s" was blocked by pending operations or open files. You can force lock this vault, however interrupting I/O may result in the loss of unsaved data.
-lock.forced.confirmBtn=Force Lock
+lock.forced.retryBtn=Retry
+lock.forced.forceBtn=Force Lock
 ## Failure
 lock.fail.heading=Locking vault failed.
 lock.fail.message=Vault "%s" could not be locked. Ensure unsaved work is saved elsewhere and important Read/Write operations are finished. In order to close the vault, kill the Cryptomator process.