Three opt-in rituals, all default OFF. Research-anchored (Barkley's point-of-performance, Sweller cognitive-load theory, Newport shutdown ritual, Gollwitzer implementation intentions, Thaler/Sunstein nudge with informed consent for the ADHD audience). Morning triage: modal gated on ritualsMorning toggle, configurable trigger time (default 08:00 to respect ADHD sleep inertia rather than the spec's 06:00), "pick up to three for today" with a gentle swap message on the fourth attempt. Skip sets last-shown-today so it never re-prompts the same calendar day. last-shown persists via kon_storage. Evening wind-down: dedicated page, user-triggered only (tray menu + Settings button). Mechanical closure + physical reset + intentional cue — the whole Newport template. Open loops are read-only reflection; Tasks page owns transactions. Copy is additive throughout: "you finished X today", never "you didn't finish Y". Autostart: tauri-plugin-autostart registered (LaunchAgent on macOS, .desktop on Linux, registry Run on Windows). No bespoke Rust commands — frontend calls the plugin's invoke-handlers directly. Toggle in Settings is one-way (click → OS call → state update) to avoid the UI lying during the round-trip. First-run presents a forced-choice prompt for all three options, with "skip all" escape hatches per step. Copy audit against RSD literature: no "overdue", "failed", or day-to-day comparison framing anywhere in ritual surfaces. Post-v0.1 ideas captured in the roadmap: calendar integration (read-only ICS as interim, cloud sync parked) and right-click-to-task (in-app simple, system-wide a separate phase).
44 lines
1.6 KiB
Rust
44 lines
1.6 KiB
Rust
//! Phase 5 of the feature-complete roadmap: start- and shutdown-rituals.
|
|
//!
|
|
//! Layer-1 scope is narrow. The frontend owns rendering and logic; this
|
|
//! module only persists the "last date the morning triage modal was
|
|
//! shown" sentinel so the modal can refuse to re-prompt on the same
|
|
//! calendar day. Task queries re-use `list_tasks_cmd` with client-side
|
|
//! filtering rather than adding a second query path.
|
|
//!
|
|
//! Stored under the existing SQLite settings table via
|
|
//! `kon_storage::{get_setting, set_setting}` — same bag as
|
|
//! `kon_preferences`.
|
|
|
|
use kon_storage::{get_setting, set_setting};
|
|
|
|
use crate::AppState;
|
|
|
|
const LAST_TRIAGE_KEY: &str = "kon_morning_triage_last_shown";
|
|
|
|
/// Returns the YYYY-MM-DD date string stored on the last successful
|
|
/// morning triage dismissal, or `None` if the user has never been
|
|
/// shown the modal.
|
|
#[tauri::command]
|
|
pub async fn get_last_morning_triage(
|
|
state: tauri::State<'_, AppState>,
|
|
) -> Result<Option<String>, String> {
|
|
get_setting(&state.db, LAST_TRIAGE_KEY)
|
|
.await
|
|
.map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Records that the morning triage modal was shown (and either skipped
|
|
/// or completed) on `date`. Caller is responsible for passing a valid
|
|
/// YYYY-MM-DD string in the user's local timezone — Rust deliberately
|
|
/// stays timezone-agnostic here so the frontend retains control.
|
|
#[tauri::command]
|
|
pub async fn mark_morning_triage_shown(
|
|
state: tauri::State<'_, AppState>,
|
|
date: String,
|
|
) -> Result<(), String> {
|
|
set_setting(&state.db, LAST_TRIAGE_KEY, &date)
|
|
.await
|
|
.map_err(|e| e.to_string())
|
|
}
|