Route todo's snackbars through the shared showToast/showError
Some checks are pending
file-length / file length <= 250 lines (push) Waiting to run
release-apk / release (APK) (push) Waiting to run

The package shipped feedback helpers while todo still had a private
_showSnack and a raw SnackBar in note_editor -- exactly the duplication
the extraction was meant to end, left live in a repo that had just
adopted the package.

Two deliberate behaviour changes come with it: the duration goes 2s ->
3s for toasts and 5s for errors (an error the user missed is an error
they will hit again), and messages now replace rather than queue, since
a queued snackbar describes an action the user moved on from seconds
ago. No test asserted on either, and the one snackbar assertion in the
suite checks that capture is *not* interrupted by one, which still holds.

Failures now read as failures: the mode-switch rejection in note_editor
and a failed sync in capture_screen use showError, while a successful
sync and the not-configured hint stay neutral toasts. Spending the danger
hue on routine confirmations is how a real failure becomes invisible.

Verified: flutter analyze clean, 308 tests pass at 100% coverage
(1964/1964). The release APK built and installed, but on-device
re-verification could not complete: the 23:00 night curfew removed the
package ~80ms after install, because dev.kuhy.todo is in the focus-mode
day WHITELIST but not NIGHT_WHITELIST. Enforcer working as designed, not
an app fault -- reverify after 05:00.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XS1m7b1piBtAL22USLW6jL
This commit is contained in:
Krzysztof Rudnicki 2026-08-14 23:09:24 +02:00
parent e6e1052c59
commit f4272d01b9
4 changed files with 19 additions and 12 deletions

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:crdt_sync/crdt_sync.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:todo/analytics/analytics_event.dart';
@ -221,6 +222,7 @@ class _CaptureScreenState extends State<CaptureScreen>
outcome.ok
? 'Synced: ${outcome.detail}'
: 'Sync failed: ${outcome.detail}',
isError: !outcome.ok,
);
} finally {
if (mounted) setState(() => _syncing = false);

View File

@ -64,11 +64,19 @@ extension _CaptureSyncBehaviour on _CaptureScreenState {
);
}
void _showSnack(String message) {
/// Shows transient feedback, if this screen is still mounted.
///
/// Delegates to the shared helpers so the styling and the
/// replace-don't-queue behaviour match every other app; [isError] picks
/// the danger hue and the longer duration, because an error the user
/// missed is an error they will hit again.
void _showSnack(String message, {bool isError = false}) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), duration: const Duration(seconds: 2)),
);
if (isError) {
showError(context, message);
} else {
showToast(context, message);
}
}
/// Reloads the persisted last-sync outcome so the status line survives a

View File

@ -1,3 +1,4 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:todo/data/note.dart';
@ -111,13 +112,9 @@ class _NoteEditorState extends State<NoteEditor> {
case NoteEditorMode.guided:
// raw -> guided: only if the edited text still fits the template.
if (!_doc.tryAdoptGuided()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
"Text doesn't match the template — staying in raw",
),
duration: Duration(seconds: 2),
),
showError(
context,
"Text doesn't match the template — staying in raw",
);
return;
}

View File

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.23+1
version: 1.0.24+1
environment:
sdk: ^3.12.2