Skip to main content

lingxia_platform/traits/
app_runtime.rs

1use std::io::Read;
2use std::path::{Path, PathBuf};
3
4use crate::AssetFileEntry;
5use crate::error::PlatformError;
6
7use super::device::{Device, DeviceHardware};
8use super::file::FileInteraction;
9use super::location::Location;
10use super::media_interaction::{MediaInteraction, MediaKind};
11use super::media_runtime::MediaRuntime;
12use super::network::Network;
13use super::secure_store::SecureStore;
14use super::ui::{PopupPresenter, UIUpdate, UserFeedback};
15use super::update::UpdateService;
16use super::wifi::Wifi;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum AnimationType {
20    None = 0,
21    Forward = 1,
22    Backward = 2,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26pub enum LxAppPresentation {
27    #[default]
28    Normal = 0,
29    Panel = 1,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum OpenUrlTarget {
34    External = 0,
35    SelfTarget = 1,
36    /// Open a new browser tab unconditionally (skips "navigate current tab" heuristic).
37    NewBrowserTab = 2,
38}
39
40impl OpenUrlTarget {
41    pub fn parse(raw: Option<&str>) -> Self {
42        match raw.map(|v| v.trim().to_ascii_lowercase()) {
43            Some(v) if v == "self" => Self::SelfTarget,
44            Some(v) if v == "new_browser_tab" => Self::NewBrowserTab,
45            Some(v) if v == "external" => Self::External,
46            Some(v) => {
47                log::warn!("Invalid openURL target='{}', fallback to external", v);
48                Self::External
49            }
50            None => Self::External,
51        }
52    }
53}
54
55#[derive(Debug, Clone)]
56pub struct OpenUrlRequest {
57    pub owner_appid: String,
58    pub owner_session_id: u64,
59    pub url: String,
60    pub target: OpenUrlTarget,
61}
62
63#[cfg(test)]
64mod tests {
65    use super::OpenUrlTarget;
66
67    #[test]
68    fn parse_supports_new_browser_tab() {
69        assert_eq!(
70            OpenUrlTarget::parse(Some("new_browser_tab")),
71            OpenUrlTarget::NewBrowserTab
72        );
73    }
74
75    #[test]
76    fn parse_unknown_falls_back_to_external() {
77        assert_eq!(
78            OpenUrlTarget::parse(Some("foobar")),
79            OpenUrlTarget::External
80        );
81    }
82}
83
84impl From<i32> for AnimationType {
85    fn from(value: i32) -> Self {
86        match value {
87            1 => AnimationType::Forward,
88            2 => AnimationType::Backward,
89            _ => AnimationType::None,
90        }
91    }
92}
93
94pub trait AppRuntime:
95    Send
96    + Sync
97    + MediaInteraction
98    + MediaRuntime
99    + Network
100    + PopupPresenter
101    + Device
102    + DeviceHardware
103    + SecureStore
104    + FileInteraction
105    + Location
106    + UIUpdate
107    + UpdateService
108    + UserFeedback
109    + Wifi
110    + 'static
111{
112    /// Reads an asset file as a streaming reader.
113    fn read_asset<'a>(&'a self, path: &str) -> Result<Box<dyn Read + 'a>, PlatformError>;
114
115    /// Iterates over files in an asset directory.
116    fn asset_dir_iter<'a>(
117        &'a self,
118        asset_dir: &str,
119    ) -> Box<dyn Iterator<Item = Result<AssetFileEntry<'a>, PlatformError>> + 'a>;
120
121    /// Returns the app's data directory path.
122    fn app_data_dir(&self) -> PathBuf;
123
124    /// Returns the app's cache directory path.
125    fn app_cache_dir(&self) -> PathBuf;
126
127    /// Obtains the application identifier.
128    fn get_app_identifier(&self) -> Result<String, PlatformError>;
129
130    /// Copies media from the system album to a local file.
131    fn copy_album_media_to_file(
132        &self,
133        uri: &str,
134        dest_path: &Path,
135        kind: MediaKind,
136    ) -> Result<(), PlatformError> {
137        MediaRuntime::copy_album_media_to_file(self, uri, dest_path, kind)
138    }
139
140    /// Returns the current system locale.
141    fn get_system_locale(&self) -> &str;
142
143    /// Show the UI container for the given LxApp and route.
144    fn show_lxapp(
145        &self,
146        appid: String,
147        path: String,
148        session_id: u64,
149        presentation: LxAppPresentation,
150        panel_id: String,
151    ) -> Result<(), PlatformError>;
152
153    /// Hide the UI container for the given LxApp (does not destroy its runtime state).
154    fn hide_lxapp(&self, appid: String, session_id: u64) -> Result<(), PlatformError>;
155
156    /// Navigates within the given LxApp using an animation.
157    fn navigate(
158        &self,
159        appid: String,
160        path: String,
161        animation_type: AnimationType,
162    ) -> Result<(), PlatformError>;
163
164    /// Opens the given URL according to the host policy for the requested target.
165    fn open_url(&self, req: OpenUrlRequest) -> Result<(), PlatformError>;
166
167    /// Gets the capsule button bounding rect in screen coordinates.
168    /// Returns JSON: {"width": f64, "height": f64, "top": f64, "right": f64, "bottom": f64, "left": f64}
169    fn get_capsule_rect(
170        &self,
171    ) -> impl std::future::Future<Output = Result<String, PlatformError>> + Send;
172}