From dfaf166635ca4fb67c0c6c51e70e0491a4d50aee Mon Sep 17 00:00:00 2001 From: Gan Jun Kai Date: Thu, 11 Apr 2024 00:53:00 +0800 Subject: [PATCH] feat: Add `active_theme_id` function (#131) * feat: add active_theme_id * feat: clear active theme after new animation or dotlottie is loaded * fix: fix file path error * test: add test for load_animation_path * fix: use str::from_utf8 to read file --- demo-player/src/main.rs | 6 +- dotlottie-ffi/emscripten_bindings.cpp | 3 +- dotlottie-ffi/src/dotlottie_player.udl | 1 + dotlottie-ffi/src/dotlottie_player_cpp.udl | 1 + dotlottie-rs/src/dotlottie_player.rs | 29 +++++++- dotlottie-rs/tests/theming.rs | 80 ++++++++++++++++++++++ 6 files changed, 114 insertions(+), 6 deletions(-) diff --git a/demo-player/src/main.rs b/demo-player/src/main.rs index 90009bca..47e5d6fe 100644 --- a/demo-player/src/main.rs +++ b/demo-player/src/main.rs @@ -143,9 +143,9 @@ fn main() { let mut markers = File::open("src/markers.json").expect("no file found"); let metadatamarkers = fs::metadata("src/markers.json").expect("unable to read metadata"); - let mut markersBuffer = vec![0; metadatamarkers.len() as usize]; - markers.read(&mut markersBuffer).expect("buffer overflow"); - let string = String::from_utf8(markersBuffer.clone()).unwrap(); + let mut markers_buffer = vec![0; metadatamarkers.len() as usize]; + markers.read(&mut markers_buffer).expect("buffer overflow"); + let string = String::from_utf8(markers_buffer.clone()).unwrap(); // lottie_player.load_animation_data(string.as_str(), WIDTH as u32, HEIGHT as u32); // println!("{:?}", Some(lottie_player.manifest())); diff --git a/dotlottie-ffi/emscripten_bindings.cpp b/dotlottie-ffi/emscripten_bindings.cpp index e50e811b..7071f65e 100644 --- a/dotlottie-ffi/emscripten_bindings.cpp +++ b/dotlottie-ffi/emscripten_bindings.cpp @@ -141,5 +141,6 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer) .function("loadTheme", &DotLottiePlayer::load_theme) .function("loadThemeData", &DotLottiePlayer::load_theme_data) .function("markers", &DotLottiePlayer::markers) - .function("activeAnimationId", &DotLottiePlayer::active_animation_id); + .function("activeAnimationId", &DotLottiePlayer::active_animation_id) + .function("activeThemeId", &DotLottiePlayer::active_theme_id); } diff --git a/dotlottie-ffi/src/dotlottie_player.udl b/dotlottie-ffi/src/dotlottie_player.udl index 1346c7a9..e7ab15fe 100644 --- a/dotlottie-ffi/src/dotlottie_player.udl +++ b/dotlottie-ffi/src/dotlottie_player.udl @@ -123,4 +123,5 @@ interface DotLottiePlayer { boolean load_theme_data([ByRef] string theme_data); sequence markers(); string active_animation_id(); + string active_theme_id(); }; diff --git a/dotlottie-ffi/src/dotlottie_player_cpp.udl b/dotlottie-ffi/src/dotlottie_player_cpp.udl index e879e9de..e6d7f5e7 100644 --- a/dotlottie-ffi/src/dotlottie_player_cpp.udl +++ b/dotlottie-ffi/src/dotlottie_player_cpp.udl @@ -126,4 +126,5 @@ interface DotLottiePlayer { boolean load_theme_data([ByRef] string theme_data); sequence markers(); string active_animation_id(); + string active_theme_id(); }; diff --git a/dotlottie-rs/src/dotlottie_player.rs b/dotlottie-rs/src/dotlottie_player.rs index 237eb48e..229a0b9e 100644 --- a/dotlottie-rs/src/dotlottie_player.rs +++ b/dotlottie-rs/src/dotlottie_player.rs @@ -94,6 +94,7 @@ struct DotLottieRuntime { direction: Direction, markers: MarkersMap, active_animation_id: String, + active_theme_id: String, } impl DotLottieRuntime { @@ -116,6 +117,7 @@ impl DotLottieRuntime { direction, markers: MarkersMap::new(), active_animation_id: String::new(), + active_theme_id: String::new(), } } @@ -609,6 +611,8 @@ impl DotLottieRuntime { pub fn load_animation_data(&mut self, animation_data: &str, width: u32, height: u32) -> bool { self.active_animation_id.clear(); + self.active_theme_id.clear(); + self.dotlottie_manager = DotLottieManager::new(None).unwrap(); self.markers = extract_markers(animation_data); @@ -622,6 +626,8 @@ impl DotLottieRuntime { pub fn load_animation_path(&mut self, file_path: &str, width: u32, height: u32) -> bool { self.active_animation_id.clear(); + self.active_theme_id.clear(); + match fs::read_to_string(file_path) { Ok(data) => self.load_animation_data(&data, width, height), Err(_) => false, @@ -630,6 +636,8 @@ impl DotLottieRuntime { pub fn load_dotlottie_data(&mut self, file_data: &[u8], width: u32, height: u32) -> bool { self.active_animation_id.clear(); + self.active_theme_id.clear(); + if self.dotlottie_manager.init(file_data).is_err() { return false; } @@ -746,11 +754,14 @@ impl DotLottieRuntime { } pub fn load_theme(&mut self, theme_id: &str) -> bool { + self.active_theme_id.clear(); + if theme_id.is_empty() { return self.renderer.load_theme_data("").is_ok(); } - self.manifest() + let ok = self + .manifest() .and_then(|manifest| manifest.themes) .map_or(false, |themes| { themes @@ -774,7 +785,13 @@ impl DotLottieRuntime { }) .is_some() }) - }) + }); + + if ok { + self.active_theme_id = theme_id.to_string(); + } + + ok } pub fn load_theme_data(&mut self, theme_data: &str) -> bool { @@ -784,6 +801,10 @@ impl DotLottieRuntime { pub fn active_animation_id(&self) -> &str { &self.active_animation_id } + + pub fn active_theme_id(&self) -> &str { + &self.active_theme_id + } } pub struct DotLottiePlayer { @@ -1094,6 +1115,10 @@ impl DotLottiePlayer { .active_animation_id() .to_string() } + + pub fn active_theme_id(&self) -> String { + self.runtime.read().unwrap().active_theme_id().to_string() + } } unsafe impl Send for DotLottiePlayer {} diff --git a/dotlottie-rs/tests/theming.rs b/dotlottie-rs/tests/theming.rs index 5cbc1e80..a2542002 100644 --- a/dotlottie-rs/tests/theming.rs +++ b/dotlottie-rs/tests/theming.rs @@ -5,6 +5,12 @@ use crate::test_utils::{HEIGHT, WIDTH}; #[cfg(test)] mod tests { + use std::{ + fs::{self, File}, + io::Read, + path::Path, + }; + use super::*; #[test] @@ -22,8 +28,10 @@ mod tests { ); assert!(player.load_dotlottie_data(include_bytes!("assets/test.lottie"), WIDTH, HEIGHT)); + assert!(player.active_theme_id().is_empty()); assert!(player.load_theme(valid_theme_id), "Expected theme to load"); + assert_eq!(player.active_theme_id(), valid_theme_id); assert!(player.is_playing()); } @@ -79,4 +87,76 @@ mod tests { assert!(player.load_theme(""), "Expected theme to unload"); } + + #[test] + fn test_clear_active_theme_id_after_new_animation_data_is_loaded() { + let player = DotLottiePlayer::new(Config { + autoplay: true, + ..Config::default() + }); + + let valid_theme_id = "test_theme"; + + assert!( + !player.load_theme(valid_theme_id), + "Expected theme to not load" + ); + + assert!(player.load_dotlottie_data(include_bytes!("assets/test.lottie"), WIDTH, HEIGHT)); + + assert!(player.load_theme(valid_theme_id), "Expected theme to load"); + assert_eq!(player.active_theme_id(), valid_theme_id); + + let data = std::str::from_utf8(include_bytes!("assets/test.json")).expect("Invalid data."); + assert!(player.load_animation_data(data, WIDTH, HEIGHT)); + assert!(player.active_theme_id().is_empty()); + + assert!(player.is_playing()); + } + + #[test] + fn test_clear_active_theme_id_after_new_animation_path_is_loaded() { + let player = DotLottiePlayer::new(Config { + autoplay: true, + ..Config::default() + }); + + let valid_theme_id = "test_theme"; + + assert!( + !player.load_theme(valid_theme_id), + "Expected theme to not load" + ); + + assert!(player.load_dotlottie_data(include_bytes!("assets/test.lottie"), WIDTH, HEIGHT)); + + assert!(player.load_theme(valid_theme_id), "Expected theme to load"); + assert_eq!(player.active_theme_id(), valid_theme_id); + + assert!(player.load_animation_path("tests/assets/test.json", WIDTH, HEIGHT)); + assert!(player.active_theme_id().is_empty()); + + assert!(player.is_playing()); + } + + #[test] + fn test_clear_active_theme_id_after_new_dotlottie_is_loaded() { + let player = DotLottiePlayer::new(Config { + autoplay: true, + ..Config::default() + }); + + let valid_theme_id = "test_theme"; + + assert!(player.load_dotlottie_data(include_bytes!("assets/test.lottie"), WIDTH, HEIGHT)); + assert!(player.active_theme_id().is_empty()); + + assert!(player.load_theme(valid_theme_id), "Expected theme to load"); + assert_eq!(player.active_theme_id(), valid_theme_id); + + assert!(player.load_dotlottie_data(include_bytes!("assets/emoji.lottie"), WIDTH, HEIGHT)); + assert!(player.active_theme_id().is_empty()); + + assert!(player.is_playing()); + } }