add theme data to circle and fix slideshow

This commit is contained in:
timurgordon 2025-06-25 03:54:49 +03:00
parent e91a44ce37
commit 41406f2d1e
6 changed files with 270 additions and 109 deletions

View File

@ -1,10 +1,33 @@
use heromodels_core::BaseModelData; use heromodels_core::BaseModelData;
use heromodels_derive::model; use heromodels_derive::model;
// Temporarily removed to fix compilation issues
// use rhai_autobind_macros::rhai_model_export;
use rhai::{CustomType, TypeBuilder}; use rhai::{CustomType, TypeBuilder};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Represents the visual theme for a circle.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType)]
pub struct ThemeData {
pub primary_color: String,
pub background_color: String,
pub background_pattern: String,
pub logo_symbol: String,
pub logo_url: String,
pub nav_dashboard_visible: bool,
pub nav_timeline_visible: bool,
}
impl Default for ThemeData {
fn default() -> Self {
Self {
primary_color: "#3b82f6".to_string(),
background_color: "#0a0a0a".to_string(),
background_pattern: "none".to_string(),
logo_symbol: "".to_string(),
logo_url: "".to_string(),
nav_dashboard_visible: true,
nav_timeline_visible: true,
}
}
}
/// Represents an event in a calendar /// Represents an event in a calendar
#[model] #[model]
@ -24,7 +47,7 @@ pub struct Circle {
/// Logo URL or symbol for the circle /// Logo URL or symbol for the circle
pub logo: Option<String>, pub logo: Option<String>,
/// Theme settings for the circle (colors, styling, etc.) /// Theme settings for the circle (colors, styling, etc.)
pub theme: HashMap<String, String>, pub theme: ThemeData,
} }
impl Circle { impl Circle {
@ -38,7 +61,7 @@ impl Circle {
circles: Vec::new(), circles: Vec::new(),
logo: None, logo: None,
members: Vec::new(), members: Vec::new(),
theme: HashMap::new(), theme: ThemeData::default(),
} }
} }
@ -66,14 +89,8 @@ impl Circle {
self self
} }
/// Sets a theme property for the circle
pub fn theme_property(mut self, key: impl ToString, value: impl ToString) -> Self {
self.theme.insert(key.to_string(), value.to_string());
self
}
/// Sets the entire theme for the circle /// Sets the entire theme for the circle
pub fn theme(mut self, theme: HashMap<String, String>) -> Self { pub fn theme(mut self, theme: ThemeData) -> Self {
self.theme = theme; self.theme = theme;
self self
} }

View File

@ -3,5 +3,5 @@ pub mod circle;
pub mod rhai; pub mod rhai;
// Re-export Calendar, Event, Attendee, and AttendanceStatus from the inner calendar module (calendar.rs) within src/models/calendar/mod.rs // Re-export Calendar, Event, Attendee, and AttendanceStatus from the inner calendar module (calendar.rs) within src/models/calendar/mod.rs
pub use self::circle::Circle; pub use self::circle::{Circle, ThemeData};
pub use rhai::register_circle_rhai_module; pub use rhai::register_circle_rhai_module;

View File

