0.1.0-1-alpha.2-fix.3
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/bridge.ts
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
@@ -10,3 +10,7 @@ export async function getRuntimeLabel(): Promise<string> {
|
||||
export async function notifyFrontendReady(): Promise<void> {
|
||||
await invoke("frontend_ready");
|
||||
}
|
||||
|
||||
export async function closeMainWindow(): Promise<void> {
|
||||
await invoke("close_main_window");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/game.ts
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
import init, { ReflexWasmGame } from "../wasm/game_reflex_poc_wasm.js";
|
||||
import { tracingDebug, tracingTrace } from "./logging";
|
||||
@@ -37,7 +37,7 @@ function render(game: ReflexWasmGame, canvas: HTMLCanvasElement, context: Canvas
|
||||
score.value = `Score : ${game.score()}`;
|
||||
}
|
||||
|
||||
export async function startGame(canvas: HTMLCanvasElement, score: HTMLOutputElement): Promise<void> {
|
||||
export async function startGame(canvas: HTMLCanvasElement, score: HTMLOutputElement): Promise<ReflexWasmGame> {
|
||||
await init();
|
||||
await tracingDebug("Reflex WASM module initialized");
|
||||
const context = canvas.getContext("2d");
|
||||
@@ -64,4 +64,5 @@ export async function startGame(canvas: HTMLCanvasElement, score: HTMLOutputElem
|
||||
}
|
||||
render(game, canvas, context, score);
|
||||
window.requestAnimationFrame(frame);
|
||||
return game;
|
||||
}
|
||||
|
||||
@@ -1,38 +1,98 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/logging.ts
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
import { attachConsole, debug, error, info, trace, warn } from "@fltsci/tauri-plugin-tracing";
|
||||
import { attachConsole } from "@fltsci/tauri-plugin-tracing";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
let detachRustConsole: (() => void) | null = null;
|
||||
export type FrontendLogLevel = "trace" | "debug" | "info" | "warn" | "error";
|
||||
export type FrontendLogTarget = "frontend" | "main";
|
||||
|
||||
export async function initializeTracing(): Promise<void> {
|
||||
detachRustConsole = await attachConsole();
|
||||
await info("Reflex Tauri frontend tracing initialized", "games::tauri::reflex::frontend");
|
||||
}
|
||||
type ConsoleMethod = (...items: unknown[]) => void;
|
||||
|
||||
export async function tracingTrace(message: string): Promise<void> {
|
||||
await trace(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
const originalConsole = {
|
||||
trace: console.trace.bind(console),
|
||||
debug: console.debug.bind(console),
|
||||
info: console.info.bind(console),
|
||||
warn: console.warn.bind(console),
|
||||
error: console.error.bind(console),
|
||||
};
|
||||
|
||||
export async function tracingDebug(message: string): Promise<void> {
|
||||
await debug(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingInfo(message: string): Promise<void> {
|
||||
await info(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingWarn(message: string): Promise<void> {
|
||||
await warn(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingError(message: string): Promise<void> {
|
||||
await error(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export function detachTracingConsole(): void {
|
||||
if (detachRustConsole !== null) {
|
||||
detachRustConsole();
|
||||
detachRustConsole = null;
|
||||
function stringifyItem(item: unknown): string {
|
||||
if (item instanceof Error) {
|
||||
return item.stack ?? item.message;
|
||||
}
|
||||
if (typeof item === "string") {
|
||||
return item;
|
||||
}
|
||||
try {
|
||||
const serialized = JSON.stringify(item);
|
||||
return serialized ?? String(item);
|
||||
} catch {
|
||||
return String(item);
|
||||
}
|
||||
}
|
||||
|
||||
function formatMessage(items: unknown[]): string {
|
||||
return items.map(item => stringifyItem(item)).join(" ");
|
||||
}
|
||||
|
||||
async function sendFrontendLog(level: FrontendLogLevel, targetId: FrontendLogTarget, message: string): Promise<void> {
|
||||
await invoke("emit_frontend_log", {
|
||||
payload: {
|
||||
level,
|
||||
targetId,
|
||||
message,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function originalConsoleFor(level: FrontendLogLevel): ConsoleMethod {
|
||||
return level === "trace"
|
||||
? originalConsole.trace
|
||||
: level === "debug"
|
||||
? originalConsole.debug
|
||||
: level === "info"
|
||||
? originalConsole.info
|
||||
: level === "warn"
|
||||
? originalConsole.warn
|
||||
: originalConsole.error;
|
||||
}
|
||||
|
||||
export async function initializeTracing(): Promise<void> {
|
||||
await attachConsole();
|
||||
await emitFrontendLog("info", "main", "Reflex Tauri frontend tracing initialized");
|
||||
}
|
||||
|
||||
export async function emitFrontendLog(level: FrontendLogLevel, targetId: FrontendLogTarget, ...items: unknown[]): Promise<void> {
|
||||
const message = formatMessage(items);
|
||||
originalConsoleFor(level)(message);
|
||||
await sendFrontendLog(level, targetId, message);
|
||||
}
|
||||
|
||||
function emitDetached(level: FrontendLogLevel, targetId: FrontendLogTarget, items: unknown[]): void {
|
||||
const message = formatMessage(items);
|
||||
originalConsoleFor(level)(message);
|
||||
void sendFrontendLog(level, targetId, message).catch(caughtError => {
|
||||
originalConsole.error("Reflex frontend logging bridge failed", caughtError);
|
||||
});
|
||||
}
|
||||
|
||||
export function tracingTrace(...items: unknown[]): void {
|
||||
emitDetached("trace", "frontend", items);
|
||||
}
|
||||
|
||||
export function tracingDebug(...items: unknown[]): void {
|
||||
emitDetached("debug", "frontend", items);
|
||||
}
|
||||
|
||||
export function tracingInfo(...items: unknown[]): void {
|
||||
emitDetached("info", "frontend", items);
|
||||
}
|
||||
|
||||
export function tracingWarn(...items: unknown[]): void {
|
||||
emitDetached("warn", "frontend", items);
|
||||
}
|
||||
|
||||
export function tracingError(...items: unknown[]): void {
|
||||
emitDetached("error", "frontend", items);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/main.ts
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
import { getRuntimeLabel, notifyFrontendReady } from "./bridge";
|
||||
import { closeMainWindow, getRuntimeLabel, notifyFrontendReady } from "./bridge";
|
||||
import { startGame } from "./game";
|
||||
import { initializeTracing, tracingError, tracingInfo } from "./logging";
|
||||
|
||||
@@ -14,12 +14,23 @@ async function main(): Promise<void> {
|
||||
throw new Error("Reflex Tauri frontend DOM is incomplete");
|
||||
}
|
||||
runtime.value = await getRuntimeLabel();
|
||||
await startGame(canvas, score);
|
||||
const game = await startGame(canvas, score);
|
||||
window.addEventListener("keydown", event => {
|
||||
if (event.key !== "Escape" || event.repeat) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
const shouldExit = game.quit_requested_escape();
|
||||
tracingInfo(`quit requested source=escape decision=${shouldExit ? "exit" : "continue"}`);
|
||||
if (shouldExit) {
|
||||
void closeMainWindow().catch(caughtError => tracingError("Tauri close command failed", caughtError));
|
||||
}
|
||||
});
|
||||
await notifyFrontendReady();
|
||||
await tracingInfo("Reflex Tauri frontend started");
|
||||
tracingInfo("Reflex Tauri frontend started");
|
||||
}
|
||||
|
||||
void main().catch(async caughtError => {
|
||||
void main().catch(caughtError => {
|
||||
const message = caughtError instanceof Error ? caughtError.stack ?? caughtError.message : String(caughtError);
|
||||
await tracingError(`Reflex Tauri frontend startup failed: ${message}`);
|
||||
tracingError(`Reflex Tauri frontend startup failed: ${message}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user