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