ferroui_browser/
browser_runtime_platform.rs1use crate::interop::ferro_module;
2use ferroui_base::platform::{
3 AssetAssembly, IAssetLoader, IRuntimePlatform, RuntimePlatformInfo, StandardAssetLoader, StandardRuntimePlatform,
4};
5use ferroui_base::utilities::DateTime;
6use ferroui_base::FerroLocator;
7use ferroui_controls::AppBuilder;
8use std::cell::Cell;
9use std::rc::Rc;
10
11pub struct BrowserRuntimePlatformServices;
13
14impl BrowserRuntimePlatformServices {
15 pub fn use_browser_runtime_platform_subsystem(builder: &AppBuilder) -> AppBuilder {
17 builder.use_runtime_platform_subsystem(|| Self::register(None), "BrowserRuntimePlatform")
18 }
19
20 pub fn register(assembly: Option<&AssetAssembly>) {
24 let asset_loader: Rc<dyn IAssetLoader> = Rc::new(StandardAssetLoader::new(assembly));
25 FerroLocator::current_mutable()
26 .bind::<dyn IRuntimePlatform>()
27 .to_singleton::<BrowserRuntimePlatform>(|instance| instance)
28 .bind::<dyn IAssetLoader>()
29 .to_constant(asset_loader);
30 }
31}
32
33ferroui_base::ferro_thread_local! {
34 static INFO: Cell<Option<RuntimePlatformInfo>> = const { Cell::new(None) };
35}
36
37#[derive(Default)]
40pub struct BrowserRuntimePlatform {
41 base: StandardRuntimePlatform,
42}
43
44impl BrowserRuntimePlatform {
45 fn runtime_info(is_mobile: bool, is_tv: bool) -> RuntimePlatformInfo {
47 RuntimePlatformInfo { is_mobile: is_mobile && !is_tv, is_desktop: !is_mobile && !is_tv, is_tv }
48 }
49}
50
51impl IRuntimePlatform for BrowserRuntimePlatform {
52 fn get_runtime_info(&self) -> RuntimePlatformInfo {
53 INFO.with(|info| match info.get() {
54 Some(value) => value,
55 None => {
56 let is_mobile = ferro_module::is_mobile();
57 let is_tv = ferro_module::is_tv();
58 let result = Self::runtime_info(is_mobile, is_tv);
59 info.set(Some(result));
60 result
61 }
62 })
63 }
64
65 fn get_utc_now(&self) -> DateTime {
66 self.base.get_utc_now()
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn a_device_is_exactly_one_of_desktop_mobile_and_tv() {
76 for (is_mobile, is_tv, expected) in [
77 (false, false, (true, false, false)),
78 (true, false, (false, true, false)),
79 (false, true, (false, false, true)),
80 (true, true, (false, false, true)),
81 ] {
82 let info = BrowserRuntimePlatform::runtime_info(is_mobile, is_tv);
83
84 assert_eq!(expected, (info.is_desktop, info.is_mobile, info.is_tv), "mobile={is_mobile} tv={is_tv}");
85 }
86 }
87}