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 NewBrowserTab = 2,
39 AsideBrowser = 3,
42}
43
44impl OpenUrlTarget {
45 pub fn parse(raw: Option<&str>) -> Self {
46 match raw.map(|v| v.trim().to_ascii_lowercase()) {
47 Some(v) if v == "self" => Self::SelfTarget,
48 Some(v) if v == "new_browser_tab" => Self::NewBrowserTab,
49 Some(v) if v == "aside" => Self::AsideBrowser,
50 Some(v) if v == "external" => Self::External,
51 Some(v) => {
52 log::warn!("Invalid openURL target='{}', fallback to external", v);
53 Self::External
54 }
55 None => Self::External,
56 }
57 }
58}
59
60#[derive(Debug, Clone)]
61pub struct OpenUrlRequest {
62 pub owner_appid: String,
63 pub owner_session_id: u64,
64 pub url: String,
65 pub target: OpenUrlTarget,
66}
67
68impl From<i32> for AnimationType {
69 fn from(value: i32) -> Self {
70 match value {
71 1 => AnimationType::Forward,
72 2 => AnimationType::Backward,
73 _ => AnimationType::None,
74 }
75 }
76}
77
78pub trait AppRuntime:
79 Send
80 + Sync
81 + MediaInteraction
82 + MediaRuntime
83 + Network
84 + SurfacePresenter
85 + Device
86 + DeviceHardware
87 + SecureStore
88 + ShareService
89 + FileService
90 + Location
91 + UIUpdate
92 + UpdateService
93 + UserFeedback
94 + Wifi
95 + 'static
96{
97 fn read_asset<'a>(&'a self, path: &str) -> Result<Box<dyn Read + 'a>, PlatformError>;
99
100 fn asset_dir_iter<'a>(
102 &'a self,
103 asset_dir: &str,
104 ) -> Box<dyn Iterator<Item = Result<AssetFileEntry<'a>, PlatformError>> + 'a>;
105
106 fn app_data_dir(&self) -> PathBuf;
108
109 fn app_cache_dir(&self) -> PathBuf;
111
112 fn get_app_identifier(&self) -> Result<String, PlatformError>;
114
115 fn copy_album_media_to_file(
117 &self,
118 uri: &str,
119 dest_path: &Path,
120 kind: MediaKind,
121 ) -> Result<(), PlatformError> {
122 MediaRuntime::copy_album_media_to_file(self, uri, dest_path, kind)
123 }
124
125 fn get_system_locale(&self) -> &str;
127
128 fn show_lxapp(
130 &self,
131 appid: String,
132 path: String,
133 session_id: u64,
134 open_mode: LxAppOpenMode,
135 panel_id: String,
136 ) -> Result<(), PlatformError>;
137
138 fn hide_lxapp(&self, appid: String, session_id: u64) -> Result<(), PlatformError>;
140
141 fn exit(&self) -> Result<(), PlatformError>;
143
144 fn set_tray_badge(&self, _text: &str) -> Result<(), PlatformError> {
151 Ok(())
152 }
153
154 fn set_tray_icon(&self, _icon: &str) -> Result<(), PlatformError> {
156 Ok(())
157 }
158
159 fn set_shell_activators(
162 &self,
163 _items: &[lingxia_shell::ResolvedShellActivator],
164 ) -> Result<(), PlatformError> {
165 Ok(())
166 }
167
168 fn set_shell_pins(&self, _items: &[lingxia_shell::ShellPin]) -> Result<(), PlatformError> {
171 Ok(())
172 }
173
174 fn set_tray_title(&self, _text: &str) -> Result<(), PlatformError> {
176 Ok(())
177 }
178
179 fn set_app_badge(&self, _text: &str) -> Result<(), PlatformError> {
182 Ok(())
183 }
184
185 fn autostart_is_enabled(&self) -> Result<bool, PlatformError> {
189 Err(PlatformError::NotSupported("autostart".to_string()))
190 }
191
192 fn autostart_set_enabled(&self, _enabled: bool) -> Result<(), PlatformError> {
194 Err(PlatformError::NotSupported("autostart".to_string()))
195 }
196
197 fn set_tray_menu(&self, _items_json: &str) -> Result<(), PlatformError> {
201 Ok(())
202 }
203
204 fn set_tray_visible(&self, _visible: bool) -> Result<(), PlatformError> {
206 Ok(())
207 }
208
209 fn set_tray_click_intercept(&self, _intercept: bool) -> Result<(), PlatformError> {
213 Ok(())
214 }
215
216 fn navigate(
218 &self,
219 appid: String,
220 path: String,
221 animation_type: AnimationType,
222 ) -> Result<(), PlatformError>;
223
224 fn open_url(&self, req: OpenUrlRequest) -> Result<(), PlatformError>;
226
227 fn get_capsule_rect(
230 &self,
231 ) -> impl std::future::Future<Output = Result<String, PlatformError>> + Send;
232}
233
234#[cfg(test)]
235mod tests {
236 use super::OpenUrlTarget;
237
238 #[test]
239 fn parse_supports_new_browser_tab() {
240 assert_eq!(
241 OpenUrlTarget::parse(Some("new_browser_tab")),
242 OpenUrlTarget::NewBrowserTab
243 );
244 }
245
246 #[test]
247 fn parse_unknown_falls_back_to_external() {
248 assert_eq!(
249 OpenUrlTarget::parse(Some("foobar")),
250 OpenUrlTarget::External
251 );
252 }
253}