Skip to main content

siglus_scene_vm/runtime/
native_ui.rs

1//! Platform UI bridge for runtime modal operations.
2//!
3//! The VM must not synchronously block on platform UI. Mobile ports should show
4//! the native dialog on the platform UI thread, then deliver the selected button
5//! back through `CommandContext::submit_native_messagebox_result` from the main
6//! engine loop or an event-loop callback.
7
8use std::collections::VecDeque;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum NativeMessageBoxKind {
12    Ok,
13    OkCancel,
14    YesNo,
15    YesNoCancel,
16}
17
18impl NativeMessageBoxKind {
19    pub fn from_system_op(op: i32) -> Self {
20        match op {
21            18 | 8 => Self::OkCancel,
22            19 | 9 => Self::YesNo,
23            20 | 10 => Self::YesNoCancel,
24            _ => Self::Ok,
25        }
26    }
27}
28
29#[derive(Debug, Clone)]
30pub struct NativeMessageBoxButton {
31    pub label: String,
32    pub value: i64,
33}
34
35#[derive(Debug, Clone)]
36pub struct NativeMessageBoxRequest {
37    pub request_id: u64,
38    pub kind: NativeMessageBoxKind,
39    pub title: String,
40    pub message: String,
41    pub buttons: Vec<NativeMessageBoxButton>,
42    pub debug_only: bool,
43}
44
45pub trait NativeUiBackend: Send + Sync {
46    fn show_system_messagebox(&self, request: NativeMessageBoxRequest);
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub struct NativeMessageBoxResult {
51    pub request_id: u64,
52    pub value: i64,
53}
54
55#[derive(Debug, Clone)]
56pub struct NativeUiRuntime {
57    next_messagebox_request_id: u64,
58    messagebox_results: VecDeque<NativeMessageBoxResult>,
59}
60
61impl Default for NativeUiRuntime {
62    fn default() -> Self {
63        Self {
64            next_messagebox_request_id: 1,
65            messagebox_results: VecDeque::new(),
66        }
67    }
68}
69
70impl NativeUiRuntime {
71    pub fn next_messagebox_request_id(&mut self) -> u64 {
72        let id = self.next_messagebox_request_id;
73        self.next_messagebox_request_id = self.next_messagebox_request_id.wrapping_add(1).max(1);
74        id
75    }
76
77    pub fn enqueue_messagebox_result(&mut self, request_id: u64, value: i64) {
78        self.messagebox_results
79            .push_back(NativeMessageBoxResult { request_id, value });
80    }
81
82    pub fn pop_messagebox_result(&mut self) -> Option<NativeMessageBoxResult> {
83        self.messagebox_results.pop_front()
84    }
85}