use serde::{Deserialize, Serialize};
pub type SurfaceId = String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Role {
Main,
Aside,
Float,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Edge {
Left,
Right,
Top,
Bottom,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum SurfaceContent {
Entry {
id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
path: Option<String>,
},
Web {
url: String,
#[serde(
default = "default_reuse_by_url",
skip_serializing_if = "is_reuse_by_url"
)]
reuse_by_url: bool,
},
}
const fn default_reuse_by_url() -> bool {
true
}
fn is_reuse_by_url(value: &bool) -> bool {
*value
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum SlotKind {
Lxapp,
Browser,
Native,
}
impl SurfaceContent {
pub fn slot_kind(&self) -> SlotKind {
match self {
SurfaceContent::Web { .. } => SlotKind::Browser,
SurfaceContent::Entry { id, .. } if id == "terminal" => SlotKind::Native,
SurfaceContent::Entry { .. } => SlotKind::Lxapp,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "scope", rename_all = "camelCase")]
pub enum SurfaceOwner {
Page { page_instance_id: String },
Lxapp { app_id: String },
Host,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Placement {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub edge: Option<Edge>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub preferred_size: Option<f64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SurfaceState {
Mounted,
Hidden,
Minimized,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "to", rename_all = "lowercase")]
pub enum FloatAnchor {
Screen,
Surface { surface_id: SurfaceId },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum FloatDismiss {
TapOutside,
Manual,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SurfaceInteraction {
pub close_button: bool,
pub dismiss: FloatDismiss,
pub modal: bool,
}
impl SurfaceInteraction {
pub const fn standard() -> Self {
Self {
close_button: false,
dismiss: FloatDismiss::TapOutside,
modal: false,
}
}
pub const fn url_callback() -> Self {
Self {
close_button: true,
dismiss: FloatDismiss::Manual,
modal: true,
}
}
pub const fn window() -> Self {
Self {
close_button: false,
dismiss: FloatDismiss::Manual,
modal: false,
}
}
}
impl Default for SurfaceInteraction {
fn default() -> Self {
Self::standard()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FloatSpec {
pub anchor: FloatAnchor,
pub dismiss: FloatDismiss,
pub modal: bool,
pub close_button: bool,
}
impl Default for FloatSpec {
fn default() -> Self {
Self {
anchor: FloatAnchor::Screen,
dismiss: FloatDismiss::TapOutside,
modal: false,
close_button: false,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Surface {
pub id: SurfaceId,
pub role: Role,
pub content: SurfaceContent,
pub owner: SurfaceOwner,
#[serde(default)]
pub placement: Placement,
pub state: SurfaceState,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub float: Option<FloatSpec>,
}
impl Surface {
pub fn entry(id: impl Into<SurfaceId>, role: Role, entry_id: impl Into<String>) -> Self {
Self {
id: id.into(),
role,
content: SurfaceContent::Entry {
id: entry_id.into(),
path: None,
},
owner: SurfaceOwner::Host,
placement: Placement::default(),
state: SurfaceState::Mounted,
float: if role == Role::Float {
Some(FloatSpec::default())
} else {
None
},
}
}
pub fn is_modal_float(&self) -> bool {
self.role == Role::Float && self.float.as_ref().is_some_and(|f| f.modal)
}
}