From f71b2ac864ee4163ab39a79c7ac7ce008a21cad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:35:07 +0800 Subject: [PATCH 1/6] update --- .../org/jackhuang/hmcl/ui/GameCrashWindow.java | 16 ++++++++++++---- .../org/jackhuang/hmcl/ui/main/SettingsPage.java | 16 +++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index 6cc322ec94..c2de71e0d7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -42,6 +42,7 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.theme.Themes; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; +import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Log4jLevel; @@ -87,6 +88,7 @@ public class GameCrashWindow extends Stage { private final LaunchOptions launchOptions; private final View view; private final StackPane stackPane; + private final SpinnerPane spinnerPane = new SpinnerPane(); private final List logs; @@ -114,6 +116,8 @@ public GameCrashWindow(ManagedProcess managedProcess, ProcessListener.ExitType e this.stackPane = new StackPane(view); this.feedbackTextFlow.getChildren().addAll(FXUtils.parseSegment(i18n("game.crash.feedback"), Controllers::onHyperlinkAction)); + spinnerPane.getStyleClass().add("small-spinner-pane"); + setScene(new Scene(stackPane, 800, 480)); StyleSheets.init(getScene()); setTitle(i18n("game.crash.title")); @@ -312,7 +316,7 @@ private void exportGameCrashInfo() { var dialog = new MessageDialogPane.Builder(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), i18n("message.error"), MessageDialogPane.MessageType.ERROR).ok(null).build(); DialogUtils.show(stackPane, dialog); } - + spinnerPane.hideSpinner(); return null; }, Schedulers.javafx()); } @@ -444,8 +448,12 @@ private final class View extends VBox { HBox toolBar = new HBox(); VBox.setMargin(toolBar, new Insets(0, 0, 4, 0)); { - JFXButton exportGameCrashInfoButton = FXUtils.newRaisedButton(i18n("logwindow.export_game_crash_logs")); - exportGameCrashInfoButton.setOnAction(e -> exportGameCrashInfo()); + JFXButton exportButton = FXUtils.newRaisedButton(i18n("logwindow.export_game_crash_logs")); + spinnerPane.setContent(exportButton); + exportButton.setOnAction(e -> { + spinnerPane.showSpinner(); + exportGameCrashInfo(); + }); JFXButton logButton = FXUtils.newRaisedButton(i18n("logwindow.title")); logButton.setOnAction(e -> showLogWindow()); @@ -457,7 +465,7 @@ private final class View extends VBox { toolBar.setPadding(new Insets(8)); toolBar.setSpacing(8); toolBar.getStyleClass().add("jfx-tool-bar"); - toolBar.getChildren().setAll(exportGameCrashInfoButton, logButton, helpButton); + toolBar.getChildren().setAll(spinnerPane, logButton, helpButton); } getChildren().setAll(titlePane, infoPane, moddedPane, gameDirPane, toolBar); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index ac7085963a..e17498b93f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -77,6 +77,8 @@ public final class SettingsPage extends ScrollPane { @SuppressWarnings("FieldCanBeLocal") private final InvalidationListener updateListener; + private final SpinnerPane spinnerPane = new SpinnerPane(); + public SettingsPage() { this.setFitToWidth(true); @@ -285,11 +287,12 @@ else if (locale.isSameLanguage(currentLocale)) openLogFolderButton.setDisable(true); JFXButton logButton = FXUtils.newBorderButton(i18n("settings.launcher.launcher_log.export")); + spinnerPane.setContent(logButton); logButton.setOnAction(e -> onExportLogs()); HBox buttonBox = new HBox(); buttonBox.setSpacing(10); - buttonBox.getChildren().addAll(openLogFolderButton, logButton); + buttonBox.getChildren().addAll(openLogFolderButton, spinnerPane); BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); debugPane.setRight(buttonBox); @@ -362,6 +365,7 @@ private static boolean exportLogFile(ZipOutputStream output, } private void onExportLogs() { + spinnerPane.showSpinner(); thread(() -> { String nameBase = "hmcl-exported-logs-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")); List recentLogFiles = LOG.findRecentLogFiles(5); @@ -434,11 +438,17 @@ private void onExportLogs() { } } catch (IOException e) { LOG.warning("Failed to export logs", e); - Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(e), null, MessageType.ERROR)); + Platform.runLater(() -> { + spinnerPane.showSpinner(); + Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(e), null, MessageType.ERROR); + }); return; } - Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", outputFile))); + Platform.runLater(() -> { + spinnerPane.showSpinner(); + Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", outputFile)); + }); FXUtils.showFileInExplorer(outputFile); }); } From eb4fc9bb55d7efef3898b5d03c1f5548b7e6b8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=9E=E5=BA=90?= <109708109+Ciilu@users.noreply.github.com> Date: Sat, 7 Mar 2026 21:22:40 +0800 Subject: [PATCH 2/6] update --- .../main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index e17498b93f..c011f74798 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -439,14 +439,14 @@ private void onExportLogs() { } catch (IOException e) { LOG.warning("Failed to export logs", e); Platform.runLater(() -> { - spinnerPane.showSpinner(); + spinnerPane.hideSpinner(); Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(e), null, MessageType.ERROR); }); return; } Platform.runLater(() -> { - spinnerPane.showSpinner(); + spinnerPane.hideSpinner(); Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", outputFile)); }); FXUtils.showFileInExplorer(outputFile); From 20863b8b54df50882d843ab05712e3e1a928833f Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 21 Mar 2026 22:09:34 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B8=B8=E6=88=8F?= =?UTF-8?q?=E5=B4=A9=E6=BA=83=E7=AA=97=E5=8F=A3=E5=AF=BC=E5=87=BA=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E7=9A=84=E5=8A=A0=E8=BD=BD=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jackhuang/hmcl/ui/GameCrashWindow.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index c2de71e0d7..aca3041d5a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -88,7 +88,6 @@ public class GameCrashWindow extends Stage { private final LaunchOptions launchOptions; private final View view; private final StackPane stackPane; - private final SpinnerPane spinnerPane = new SpinnerPane(); private final List logs; @@ -116,8 +115,6 @@ public GameCrashWindow(ManagedProcess managedProcess, ProcessListener.ExitType e this.stackPane = new StackPane(view); this.feedbackTextFlow.getChildren().addAll(FXUtils.parseSegment(i18n("game.crash.feedback"), Controllers::onHyperlinkAction)); - spinnerPane.getStyleClass().add("small-spinner-pane"); - setScene(new Scene(stackPane, 800, 480)); StyleSheets.init(getScene()); setTitle(i18n("game.crash.title")); @@ -277,10 +274,10 @@ private void showLogWindow() { logWindow.show(); } - private void exportGameCrashInfo() { + private CompletableFuture exportGameCrashInfo() { Path logFile = Paths.get("minecraft-exported-crash-info-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")) + ".zip").toAbsolutePath(); - CompletableFuture.supplyAsync(() -> + return CompletableFuture.supplyAsync(() -> logs.stream().map(Log::getLog).collect(Collectors.joining("\n"))) .thenComposeAsync(logs -> { long processStartTime = managedProcess.getProcess().info() @@ -316,7 +313,6 @@ private void exportGameCrashInfo() { var dialog = new MessageDialogPane.Builder(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), i18n("message.error"), MessageDialogPane.MessageType.ERROR).ok(null).build(); DialogUtils.show(stackPane, dialog); } - spinnerPane.hideSpinner(); return null; }, Schedulers.javafx()); } @@ -448,11 +444,16 @@ private final class View extends VBox { HBox toolBar = new HBox(); VBox.setMargin(toolBar, new Insets(0, 0, 4, 0)); { + SpinnerPane exportButtonPane = new SpinnerPane(); + exportButtonPane.getStyleClass().add("small-spinner-pane"); + JFXButton exportButton = FXUtils.newRaisedButton(i18n("logwindow.export_game_crash_logs")); - spinnerPane.setContent(exportButton); + exportButtonPane.setContent(exportButton); exportButton.setOnAction(e -> { - spinnerPane.showSpinner(); - exportGameCrashInfo(); + exportButtonPane.showSpinner(); + exportGameCrashInfo().whenCompleteAsync((result, exception) -> { + exportButtonPane.hideSpinner(); + }, Schedulers.javafx()); }); JFXButton logButton = FXUtils.newRaisedButton(i18n("logwindow.title")); @@ -465,7 +466,7 @@ private final class View extends VBox { toolBar.setPadding(new Insets(8)); toolBar.setSpacing(8); toolBar.getStyleClass().add("jfx-tool-bar"); - toolBar.getChildren().setAll(spinnerPane, logButton, helpButton); + toolBar.getChildren().setAll(exportButtonPane, logButton, helpButton); } getChildren().setAll(titlePane, infoPane, moddedPane, gameDirPane, toolBar); From f15f394b037bf0d89bf77c9f77532b741379a4b1 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 21 Mar 2026 22:35:16 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD=E7=9A=84=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=92=8C=E5=8A=A0=E8=BD=BD=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jackhuang/hmcl/ui/GameCrashWindow.java | 34 ++-- .../jackhuang/hmcl/ui/main/SettingsPage.java | 150 +++++++++--------- 2 files changed, 96 insertions(+), 88 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index aca3041d5a..e6e5c39300 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -274,7 +274,7 @@ private void showLogWindow() { logWindow.show(); } - private CompletableFuture exportGameCrashInfo() { + private CompletableFuture exportGameCrashInfo() { Path logFile = Paths.get("minecraft-exported-crash-info-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")) + ".zip").toAbsolutePath(); return CompletableFuture.supplyAsync(() -> @@ -302,19 +302,7 @@ private CompletableFuture exportGameCrashInfo() { return false; } }); - }) - .handleAsync((result, exception) -> { - if (exception == null) { - FXUtils.showFileInExplorer(logFile); - var dialog = new MessageDialogPane.Builder(i18n("settings.launcher.launcher_log.export.success", logFile), i18n("message.success"), MessageDialogPane.MessageType.SUCCESS).ok(null).build(); - DialogUtils.show(stackPane, dialog); - } else { - LOG.warning("Failed to export game crash info", exception); - var dialog = new MessageDialogPane.Builder(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), i18n("message.error"), MessageDialogPane.MessageType.ERROR).ok(null).build(); - DialogUtils.show(stackPane, dialog); - } - return null; - }, Schedulers.javafx()); + }).thenApply(ignored -> logFile); } private final class View extends VBox { @@ -453,6 +441,24 @@ private final class View extends VBox { exportButtonPane.showSpinner(); exportGameCrashInfo().whenCompleteAsync((result, exception) -> { exportButtonPane.hideSpinner(); + + if (exception == null) { + FXUtils.showFileInExplorer(result); + var dialog = new MessageDialogPane.Builder( + i18n("settings.launcher.launcher_log.export.success", result), + i18n("message.success"), + MessageDialogPane.MessageType.SUCCESS + ).ok(null).build(); + DialogUtils.show(stackPane, dialog); + } else { + LOG.warning("Failed to export game crash info", exception); + var dialog = new MessageDialogPane.Builder( + i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), + i18n("message.error"), + MessageDialogPane.MessageType.ERROR + ).ok(null).build(); + DialogUtils.show(stackPane, dialog); + } }, Schedulers.javafx()); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index ba195ed8bb..6489128cd6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -19,7 +19,6 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; -import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.beans.WeakInvalidationListener; import javafx.beans.binding.Bindings; @@ -46,6 +45,7 @@ import org.jackhuang.hmcl.upgrade.UpdateChecker; import org.jackhuang.hmcl.upgrade.UpdateHandler; import org.jackhuang.hmcl.util.AprilFools; +import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.i18n.SupportedLocale; @@ -61,12 +61,12 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import static org.jackhuang.hmcl.setting.ConfigHolder.config; -import static org.jackhuang.hmcl.util.Lang.thread; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -78,8 +78,6 @@ public final class SettingsPage extends ScrollPane { @SuppressWarnings("FieldCanBeLocal") private final InvalidationListener updateListener; - private final SpinnerPane spinnerPane = new SpinnerPane(); - public SettingsPage() { this.setFitToWidth(true); @@ -303,13 +301,31 @@ else if (locale.isSameLanguage(currentLocale)) if (LOG.getLogFile() == null) openLogFolderButton.setDisable(true); + SpinnerPane exportLogPane = new SpinnerPane(); + JFXButton logButton = FXUtils.newBorderButton(i18n("settings.launcher.launcher_log.export")); - spinnerPane.setContent(logButton); - logButton.setOnAction(e -> onExportLogs()); + exportLogPane.setContent(logButton); + logButton.setOnAction(e -> { + exportLogPane.showSpinner(); + onExportLogs().whenCompleteAsync((result, exception) -> { + exportLogPane.hideSpinner(); + if (exception == null) { + Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", result)); + FXUtils.showFileInExplorer(result); + } else { + LOG.warning("Failed to export logs", exception); + Controllers.dialog( + i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(exception), + null, + MessageType.ERROR + ); + } + }); + }); HBox buttonBox = new HBox(); buttonBox.setSpacing(10); - buttonBox.getChildren().addAll(openLogFolderButton, spinnerPane); + buttonBox.getChildren().addAll(openLogFolderButton, exportLogPane); BorderPane.setAlignment(buttonBox, Pos.CENTER_RIGHT); debugPane.setRight(buttonBox); @@ -381,93 +397,79 @@ private static boolean exportLogFile(ZipOutputStream output, } } - private void onExportLogs() { - spinnerPane.showSpinner(); - thread(() -> { + private CompletableFuture onExportLogs() { + return CompletableFuture.supplyAsync(Lang.wrap(() -> { String nameBase = "hmcl-exported-logs-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")); List recentLogFiles = LOG.findRecentLogFiles(5); Path outputFile; - try { - if (recentLogFiles.isEmpty()) { - outputFile = Metadata.CURRENT_DIRECTORY.resolve(nameBase + ".log"); + if (recentLogFiles.isEmpty()) { + outputFile = Metadata.CURRENT_DIRECTORY.resolve(nameBase + ".log"); - LOG.info("Exporting latest logs to " + outputFile); - try (OutputStream output = Files.newOutputStream(outputFile)) { - LOG.exportLogs(output); - } - } else { - outputFile = Metadata.CURRENT_DIRECTORY.resolve(nameBase + ".zip"); - - LOG.info("Exporting latest logs to " + outputFile); - - byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; - try (var os = Files.newOutputStream(outputFile); - var zos = new ZipOutputStream(os)) { - - Set entryNames = new HashSet<>(); - - for (Path path : recentLogFiles) { - String fileName = FileUtils.getName(path); - String extension = StringUtils.substringAfterLast(fileName, '.'); - - if ("gz".equals(extension) || "xz".equals(extension)) { - // If an exception occurs while decompressing the input file, we should - // ensure the input file and the current zip entry are closed, - // then copy the compressed file content as-is into a new entry in the zip file. - - InputStream input = null; - try { - input = Files.newInputStream(path); - input = "gz".equals(extension) - ? new GZIPInputStream(input) - : new XZInputStream(input); - } catch (Throwable ex) { - LOG.warning("Failed to open log file " + path, ex); - IOUtils.closeQuietly(input, ex); - input = null; - } - - String entryName = getEntryName(entryNames, StringUtils.substringBeforeLast(fileName, ".")); - if (input != null && exportLogFile(zos, path, entryName, input, buffer)) - continue; - } + LOG.info("Exporting latest logs to " + outputFile); + try (OutputStream output = Files.newOutputStream(outputFile)) { + LOG.exportLogs(output); + } + } else { + outputFile = Metadata.CURRENT_DIRECTORY.resolve(nameBase + ".zip"); + + LOG.info("Exporting latest logs to " + outputFile); - // Copy the log file content as-is into a new entry in the zip file. + byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; + try (var os = Files.newOutputStream(outputFile); + var zos = new ZipOutputStream(os)) { + + Set entryNames = new HashSet<>(); + + for (Path path : recentLogFiles) { + String fileName = FileUtils.getName(path); + String extension = StringUtils.substringAfterLast(fileName, '.'); + + if ("gz".equals(extension) || "xz".equals(extension)) { // If an exception occurs while decompressing the input file, we should - // ensure the input file and the current zip entry are closed. + // ensure the input file and the current zip entry are closed, + // then copy the compressed file content as-is into a new entry in the zip file. - InputStream input; + InputStream input = null; try { input = Files.newInputStream(path); + input = "gz".equals(extension) + ? new GZIPInputStream(input) + : new XZInputStream(input); } catch (Throwable ex) { LOG.warning("Failed to open log file " + path, ex); - continue; + IOUtils.closeQuietly(input, ex); + input = null; } - exportLogFile(zos, path, getEntryName(entryNames, fileName), input, buffer); + String entryName = getEntryName(entryNames, StringUtils.substringBeforeLast(fileName, ".")); + if (input != null && exportLogFile(zos, path, entryName, input, buffer)) + continue; + } + + // Copy the log file content as-is into a new entry in the zip file. + // If an exception occurs while decompressing the input file, we should + // ensure the input file and the current zip entry are closed. + + InputStream input; + try { + input = Files.newInputStream(path); + } catch (Throwable ex) { + LOG.warning("Failed to open log file " + path, ex); + continue; } - zos.putNextEntry(new ZipEntry(getEntryName(entryNames, "hmcl-latest.log"))); - LOG.exportLogs(zos); - zos.closeEntry(); + exportLogFile(zos, path, getEntryName(entryNames, fileName), input, buffer); } + + zos.putNextEntry(new ZipEntry(getEntryName(entryNames, "hmcl-latest.log"))); + LOG.exportLogs(zos); + zos.closeEntry(); } - } catch (IOException e) { - LOG.warning("Failed to export logs", e); - Platform.runLater(() -> { - spinnerPane.hideSpinner(); - Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + StringUtils.getStackTrace(e), null, MessageType.ERROR); - }); - return; } - Platform.runLater(() -> { - spinnerPane.hideSpinner(); - Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", outputFile)); - }); - FXUtils.showFileInExplorer(outputFile); - }); + return outputFile; + })); } private void onSponsor() { From 9f0cab550bd57010299b13cfac1bf679c6df032c Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 21 Mar 2026 22:41:34 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=BC=82=E6=AD=A5=E4=BB=BB=E5=8A=A1=E8=B0=83?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index 6489128cd6..7444b9cfc1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -35,6 +35,7 @@ import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; @@ -320,7 +321,7 @@ else if (locale.isSameLanguage(currentLocale)) MessageType.ERROR ); } - }); + }, Schedulers.javafx()); }); HBox buttonBox = new HBox(); From f38cfaaa8c610b26b8b83eb31a699d2cb11a64fe Mon Sep 17 00:00:00 2001 From: Glavo Date: Mon, 23 Mar 2026 21:59:03 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=97=A5=E5=BF=97=E5=AF=BC=E5=87=BA=E7=9A=84?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E8=B0=83=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index 7444b9cfc1..be4f349e55 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -470,7 +470,7 @@ private CompletableFuture onExportLogs() { } return outputFile; - })); + }), Schedulers.io()); } private void onSponsor() {