Skip to main content

lingxia_platform/traits/
ui.rs

1use std::future::Future;
2
3use lingxia_surface::LayoutPresentationPlan;
4
5use crate::error::PlatformError;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ToastIcon {
9    Success,
10    Error,
11    Loading,
12    None,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ToastPosition {
17    Top,
18    Center,
19    Bottom,
20}
21
22#[derive(Debug, Clone)]
23pub struct ToastOptions {
24    pub title: String,
25    pub icon: ToastIcon,
26    pub image: Option<String>,
27    pub duration: f64,
28    pub mask: bool,
29    pub position: ToastPosition,
30}
31
32#[derive(Debug, Clone)]
33pub struct ModalOptions {
34    pub title: String,
35    pub content: String,
36    pub show_cancel: bool,
37    pub cancel_text: String,
38    pub cancel_color: Option<String>,
39    pub confirm_text: String,
40    pub confirm_color: Option<String>,
41}
42
43#[repr(i32)]
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum SurfaceKind {
46    Window = 0,
47    Overlay = 1,
48}
49
50/// The arbitrated role that drives how the platform presents a surface:
51/// `Main` = a top-level window/primary, `Aside` = a docked split companion,
52/// `Float` = a positioned popup (it keeps its edge/center placement but never
53/// splits the main). Distinguishes a float-popup-at-edge from an aside-dock.
54#[repr(i32)]
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
56pub enum SurfaceRole {
57    #[default]
58    Main = 0,
59    Aside = 1,
60    Float = 2,
61}
62
63#[repr(i32)]
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
65pub enum SurfaceContent {
66    #[default]
67    Page = 0,
68    Url = 1,
69}
70
71#[repr(i32)]
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
73pub enum SurfacePosition {
74    #[default]
75    Center = 0,
76    Bottom = 1,
77    Left = 2,
78    Right = 3,
79    Top = 4,
80}
81
82#[derive(Debug, Clone)]
83pub struct SurfaceRequest {
84    pub id: String,
85    pub app_id: String,
86    pub path: String,
87    pub session_id: u64,
88    pub page_instance_id: String,
89    pub content: SurfaceContent,
90    pub kind: SurfaceKind,
91    pub width: f64,
92    pub height: f64,
93    pub width_ratio: f64,
94    pub height_ratio: f64,
95    pub position: SurfacePosition,
96    /// Arbitrated role; the platform uses it to decide dock vs popup vs window.
97    pub role: SurfaceRole,
98}
99
100pub trait SurfacePresenter: Send + Sync + 'static {
101    /// The shared core resolves a `LayoutPresentationPlan` for one window/graph
102    /// and the platform skin binds it. The per-surface methods below present a
103    /// single surface at a time.
104    fn present_layout(
105        &self,
106        _window_id: &str,
107        _plan: &LayoutPresentationPlan,
108    ) -> Result<(), PlatformError> {
109        Err(PlatformError::NotSupported(
110            "present_layout is not supported on this platform".to_string(),
111        ))
112    }
113
114    fn present_surface(&self, _request: SurfaceRequest) -> Result<(), PlatformError> {
115        Err(PlatformError::NotSupported(
116            "surface is not supported on this platform".to_string(),
117        ))
118    }
119
120    fn close_surface(&self, _app_id: &str, _id: &str, _reason: &str) -> Result<(), PlatformError> {
121        Err(PlatformError::NotSupported(
122            "surface close is not supported on this platform".to_string(),
123        ))
124    }
125
126    fn show_surface(&self, _app_id: &str, _id: &str) -> Result<(), PlatformError> {
127        Err(PlatformError::NotSupported(
128            "surface show is not supported on this platform".to_string(),
129        ))
130    }
131
132    fn hide_surface(&self, _app_id: &str, _id: &str) -> Result<(), PlatformError> {
133        Err(PlatformError::NotSupported(
134            "surface hide is not supported on this platform".to_string(),
135        ))
136    }
137
138    /// Show or hide a top-level surface declared by the host (e.g. the AI-chat
139    /// panel or terminal in `ui` config). Only platforms with a host shell that
140    /// manages declared surfaces (currently macOS) support it; others have no
141    /// such shell and return `NotSupported`.
142    fn set_managed_surface_visible(&self, _id: &str, _visible: bool) -> Result<(), PlatformError> {
143        Err(PlatformError::NotSupported(
144            "managed surfaces are not supported on this platform".to_string(),
145        ))
146    }
147
148    /// Toggle a host-declared top-level surface's visibility. See
149    /// [`set_managed_surface_visible`](Self::set_managed_surface_visible).
150    fn toggle_managed_surface(&self, _id: &str) -> Result<(), PlatformError> {
151        Err(PlatformError::NotSupported(
152            "managed surfaces are not supported on this platform".to_string(),
153        ))
154    }
155}
156
157pub trait UIUpdate: Send + Sync + 'static {
158    fn update_navbar_ui(&self, appid: String) -> Result<(), PlatformError>;
159    fn update_tabbar_ui(&self, appid: String) -> Result<(), PlatformError>;
160
161    fn update_orientation_ui(&self, _appid: String) -> Result<(), PlatformError> {
162        Err(PlatformError::NotSupported(
163            "update_orientation_ui not implemented for this platform".to_string(),
164        ))
165    }
166}
167
168pub trait UserFeedback: Send + Sync + 'static {
169    fn show_toast(&self, options: ToastOptions) -> Result<(), PlatformError>;
170    fn hide_toast(&self) -> Result<(), PlatformError>;
171
172    fn show_modal(
173        &self,
174        options: ModalOptions,
175    ) -> impl Future<Output = Result<String, PlatformError>> + Send;
176
177    fn show_action_sheet(
178        &self,
179        options: Vec<String>,
180        cancel_text: String,
181        item_color: String,
182    ) -> impl Future<Output = Result<String, PlatformError>> + Send;
183}