feat(todo): a task done ticks on phones and chimes on desktops

The developer's request of 10 Nov 2026: completing a task should feel like
something. `CompletionFeedback`, held by `TodoDevice` and handed to each
person's `TodoPerson`, gives a light haptic tick on Android and iOS and, on
desktops, a short quiet chime of our own: two soft bell tones a fifth apart,
synthesized by `apps/todo/tool/completion_sound.dart` into
`assets/sounds/task_done.wav`, so it needs no one's licence. A task's check
and the selection's Complete call it once, however many tasks are done;
an undo is silent.

Settings' Tasks turns the chime off on a desktop, kept per device in
`<app support>/completion_feedback.json`; a phone is offered no switch. A
device that can't play loses only the sound. The player is `audioplayers`,
as Learn's sounds: on Linux it links GStreamer, so Todo's snap gains the
`audio-playback` plug and GStreamer's headers to build, as Learn's recipe has.

Whats-New: Completing a task now gives a light tap on phones and a short chime on computers, which Settings › Tasks turns off.
Whats-New-De: Eine erledigte Aufgabe gibt jetzt auf dem Handy ein leichtes Tippen und am Computer einen kurzen Klang, den du unter Einstellungen › Aufgaben ausschaltest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-10 23:04:59 +01:00
commit fd6647d752
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 470 additions and 7 deletions

View file

@ -340,6 +340,8 @@
"weekStartLanguage": "Wie in der Sprache",
"resetSubTasksTitle": "Unteraufgaben zurücksetzen",
"resetSubTasksHint": "Wieder öffnen, wenn eine wiederkehrende Aufgabe erledigt ist",
"completionSoundTitle": "Ton beim Erledigen",
"completionSoundHint": "Ein kurzer Klang, wenn du eine Aufgabe erledigst",
"automaticReminderTitle": "Automatische Erinnerung",
"automaticReminderHint": "Für eine Aufgabe mit Uhrzeit, wenn sie keine eigene Erinnerung hat",
"automaticReminderNone": "Keine",

View file

@ -961,6 +961,14 @@
"@resetSubTasksHint": {
"description": "Settings of tasks and reminders (ADR 0033, D4)."
},
"completionSoundTitle": "Sound when done",
"@completionSoundTitle": {
"description": "Settings of tasks, on a desktop alone: whether a short chime plays as a task is marked done (decided 10 Nov 2026)."
},
"completionSoundHint": "A short chime as a task is marked done",
"@completionSoundHint": {
"description": "Explains completionSoundTitle."
},
"automaticReminderTitle": "Automatic reminder",
"@automaticReminderTitle": {
"description": "Settings of tasks and reminders (ADR 0033, D4)."

View file

@ -2140,6 +2140,18 @@ abstract class AppLocalizations {
/// **'Open them again when a recurring task is done'**
String get resetSubTasksHint;
/// Settings of tasks, on a desktop alone: whether a short chime plays as a task is marked done (decided 10 Nov 2026).
///
/// In en, this message translates to:
/// **'Sound when done'**
String get completionSoundTitle;
/// Explains completionSoundTitle.
///
/// In en, this message translates to:
/// **'A short chime as a task is marked done'**
String get completionSoundHint;
/// Settings of tasks and reminders (ADR 0033, D4).
///
/// In en, this message translates to:

View file

@ -1306,6 +1306,13 @@ class AppLocalizationsDe extends AppLocalizations {
String get resetSubTasksHint =>
'Wieder öffnen, wenn eine wiederkehrende Aufgabe erledigt ist';
@override
String get completionSoundTitle => 'Ton beim Erledigen';
@override
String get completionSoundHint =>
'Ein kurzer Klang, wenn du eine Aufgabe erledigst';
@override
String get automaticReminderTitle => 'Automatische Erinnerung';

View file

@ -1305,6 +1305,12 @@ class AppLocalizationsEn extends AppLocalizations {
String get resetSubTasksHint =>
'Open them again when a recurring task is done';
@override
String get completionSoundTitle => 'Sound when done';
@override
String get completionSoundHint => 'A short chime as a task is marked done';
@override
String get automaticReminderTitle => 'Automatic reminder';