functional runtime

This commit is contained in:
2026-02-15 22:27:08 +08:00
parent 285fdcab1f
commit 44556ca3a1
5 changed files with 176 additions and 6 deletions

92
src-tauri/Cargo.lock generated
View File

@@ -361,6 +361,16 @@ dependencies = [
"alloc-stdlib",
]
[[package]]
name = "bstr"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.19.0"
@@ -945,6 +955,12 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "embed-resource"
version = "3.0.6"
@@ -1026,6 +1042,12 @@ dependencies = [
"syn 2.0.110",
]
[[package]]
name = "env_home"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe"
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -1185,6 +1207,7 @@ dependencies = [
"image",
"keyring",
"lazy_static",
"mlua",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-foundation 0.3.2",
@@ -2281,6 +2304,25 @@ version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "lua-src"
version = "547.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edaf29e3517b49b8b746701e5648ccb5785cde1c119062cbabbc5d5cd115e42"
dependencies = [
"cc",
]
[[package]]
name = "luajit-src"
version = "210.5.12+a4f56a4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3a8e7962a5368d5f264d045a5a255e90f9aa3fc1941ae15a8d2940d42cac671"
dependencies = [
"cc",
"which",
]
[[package]]
name = "mac"
version = "0.1.1"
@@ -2388,6 +2430,32 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "mlua"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d111deb18a9c9bd33e1541309f4742523bfab01d276bfa9a27519f6de9c11dc7"
dependencies = [
"bstr",
"mlua-sys",
"num-traits",
"once_cell",
"rustc-hash",
]
[[package]]
name = "mlua-sys"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380c1f7e2099cafcf40e51d3a9f20a346977587aa4d012eae1f043149a728a93"
dependencies = [
"cc",
"cfg-if",
"lua-src",
"luajit-src",
"pkg-config",
]
[[package]]
name = "moxcms"
version = "0.7.11"
@@ -3624,6 +3692,12 @@ dependencies = [
"url",
]
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustc_version"
version = "0.4.1"
@@ -5628,6 +5702,18 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
[[package]]
name = "which"
version = "7.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762"
dependencies = [
"either",
"env_home",
"rustix",
"winsafe",
]
[[package]]
name = "winapi"
version = "0.3.9"
@@ -6200,6 +6286,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "winsafe"
version = "0.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
[[package]]
name = "wit-bindgen"
version = "0.46.0"

View File

@@ -45,6 +45,7 @@ gif = "0.14.1"
raw-window-handle = "0.6"
enigo = { version = "0.6.1", features = ["wayland"] }
lazy_static = "1.5.0"
mlua = { version = "0.9", default-features = false, features = ["lua54", "vendored"] }
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-global-shortcut = "2"
tauri-plugin-positioner = "2"

View File

@@ -1,10 +1,12 @@
use tauri::Manager;
use tracing::{error, info, warn};
use crate::get_app_handle;
use crate::{get_app_handle, lock_w};
use serde::{Deserialize, Serialize};
use serde_json;
use std::{fs, path::PathBuf};
use std::fs;
pub mod runtime;
#[derive(Serialize, Deserialize, Debug)]
pub struct ModuleMetadata {
@@ -13,7 +15,7 @@ pub struct ModuleMetadata {
pub description: Option<String>,
}
fn get_module_metadata(path: PathBuf) -> Option<ModuleMetadata> {
fn get_module_metadata(path: &std::path::Path) -> Option<ModuleMetadata> {
let metadata_path = path.join("metadata.json");
if metadata_path.exists() {
match fs::read_to_string(&metadata_path) {
@@ -65,6 +67,15 @@ pub fn init_modules() {
}
};
let state = lock_w!(crate::state::FDOLL);
let mut state_guard = match state.module_handles.lock() {
Ok(guard) => guard,
Err(e) => {
error!("Failed to lock module handles: {}", e);
return;
}
};
for entry in entries {
let entry = match entry {
Ok(entry) => entry,
@@ -76,12 +87,26 @@ pub fn init_modules() {
let path = entry.path();
if path.is_dir() {
let module_metadata = match get_module_metadata(path) {
let module_metadata = match get_module_metadata(&path) {
Some(metadata) => metadata,
None => continue,
};
dbg!(module_metadata);
// TODO: Initialize the module based on metadata
let script_path = path.join("main.lua");
if script_path.exists() {
match runtime::spawn_lua_runtime_from_path(&script_path) {
Ok(handle) => {
state_guard.push(handle);
}
Err(e) => {
error!(
"Failed to spawn runtime for module {}: {}",
module_metadata.name, e
);
}
}
} else {
warn!("Module {} has no main.lua script", module_metadata.name);
}
}
}
}

View File

@@ -0,0 +1,50 @@
use mlua::{Lua, UserData, UserDataMethods};
use std::{path::Path, thread, time::Duration};
use tracing::{error, info};
pub struct Engine;
impl UserData for Engine {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_method("log", |_, _, message: String| {
info!("{}", message);
Ok(())
});
methods.add_method("sleep", |_, _, seconds: u64| {
thread::sleep(Duration::from_secs(seconds));
Ok(())
});
}
}
fn load_script(path: &Path) -> Result<String, std::io::Error> {
std::fs::read_to_string(path)
}
fn setup_engine_globals(lua: &Lua) -> Result<(), mlua::Error> {
let globals = lua.globals();
globals.set("engine", Engine)
}
pub fn spawn_lua_runtime(script: &str) -> thread::JoinHandle<()> {
let script = script.to_string();
thread::spawn(move || {
let lua = Lua::new();
if let Err(e) = setup_engine_globals(&lua) {
error!("Failed to set engine global: {}", e);
return;
}
if let Err(e) = lua.load(&script).exec() {
error!("Failed to execute lua script: {}", e);
return;
}
})
}
pub fn spawn_lua_runtime_from_path(path: &Path) -> Result<thread::JoinHandle<()>, std::io::Error> {
let script = load_script(path)?;
Ok(spawn_lua_runtime(&script))
}

View File

@@ -19,6 +19,7 @@ pub struct AppState {
pub auth: AuthState,
pub user_data: AppData,
pub tray: Option<TrayIcon>,
pub module_handles: std::sync::Mutex<Vec<std::thread::JoinHandle<()>>>,
}
// Global application state
@@ -36,6 +37,7 @@ pub fn init_app_state() {
guard.network = init_network_state();
guard.auth = init_auth_state();
guard.user_data = AppData::default();
guard.module_handles = std::sync::Mutex::new(Vec::new());
}
update_display_dimensions_for_scene_state();
info!("Initialized FDOLL state (WebSocket client & user data initializing asynchronously)");