0.1.0-1-alpha.2-fix.3
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
// file: Android/game-reflex-poc/build.gradle
|
// file: Android/game-reflex-poc/build.gradle
|
||||||
// version: 13
|
// version: 14
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
@@ -18,7 +18,7 @@ android {
|
|||||||
minSdk 21
|
minSdk 21
|
||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName '0.1.0-1-alpha.2.fix.2'
|
versionName '0.1.0-1-alpha.2.fix.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: Android/game-snake-poc/build.gradle
|
// file: Android/game-snake-poc/build.gradle
|
||||||
// version: 13
|
// version: 14
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
@@ -18,7 +18,7 @@ android {
|
|||||||
minSdk 21
|
minSdk 21
|
||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName '0.1.0-1-alpha.2.fix.2'
|
versionName '0.1.0-1-alpha.2.fix.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 30
|
# version: 31
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
@@ -19,7 +19,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0-1-alpha.2.fix.2"
|
version = "0.1.0-1-alpha.2.fix.3"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/games"
|
repository = "https://git.sasedev.com/Sasedev/games"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# file: crates/apps/game-reflex-poc-tauri/Cargo.toml
|
# file: crates/apps/game-reflex-poc-tauri/Cargo.toml
|
||||||
# version: 3
|
# version: 4
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "game-reflex-poc-tauri"
|
name = "game-reflex-poc-tauri"
|
||||||
@@ -23,6 +23,7 @@ path = "src/main.rs"
|
|||||||
tauri-build.workspace = true
|
tauri-build.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
game-logging-lib = { path = "../../common/game-logging-lib" }
|
||||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||||
tauri.workspace = true
|
tauri.workspace = true
|
||||||
tauri-plugin-tracing.workspace = true
|
tauri-plugin-tracing.workspace = true
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/bridge.ts
|
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/bridge.ts
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
|
|
||||||
@@ -10,3 +10,7 @@ export async function getRuntimeLabel(): Promise<string> {
|
|||||||
export async function notifyFrontendReady(): Promise<void> {
|
export async function notifyFrontendReady(): Promise<void> {
|
||||||
await invoke("frontend_ready");
|
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
|
// 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 init, { ReflexWasmGame } from "../wasm/game_reflex_poc_wasm.js";
|
||||||
import { tracingDebug, tracingTrace } from "./logging";
|
import { tracingDebug, tracingTrace } from "./logging";
|
||||||
@@ -37,7 +37,7 @@ function render(game: ReflexWasmGame, canvas: HTMLCanvasElement, context: Canvas
|
|||||||
score.value = `Score : ${game.score()}`;
|
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 init();
|
||||||
await tracingDebug("Reflex WASM module initialized");
|
await tracingDebug("Reflex WASM module initialized");
|
||||||
const context = canvas.getContext("2d");
|
const context = canvas.getContext("2d");
|
||||||
@@ -64,4 +64,5 @@ export async function startGame(canvas: HTMLCanvasElement, score: HTMLOutputElem
|
|||||||
}
|
}
|
||||||
render(game, canvas, context, score);
|
render(game, canvas, context, score);
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
|
return game;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,98 @@
|
|||||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/logging.ts
|
// 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> {
|
type ConsoleMethod = (...items: unknown[]) => void;
|
||||||
detachRustConsole = await attachConsole();
|
|
||||||
await info("Reflex Tauri frontend tracing initialized", "games::tauri::reflex::frontend");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function tracingTrace(message: string): Promise<void> {
|
const originalConsole = {
|
||||||
await trace(message, "games::tauri::reflex::frontend");
|
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> {
|
function stringifyItem(item: unknown): string {
|
||||||
await debug(message, "games::tauri::reflex::frontend");
|
if (item instanceof Error) {
|
||||||
}
|
return item.stack ?? item.message;
|
||||||
|
}
|
||||||
export async function tracingInfo(message: string): Promise<void> {
|
if (typeof item === "string") {
|
||||||
await info(message, "games::tauri::reflex::frontend");
|
return item;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
export async function tracingWarn(message: string): Promise<void> {
|
const serialized = JSON.stringify(item);
|
||||||
await warn(message, "games::tauri::reflex::frontend");
|
return serialized ?? String(item);
|
||||||
}
|
} catch {
|
||||||
|
return String(item);
|
||||||
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 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
|
// 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 { startGame } from "./game";
|
||||||
import { initializeTracing, tracingError, tracingInfo } from "./logging";
|
import { initializeTracing, tracingError, tracingInfo } from "./logging";
|
||||||
|
|
||||||
@@ -14,12 +14,23 @@ async function main(): Promise<void> {
|
|||||||
throw new Error("Reflex Tauri frontend DOM is incomplete");
|
throw new Error("Reflex Tauri frontend DOM is incomplete");
|
||||||
}
|
}
|
||||||
runtime.value = await getRuntimeLabel();
|
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 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);
|
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}`);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "game-reflex-poc-tauri",
|
"name": "game-reflex-poc-tauri",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.0-1-alpha.2.fix.2",
|
"version": "0.1.0-1-alpha.2.fix.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/apps/game-reflex-poc-tauri/src/lib.rs
|
// file: crates/apps/game-reflex-poc-tauri/src/lib.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Tauri desktop application facade for the Reflex WebAssembly POC.
|
//! Tauri desktop application facade for the Reflex WebAssembly POC.
|
||||||
|
|
||||||
@@ -15,5 +15,7 @@ pub use self::tauri::run;
|
|||||||
|
|
||||||
/// Records that the Vite/TypeScript frontend reached its ready state.
|
/// Records that the Vite/TypeScript frontend reached its ready state.
|
||||||
pub(crate) use self::runtime::record_frontend_ready;
|
pub(crate) use self::runtime::record_frontend_ready;
|
||||||
|
/// Records one accepted native window close request.
|
||||||
|
pub(crate) use self::runtime::record_window_close;
|
||||||
/// Returns the runtime label exposed by the Tauri bridge.
|
/// Returns the runtime label exposed by the Tauri bridge.
|
||||||
pub(crate) use self::runtime::runtime_label;
|
pub(crate) use self::runtime::runtime_label;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/apps/game-reflex-poc-tauri/src/runtime.rs
|
// file: crates/apps/game-reflex-poc-tauri/src/runtime.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
/// Stable label for the current Tauri/WASM runtime combination.
|
/// Stable label for the current Tauri/WASM runtime combination.
|
||||||
pub(crate) fn runtime_label() -> &'static str {
|
pub(crate) fn runtime_label() -> &'static str {
|
||||||
@@ -16,3 +16,14 @@ pub(crate) fn record_frontend_ready() {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Records one accepted native window close request.
|
||||||
|
pub(crate) fn record_window_close(source: &str) {
|
||||||
|
tracing::info!(
|
||||||
|
target: "games::tauri::reflex",
|
||||||
|
action = "window_close",
|
||||||
|
source = source,
|
||||||
|
"Reflex Tauri window close accepted"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
// file: crates/apps/game-reflex-poc-tauri/src/tauri.rs
|
// file: crates/apps/game-reflex-poc-tauri/src/tauri.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
|
//! Tauri runtime assembly and Web/Rust commands for the Reflex POC.
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct FrontendLogPayload {
|
||||||
|
level: String,
|
||||||
|
target_id: String,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn get_runtime_label() -> String {
|
fn get_runtime_label() -> String {
|
||||||
@@ -12,6 +22,47 @@ fn frontend_ready() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn emit_frontend_log(payload: FrontendLogPayload) -> std::result::Result<(), String> {
|
||||||
|
let target_id = payload.target_id.trim();
|
||||||
|
if target_id != "frontend" && target_id != "main" {
|
||||||
|
return std::result::Result::Err("unsupported frontend log target".to_string());
|
||||||
|
}
|
||||||
|
let message = payload.message.as_str();
|
||||||
|
return match payload.level.trim().to_ascii_lowercase().as_str() {
|
||||||
|
"trace" => {
|
||||||
|
tracing::trace!(target: "games::tauri::reflex::frontend", action = "frontend_log", target_id = target_id, "{message}");
|
||||||
|
std::result::Result::Ok(())
|
||||||
|
},
|
||||||
|
"debug" => {
|
||||||
|
tracing::debug!(target: "games::tauri::reflex::frontend", action = "frontend_log", target_id = target_id, "{message}");
|
||||||
|
std::result::Result::Ok(())
|
||||||
|
},
|
||||||
|
"info" => {
|
||||||
|
tracing::info!(target: "games::tauri::reflex::frontend", action = "frontend_log", target_id = target_id, "{message}");
|
||||||
|
std::result::Result::Ok(())
|
||||||
|
},
|
||||||
|
"warn" => {
|
||||||
|
tracing::warn!(target: "games::tauri::reflex::frontend", action = "frontend_log", target_id = target_id, "{message}");
|
||||||
|
std::result::Result::Ok(())
|
||||||
|
},
|
||||||
|
"error" => {
|
||||||
|
tracing::error!(target: "games::tauri::reflex::frontend", action = "frontend_log", target_id = target_id, "{message}");
|
||||||
|
std::result::Result::Ok(())
|
||||||
|
},
|
||||||
|
_ => std::result::Result::Err("unsupported frontend log level".to_string()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn close_main_window(window: tauri::WebviewWindow) -> std::result::Result<(), String> {
|
||||||
|
crate::record_window_close("game_quit_decision");
|
||||||
|
return match window.close() {
|
||||||
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
|
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn configure_plugins(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
fn configure_plugins(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
||||||
let tracing_plugin = tauri_plugin_tracing::Builder::new().build::<tauri::Wry>();
|
let tracing_plugin = tauri_plugin_tracing::Builder::new().build::<tauri::Wry>();
|
||||||
return builder.plugin(tracing_plugin);
|
return builder.plugin(tracing_plugin);
|
||||||
@@ -19,11 +70,16 @@ fn configure_plugins(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<taur
|
|||||||
|
|
||||||
#[allow(clippy::question_mark_used)] // Tauri generates the question-mark operator internally for command dispatch.
|
#[allow(clippy::question_mark_used)] // Tauri generates the question-mark operator internally for command dispatch.
|
||||||
fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
||||||
return builder.invoke_handler(tauri::generate_handler![get_runtime_label, frontend_ready]);
|
return builder.invoke_handler(tauri::generate_handler![get_runtime_label, frontend_ready, emit_frontend_log, close_main_window]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the Reflex Tauri desktop application.
|
/// Runs the Reflex Tauri desktop application.
|
||||||
pub fn run() -> std::result::Result<(), String> {
|
pub fn run() -> std::result::Result<(), String> {
|
||||||
|
let logging_guard = game_logging_lib::init_console_tracing();
|
||||||
|
let _logging_guard = match logging_guard {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
|
||||||
|
};
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
target: "games::tauri::reflex",
|
target: "games::tauri::reflex",
|
||||||
action = "runtime_start",
|
action = "runtime_start",
|
||||||
@@ -33,7 +89,22 @@ pub fn run() -> std::result::Result<(), String> {
|
|||||||
let builder = configure_plugins(builder);
|
let builder = configure_plugins(builder);
|
||||||
let builder = configure_commands(builder);
|
let builder = configure_commands(builder);
|
||||||
return match builder.run(tauri::generate_context!()) {
|
return match builder.run(tauri::generate_context!()) {
|
||||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
std::result::Result::Ok(()) => {
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
|
tracing::info!(
|
||||||
|
target: "games::tauri::reflex",
|
||||||
|
action = "runtime_stop",
|
||||||
|
"Reflex Tauri runtime stopped"
|
||||||
|
);
|
||||||
|
std::result::Result::Ok(())
|
||||||
|
},
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
tracing::error!(
|
||||||
|
target: "games::tauri::reflex",
|
||||||
|
action = "runtime_error",
|
||||||
|
error = error.to_string(),
|
||||||
|
"Reflex Tauri runtime failed"
|
||||||
|
);
|
||||||
|
std::result::Result::Err(error.to_string())
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Reflex POC Tauri",
|
"productName": "Reflex POC Tauri",
|
||||||
"version": "0.1.0-1-alpha.2.fix.2",
|
"version": "0.1.0-1-alpha.2.fix.3",
|
||||||
"identifier": "com.sasedev.games.reflex.tauri",
|
"identifier": "com.sasedev.games.reflex.tauri",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": {
|
"beforeDevCommand": {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/apps/game-reflex-poc-wasm/src/runtime.rs
|
// file: crates/apps/game-reflex-poc-wasm/src/runtime.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
/// WebAssembly-owned Reflex game state consumed by the Tauri WebView.
|
/// WebAssembly-owned Reflex game state consumed by the Tauri WebView.
|
||||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||||
@@ -33,6 +33,12 @@ impl ReflexWasmGame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Routes the Escape key through the shared game's quit policy.
|
||||||
|
pub fn quit_requested_escape(&mut self) -> bool {
|
||||||
|
let request = engine_v1_common::QuitRequest::new(engine_v1_common::QuitSource::Escape);
|
||||||
|
return engine_v1_common::EngineGame::quit_requested(&mut self.state, request) == engine_v1_common::QuitDecision::Exit;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the current gameplay score.
|
/// Returns the current gameplay score.
|
||||||
pub fn score(&self) -> u32 {
|
pub fn score(&self) -> u32 {
|
||||||
return self.state.score().min(u32::MAX as u64) as u32;
|
return self.state.score().min(u32::MAX as u64) as u32;
|
||||||
|
|||||||
98
deltas/0.1.0/1-alpha.2.fix.3.md
Normal file
98
deltas/0.1.0/1-alpha.2.fix.3.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<!-- file: deltas/0.1.0/1-alpha.2.fix.3.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta 0.1.0-1-alpha.2.fix.3
|
||||||
|
|
||||||
|
## Base
|
||||||
|
|
||||||
|
Base déclarée : `0.1.0-1-alpha.2.fix.2`, gates techniques propres et smoke Tauri fonctionnel.
|
||||||
|
|
||||||
|
Deux défauts fonctionnels restent ouverts :
|
||||||
|
|
||||||
|
- aucun événement `tracing` n'est visible dans le terminal ;
|
||||||
|
- `Escape` ne produit aucune action dans la variante Tauri.
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
La variante Tauri dépend désormais de `game-logging-lib` et initialise :
|
||||||
|
|
||||||
|
```text
|
||||||
|
game_logging_lib::init_console_tracing()
|
||||||
|
```
|
||||||
|
|
||||||
|
avant le premier événement `tracing`.
|
||||||
|
|
||||||
|
Le frontend utilise son wrapper TypeScript :
|
||||||
|
|
||||||
|
```text
|
||||||
|
module TS
|
||||||
|
-> logging.ts
|
||||||
|
-> invoke("emit_frontend_log")
|
||||||
|
-> tauri.rs
|
||||||
|
-> tracing
|
||||||
|
-> game-logging-lib subscriber
|
||||||
|
-> terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
Le plugin `tauri-plugin-tracing` reste installé et `attachConsole()` conserve la direction Rust vers console WebView.
|
||||||
|
|
||||||
|
## Escape
|
||||||
|
|
||||||
|
La crate WASM expose :
|
||||||
|
|
||||||
|
```text
|
||||||
|
quit_requested_escape() -> bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette méthode appelle le contrat moteur :
|
||||||
|
|
||||||
|
```text
|
||||||
|
EngineGame::quit_requested(QuitRequest::new(QuitSource::Escape))
|
||||||
|
```
|
||||||
|
|
||||||
|
Le frontend invoque `close_main_window` seulement si la décision vaut `Exit`.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo fmt --all
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android deltas history
|
||||||
|
|
||||||
|
cargo check --workspace
|
||||||
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||||
|
|
||||||
|
cargo test -p game-logging-lib --all-targets --all-features
|
||||||
|
cargo test -p game-reflex-poc --all-targets --all-features
|
||||||
|
cargo test -p game-reflex-poc-wasm --all-targets --all-features
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gate WASM
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 scripts/build_reflex_tauri_wasm.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Smoke Tauri
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd crates/apps/game-reflex-poc-tauri
|
||||||
|
cargo tauri dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Des événements Rust et frontend doivent apparaître dans le terminal, notamment le démarrage du runtime et le ready frontend.
|
||||||
|
|
||||||
|
Presser ensuite `Escape`.
|
||||||
|
|
||||||
|
Attendus :
|
||||||
|
|
||||||
|
- événement frontend indiquant `source=escape` et la décision ;
|
||||||
|
- événement Rust `window close accepted` ;
|
||||||
|
- fermeture de la fenêtre ;
|
||||||
|
- retour propre au shell.
|
||||||
|
|
||||||
|
## Transition
|
||||||
|
|
||||||
|
Si les gates et le smoke passent, `0.1.0-1-alpha.2.fix.3` valide le POC Tauri/WASM avec logging visible et politique de sortie commune.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/development/008-WASM_TAURI_POC.md -->
|
<!-- file: docs/development/008-WASM_TAURI_POC.md -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
|
|
||||||
# POC WebAssembly embarqué dans Tauri
|
# POC WebAssembly embarqué dans Tauri
|
||||||
|
|
||||||
@@ -145,3 +145,27 @@ Le logging est unifié avec `tracing` :
|
|||||||
- capability `tracing:default`.
|
- capability `tracing:default`.
|
||||||
|
|
||||||
Les événements frontend utiles sont donc remontés dans le même système de traces que le backend Rust.
|
Les événements frontend utiles sont donc remontés dans le même système de traces que le backend Rust.
|
||||||
|
|
||||||
|
## Logging fix.3
|
||||||
|
|
||||||
|
Le plugin Tauri ne remplace pas l'initialisation du subscriber `tracing`.
|
||||||
|
|
||||||
|
`game-logging-lib::init_console_tracing()` installe le subscriber console avant le premier événement Tauri.
|
||||||
|
|
||||||
|
Le frontend possède un wrapper TypeScript unique qui invoque `emit_frontend_log`; Rust valide le niveau et la cible puis réémet l'événement avec `tracing`.
|
||||||
|
|
||||||
|
`attachConsole()` reste activé pour rendre également les événements Rust observables dans la console WebView.
|
||||||
|
|
||||||
|
## Escape fix.3
|
||||||
|
|
||||||
|
`Escape` suit désormais le contrat moteur commun :
|
||||||
|
|
||||||
|
```text
|
||||||
|
keydown Escape
|
||||||
|
-> ReflexWasmGame::quit_requested_escape()
|
||||||
|
-> EngineGame::quit_requested(QuitSource::Escape)
|
||||||
|
-> QuitDecision
|
||||||
|
-> close_main_window uniquement si Exit
|
||||||
|
```
|
||||||
|
|
||||||
|
Une future politique de pause/confirmation pourra retourner `Continue` sans modifier le bridge Tauri.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/rules/RULES_PROJECT.md -->
|
<!-- file: docs/rules/RULES_PROJECT.md -->
|
||||||
<!-- version: 6 -->
|
<!-- version: 7 -->
|
||||||
|
|
||||||
# Règles spécifiques games.sasedev
|
# Règles spécifiques games.sasedev
|
||||||
|
|
||||||
@@ -67,3 +67,6 @@
|
|||||||
- **GAME-PLATFORM-009** — Une adaptation WebAssembly réutilisable est une crate dédiée distincte de la crate Tauri.
|
- **GAME-PLATFORM-009** — Une adaptation WebAssembly réutilisable est une crate dédiée distincte de la crate Tauri.
|
||||||
- **GAME-PLATFORM-010** — Dans une app Tauri, `lib.rs` reste une façade/reexport ; `tauri.rs` assemble Tauri et expose les commandes qui délèguent aux modules propriétaires.
|
- **GAME-PLATFORM-010** — Dans une app Tauri, `lib.rs` reste une façade/reexport ; `tauri.rs` assemble Tauri et expose les commandes qui délèguent aux modules propriétaires.
|
||||||
- **GAME-PLATFORM-011** — Les traces frontend Tauri passent par `@fltsci/tauri-plugin-tracing` vers `tauri-plugin-tracing`/`tracing`; les `console.*` applicatifs directs sont interdits hors fallback interne.
|
- **GAME-PLATFORM-011** — Les traces frontend Tauri passent par `@fltsci/tauri-plugin-tracing` vers `tauri-plugin-tracing`/`tracing`; les `console.*` applicatifs directs sont interdits hors fallback interne.
|
||||||
|
|
||||||
|
- **GAME-PLATFORM-012** — Le plugin tracing Tauri ne remplace pas l'initialisation du subscriber Rust ; une app Tauri initialise le runtime de logging partagé avant son premier événement `tracing`.
|
||||||
|
- **GAME-PLATFORM-013** — Les demandes de sortie Tauri sont évaluées par la politique `EngineGame::quit_requested` avant toute fermeture native.
|
||||||
|
|||||||
Reference in New Issue
Block a user