//! Rust-owned PTY sessions and the typed Tauri transport for Buzz Substrate. use std::io::{Read, Write}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::thread::JoinHandle; use buzz_terminal::context::{context_vars, GuiContext}; use buzz_terminal::damage::{Frame, Style}; use buzz_terminal::{Fences, SharedTerminal, Size, Terminal, Viewport}; use portable_pty::{native_pty_system, CommandBuilder, MasterPty, PtySize}; use serde::{Deserialize, Serialize}; use tauri::ipc::Channel; use uuid::Uuid; use crate::terminal_transport::{FramePublisher, OfferError, Publication, SubscriptionId}; mod scroll_sign; use scroll_sign::{scroll_by_dom_lines, DomLines}; const MAX_LIVE_SESSIONS: usize = 20; const MAX_INPUT_BYTES: usize = 1024 * 1024; type Result = std::result::Result; #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct AttachRequest { /// Present when a renderer remounts onto an existing PTY-backed tab. session_id: Option, channel_id: String, channel_name: String, thread_id: Option, npub: String, relay_url: String, columns: u16, rows: u16, pixel_width: u16, pixel_height: u16, } #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub(crate) struct WireViewport { generation: u64, columns: usize, screen_lines: usize, } impl From for WireViewport { fn from(value: Viewport) -> Self { Self { generation: value.generation, columns: value.columns, screen_lines: value.screen_lines, } } } impl From for Viewport { fn from(value: WireViewport) -> Self { Self { generation: value.generation, columns: value.columns, screen_lines: value.screen_lines, } } } #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct AttachResponse { session_id: String, subscription_id: String, viewport: WireViewport, } #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct WireStyle { fg: u32, bg: u32, flags: u16, } impl From