Skip to main content

lingxia_platform/traits/
media_interaction.rs

1use std::future::Future;
2
3use crate::error::PlatformError;
4
5#[derive(Debug, Clone)]
6pub struct PreviewMediaItem {
7    pub path: String,
8    pub media_type: MediaKind,
9    pub rotate: Option<u16>,
10    pub object_fit: Option<MediaObjectFit>,
11    pub duration_ms: Option<u64>,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
15pub enum PreviewMediaAdvance {
16    #[default]
17    Manual,
18    Next,
19    Loop,
20}
21
22impl PreviewMediaAdvance {
23    pub fn as_str(self) -> &'static str {
24        match self {
25            Self::Manual => "manual",
26            Self::Next => "next",
27            Self::Loop => "loop",
28        }
29    }
30}
31
32#[derive(Debug, Clone)]
33pub struct PreviewMediaRequest {
34    pub items: Vec<PreviewMediaItem>,
35    pub start_index: i32,
36    pub advance: PreviewMediaAdvance,
37    pub show_index_indicator: bool,
38    /// Callback_id for the final preview result. Fires once when the session
39    /// ends (manual/auto/interrupted/error). Payload: serialized
40    /// `PreviewMediaResultObj` ({reason, lastIndex}).
41    pub callback_id: u64,
42    /// Callback_id for the "first frame composited" signal. Fires once when
43    /// the first pixel of the underlying media has been painted to screen.
44    /// Native MAY skip on degenerate paths (abort before any item rendered,
45    /// process tear-down, etc.) — the JS-side `presented` Promise is also
46    /// woken by a fallback when `completed` settles, and by a total timeout
47    /// after that, so it never hangs. The callback payload, when fired, is
48    /// an empty JSON object `{}`.
49    pub presented_callback_id: u64,
50    /// Stream callback_id for current-item changes. Native fires it with
51    /// payload `{"index": N}` whenever the displayed item changes — including
52    /// the initially displayed item — for swipes, taps, and auto-advance.
53    /// Consecutive duplicates are tolerated (the JS side dedupes); missing
54    /// the initial fire is also tolerated (the JS side seeds the snapshot
55    /// from startIndex).
56    pub change_callback_id: u64,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum MediaKind {
61    Image,
62    Video,
63    Unknown,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum MediaObjectFit {
68    Cover,
69    Contain,
70    Fill,
71    Fit,
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum ChooseMediaMode {
76    Images,
77    Videos,
78    Mix,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum MediaSource {
83    Album,
84    Camera,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum CameraFacing {
89    Front,
90    Back,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub enum MediaQuality {
95    Original,
96    Compressed,
97}
98
99#[derive(Debug, Clone)]
100pub struct ChooseMediaRequest {
101    pub max_count: u32,
102    pub mode: ChooseMediaMode,
103    pub source_types: Vec<MediaSource>,
104    pub max_duration_seconds: Option<u32>,
105    pub camera_facing: Option<CameraFacing>,
106}
107
108impl Default for ChooseMediaRequest {
109    fn default() -> Self {
110        Self {
111            max_count: 9,
112            mode: ChooseMediaMode::Images,
113            source_types: vec![MediaSource::Album, MediaSource::Camera],
114            max_duration_seconds: None,
115            camera_facing: None,
116        }
117    }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum ScanType {
122    BarCode,
123    QrCode,
124    DataMatrix,
125    Pdf417,
126}
127
128#[derive(Debug, Clone)]
129pub struct ScanCodeRequest {
130    pub scan_types: Vec<ScanType>,
131    pub only_from_camera: bool,
132}
133
134impl Default for ScanCodeRequest {
135    fn default() -> Self {
136        Self {
137            scan_types: Vec::new(),
138            only_from_camera: true,
139        }
140    }
141}
142
143#[derive(Debug, Clone)]
144pub struct SaveMediaRequest {
145    pub file_uri: String,
146}
147
148pub trait MediaInteraction: Send + Sync + 'static {
149    /// Preview media. Keeps callback_id pattern for AbortSignal support.
150    fn preview_media(&self, request: PreviewMediaRequest) -> Result<(), PlatformError>;
151    fn cancel_preview(&self, callback_id: u64) -> Result<(), PlatformError>;
152
153    fn choose_media(
154        &self,
155        request: ChooseMediaRequest,
156    ) -> impl Future<Output = Result<String, PlatformError>> + Send;
157
158    fn scan_code(
159        &self,
160        request: ScanCodeRequest,
161    ) -> impl Future<Output = Result<String, PlatformError>> + Send;
162
163    fn save_image_to_photos_album(
164        &self,
165        request: SaveMediaRequest,
166    ) -> impl Future<Output = Result<(), PlatformError>> + Send;
167
168    fn save_video_to_photos_album(
169        &self,
170        request: SaveMediaRequest,
171    ) -> impl Future<Output = Result<(), PlatformError>> + Send;
172}