Problem
GoRouter.refreshListenable currently subscribes to ScheduleBloc.stream. During an active preparation session, ScheduleBloc emits a ScheduleTick update every second, so GoRouter can refresh and re-run redirect evaluation every second even though the global redirect logic does not read schedule progress.
This makes the router refresh path depend on high-frequency timer state and risks unnecessary route work during preparation.
Evidence
lib/presentation/app/go_router.dart wires scheduleBloc.stream into refreshListenable through StreamToListenable.
lib/core/utils/stream_to_listenable.dart calls notifyListeners() for every stream event.
lib/presentation/app/bloc/schedule/schedule_bloc.dart starts a Timer.periodic(Duration(seconds: 1), ...) and emits schedule progress on each tick.
- The global redirect logic depends on auth, notification gate, alarm gate, and path; it does not need per-second schedule elapsed time.
Proposed direction
Remove raw scheduleBloc.stream from the router-level refreshListenable, or replace it with a filtered/listenable source that only notifies on schedule state transitions that routing actually needs.
If schedule-driven routing is required for specific flows, model that explicitly with a narrow signal such as status/id changes, not per-second preparation progress.
Acceptance criteria
- GoRouter global redirects are not refreshed by every
ScheduleTick during active preparation.
- Auth, onboarding, notification permission, and alarm permission redirects still refresh immediately when their source states change.
- Any schedule-dependent navigation remains covered by explicit bloc listeners or a filtered router refresh signal.
- Add or update a focused test proving per-second schedule progress does not notify the router refresh listenable while relevant route-affecting state changes still do.
Source: Codex codebase audit on 2026-06-28.
Problem
GoRouter.refreshListenablecurrently subscribes toScheduleBloc.stream. During an active preparation session,ScheduleBlocemits aScheduleTickupdate every second, so GoRouter can refresh and re-run redirect evaluation every second even though the global redirect logic does not read schedule progress.This makes the router refresh path depend on high-frequency timer state and risks unnecessary route work during preparation.
Evidence
lib/presentation/app/go_router.dartwiresscheduleBloc.streamintorefreshListenablethroughStreamToListenable.lib/core/utils/stream_to_listenable.dartcallsnotifyListeners()for every stream event.lib/presentation/app/bloc/schedule/schedule_bloc.dartstarts aTimer.periodic(Duration(seconds: 1), ...)and emits schedule progress on each tick.Proposed direction
Remove raw
scheduleBloc.streamfrom the router-levelrefreshListenable, or replace it with a filtered/listenable source that only notifies on schedule state transitions that routing actually needs.If schedule-driven routing is required for specific flows, model that explicitly with a narrow signal such as status/id changes, not per-second preparation progress.
Acceptance criteria
ScheduleTickduring active preparation.Source: Codex codebase audit on 2026-06-28.