Add session-owned Pomodoro cycles and controls

Add configurable work and break intervals, pause/resume, CLI and activity-popup controls, and silent completion alerts. Use CLOCK_BOOTTIME deadlines so running timers include suspend without consuming paused time.

Refs #31
This commit is contained in:
Samuel Onoja committed 2026-10-20 15:19:55 +01:00
1 parent 53ba599918
commit 2c9bb85f2c
18 files changed
+1209 -16

No files matched your search

+6 -1
View File
@@ -24,6 +24,11 @@ pub enum Command {
#[command(subcommand)]
action: LauncherAction,
},
/// Control the session’s work and break timer.
Pomodoro {
#[command(subcommand)]
action: crate::pomodoro::Action,
},
/// Publish bounded activity data owned by the invoking shell.
Activity {
#[command(subcommand)]
@@ -248,7 +253,7 @@ pub enum LauncherAction {
impl Command {
pub fn ipc(&self) -> Option<(&'static str, Value)> {
let (command, args) = match self {
Self::Activity { .. } | Self::Run { .. } => return None,
Self::Pomodoro { .. } | Self::Activity { .. } | Self::Run { .. } => return None,
Self::Launcher {
action: LauncherAction::Toggle,
} => ("toggle-launcher", json!({})),
+2
View File
@@ -2,6 +2,7 @@ mod activities;
mod autostart;
mod cli;
mod output;
mod pomodoro;
use std::error::Error;
use std::io::Write;
@@ -55,6 +56,7 @@ fn main() -> Result<(), Box<dyn Error>> {
match &cli.command {
Command::Theme { action } => theme_command(action, &socket, cli.json),
Command::Activity { action } => activities::command(action, &socket, cli.json),
Command::Pomodoro { action } => pomodoro::command(action, &socket, cli.json),
Command::EventStream => event_stream(&socket),
command => {
let (command, args) = command.ipc().expect("IPC command");
+42
View File
@@ -0,0 +1,42 @@
use clap::Subcommand;
use ferese_ipc::activities::{PomodoroAction, PomodoroRequest, VERSION};
use std::{error::Error, os::unix::net::UnixStream, path::Path, time::Duration};
#[derive(Debug, Subcommand)]
pub enum Action {
/// Start a session using activities.pomodoro settings.
Start,
Pause,
Resume,
/// Skip the current interval, or start a phase that is ready.
Next,
/// Cancel and remove the session without a completion alert.
Stop,
/// Cancel and start a new session with current settings.
Reset,
Status,
}
pub fn command(action: &Action, socket: &Path, json: bool) -> Result<(), Box<dyn Error>> {
let action = match action {
Action::Start => PomodoroAction::Start,
Action::Pause => PomodoroAction::Pause,
Action::Resume => PomodoroAction::Resume,
Action::Next => PomodoroAction::Next,
Action::Stop => PomodoroAction::Stop,
Action::Reset => PomodoroAction::Reset,
Action::Status => PomodoroAction::Status,
};
let mut stream = UnixStream::connect(socket)?;
stream.set_read_timeout(Some(Duration::from_secs(2)))?;
stream.set_write_timeout(Some(Duration::from_secs(2)))?;
let result = super::request(
&mut stream,
"pomodoro",
serde_json::to_value(PomodoroRequest {
version: VERSION,
action,
session: None,
})?,
)?;
super::output::print(&result, json)
}