ScriptUI: install scheduled task runner in host sessions

This commit is contained in:
dorfee
2026-10-19 16:45:39 +03:00
parent ef74d82902
commit 80158bb69b
3 changed files with 37 additions and 4 deletions
+18 -4
View File
@@ -82,7 +82,7 @@ impl Exporter for FileExporter {
/// A new session with media, import, expressions, scripting and export enabled.
pub fn session() -> Session {
Session {
let mut s = Session {
// The desktop app, the CLI and the MCP server share installed Roto Brush models.
models_dir: config_dir().map(|d| d.join("models")),
exporter: Some(Arc::new(FileExporter::default())),
@@ -90,11 +90,11 @@ pub fn session() -> Session {
importer: Some(Arc::new(MediaImporter)),
expr: Some(Arc::new(effectcraft_expr::Expressions)),
expr_check: Some(effectcraft_expr::check_syntax),
script: Some(effectcraft_script::runner),
script_ui: effectcraft_engine::scriptui::ScriptUi { dispatch: Some(effectcraft_script::dispatch_ui), ..Default::default() },
plugin_loader: effectcraft_plugin::wasm_available().then_some(effectcraft_plugin::loader as effectcraft_engine::PluginLoader),
..Default::default()
}
};
effectcraft_script::install(&mut s);
s
}
/// The platform config directory for EffectCraft (`EFFECTCRAFT_CONFIG_DIR` overrides):
@@ -109,6 +109,20 @@ pub fn config_dir() -> Option<std::path::PathBuf> {
mod tests {
use serde_json::json;
#[test]
fn host_runs_tasks_scheduled_by_panel_handlers() {
let mut s = super::session();
let result = s.execute("script.run", json!({"code": "var w=new Window('palette','Timer regression'); var b=w.add('button',undefined,'Import'); b.onClick=function(){app.scheduleTask(\"app.project.items.addComp('Scheduled',64,64,1,1,25)\",0,false);};w.show();"})).unwrap();
assert_eq!(result["ok"], true, "{result}");
s.execute("scriptui.click", json!({"window":"Timer regression","widget":"Import"})).unwrap();
assert!(s.project.items.is_empty());
let tick = s.execute("script.runTasks", json!({})).unwrap();
assert_eq!(tick["ran"], 1, "{tick}");
assert_eq!(tick["errors"], json!([]), "{tick}");
assert!(s.project.items.values().any(|item| item.name == "Scheduled"));
s.execute("scriptui.close", json!({"window":"Timer regression"})).unwrap();
}
/// Layer ▸ Camera ▸ Link Focus Distance to Point of Interest / to Layer: the expressions
/// evaluate to the camera's focus on the target.
#[test]
+4
View File
@@ -1775,7 +1775,11 @@ impl EffectcraftApp {
if self.session.script_ui.task_hosts.is_empty() {
return;
}
let previous_comp = self.session.active_comp_id();
let Some(r) = effectcraft_engine::scriptui::ScriptUi::run_tasks(&mut self.session) else { return };
if self.session.active_comp_id().is_some() && self.session.active_comp_id() != previous_comp {
self.ui.start_screen = false;
}
if let Some(msg) = r["errors"].as_array().and_then(|e| e.first()).and_then(|e| e["message"].as_str()) {
self.toast = Some((format!("Scheduled script task: {msg}"), ctx.input(|i| i.time)));
} else if let Some(line) = r["output"].as_array().and_then(|o| o.last()).and_then(|l| l.as_str()) {
+15
View File
@@ -271,3 +271,18 @@ fn click_at(h: &mut Harness<'_, EffectcraftApp>, c: egui::Pos2) {
}
h.run_steps(3);
}
#[test]
fn scheduled_import_reveals_its_composition_without_manual_clicks() {
let mut s = effectcraft_host::session();
let result = s.execute("script.run", json!({"code": "var w=new Window('palette','Automatic import');var b=w.add('button',undefined,'Open');b.onClick=function(){app.scheduleTask(\"var c=app.project.items.addComp('Imported',64,64,1,1,25);c.openInViewer();\",0,false);};w.show();"})).unwrap();
assert_eq!(result["ok"], true, "{result}");
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_| EffectcraftApp::new(s));
h.state_mut().ui.start_screen = true;
h.run_steps(2);
h.state_mut().session.execute("scriptui.click", json!({"window":"Automatic import","widget":"Open"})).unwrap();
h.run_steps(4);
let active = h.state().session.active_comp_id().unwrap();
assert_eq!(h.state().session.project.items.get(&active).unwrap().name, "Imported");
assert!(!h.state().ui.start_screen, "Home must not hide a composition opened by the scheduled import");
h.state_mut().session.execute("scriptui.close", json!({"window":"Automatic import"})).unwrap();
}