|
17 | 17 | */ |
18 | 18 | package org.jackhuang.hmcl; |
19 | 19 |
|
| 20 | +import javafx.animation.KeyFrame; |
| 21 | +import javafx.animation.KeyValue; |
| 22 | +import javafx.animation.Timeline; |
20 | 23 | import javafx.application.Application; |
21 | 24 | import javafx.application.Platform; |
22 | 25 | import javafx.beans.value.ObservableBooleanValue; |
23 | 26 | import javafx.geometry.Rectangle2D; |
24 | 27 | import javafx.scene.control.Alert; |
25 | 28 | import javafx.scene.control.Alert.AlertType; |
| 29 | +import javafx.scene.control.Button; |
26 | 30 | import javafx.scene.control.ButtonType; |
27 | 31 | import javafx.scene.input.Clipboard; |
28 | 32 | import javafx.scene.input.DataFormat; |
29 | 33 | import javafx.stage.Screen; |
30 | 34 | import javafx.stage.Stage; |
| 35 | +import javafx.util.Duration; |
31 | 36 | import org.jackhuang.hmcl.setting.ConfigHolder; |
32 | 37 | import org.jackhuang.hmcl.setting.SambaException; |
33 | | -import org.jackhuang.hmcl.ui.FXUtils; |
34 | | -import org.jackhuang.hmcl.util.FileSaver; |
35 | 38 | import org.jackhuang.hmcl.task.AsyncTaskExecutor; |
36 | 39 | import org.jackhuang.hmcl.task.Schedulers; |
37 | 40 | import org.jackhuang.hmcl.ui.Controllers; |
| 41 | +import org.jackhuang.hmcl.ui.FXUtils; |
38 | 42 | import org.jackhuang.hmcl.upgrade.UpdateChecker; |
39 | 43 | import org.jackhuang.hmcl.upgrade.UpdateHandler; |
40 | 44 | import org.jackhuang.hmcl.util.CrashReporter; |
| 45 | +import org.jackhuang.hmcl.util.FileSaver; |
41 | 46 | import org.jackhuang.hmcl.util.Lang; |
42 | 47 | import org.jackhuang.hmcl.util.StringUtils; |
43 | 48 | import org.jackhuang.hmcl.util.io.JarUtils; |
44 | | -import org.jackhuang.hmcl.util.platform.Architecture; |
45 | | -import org.jackhuang.hmcl.util.platform.CommandBuilder; |
46 | | -import org.jackhuang.hmcl.util.platform.NativeUtils; |
47 | | -import org.jackhuang.hmcl.util.platform.OperatingSystem; |
48 | | -import org.jackhuang.hmcl.util.platform.SystemInfo; |
| 49 | +import org.jackhuang.hmcl.util.platform.*; |
49 | 50 |
|
50 | 51 | import java.io.File; |
51 | 52 | import java.io.IOException; |
|
65 | 66 |
|
66 | 67 | import static org.jackhuang.hmcl.ui.FXUtils.runInFX; |
67 | 68 | import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; |
68 | | -import static org.jackhuang.hmcl.util.logging.Logger.LOG; |
69 | 69 | import static org.jackhuang.hmcl.util.i18n.I18n.i18n; |
| 70 | +import static org.jackhuang.hmcl.util.logging.Logger.LOG; |
70 | 71 |
|
71 | 72 | public final class Launcher extends Application { |
72 | 73 | public static final CookieManager COOKIE_MANAGER = new CookieManager(); |
@@ -111,7 +112,7 @@ public void start(Stage primaryStage) { |
111 | 112 | if (OperatingSystem.CURRENT_OS == OperatingSystem.MACOS |
112 | 113 | && ConfigHolder.isNewlyCreated() |
113 | 114 | && System.getProperty("user.dir").startsWith("/private/var/folders/")) { |
114 | | - if (showAlert(AlertType.WARNING, i18n("fatal.mac_app_translocation"), ButtonType.YES, ButtonType.NO) == ButtonType.NO) |
| 115 | + if (!confirmWithCountdown(AlertType.WARNING, i18n("fatal.mac_app_translocation"), 5)) |
115 | 116 | return; |
116 | 117 | } else { |
117 | 118 | checkConfigInTempDir(); |
@@ -182,6 +183,27 @@ private static ButtonType showAlert(AlertType alertType, String contentText, But |
182 | 183 | return new Alert(alertType, contentText, buttons).showAndWait().orElse(null); |
183 | 184 | } |
184 | 185 |
|
| 186 | + private static boolean confirmWithCountdown(Alert.AlertType alertType, String contentText, int seconds) { |
| 187 | + Alert alert = new Alert(alertType, contentText, ButtonType.YES, ButtonType.NO); |
| 188 | + Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.YES); |
| 189 | + |
| 190 | + okButton.setDisable(true); |
| 191 | + |
| 192 | + KeyFrame[] keyFrames = new KeyFrame[seconds + 1]; |
| 193 | + for (int i = 0; i < seconds; i++) { |
| 194 | + keyFrames[i] = new KeyFrame(Duration.seconds(i), |
| 195 | + new KeyValue(okButton.textProperty(), i18n("button.ok.countdown", seconds - i))); |
| 196 | + } |
| 197 | + keyFrames[seconds] = new KeyFrame(Duration.seconds(seconds), |
| 198 | + new KeyValue(okButton.textProperty(), i18n("button.ok")), |
| 199 | + new KeyValue(okButton.disableProperty(), false)); |
| 200 | + |
| 201 | + Timeline timeline = new Timeline(keyFrames); |
| 202 | + alert.setOnShown(e -> timeline.play()); |
| 203 | + alert.setOnCloseRequest(e -> timeline.stop()); |
| 204 | + return alert.showAndWait().orElse(null) == ButtonType.YES; |
| 205 | + } |
| 206 | + |
185 | 207 | private static boolean isConfigInTempDir() { |
186 | 208 | String configPath = ConfigHolder.configLocation().toString(); |
187 | 209 |
|
@@ -221,7 +243,7 @@ private static boolean isConfigInTempDir() { |
221 | 243 |
|
222 | 244 | private static void checkConfigInTempDir() { |
223 | 245 | if (ConfigHolder.isNewlyCreated() && isConfigInTempDir() |
224 | | - && showAlert(AlertType.WARNING, i18n("fatal.config_in_temp_dir"), ButtonType.YES, ButtonType.NO) == ButtonType.NO) { |
| 246 | + && !confirmWithCountdown(AlertType.WARNING, i18n("fatal.config_in_temp_dir"), 5)) { |
225 | 247 | EntryPoint.exit(0); |
226 | 248 | } |
227 | 249 | } |
|
0 commit comments