|
10 | 10 | import com.intellij.openapi.fileChooser.FileChooser; |
11 | 11 | import com.intellij.openapi.fileChooser.FileChooserDescriptor; |
12 | 12 | import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; |
| 13 | +import com.intellij.openapi.progress.ProcessCanceledException; |
13 | 14 | import com.intellij.openapi.progress.ProgressIndicator; |
14 | 15 | import com.intellij.openapi.progress.ProgressManager; |
15 | 16 | import com.intellij.openapi.project.Project; |
|
49 | 50 | import reactor.core.scheduler.Schedulers; |
50 | 51 | import reactor.util.function.Tuple2; |
51 | 52 | import rx.Single; |
52 | | -import rx.exceptions.Exceptions; |
53 | 53 |
|
54 | 54 | import javax.swing.*; |
55 | 55 | import java.awt.*; |
|
58 | 58 | import java.util.List; |
59 | 59 | import java.util.*; |
60 | 60 | import java.util.concurrent.Callable; |
| 61 | +import java.util.concurrent.CancellationException; |
61 | 62 | import java.util.concurrent.CompletableFuture; |
62 | 63 | import java.util.stream.Stream; |
63 | 64 |
|
|
66 | 67 | public class SignInWindow extends AzureDialogWrapper { |
67 | 68 | private static final Logger LOGGER = Logger.getInstance(SignInWindow.class); |
68 | 69 | private static final String SIGN_IN_ERROR = "Sign In Error"; |
69 | | - private static final String USER_CANCEL = "user cancel"; |
70 | 70 |
|
71 | 71 | private JPanel contentPane; |
72 | 72 |
|
@@ -215,21 +215,26 @@ public Single<AuthMethodDetails> login() { |
215 | 215 | } |
216 | 216 |
|
217 | 217 | private static AuthMethodDetails checkCanceled(ProgressIndicator indicator, Mono<? extends AuthMethodDetails> mono) { |
218 | | - CompletableFuture<AuthMethodDetails> loginFuture = new CompletableFuture<>(); |
| 218 | + CompletableFuture<? extends AuthMethodDetails> future = mono.toFuture(); |
219 | 219 | Disposable disposable = Flux.interval(Duration.ofSeconds(1)).map(ts -> { |
220 | | - if (indicator != null && indicator.isCanceled()) { |
221 | | - IllegalStateException e = new IllegalStateException(USER_CANCEL); |
222 | | - loginFuture.completeExceptionally(e); |
223 | | - throw e; |
| 220 | + if (indicator != null) { |
| 221 | + indicator.checkCanceled(); |
224 | 222 | } |
225 | 223 | return 1; |
226 | | - }).onErrorResume(e -> Mono.empty()).subscribe(); |
227 | | - mono.doOnError(loginFuture::completeExceptionally).doOnSuccess(loginFuture::complete).doFinally(e -> disposable.dispose()).subscribe(); |
| 224 | + }).onErrorResume(e -> { |
| 225 | + if (e instanceof ProcessCanceledException) { |
| 226 | + future.cancel(true); |
| 227 | + } |
| 228 | + return Mono.empty(); |
| 229 | + }).subscribeOn(Schedulers.boundedElastic()).subscribe(); |
228 | 230 | try { |
229 | | - return loginFuture.get(); |
230 | | - } catch (Throwable ex) { |
231 | | - Throwable e = Exceptions.getFinalCause(ex); |
232 | | - throw new AzureToolkitRuntimeException("Cannot login due to error: " + ex.getMessage(), ex); |
| 231 | + return future.get(); |
| 232 | + } catch (CancellationException e) { |
| 233 | + return null; |
| 234 | + } catch (Throwable e) { |
| 235 | + throw new AzureToolkitRuntimeException("Cannot login due to error: " + e.getMessage(), e); |
| 236 | + } finally { |
| 237 | + disposable.dispose(); |
233 | 238 | } |
234 | 239 | } |
235 | 240 |
|
@@ -334,25 +339,22 @@ private synchronized AuthMethodDetails doDeviceLogin() { |
334 | 339 | final IDeviceLoginUI deviceLoginUI = CommonSettings.getUiFactory().getDeviceLoginUI(); |
335 | 340 | final AzureAccount az = com.microsoft.azure.toolkit.lib.Azure.az(AzureAccount.class); |
336 | 341 | final Account account = az.loginAsync(AuthType.DEVICE_CODE, true).block(); |
337 | | - Disposable subscribe = account.continueLogin().doOnCancel(() -> { |
338 | | - deviceCodeLoginFuture.completeExceptionally(new IllegalStateException("user cancel")); |
339 | | - }).doOnSuccess(ac -> { |
340 | | - deviceCodeLoginFuture.complete(fromAccountEntity(ac.getEntity())); |
341 | | - }).doOnError(deviceCodeLoginFuture::completeExceptionally).doFinally(signal -> { |
342 | | - deviceLoginUI.closePrompt(); |
343 | | - }).subscribe(); |
344 | | - deviceLoginUI.setDisposable(subscribe); |
| 342 | + |
| 343 | + CompletableFuture<AuthMethodDetails> future = |
| 344 | + account.continueLogin().map(ac -> fromAccountEntity(ac.getEntity())).doFinally(signal -> { |
| 345 | + deviceLoginUI.closePrompt(); |
| 346 | + }).toFuture(); |
| 347 | + deviceLoginUI.setFuture(future); |
345 | 348 | if (ApplicationManager.getApplication().isDispatchThread()) { |
346 | 349 | deviceLoginUI.promptDeviceCode(((DeviceCodeAccount) account).getDeviceCode()); |
347 | 350 | } else { |
348 | 351 | AzureTaskManager.getInstance().runAndWait(() -> |
349 | 352 | deviceLoginUI.promptDeviceCode(((DeviceCodeAccount) account).getDeviceCode())); |
350 | 353 | } |
351 | | - return Mono.fromFuture(deviceCodeLoginFuture).block(); |
| 354 | + return future.get(); |
352 | 355 |
|
353 | 356 | } catch (Exception ex) { |
354 | | - if (ex instanceof IllegalStateException && USER_CANCEL.equals(ex.getMessage())) { |
355 | | - } else { |
| 357 | + if (!(ex instanceof CancellationException)) { |
356 | 358 | ex.printStackTrace(); |
357 | 359 | ErrorWindow.show(project, ex.getMessage(), SIGN_IN_ERROR); |
358 | 360 | } |
|
0 commit comments