@ -4,28 +4,23 @@ use rhai::{Array, CustomType, Dynamic, Engine, EvalAltResult, INT, Module, Posit
use std::mem; use std::mem;
use std::sync::Arc; use std::sync::Arc;
use super::circle::Circle; use super::circle::{Circle, ThemeData};
type RhaiCircle = Circle; type RhaiCircle = Circle;
type RhaiThemeData = ThemeData;
use crate::db::Collection; use crate::db::Collection;
use crate::db::hero::OurDB; use crate::db::hero::OurDB;
use serde::Serialize; use serde::Serialize;
use serde_json; use serde_json;
use std::collections::HashMap;
/// Registers a `.json()` method for any type `T` that implements the required traits. /// Registers a `.json()` method for any type `T` that implements the required traits.
fn register_json_method<T>(engine: &mut Engine) fn register_json_method<T>(engine: &mut Engine)
where where
// The type must be: T: CustomType + Clone + Serialize,
T: CustomType + Clone + Serialize, // A clonable, serializable, custom type for Rhai
{ {
// This is the function that will be called when a script runs '.json()'
let to_json_fn = |obj: &mut T| -> Result<String, Box<EvalAltResult>> { let to_json_fn = |obj: &mut T| -> Result<String, Box<EvalAltResult>> {
// Use serde_json to serialize the object to a pretty-formatted string.
// The '?' will automatically convert any serialization error into a Rhai error.
serde_json::to_string(obj).map_err(|e| e.to_string().into()) serde_json::to_string(obj).map_err(|e| e.to_string().into())
}; };
// Register the function as a method named "json" for the type 'T'.
engine.build_type::<T>().register_fn("json", to_json_fn); engine.build_type::<T>().register_fn("json", to_json_fn);
} }
@ -39,6 +34,128 @@ fn id_from_i64_to_u32(id_i64: i64) -> Result<u32, Box<EvalAltResult>> {
}) })
} }
#[export_module]
mod rhai_theme_data_module {
#[rhai_fn(name = "new_theme_data")]
pub fn new_theme_data() -> RhaiThemeData {
ThemeData::default()
}
// --- Setters for ThemeData ---
#[rhai_fn(name = "primary_color", return_raw, global, pure)]
pub fn set_primary_color(
theme: &mut RhaiThemeData,
color: String,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.primary_color = color;
*theme = owned_theme;
Ok(theme.clone())
}
#[rhai_fn(name = "background_color", return_raw, global, pure)]
pub fn set_background_color(
theme: &mut RhaiThemeData,
color: String,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.background_color = color;
*theme = owned_theme;
Ok(theme.clone())
}
#[rhai_fn(name = "background_pattern", return_raw, global, pure)]
pub fn set_background_pattern(
theme: &mut RhaiThemeData,
pattern: String,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.background_pattern = pattern;
*theme = owned_theme;
Ok(theme.clone())
}
#[rhai_fn(name = "logo_symbol", return_raw, global, pure)]
pub fn set_logo_symbol(
theme: &mut RhaiThemeData,
symbol: String,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.logo_symbol = symbol;
*theme = owned_theme;
Ok(theme.clone())
}
#[rhai_fn(name = "logo_url", return_raw, global, pure)]
pub fn set_logo_url(
theme: &mut RhaiThemeData,
url: String,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.logo_url = url;
*theme = owned_theme;
Ok(theme.clone())
}
#[rhai_fn(name = "nav_dashboard_visible", return_raw, global, pure)]
pub fn set_nav_dashboard_visible(
theme: &mut RhaiThemeData,
visible: bool,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.nav_dashboard_visible = visible;
*theme = owned_theme;
Ok(theme.clone())
}
#[rhai_fn(name = "nav_timeline_visible", return_raw, global, pure)]
pub fn set_nav_timeline_visible(
theme: &mut RhaiThemeData,
visible: bool,
) -> Result<RhaiThemeData, Box<EvalAltResult>> {
let mut owned_theme = mem::take(theme);
owned_theme.nav_timeline_visible = visible;
*theme = owned_theme;
Ok(theme.clone())
}
// --- Getters for ThemeData ---
#[rhai_fn(name = "get_primary_color", pure)]
pub fn get_primary_color(theme: &mut RhaiThemeData) -> String {
theme.primary_color.clone()
}
#[rhai_fn(name = "get_background_color", pure)]
pub fn get_background_color(theme: &mut RhaiThemeData) -> String {
theme.background_color.clone()
}
#[rhai_fn(name = "get_background_pattern", pure)]
pub fn get_background_pattern(theme: &mut RhaiThemeData) -> String {
theme.background_pattern.clone()
}
#[rhai_fn(name = "get_logo_symbol", pure)]
pub fn get_logo_symbol(theme: &mut RhaiThemeData) -> String {
theme.logo_symbol.clone()
}
#[rhai_fn(name = "get_logo_url", pure)]
pub fn get_logo_url(theme: &mut RhaiThemeData) -> String {
theme.logo_url.clone()
}
#[rhai_fn(name = "get_nav_dashboard_visible", pure)]
pub fn get_nav_dashboard_visible(theme: &mut RhaiThemeData) -> bool {
theme.nav_dashboard_visible
}
#[rhai_fn(name = "get_nav_timeline_visible", pure)]
pub fn get_nav_timeline_visible(theme: &mut RhaiThemeData) -> bool {
theme.nav_timeline_visible
}
}
#[export_module] #[export_module]
mod rhai_circle_module { mod rhai_circle_module {
// --- Circle Functions --- // --- Circle Functions ---
@ -95,7 +212,7 @@ mod rhai_circle_module {
#[rhai_fn(name = "theme", return_raw, global, pure)] #[rhai_fn(name = "theme", return_raw, global, pure)]
pub fn circle_theme( pub fn circle_theme(
circle: &mut RhaiCircle, circle: &mut RhaiCircle,
theme: HashMap<String, String>, theme: RhaiThemeData,
) -> Result<RhaiCircle, Box<EvalAltResult>> { ) -> Result<RhaiCircle, Box<EvalAltResult>> {
let owned_circle = mem::take(circle); let owned_circle = mem::take(circle);
*circle = owned_circle.theme(theme); *circle = owned_circle.theme(theme);
@ -108,7 +225,6 @@ mod rhai_circle_module {
circle: &mut RhaiCircle, circle: &mut RhaiCircle,
added_circle: String, added_circle: String,
) -> Result<RhaiCircle, Box<EvalAltResult>> { ) -> Result<RhaiCircle, Box<EvalAltResult>> {
// Use take to get ownership of the circle
let owned_circle = mem::take(circle); let owned_circle = mem::take(circle);
*circle = owned_circle.add_circle(added_circle); *circle = owned_circle.add_circle(added_circle);
Ok(circle.clone()) Ok(circle.clone())
@ -120,93 +236,89 @@ mod rhai_circle_module {
circle: &mut RhaiCircle, circle: &mut RhaiCircle,
added_member: String, added_member: String,
) -> Result<RhaiCircle, Box<EvalAltResult>> { ) -> Result<RhaiCircle, Box<EvalAltResult>> {
// Use take to get ownership of the circle
let owned_circle = mem::take(circle); let owned_circle = mem::take(circle);
*circle = owned_circle.add_member(added_member); *circle = owned_circle.add_member(added_member);
Ok(circle.clone()) Ok(circle.clone())
} }
// Circle Getters // Circle Getters
#[rhai_fn(get = "id", pure)] #[rhai_fn(name = "get_id", pure)]
pub fn get_circle_id(circle: &mut RhaiCircle) -> i64 { pub fn get_circle_id(circle: &mut RhaiCircle) -> i64 {
circle.base_data.id as i64 circle.base_data.id as i64
} }
#[rhai_fn(get = "created_at", pure)] #[rhai_fn(name = "get_created_at", pure)]
pub fn get_circle_created_at(circle: &mut RhaiCircle) -> i64 { pub fn get_circle_created_at(circle: &mut RhaiCircle) -> i64 {
circle.base_data.created_at circle.base_data.created_at
} }
#[rhai_fn(get = "modified_at", pure)] #[rhai_fn(name = "get_modified_at", pure)]
pub fn get_circle_modified_at(circle: &mut RhaiCircle) -> i64 { pub fn get_circle_modified_at(circle: &mut RhaiCircle) -> i64 {
circle.base_data.modified_at circle.base_data.modified_at
} }
#[rhai_fn(get = "title", pure)] #[rhai_fn(name = "get_title", pure)]
pub fn get_circle_title(circle: &mut RhaiCircle) -> String { pub fn get_circle_title(circle: &mut RhaiCircle) -> String {
circle.title.clone() circle.title.clone()
} }
#[rhai_fn(get = "description", pure)] #[rhai_fn(name = "get_description", pure)]
pub fn get_circle_description(circle: &mut RhaiCircle) -> Option<String> { pub fn get_circle_description(circle: &mut RhaiCircle) -> Option<String> {
circle.description.clone() circle.description.clone()
} }
#[rhai_fn(get = "circles", pure)] #[rhai_fn(name = "get_circles", pure)]
pub fn get_circle_circles(circle: &mut RhaiCircle) -> Vec<String> { pub fn get_circle_circles(circle: &mut RhaiCircle) -> Vec<String> {
circle.circles.clone() circle.circles.clone()
} }
#[rhai_fn(get = "ws_url", pure)] #[rhai_fn(name = "get_ws_url", pure)]
pub fn get_circle_ws_url(circle: &mut RhaiCircle) -> String { pub fn get_circle_ws_url(circle: &mut RhaiCircle) -> String {
circle.ws_url.clone() circle.ws_url.clone()
} }
#[rhai_fn(get = "logo", pure)] #[rhai_fn(name = "get_logo", pure)]
pub fn get_circle_logo(circle: &mut RhaiCircle) -> Option<String> { pub fn get_circle_logo(circle: &mut RhaiCircle) -> Option<String> {
circle.logo.clone() circle.logo.clone()
} }
#[rhai_fn(get = "theme", pure)] #[rhai_fn(name = "get_theme", pure)]
pub fn get_circle_theme(circle: &mut RhaiCircle) -> HashMap<String, String> { pub fn get_circle_theme(circle: &mut RhaiCircle) -> RhaiThemeData {
circle.theme.clone() circle.theme.clone()
} }
} }
pub fn register_circle_rhai_module(engine: &mut Engine, db: Arc<OurDB>) { pub fn register_circle_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
// Register the exported module globally engine.build_type::<RhaiCircle>();
let module = exported_module!(rhai_circle_module); engine.build_type::<RhaiThemeData>();
engine.register_global_module(module.into());
// Create a module for database functions
let mut db_module = Module::new(); let mut db_module = Module::new();
let circle_module = exported_module!(rhai_circle_module);
let theme_data_module = exported_module!(rhai_theme_data_module);
engine.register_global_module(circle_module.into());
engine.register_global_module(theme_data_module.into());
register_json_method::<Circle>(engine);
register_json_method::<ThemeData>(engine);
// Manually register database functions as they need to capture 'db' // Manually register database functions as they need to capture 'db'
let db_clone_set_circle = db.clone(); let db_clone_set_circle = db.clone();
db_module.set_native_fn( db_module.set_native_fn(
"save_circle", "save_circle",
move |circle: Circle| -> Result<Circle, Box<EvalAltResult>> { move |circle: Circle| -> Result<Circle, Box<EvalAltResult>> {
// Use the Collection trait method directly
let result = db_clone_set_circle.set(&circle).map_err(|e| { let result = db_clone_set_circle.set(&circle).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime( Box::new(EvalAltResult::ErrorRuntime(
format!("DB Error set_circle: {}", e).into(), format!("DB Error set_circle: {}", e).into(),
Position::NONE, Position::NONE,
)) ))
})?; })?;
// Return the updated circle with the correct ID
Ok(result.1) Ok(result.1)
}, },
); );
register_json_method::<Circle>(engine);
// Manually register database functions as they need to capture 'db'
let db_clone_delete_circle = db.clone(); let db_clone_delete_circle = db.clone();
db_module.set_native_fn( db_module.set_native_fn(
"delete_circle", "delete_circle",
move |circle: Circle| -> Result<(), Box<EvalAltResult>> { move |circle: Circle| -> Result<(), Box<EvalAltResult>> {
// Use the Collection trait method directly
let result = db_clone_delete_circle let result = db_clone_delete_circle
.collection::<Circle>() .collection::<Circle>()
.expect("can open circle collection") .expect("can open circle collection")
.delete_by_id(circle.base_data.id) .delete_by_id(circle.base_data.id)
.expect("can delete circle"); .expect("can delete circle");
// Return the updated circle with the correct ID
Ok(result) Ok(result)
}, },
); );
@ -215,7 +327,6 @@ pub fn register_circle_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
db_module.set_native_fn( db_module.set_native_fn(
"get_circle", "get_circle",
move || -> Result<Circle, Box<EvalAltResult>> { move || -> Result<Circle, Box<EvalAltResult>> {
// Use the Collection trait method directly
let all_circles: Vec<Circle> = db_clone_get_circle.get_all().map_err(|e| { let all_circles: Vec<Circle> = db_clone_get_circle.get_all().map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime( Box::new(EvalAltResult::ErrorRuntime(
format!("DB Error get_circle: {}", e).into(), format!("DB Error get_circle: {}", e).into(),
@ -234,12 +345,26 @@ pub fn register_circle_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
}, },
); );
// --- Collection DB Functions ---
let db_clone = db.clone();
db_module.set_native_fn(
"save_circle",
move |circle: RhaiCircle| -> Result<RhaiCircle, Box<EvalAltResult>> {
let result = db_clone.set(&circle).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("DB Error: {:?}", e).into(),
Position::NONE,
))
})?;
Ok(result.1)
},
);
let db_clone_get_circle_by_id = db.clone(); let db_clone_get_circle_by_id = db.clone();
db_module.set_native_fn( db_module.set_native_fn(
"get_circle_by_id", "get_circle_by_id",
move |id_i64: INT| -> Result<Circle, Box<EvalAltResult>> { move |id_i64: INT| -> Result<Circle, Box<EvalAltResult>> {
let id_u32 = id_from_i64_to_u32(id_i64)?; let id_u32 = id_from_i64_to_u32(id_i64)?;
// Use the Collection trait method directly
db_clone_get_circle_by_id db_clone_get_circle_by_id
.get_by_id(id_u32) .get_by_id(id_u32)
.map_err(|e| { .map_err(|e| {
@ -257,7 +382,6 @@ pub fn register_circle_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
}, },
); );
// Add list_circles function to get all circles
let db_clone_list_circles = db.clone(); let db_clone_list_circles = db.clone();
db_module.set_native_fn( db_module.set_native_fn(
"list_circles", "list_circles",
@ -282,7 +406,6 @@ pub fn register_circle_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
}, },
); );
// Register the database module globally
engine.register_global_module(db_module.into()); engine.register_global_module(db_module.into());
println!("Successfully registered circle Rhai module using export_module approach."); println!("Successfully registered circle Rhai module using export_module approach.");

View File

@ -301,10 +301,10 @@ impl Book {
} }
} }
/// Represents a Slides library item (collection of images for slideshow). /// Represents a Slideshow library item (collection of images for slideshow).
#[model] #[model]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType)] #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, CustomType)]
pub struct Slides { pub struct Slideshow {
/// Base model data /// Base model data
pub base_data: BaseModelData, pub base_data: BaseModelData,
/// Title of the slideshow /// Title of the slideshow
@ -312,26 +312,44 @@ pub struct Slides {
pub title: String, pub title: String,
/// Optional description of the slideshow /// Optional description of the slideshow
pub description: Option<String>, pub description: Option<String>,
/// List of slide image URLs /// List of slides
pub slide_urls: Vec<String>, pub slides: Vec<Slide>,
/// Optional slide titles/captions
pub slide_titles: Vec<Option<String>>,
} }
impl Default for Slides { #[derive(Debug, Clone, Serialize, Default, Deserialize, PartialEq, CustomType)]
fn default() -> Self { pub struct Slide {
pub image_url: String,
pub title: Option<String>,
pub description: Option<String>,
}
impl Slide {
pub fn new() -> Self {
Self { Self {
base_data: BaseModelData::new(), image_url: String::new(),
title: String::new(), title: None,
description: None, description: None,
slide_urls: Vec::new(),
slide_titles: Vec::new(),
} }
} }
pub fn url(mut self, url: impl Into<String>) -> Self {
self.image_url = url.into();
self
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
} }
impl Slides { impl Slideshow {
/// Creates a new `Slides` with default values. /// Creates a new `Slideshow` with default values.
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
@ -349,21 +367,8 @@ impl Slides {
} }
/// Adds a slide with URL and optional title. /// Adds a slide with URL and optional title.
pub fn add_slide(mut self, url: impl Into<String>, title: Option<String>) -> Self { pub fn add_slide(mut self, slide: Slide) -> Self {
self.slide_urls.push(url.into()); self.slides.push(slide);
self.slide_titles.push(title);
self
}
/// Sets all slide URLs at once.
pub fn slide_urls(mut self, urls: Vec<String>) -> Self {
self.slide_urls = urls;
self
}
/// Sets all slide titles at once.
pub fn slide_titles(mut self, titles: Vec<Option<String>>) -> Self {
self.slide_titles = titles;
self self
} }
} }

View File

@ -9,7 +9,7 @@ use std::sync::Arc;
use super::collection::Collection as RhaiCollection; use super::collection::Collection as RhaiCollection;
use super::items::{ use super::items::{
Book as RhaiBook, Image as RhaiImage, Markdown as RhaiMarkdown, Pdf as RhaiPdf, Book as RhaiBook, Image as RhaiImage, Markdown as RhaiMarkdown, Pdf as RhaiPdf,
Slides as RhaiSlides, TocEntry as RhaiTocEntry, Slide as RhaiSlide, Slideshow as RhaiSlides, TocEntry as RhaiTocEntry,
}; };
use crate::db::Collection as DbCollectionTrait; use crate::db::Collection as DbCollectionTrait;
use crate::db::hero::OurDB; use crate::db::hero::OurDB;
@ -565,7 +565,40 @@ mod rhai_library_module {
book.pages.clone() book.pages.clone()
} }
// --- Slides Functions --- // --- Slideshow Functions ---
#[rhai_fn(name = "new_slide")]
pub fn new_slide() -> RhaiSlide {
RhaiSlide::new()
}
#[rhai_fn(name = "title", return_raw, global, pure)]
pub fn slide_title(
slide: &mut RhaiSlide,
title: String,
) -> Result<RhaiSlide, Box<EvalAltResult>> {
let owned = mem::take(slide);
*slide = owned.title(title);
Ok(slide.clone())
}
#[rhai_fn(name = "description", return_raw, global, pure)]
pub fn slide_description(
slide: &mut RhaiSlide,
description: String,
) -> Result<RhaiSlide, Box<EvalAltResult>> {
let owned = mem::take(slide);
*slide = owned.description(description);
Ok(slide.clone())
}
#[rhai_fn(name = "url", return_raw, global, pure)]
pub fn slide_url(slide: &mut RhaiSlide, url: String) -> Result<RhaiSlide, Box<EvalAltResult>> {
let owned = mem::take(slide);
*slide = owned.url(url);
Ok(slide.clone())
}
// --- Slideshow Functions ---
#[rhai_fn(name = "new_slides")] #[rhai_fn(name = "new_slides")]
pub fn new_slides() -> RhaiSlides { pub fn new_slides() -> RhaiSlides {
RhaiSlides::new() RhaiSlides::new()
@ -594,22 +627,10 @@ mod rhai_library_module {
#[rhai_fn(name = "add_slide", return_raw, global, pure)] #[rhai_fn(name = "add_slide", return_raw, global, pure)]
pub fn slides_add_slide( pub fn slides_add_slide(
slides: &mut RhaiSlides, slides: &mut RhaiSlides,
url: String, slide: RhaiSlide,
title: String,
) -> Result<RhaiSlides, Box<EvalAltResult>> { ) -> Result<RhaiSlides, Box<EvalAltResult>> {
let owned = mem::take(slides); let owned = mem::take(slides);
let title_opt = if title.is_empty() { None } else { Some(title) }; *slides = owned.add_slide(slide);
*slides = owned.add_slide(url, title_opt);
Ok(slides.clone())
}
#[rhai_fn(name = "add_slide", return_raw, global, pure)]
pub fn slides_add_slide_no_title(
slides: &mut RhaiSlides,
url: String,
) -> Result<RhaiSlides, Box<EvalAltResult>> {
let owned = mem::take(slides);
*slides = owned.add_slide(url, None);
Ok(slides.clone()) Ok(slides.clone())
} }
@ -638,14 +659,9 @@ mod rhai_library_module {
slides.description.clone() slides.description.clone()
} }
#[rhai_fn(get = "slide_urls", pure)] #[rhai_fn(get = "slides", pure)]
pub fn get_slides_slide_urls(slides: &mut RhaiSlides) -> Vec<String> { pub fn get_slides_slides(slides: &mut RhaiSlides) -> Vec<RhaiSlide> {
slides.slide_urls.clone() slides.slides.clone()
}
#[rhai_fn(get = "slide_titles", pure)]
pub fn get_slides_slide_titles(slides: &mut RhaiSlides) -> Vec<Option<String>> {
slides.slide_titles.clone()
} }
} }
@ -969,7 +985,7 @@ pub fn register_library_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
}, },
); );
// --- Slides DB Functions --- // --- Slideshow DB Functions ---
let db_clone = db.clone(); let db_clone = db.clone();
db_module.set_native_fn( db_module.set_native_fn(
"save_slides", "save_slides",
@ -999,7 +1015,7 @@ pub fn register_library_rhai_module(engine: &mut Engine, db: Arc<OurDB>) {
})? })?
.ok_or_else(|| { .ok_or_else(|| {
Box::new(EvalAltResult::ErrorRuntime( Box::new(EvalAltResult::ErrorRuntime(
format!("Slides with ID {} not found", slides_id).into(), format!("Slideshow with ID {} not found", slides_id).into(),
Position::NONE, Position::NONE,
)) ))
}) })

View File

@ -20,7 +20,7 @@ pub use userexample::User;
// pub use productexample::Product; // Temporarily remove // pub use productexample::Product; // Temporarily remove
pub use biz::{Sale, SaleItem, SaleStatus}; pub use biz::{Sale, SaleItem, SaleStatus};
pub use calendar::{AttendanceStatus, Attendee, Calendar, Event}; pub use calendar::{AttendanceStatus, Attendee, Calendar, Event};
pub use circle::Circle; pub use circle::{Circle, ThemeData};
pub use finance::marketplace::{Bid, BidStatus, Listing, ListingStatus, ListingType}; pub use finance::marketplace::{Bid, BidStatus, Listing, ListingStatus, ListingType};
pub use finance::{Account, Asset, AssetType}; pub use finance::{Account, Asset, AssetType};
pub use flow::{Flow, FlowStep, SignatureRequirement}; pub use flow::{Flow, FlowStep, SignatureRequirement};