* Add Live Activities as configurable bar items * Fix activity owner monitoring and Morph list interactions * Keep activity rows stable during updates and tighten their layout * Use subtle theme tint for activity cards * Tighten activity title and progress spacing * Use theme accent for active progress rings * Fit compact activities to measured titles and badge * Expose Live Activities display controls in Settings * Open activity terminals and streamline the Morph header * Give Morph continuous icons and prioritize workspace navigation * Show activity progress inside its ring * Inset activity progress rings and strengthen their stroke * Fix activity lifecycle, command output handling and list navigation * Reduce activity update work and harden publisher lifetimes * Set up Live Activities for the detected user shell during installation * Document Activities setup, daily use and troubleshooting * Preserve Morph idle width across empty activity updates * Fix dimming flicker, hide inactive music tab and consolidate Activities docs * Fix panel clearance across styles and match previews to theme settings * Prevent panel blur from repainting neighboring islands --------- Co-authored-by: Samuel Onoja <[email protected]>
103 lines
2.6 KiB
Rust
103 lines
2.6 KiB
Rust
//! Activity schema uses the session's existing versioned framing and socket.
|
|
use ferese_activities::{Activity, Data, Id, Limits, Value};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
pub const VERSION: u32 = 1;
|
|
|
|
pub fn now_ms() -> u64 {
|
|
let mut time = libc::timespec { tv_sec: 0, tv_nsec: 0 };
|
|
// SAFETY: time is a correctly sized writable timespec. CLOCK_BOOTTIME
|
|
// includes suspend, unlike the renderer's animation clock.
|
|
if unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &raw mut time) } != 0 {
|
|
return 0;
|
|
}
|
|
(time.tv_sec.max(0) as u64)
|
|
.saturating_mul(1_000)
|
|
.saturating_add(time.tv_nsec.max(0) as u64 / 1_000_000)
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
pub enum OwnerScope {
|
|
#[default]
|
|
Parent,
|
|
Publisher,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(tag = "action", rename_all = "kebab-case", deny_unknown_fields)]
|
|
pub enum Publish {
|
|
Start {
|
|
local: String,
|
|
data: Data,
|
|
lease_ms: Option<u64>,
|
|
},
|
|
Update {
|
|
local: String,
|
|
handle: Option<Id>,
|
|
value: Option<Value>,
|
|
lease_ms: Option<u64>,
|
|
},
|
|
End {
|
|
local: String,
|
|
handle: Option<Id>,
|
|
result: ferese_activities::State,
|
|
message: Option<String>,
|
|
},
|
|
Cancel {
|
|
local: String,
|
|
handle: Option<Id>,
|
|
},
|
|
/// Opt-in rule matching. Raw metadata is discarded before dispatch.
|
|
Hook {
|
|
local: String,
|
|
command: String,
|
|
cwd: String,
|
|
},
|
|
Run {
|
|
local: String,
|
|
title: Option<String>,
|
|
command: String,
|
|
cwd: String,
|
|
},
|
|
}
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct Request {
|
|
pub version: u32,
|
|
#[serde(default)]
|
|
pub owner: OwnerScope,
|
|
pub publish: Publish,
|
|
}
|
|
/// Assigned by the compositor, never supplied by publishers.
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct ActivityWindow {
|
|
pub activity: Id,
|
|
pub window: u64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct Snapshot {
|
|
pub version: u32,
|
|
pub revision: u64,
|
|
pub now_ms: u64,
|
|
pub limits: Limits,
|
|
pub activities: Vec<Activity>,
|
|
#[serde(default)]
|
|
pub windows: Vec<ActivityWindow>,
|
|
}
|
|
impl Default for Snapshot {
|
|
fn default() -> Self {
|
|
Self {
|
|
version: VERSION,
|
|
revision: 0,
|
|
now_ms: now_ms(),
|
|
limits: Limits::default(),
|
|
activities: vec![],
|
|
windows: vec![],
|
|
}
|
|
}
|
|
}
|