@@ -21,6 +21,7 @@ import 'package:dpip/features/earthquake/domain/eew.dart';
2121import 'package:dpip/features/earthquake/domain/eew_local_estimate.dart' ;
2222import 'package:dpip/features/earthquake/domain/rts.dart' ;
2323import 'package:dpip/features/map/presentation/pages/map_page.dart' ;
24+ import 'package:dpip/core/settings/eew_spoken_announcement_settings.dart' ;
2425import 'package:dpip/features/map/presentation/monitor_eew_announcement_controller.dart' ;
2526import 'package:dpip/features/map/presentation/widgets/monitor_eew_card.dart' ;
2627import 'package:dpip/l10n/gen/app_localizations.dart' ;
@@ -75,6 +76,10 @@ class _RtsMonitorPanelState extends State<RtsMonitorPanel>
7576 bool _visible = true ;
7677 VisibleTab ? _visibleTab;
7778 MonitorEewAnnouncementController ? _announcement;
79+
80+ /// The user's on/off switch for the announcement, watched so flipping it
81+ /// takes effect on the alert already on screen rather than the next one.
82+ EewSpokenAnnouncementSettings ? _speechSettings;
7883 AppLocalizations ? _l10n;
7984 String _languageTag = 'zh-TW' ;
8085 AppLifecycleState ? _lifecycleState;
@@ -126,6 +131,12 @@ class _RtsMonitorPanelState extends State<RtsMonitorPanel>
126131 visibleTab? .addListener (_syncVisibility);
127132 _syncVisibility ();
128133 }
134+ final speechSettings = context.read <EewSpokenAnnouncementSettings ?>();
135+ if (! identical (speechSettings, _speechSettings)) {
136+ _speechSettings? .removeListener (_syncAnnouncement);
137+ _speechSettings = speechSettings;
138+ speechSettings? .addListener (_syncAnnouncement);
139+ }
129140 _syncAnnouncement ();
130141 }
131142
@@ -180,7 +191,12 @@ class _RtsMonitorPanelState extends State<RtsMonitorPanel>
180191 if (controller == null || l10n == null ) return ;
181192 final foreground =
182193 _lifecycleState == null || _lifecycleState == AppLifecycleState .resumed;
183- controller.setActive (_isMonitorOnScreen && foreground);
194+ // Absent provider means a test that supplied neither — announce, matching
195+ // the default. Switching off deactivates the controller, which stops any
196+ // phrase in flight and releases the notification the gate was holding, so
197+ // the warning sound is never delayed by a setting the user just turned off.
198+ final speechEnabled = _speechSettings? .enabled ?? true ;
199+ controller.setActive (speechEnabled && _isMonitorOnScreen && foreground);
184200 controller.update (
185201 widget.eew.state,
186202 languageTag: _languageTag,
@@ -229,6 +245,7 @@ class _RtsMonitorPanelState extends State<RtsMonitorPanel>
229245 widget.eew.removeListener (_onData);
230246 widget.eewIndex.removeListener (_onData);
231247 _visibleTab? .removeListener (_syncVisibility);
248+ _speechSettings? .removeListener (_syncAnnouncement);
232249 WidgetsBinding .instance.removeObserver (this );
233250 _announcement? .dispose ();
234251 super .dispose ();
0 commit comments