Files
feresaria/crates/ferese-ipc/src/activities.rs
T
Samuel OnojaandSamuel Onoja 6b0d903ad0 Add Live Activities as configurable bar items (#30)
* 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]>
2026-10-12 22:52:25 +01:00

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![],
}
}
}