@@ -30,21 +30,33 @@ import javafx.scene.paint.Color;
|
|||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
import org.jackhuang.hmcl.Metadata;
|
import org.jackhuang.hmcl.Metadata;
|
||||||
import org.jackhuang.hmcl.setting.*;
|
import org.jackhuang.hmcl.setting.*;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||||
import org.jackhuang.hmcl.ui.construct.Validator;
|
import org.jackhuang.hmcl.ui.construct.Validator;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.upgrade.RemoteVersion;
|
import org.jackhuang.hmcl.upgrade.RemoteVersion;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateChannel;
|
import org.jackhuang.hmcl.upgrade.UpdateChannel;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
||||||
import org.jackhuang.hmcl.upgrade.UpdateHandler;
|
import org.jackhuang.hmcl.upgrade.UpdateHandler;
|
||||||
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
import org.jackhuang.hmcl.util.i18n.Locales;
|
import org.jackhuang.hmcl.util.i18n.Locales;
|
||||||
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
|
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
|
||||||
|
|
||||||
|
import java.awt.Desktop;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
||||||
|
import static org.jackhuang.hmcl.util.Lang.thread;
|
||||||
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reservedSelectedPropertyFor;
|
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reservedSelectedPropertyFor;
|
||||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
||||||
@@ -201,8 +213,29 @@ public final class SettingsPage extends SettingsView implements DecoratorPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onOpenLogFolder() {
|
protected void onExportLogs() {
|
||||||
FXUtils.openFolder(Metadata.HMCL_DIRECTORY.resolve("logs").toFile());
|
// We cannot determine which file is JUL using.
|
||||||
|
// So we write all the logs to a new file.
|
||||||
|
thread(() -> {
|
||||||
|
Path logFile = Paths.get("hmcl-exported-logs-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")) + ".log").toAbsolutePath();
|
||||||
|
|
||||||
|
LOG.info("Exporting logs to " + logFile);
|
||||||
|
try {
|
||||||
|
Files.write(logFile, Logging.getRawLogs());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + e, null, MessageBox.ERROR_MESSAGE));
|
||||||
|
LOG.log(Level.WARNING, "Failed to export logs", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", logFile)));
|
||||||
|
if (Desktop.isDesktopSupported()) {
|
||||||
|
try {
|
||||||
|
Desktop.getDesktop().open(logFile.toFile());
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import org.jackhuang.hmcl.setting.EnumBackgroundImage;
|
|||||||
import org.jackhuang.hmcl.setting.EnumCommonDirectory;
|
import org.jackhuang.hmcl.setting.EnumCommonDirectory;
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
import org.jackhuang.hmcl.ui.construct.*;
|
import org.jackhuang.hmcl.ui.construct.*;
|
||||||
import org.jackhuang.hmcl.util.i18n.I18n;
|
|
||||||
import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale;
|
import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale;
|
||||||
|
|
||||||
public abstract class SettingsView extends StackPane {
|
public abstract class SettingsView extends StackPane {
|
||||||
@@ -337,8 +336,8 @@ public abstract class SettingsView extends StackPane {
|
|||||||
logPane.setTitle(i18n("settings.launcher.log"));
|
logPane.setTitle(i18n("settings.launcher.log"));
|
||||||
|
|
||||||
{
|
{
|
||||||
JFXButton logButton = new JFXButton(i18n("settings.launcher.log.dir"));
|
JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export"));
|
||||||
logButton.setOnMouseClicked(e -> onOpenLogFolder());
|
logButton.setOnMouseClicked(e -> onExportLogs());
|
||||||
logButton.getStyleClass().setAll("jfx-button-border");
|
logButton.getStyleClass().setAll("jfx-button-border");
|
||||||
|
|
||||||
logPane.setHeaderRight(logButton);
|
logPane.setHeaderRight(logButton);
|
||||||
@@ -492,5 +491,5 @@ public abstract class SettingsView extends StackPane {
|
|||||||
|
|
||||||
protected abstract void onUpdate();
|
protected abstract void onUpdate();
|
||||||
protected abstract void onHelp();
|
protected abstract void onHelp();
|
||||||
protected abstract void onOpenLogFolder();
|
protected abstract void onExportLogs();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,9 +326,11 @@ settings.launcher.common_path.tooltip=This app will save all game libraries and
|
|||||||
settings.launcher.download_source=Download Source
|
settings.launcher.download_source=Download Source
|
||||||
settings.launcher.enable_game_list=Display game list in main page
|
settings.launcher.enable_game_list=Display game list in main page
|
||||||
settings.launcher.language=Language
|
settings.launcher.language=Language
|
||||||
|
settings.launcher.launcher_log.export=Export launcher logs
|
||||||
|
settings.launcher.launcher_log.export.failed=Failed to export logs
|
||||||
|
settings.launcher.launcher_log.export.success=Logs have been exported to %s
|
||||||
settings.launcher.log=Log
|
settings.launcher.log=Log
|
||||||
settings.launcher.log.font=Log Font
|
settings.launcher.log.font=Log Font
|
||||||
settings.launcher.log.dir=Open Log Directory
|
|
||||||
settings.launcher.proxy=Proxy
|
settings.launcher.proxy=Proxy
|
||||||
settings.launcher.proxy.authentication=Proxy Authentication
|
settings.launcher.proxy.authentication=Proxy Authentication
|
||||||
settings.launcher.proxy.disable=Use system proxies
|
settings.launcher.proxy.disable=Use system proxies
|
||||||
|
|||||||
@@ -326,9 +326,11 @@ settings.launcher.common_path.tooltip=啟動器將所有遊戲資源及依賴庫
|
|||||||
settings.launcher.download_source=下載來源
|
settings.launcher.download_source=下載來源
|
||||||
settings.launcher.enable_game_list=在首頁內顯示遊戲列表
|
settings.launcher.enable_game_list=在首頁內顯示遊戲列表
|
||||||
settings.launcher.language=語言
|
settings.launcher.language=語言
|
||||||
|
settings.launcher.launcher_log.export=導出啟動器日誌
|
||||||
|
settings.launcher.launcher_log.export.failed=無法導出日誌
|
||||||
|
settings.launcher.launcher_log.export.success=日誌已保存到 %s
|
||||||
settings.launcher.log=記錄
|
settings.launcher.log=記錄
|
||||||
settings.launcher.log.font=記錄字體
|
settings.launcher.log.font=記錄字體
|
||||||
settings.launcher.log.dir=打開記錄資料夾
|
|
||||||
settings.launcher.proxy=代理
|
settings.launcher.proxy=代理
|
||||||
settings.launcher.proxy.authentication=身份驗證
|
settings.launcher.proxy.authentication=身份驗證
|
||||||
settings.launcher.proxy.disable=使用系統代理
|
settings.launcher.proxy.disable=使用系統代理
|
||||||
|
|||||||
@@ -326,9 +326,11 @@ settings.launcher.common_path.tooltip=启动器将所有游戏资源及依赖库
|
|||||||
settings.launcher.download_source=下载源
|
settings.launcher.download_source=下载源
|
||||||
settings.launcher.enable_game_list=在主页内显示游戏列表
|
settings.launcher.enable_game_list=在主页内显示游戏列表
|
||||||
settings.launcher.language=语言
|
settings.launcher.language=语言
|
||||||
|
settings.launcher.launcher_log.export=导出启动器日志
|
||||||
|
settings.launcher.launcher_log.export.failed=无法导出日志
|
||||||
|
settings.launcher.launcher_log.export.success=日志已保存到 %s
|
||||||
settings.launcher.log=日志
|
settings.launcher.log=日志
|
||||||
settings.launcher.log.font=日志字体
|
settings.launcher.log.font=日志字体
|
||||||
settings.launcher.log.dir=打开日志文件夹
|
|
||||||
settings.launcher.proxy=代理
|
settings.launcher.proxy=代理
|
||||||
settings.launcher.proxy.authentication=身份验证
|
settings.launcher.proxy.authentication=身份验证
|
||||||
settings.launcher.proxy.disable=使用系统代理
|
settings.launcher.proxy.disable=使用系统代理
|
||||||
|
|||||||
@@ -32,21 +32,16 @@ import java.util.logging.*;
|
|||||||
*/
|
*/
|
||||||
public final class Logging {
|
public final class Logging {
|
||||||
|
|
||||||
public static final Logger LOG;
|
public static final Logger LOG = Logger.getLogger("HMCL");
|
||||||
private static final ByteArrayOutputStream OUTPUT_STREAM = new ByteArrayOutputStream();
|
private static ByteArrayOutputStream storedLogs = new ByteArrayOutputStream();
|
||||||
|
|
||||||
static {
|
|
||||||
LOG = Logger.getLogger("HMCL");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void start(Path logFolder) {
|
public static void start(Path logFolder) {
|
||||||
LOG.setLevel(Level.FINER);
|
LOG.setLevel(Level.ALL);
|
||||||
LOG.setUseParentHandlers(false);
|
LOG.setUseParentHandlers(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(logFolder);
|
Files.createDirectories(logFolder);
|
||||||
FileHandler fileHandler = new FileHandler(logFolder.resolve("hmcl.log").toAbsolutePath().toString());
|
FileHandler fileHandler = new FileHandler(logFolder.resolve("hmcl.log").toAbsolutePath().toString());
|
||||||
fileHandler.setLevel(Level.FINEST);
|
|
||||||
fileHandler.setFormatter(DefaultFormatter.INSTANCE);
|
fileHandler.setFormatter(DefaultFormatter.INSTANCE);
|
||||||
LOG.addHandler(fileHandler);
|
LOG.addHandler(fileHandler);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -54,31 +49,28 @@ public final class Logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConsoleHandler consoleHandler = new ConsoleHandler();
|
ConsoleHandler consoleHandler = new ConsoleHandler();
|
||||||
consoleHandler.setLevel(Level.FINER);
|
|
||||||
consoleHandler.setFormatter(DefaultFormatter.INSTANCE);
|
consoleHandler.setFormatter(DefaultFormatter.INSTANCE);
|
||||||
LOG.addHandler(consoleHandler);
|
LOG.addHandler(consoleHandler);
|
||||||
|
|
||||||
StreamHandler streamHandler = new StreamHandler(OUTPUT_STREAM, DefaultFormatter.INSTANCE) {
|
StreamHandler streamHandler = new StreamHandler(storedLogs, DefaultFormatter.INSTANCE) {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void publish(LogRecord record) {
|
public synchronized void publish(LogRecord record) {
|
||||||
super.publish(record);
|
super.publish(record);
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
streamHandler.setLevel(Level.FINEST);
|
|
||||||
LOG.addHandler(streamHandler);
|
LOG.addHandler(streamHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stop() {
|
public static byte[] getRawLogs() {
|
||||||
for (Handler handler : LOG.getHandlers())
|
return storedLogs.toByteArray();
|
||||||
LOG.removeHandler(handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getLogs() {
|
public static String getLogs() {
|
||||||
return OUTPUT_STREAM.toString();
|
return storedLogs.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class DefaultFormatter extends Formatter {
|
private static final class DefaultFormatter extends Formatter {
|
||||||
|
|
||||||
static final DefaultFormatter INSTANCE = new DefaultFormatter();
|
static final DefaultFormatter INSTANCE = new DefaultFormatter();
|
||||||
private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
|
private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
|||||||
Reference in New Issue
Block a user