feat(gui): add GuiViewState three-panel split view model (GH-29) #58

Merged
KofTwentyTwo merged 1 commits from feature/GH-29-react-vite-frontend-shell into main 2026-07-23 00:53:35 +00:00
2 changed files with 87 additions and 2 deletions

No files matched your search

+5 -2
View File
@@ -2,16 +2,19 @@
mod ipc;
mod sandbox;
mod view;
use ipc::IpcBridge;
use nuncio_core::EventBus;
use view::GuiViewState;
fn main() {
let bus = EventBus::new();
let state = IpcBridge::get_app_state(&bus);
let view_state = GuiViewState::default();
println!(
"Nuncio GUI Desktop Shell Initialized: status={:?}, unread={}",
state.status, state.unread_count
"Nuncio GUI Desktop Shell Initialized: status={:?}, unread={}, active_folder={}",
state.status, state.unread_count, view_state.active_folder_id
);
}
+82
View File
@@ -0,0 +1,82 @@
//! React/Vite Webview component layout model and state bindings.
use nuncio_core::model::{Email, Folder};
use serde::{Deserialize, Serialize};
/// Frontend split-view layout state container.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GuiViewState {
/// Available folders list.
pub folders: Vec<Folder>,
/// Active selected folder ID.
pub active_folder_id: String,
/// Loaded email message list.
pub messages: Vec<Email>,
/// Currently selected email ID for reading preview.
pub selected_message_id: Option<String>,
/// Dark mode UI theme preference flag.
pub dark_mode: bool,
}
impl GuiViewState {
/// Create a new default GUI view state.
pub fn new() -> Self {
Self {
folders: vec![
Folder {
id: "inbox".to_string(),
name: "Inbox".to_string(),
total_messages: 5,
unread_messages: 2,
},
Folder {
id: "sent".to_string(),
name: "Sent".to_string(),
total_messages: 3,
unread_messages: 0,
},
],
active_folder_id: "inbox".to_string(),
messages: Vec::new(),
selected_message_id: None,
dark_mode: true,
}
}
/// Select active folder.
pub fn select_folder(&mut self, folder_id: &str) {
self.active_folder_id = folder_id.to_string();
self.selected_message_id = None;
}
/// Select active message preview.
pub fn select_message(&mut self, message_id: &str) {
self.selected_message_id = Some(message_id.to_string());
}
}
impl Default for GuiViewState {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gui_view_state_navigation() {
let mut state = GuiViewState::default();
assert_eq!(state.active_folder_id, "inbox");
assert!(state.dark_mode);
state.select_folder("sent");
assert_eq!(state.active_folder_id, "sent");
assert!(state.selected_message_id.is_none());
state.select_message("msg-101");
assert_eq!(state.selected_message_id, Some("msg-101".to_string()));
}
}