use std::time::Duration;
use super::super::{ProgressState, Screen, ScreenEvent};
const SLEEP_MAX_MS: u64 = 10_000;
pub(in crate::screen) fn handle_osc9(screen: &mut Screen, params: &[&[u8]]) {
match params.len() {
0 | 1 => {}
2 => emit_notification(screen, params[1]),
_ => match params[1] {
b"1" => emit_sleep(screen, params[2]),
b"4" => {
if let Some(value) = params.get(3) {
emit_progress(screen, params[2], value);
}
}
_ => {}
},
}
}
fn emit_notification(screen: &mut Screen, body: &[u8]) {
if body.is_empty() {
return;
}
screen
.pending_events
.push(ScreenEvent::DesktopNotification {
title: String::new(),
body: String::from_utf8_lossy(body).into_owned(),
});
}
fn emit_sleep(screen: &mut Screen, ms_bytes: &[u8]) {
let Some(ms) = parse_u64(ms_bytes) else {
return;
};
let clamped = ms.min(SLEEP_MAX_MS);
screen.pending_events.push(ScreenEvent::Sleep {
duration: Duration::from_millis(clamped),
});
}
fn emit_progress(screen: &mut Screen, state_bytes: &[u8], value_bytes: &[u8]) {
let Some(state_num) = parse_u64(state_bytes) else {
return;
};
let state = match state_num {
0 => ProgressState::Remove,
1 => ProgressState::Set,
2 => ProgressState::Error,
3 => ProgressState::Indeterminate,
4 => ProgressState::Warning,
_ => return,
};
let Some(value) = parse_u64(value_bytes) else {
return;
};
let clamped: u8 = value.min(100) as u8;
screen.pending_events.push(ScreenEvent::ProgressReport {
state,
value: clamped,
});
}
fn parse_u64(bytes: &[u8]) -> Option<u64> {
std::str::from_utf8(bytes).ok()?.parse().ok()
}
pub(in crate::screen) fn handle_osc777(screen: &mut Screen, params: &[&[u8]]) {
if params.get(1) != Some(&&b"notify"[..]) {
return;
}
let title = params.get(2).copied().unwrap_or(b"");
let body = params.get(3).copied().unwrap_or(b"");
screen
.pending_events
.push(ScreenEvent::DesktopNotification {
title: String::from_utf8_lossy(title).into_owned(),
body: String::from_utf8_lossy(body).into_owned(),
});
}