feat: add comprehensive diagnostic logging subsystem and UI controls

This commit is contained in:
CAtlas0784 committed 2026-10-30 23:08:23 +07:00
1 parent 517436321b
commit 5f45841936
15 files changed
+495 -23

No files matched your search

+41 -1
View File
@@ -2,6 +2,7 @@ import { CheckUpdateLauncher } from "@/helper"
import useModalStore from "@/stores/modalStore"
import useSettingStore from "@/stores/settingStore"
import useLauncherStore from "@/stores/launcherStore"
import { FSService } from "@bindings/g-launcher/internal/fs-service"
import { toast } from "react-toastify"
import { useTranslation } from "react-i18next"
@@ -91,8 +92,47 @@ export default function SettingModal({
</label>
</div>
{/* Section 3: Diagnostic Logs */}
<div className="p-4 bg-base-200 rounded-xl border border-cyan-500/40 shadow-sm">
<h4 className="font-bold text-lg mb-1 flex items-center gap-2">
<span>📋</span>
<span>Diagnostic Logs</span>
</h4>
<p className="text-xs text-white/70 mb-3">
เปิดโฟลเดอร์หรือคัดลอก Log เพื่อส่งให้ทีมพัฒนาช่วยวิเคราะห์ปัญหาการเข้าเกม
</p>
<div className="flex flex-wrap gap-2">
<button
className="btn btn-sm btn-info text-white shadow"
onClick={async () => {
const [ok, err] = await FSService.OpenLogsFolder()
if (!ok) toast.error("Failed to open logs: " + err)
}}
>
📂 เปิดโฟลเดอร์ Log
</button>
<button
className="btn btn-sm btn-outline btn-secondary"
onClick={async () => {
try {
const [logs, err] = await FSService.ReadLogs(200)
if (err) {
toast.error("Failed to read logs: " + err)
return
}
await navigator.clipboard.writeText(logs)
toast.success("คัดลอก Log 200 บรรทัดล่าสุดเรียบร้อย!")
} catch (e: any) {
toast.error("Cannot copy logs: " + e)
}
}}
>
📋 คัดลอก Log ล่าสุด
</button>
</div>
</div>
{/* Section 3: Launcher Version */}
{/* Section 4: Launcher Version */}
<div className="p-4 bg-base-200 rounded-xl border border-purple-300 shadow-sm">
<h4 className="font-bold text-lg mb-2">{t("setting.version_label")}</h4>
<div className="flex flex-wrap gap-2">
+48 -4
View File
@@ -158,22 +158,29 @@ export default function LauncherPage() {
try {
setIsLoading(true)
const basePath = await FSService.PickFile("exe")
await FSService.LogMessage("INFO", "handlePickFile: selected file=" + basePath)
if (basePath.endsWith("StarRail.exe") || basePath.endsWith("launcher.exe")) {
const normalized = basePath.replace(/\\/g, '/')
const normalized = basePath.replace(/\\/g, "/")
const folderPath = path.dirname(normalized)
const fullPath = `${folderPath}/StarRail_Data/StreamingAssets/DesignData/Windows`
const fullPath = folderPath + "/StarRail_Data/StreamingAssets/DesignData/Windows"
const exists = await FSService.DirExists(fullPath)
await FSService.LogMessage("INFO", "handlePickFile: folderPath=" + folderPath + ", DesignData exists=" + exists)
if (!exists) {
await FSService.LogMessage("WARN", "handlePickFile: DesignData not found at " + fullPath)
toast.error(t("home.error_game_dir"))
} else {
setGamePath(basePath)
setGameDir(folderPath)
await FSService.SaveGameSelection(basePath, folderPath)
toast.success(t("home.game_path_success"))
}
} else {
await FSService.LogMessage("WARN", "handlePickFile: invalid file type: " + basePath)
toast.error(t("home.error_file_type"))
}
} catch (err: any) {
const errStr = err?.stack || err?.message || String(err)
await FSService.LogMessage("ERROR", "handlePickFile error: " + errStr)
toast.error(t("home.toast_pick_folder_error"), err)
} finally {
setIsLoading(false)
@@ -181,21 +188,27 @@ export default function LauncherPage() {
}
const handleStartGame = async () => {
await FSService.LogMessage("INFO", "handleStartGame initiated: selectedServer=" + selectedServer + ", gamePath=" + gamePath + ", serverPath=" + serverPath + ", proxyPath=" + proxyPath)
if (!gamePath) {
await FSService.LogMessage("WARN", "handleStartGame aborted: gamePath is empty")
toast.info("Please select the game executable first")
return
}
if (gameRunning) {
await FSService.LogMessage("WARN", "handleStartGame aborted: game is already marked as running")
return
}
try {
setIsLoading(true)
if (selectedServer === "gacy-ps") {
await FSService.LogMessage("INFO", "handleStartGame: querying GaCy PS server executables...")
const [gameServer, sdkServer] = await GitService.FindServerExecutables()
const activeServer = gameServer || serverPath
await FSService.LogMessage("INFO", "handleStartGame: found gameServer=" + gameServer + ", sdkServer=" + sdkServer + ", activeServer=" + activeServer)
if (!activeServer) {
await FSService.LogMessage("ERROR", "handleStartGame: activeServer missing. Opening download modal.")
toast.error("Please download GaCy PS server files first")
setIsOpenDownloadDataModal(true)
return
@@ -203,12 +216,16 @@ export default function LauncherPage() {
// 1. Start Proxy
const activeProxy = proxyPath || "./proxy/firefly-go-proxy.exe"
await FSService.LogMessage("INFO", "handleStartGame: activeProxy=" + activeProxy + ", proxyRunning=" + proxyRunning)
if (!proxyRunning && !gamePath.endsWith("launcher.exe")) {
await FSService.LogMessage("INFO", "handleStartGame: starting proxy via StartWithConsole(" + activeProxy + ")")
const [resultProxy, error] = await FSService.StartWithConsole(activeProxy)
if (!resultProxy) {
await FSService.LogMessage("ERROR", "handleStartGame: proxy start failed: " + error)
toast.error(t("home.toast_start_proxy_failed") + ": " + error)
return
}
await FSService.LogMessage("INFO", "handleStartGame: proxy started successfully")
setProxyRunning(true)
}
await sleep(500)
@@ -216,39 +233,56 @@ export default function LauncherPage() {
// 2. Start SDK Server if exists
const activeSdk = sdkServer || sdkServerPath
if (activeSdk) {
await FSService.StartWithConsole(activeSdk)
await FSService.LogMessage("INFO", "handleStartGame: starting SDK server via StartWithConsole(" + activeSdk + ")")
const [resultSdk, sdkErr] = await FSService.StartWithConsole(activeSdk)
if (!resultSdk) {
await FSService.LogMessage("WARN", "handleStartGame: SDK server start warning: " + sdkErr)
} else {
await FSService.LogMessage("INFO", "handleStartGame: SDK server started successfully")
}
await sleep(400)
}
// 3. Start Game Server
if (!serverRunning) {
await FSService.LogMessage("INFO", "handleStartGame: starting Game server via StartWithConsole(" + activeServer + ")")
const [resultServer, error] = await FSService.StartWithConsole(activeServer)
if (!resultServer) {
await FSService.LogMessage("ERROR", "handleStartGame: Game server start failed: " + error)
toast.error(t("home.toast_start_server_failed") + ": " + error)
return
}
await FSService.LogMessage("INFO", "handleStartGame: Game server started successfully")
setServerRunning(true)
}
await sleep(1000)
} else {
await FSService.LogMessage("INFO", "handleStartGame: running in Official Server mode (no proxy/PS)")
}
// 4. Start Game
await FSService.LogMessage("INFO", "handleStartGame: starting game binary: " + gamePath)
if (gamePath.endsWith("launcher.exe")) {
const [resultGame, error] = await FSService.StartWithConsole(gamePath)
if (!resultGame) {
await FSService.LogMessage("ERROR", "handleStartGame: StartWithConsole game failed: " + error)
toast.error(t("home.toast_start_game_failed") + ": " + error)
return
}
} else {
const [resultGame, error] = await FSService.StartApp(gamePath)
if (!resultGame) {
await FSService.LogMessage("ERROR", "handleStartGame: StartApp game failed: " + error)
toast.error(t("home.toast_start_game_failed") + ": " + error)
return
}
}
await FSService.LogMessage("INFO", "handleStartGame: Game process started successfully!")
setGameRunning(true)
} catch (err: any) {
const errStr = err?.stack || err?.message || String(err)
await FSService.LogMessage("ERROR", "handleStartGame uncaught exception: " + errStr)
console.log(err)
toast.error(t("home.toast_start_game_error"), err)
} finally {
@@ -256,7 +290,6 @@ export default function LauncherPage() {
}
}
const handlerUpdateData = async () => {
setIsDownloading(true)
if (updateData.launcher.isUpdate) {
@@ -486,6 +519,17 @@ export default function LauncherPage() {
{t("home.menu_open_voice")}
</button>
</li>
<li>
<button onClick={async () => {
const [ok, err] = await FSService.OpenLogsFolder()
if (!ok) {
toast.error("Failed to open logs: " + err)
}
}}
>
📋 {t("home.menu_open_logs") || "Open Logs"}
</button>
</li>
</ul>
</div>
</div>