From 4001fd2ec8ff05a982da18744b8cbde9df3ab530 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Sat, 6 Jun 2026 17:41:44 +0300 Subject: feat: improve toast ergonomics refs #486 --- src/api/mod.rs | 1 + src/api/schema.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/api/server.rs | 1 + 3 files changed, 80 insertions(+) (limited to 'src/api') diff --git a/src/api/mod.rs b/src/api/mod.rs index 7d2d5bc1..c168313b 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -22,6 +22,7 @@ pub(crate) fn request_changes_ui(request: &Request) -> bool { matches!( &request.method, Method::ServerReloadConfig(_) + | Method::NotificationShow(_) | Method::WorkspaceCreate(_) | Method::WorkspaceFocus(_) | Method::WorkspaceRename(_) diff --git a/src/api/schema.rs b/src/api/schema.rs index c0715758..ce1ca9bd 100644 --- a/src/api/schema.rs +++ b/src/api/schema.rs @@ -24,6 +24,8 @@ pub enum Method { ServerLiveHandoff(ServerLiveHandoffParams), #[serde(rename = "server.reload_config")] ServerReloadConfig(EmptyParams), + #[serde(rename = "notification.show")] + NotificationShow(NotificationShowParams), #[serde(rename = "workspace.create")] WorkspaceCreate(WorkspaceCreateParams), #[serde(rename = "workspace.list")] @@ -130,6 +132,50 @@ pub struct EmptyParams {} #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct PingParams {} +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct NotificationShowParams { + pub title: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub body: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub position: Option, + #[serde(default, skip_serializing_if = "NotificationShowSound::is_none")] + pub sound: NotificationShowSound, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "snake_case")] +pub enum NotificationShowSound { + #[default] + None, + Done, + Request, +} + +impl NotificationShowSound { + pub fn is_none(&self) -> bool { + matches!(self, Self::None) + } + + pub fn to_sound(self) -> Option { + match self { + Self::None => None, + Self::Done => Some(crate::sound::Sound::Done), + Self::Request => Some(crate::sound::Sound::Request), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum NotificationShowReason { + Shown, + Disabled, + RateLimited, + NoForegroundClient, + Busy, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct WorkspaceTarget { pub workspace_id: String, @@ -627,6 +673,10 @@ pub enum ResponseResult { matched_line: Option, read: PaneReadResult, }, + NotificationShow { + shown: bool, + reason: NotificationShowReason, + }, IntegrationInstall { target: IntegrationTarget, details: IntegrationInstallResult, @@ -1063,6 +1113,34 @@ mod tests { assert_eq!(restored, request); } + #[test] + fn notification_show_request_parses() { + let json = r#"{"id":"req_1","method":"notification.show","params":{"title":"build failed","body":"api workspace","position":"top-left","sound":"request"}}"#; + let request: Request = serde_json::from_str(json).unwrap(); + let Method::NotificationShow(params) = request.method else { + panic!("wrong method parsed"); + }; + assert_eq!(params.title, "build failed"); + assert_eq!(params.body.as_deref(), Some("api workspace")); + assert_eq!( + params.position, + Some(crate::config::ToastHerdrPosition::TopLeft) + ); + assert_eq!(params.sound, NotificationShowSound::Request); + } + + #[test] + fn notification_show_sound_defaults_to_none() { + let json = + r#"{"id":"req_1","method":"notification.show","params":{"title":"build failed"}}"#; + let request: Request = serde_json::from_str(json).unwrap(); + let Method::NotificationShow(params) = request.method else { + panic!("wrong method parsed"); + }; + + assert_eq!(params.sound, NotificationShowSound::None); + } + #[test] fn unknown_method_is_rejected() { let json = r#"{"id":"req_1","method":"nope","params":{}}"#; diff --git a/src/api/server.rs b/src/api/server.rs index 7e4dc3b1..e2c4b4a1 100644 --- a/src/api/server.rs +++ b/src/api/server.rs @@ -271,6 +271,7 @@ fn api_method_name(method: &Method) -> &'static str { Method::ServerStop(_) => "server.stop", Method::ServerLiveHandoff(_) => "server.live_handoff", Method::ServerReloadConfig(_) => "server.reload_config", + Method::NotificationShow(_) => "notification.show", Method::WorkspaceCreate(_) => "workspace.create", Method::WorkspaceList(_) => "workspace.list", Method::WorkspaceGet(_) => "workspace.get", -- cgit v1.2.3