From 58957ec597ce991d99992360c83a06b6fd36875f Mon Sep 17 00:00:00 2001 From: Byson94 Date: Mon, 27 Oct 2025 18:05:55 +0530 Subject: [PATCH 1/2] fix: poll/listen variables not working in other files --- CHANGELOG.md | 2 + .../ewwii/src/widgets/widget_definitions.rs | 34 ++++++++ crates/rhai_impl/src/helper.rs | 86 ++++++++++++++++++- 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8869ad..0c4851a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/). - Ewwii defaulting to default gtk4 theme. #9 - Few issues with eventbox drop target. - Poll/Listen variables not exposed in other modules on first launch. +- Not able to define poll/listen variables in other files. +- Overlay and Tooltip widgets not being reactive. ## [0.3.0-beta] - 2025-10-11 diff --git a/crates/ewwii/src/widgets/widget_definitions.rs b/crates/ewwii/src/widgets/widget_definitions.rs index 4d9d020..8b4b7b7 100644 --- a/crates/ewwii/src/widgets/widget_definitions.rs +++ b/crates/ewwii/src/widgets/widget_definitions.rs @@ -303,6 +303,23 @@ pub(super) fn build_gtk_overlay( gtk_widget.add_overlay(&child); } + let gtk_widget_clone = gtk_widget.clone(); + + let update_fn: UpdateFn = Box::new(move |props: &Map| { + // now re-apply generic widget attrs + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { + eprintln!("Failed to update widget attrs: {:?}", err); + } + }); + + let id = hash_props_and_type(&props, "Overlay"); + + widget_registry + .widgets + .insert(id, WidgetEntry { widget: gtk_widget.clone().upcast(), update_fn }); + resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) @@ -343,6 +360,23 @@ pub(super) fn build_tooltip( true }); + let gtk_widget_clone = gtk_widget.clone(); + + let update_fn: UpdateFn = Box::new(move |props: &Map| { + // now re-apply generic widget attrs + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { + eprintln!("Failed to update widget attrs: {:?}", err); + } + }); + + let id = hash_props_and_type(&props, "Tooltip"); + + widget_registry + .widgets + .insert(id, WidgetEntry { widget: gtk_widget.clone().upcast(), update_fn }); + resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) diff --git a/crates/rhai_impl/src/helper.rs b/crates/rhai_impl/src/helper.rs index f74fcb8..cfe164c 100644 --- a/crates/rhai_impl/src/helper.rs +++ b/crates/rhai_impl/src/helper.rs @@ -1,21 +1,60 @@ use crate::error::format_eval_error; use anyhow::Result; use rhai::Engine; +use std::{ + collections::HashSet, + fs, + path::{Path, PathBuf}, +}; pub fn extract_poll_and_listen_vars(code: &str) -> Result)>> { + extract_poll_and_listen_vars_inner(code, &mut HashSet::new()) +} + +fn extract_poll_and_listen_vars_inner( + code: &str, + visited: &mut HashSet, +) -> Result)>> { let mut results = Vec::new(); let mut engine = Engine::new(); - register_temp_poll_listen(&mut engine); + // Handle imports manually + for import_path in extract_import_paths(code)? { + let resolved = resolve_import_path(&import_path)?; + + // Prevent infinite recursion + let canonical = fs::canonicalize(&resolved).unwrap_or(resolved.clone()); + if visited.contains(&canonical) { + continue; + } + + visited.insert(canonical.clone()); + + if resolved.exists() { + let imported_code = fs::read_to_string(&resolved)?; + let inner = extract_poll_and_listen_vars_inner(&imported_code, visited)?; + results.extend(inner); + } + } + + // Process this file’s own poll/listen calls for expr in extract_poll_listen_exprs(code) { match engine.eval_expression::(&expr) { Ok(sig) => { - let initial = sig.props.get("initial").and_then(|v| v.clone().try_cast::()); + let initial = sig + .props + .get("initial") + .and_then(|v| v.clone().try_cast::()); results.push((sig.var, initial)); } Err(e) => { - return Err(anyhow::anyhow!(format_eval_error(&e, code, &engine, None))); + return Err(anyhow::anyhow!(format_eval_error( + &e, + code, + &engine, + None + ))); } } } @@ -23,6 +62,45 @@ pub fn extract_poll_and_listen_vars(code: &str) -> Result Result> { + let mut imports = Vec::new(); + + for line in code.lines() { + let trimmed = line.trim_start(); + + if trimmed.starts_with("import ") { + if let Some(start) = trimmed.find('"') { + if let Some(end_rel) = trimmed[start + 1..].find('"') { + let end = start + 1 + end_rel; + let path = &trimmed[start + 1..end]; + imports.push(path.to_string()); + } + } + } + } + + Ok(imports) +} + +/// Resolve relative and absolute import paths. +fn resolve_import_path(import_path: &str) -> Result { + let path = Path::new(import_path); + let abs = if path.is_absolute() { + path.to_path_buf() + } else { + std::env::current_dir()?.join(path) + }; + + let abs = if abs.extension().is_none() { + abs.with_extension("rhai") + } else { + abs + }; + + Ok(abs) +} + pub fn extract_poll_listen_exprs(code: &str) -> Vec { let mut exprs = Vec::new(); let mut i = 0; @@ -35,7 +113,7 @@ pub fn extract_poll_listen_exprs(code: &str) -> Vec { while i < len && code_bytes[i] as char != '\n' { i += 1; } - i += 1; // skipp a full line + i += 1; // skip a full line continue; } From 5e827a73c86e4249d8b95d2cb52e8aa9d46ae502 Mon Sep 17 00:00:00 2001 From: Byson94 Date: Mon, 27 Oct 2025 18:09:26 +0530 Subject: [PATCH 2/2] chore: run cargo fmt --- crates/rhai_impl/src/helper.rs | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/crates/rhai_impl/src/helper.rs b/crates/rhai_impl/src/helper.rs index cfe164c..2bc6f6a 100644 --- a/crates/rhai_impl/src/helper.rs +++ b/crates/rhai_impl/src/helper.rs @@ -42,19 +42,11 @@ fn extract_poll_and_listen_vars_inner( for expr in extract_poll_listen_exprs(code) { match engine.eval_expression::(&expr) { Ok(sig) => { - let initial = sig - .props - .get("initial") - .and_then(|v| v.clone().try_cast::()); + let initial = sig.props.get("initial").and_then(|v| v.clone().try_cast::()); results.push((sig.var, initial)); } Err(e) => { - return Err(anyhow::anyhow!(format_eval_error( - &e, - code, - &engine, - None - ))); + return Err(anyhow::anyhow!(format_eval_error(&e, code, &engine, None))); } } } @@ -86,17 +78,10 @@ fn extract_import_paths(code: &str) -> Result> { /// Resolve relative and absolute import paths. fn resolve_import_path(import_path: &str) -> Result { let path = Path::new(import_path); - let abs = if path.is_absolute() { - path.to_path_buf() - } else { - std::env::current_dir()?.join(path) - }; + let abs = + if path.is_absolute() { path.to_path_buf() } else { std::env::current_dir()?.join(path) }; - let abs = if abs.extension().is_none() { - abs.with_extension("rhai") - } else { - abs - }; + let abs = if abs.extension().is_none() { abs.with_extension("rhai") } else { abs }; Ok(abs) }