use std::{
collections::HashMap,
path::PathBuf,
sync::{Arc, Mutex, RwLock},
};
pub type VirtualModulesStore = Arc<Mutex<HashMap<String, String>>>;
#[derive(Clone, Debug, Default)]
pub struct RuntimeContext {
pub app_version: String,
pub app_data_dir: Option<PathBuf>,
pub resource_dir: Option<PathBuf>,
pub workspace_dir: Option<PathBuf>,
pub dev_mode: bool,
pub ready: bool,
pub rpc_port: Option<u16>,
pub echo_server_port: Option<u16>,
pub mcp_server_port: Option<u16>,
}
#[derive(Clone, Debug)]
pub enum RuntimeEvent {
Renderer(String),
Failure(String),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PermissionPromptResponse {
Allow,
AllowAll,
Deny,
}
pub trait RuntimeHost: Send + Sync + 'static {
fn emit_event(&self, event: RuntimeEvent);
fn confirm(&self, _title: &str, _message: &str, _yes: &str, _no: &str, _cancel: &str) -> bool {
false
}
fn prompt_permission(
&self,
message: &str,
name: &str,
api_name: Option<&str>,
_is_unary: bool,
) -> PermissionPromptResponse {
let api_suffix = api_name
.map(|api| format!("\nRequested by: {api}"))
.unwrap_or_default();
let title = format!("Allow {name} permission?");
if self.confirm(
&title,
&format!("{message}{api_suffix}"),
"Allow",
"Deny",
"Deny",
) {
PermissionPromptResponse::Allow
} else {
PermissionPromptResponse::Deny
}
}
}
#[derive(Default)]
pub struct NoopHost;
impl RuntimeHost for NoopHost {
fn emit_event(&self, _event: RuntimeEvent) {}
}
pub struct RuntimeState {
pub context: RwLock<RuntimeContext>,
pub virtual_modules: VirtualModulesStore,
pub event_sender: Mutex<Option<tokio::sync::mpsc::UnboundedSender<String>>>,
}
impl RuntimeState {
pub fn new(context: RuntimeContext) -> Self {
Self {
context: RwLock::new(context),
virtual_modules: Arc::new(Mutex::new(HashMap::new())),
event_sender: Mutex::new(None),
}
}
}