@@ -18,7 +18,7 @@ import 'pages/home_page.dart';
1818import 'pages/logs_page.dart' ;
1919import 'services/app_icon_controller.dart' ;
2020import 'services/log_service.dart' ;
21- import 'services/command_builder_service .dart' ;
21+ import 'services/command_notifier .dart' ;
2222import 'services/device_manager_service.dart' ;
2323import 'services/settings_service.dart' ;
2424import 'theme/app_colors.dart' ;
@@ -57,9 +57,10 @@ Future<void> main() async {
5757 final deviceManager = DeviceManagerService ();
5858 await deviceManager.initialize ();
5959
60- // Initialize CommandBuilderService with reference to DeviceManagerService
61- final commandBuilder = CommandBuilderService ();
62- commandBuilder.deviceManagerService = deviceManager;
60+ // Initialize CommandNotifier — unified state for the new architecture
61+ final commandNotifier = CommandNotifier ();
62+ commandNotifier.setDeviceManager (deviceManager);
63+ commandNotifier.loadDefault ();
6364
6465 final iconController = AppIconController (
6566 appDrawerSettings: appDrawerSettings,
@@ -71,9 +72,7 @@ Future<void> main() async {
7172 ChangeNotifierProvider <DeviceManagerService >.value (
7273 value: deviceManager,
7374 ),
74- ChangeNotifierProvider <CommandBuilderService >.value (
75- value: commandBuilder,
76- ),
75+ ChangeNotifierProvider <CommandNotifier >.value (value: commandNotifier),
7776 ChangeNotifierProvider <AppIconController >.value (value: iconController),
7877 ChangeNotifierProvider <LogService >.value (value: LogService .instance),
7978 ],
@@ -105,20 +104,50 @@ class _ScrcpyGuiAppState extends State<ScrcpyGuiApp> {
105104 /// Currently selected page index (0: Home, 1: Favorites, 2: Resources, 3: Settings)
106105 late int selectedIndex;
107106 late AppSettings _currentSettings;
108- final SettingsService _settingsService = SettingsService ();
109107 UpdateService ? _updateResult;
110108 bool _hideBanner = false ;
111109
112110 @override
113111 void initState () {
114112 super .initState ();
115113 _currentSettings = widget.settings;
116- // Set initial tab based on bootTab setting
117114 selectedIndex = _getInitialTabIndex ();
118- _startSettingsPolling ( );
115+ SettingsService ().appSettingsNotifier. addListener (_onSettingsChanged );
119116 _checkUpdateOnStartup ();
120117 }
121118
119+ @override
120+ void dispose () {
121+ SettingsService ().appSettingsNotifier.removeListener (_onSettingsChanged);
122+ super .dispose ();
123+ }
124+
125+ void _onSettingsChanged () {
126+ final newSettings = SettingsService .currentSettings;
127+ if (newSettings == null || ! mounted) return ;
128+
129+ final tabsVisibilityChanged =
130+ newSettings.showBatFilesTab != _currentSettings.showBatFilesTab ||
131+ newSettings.showAppDrawerTab != _currentSettings.showAppDrawerTab ||
132+ newSettings.loggingEnabled != _currentSettings.loggingEnabled;
133+
134+ int newIndex = selectedIndex;
135+ if (tabsVisibilityChanged) {
136+ final currentTabs = _visibleTabLabelsFor (_currentSettings);
137+ final label = selectedIndex < currentTabs.length
138+ ? currentTabs[selectedIndex]
139+ : 'Home' ;
140+ final newTabs = _visibleTabLabelsFor (newSettings);
141+ final idx = newTabs.indexOf (label);
142+ newIndex = idx >= 0 ? idx : 0 ;
143+ }
144+
145+ setState (() {
146+ _currentSettings = newSettings;
147+ selectedIndex = newIndex;
148+ });
149+ }
150+
122151 Future <void > _checkUpdateOnStartup () async {
123152 if (! _currentSettings.checkForUpdatesOnStartup) return ;
124153
@@ -160,36 +189,6 @@ class _ScrcpyGuiAppState extends State<ScrcpyGuiApp> {
160189 ];
161190 }
162191
163- void _startSettingsPolling () {
164- // Poll for settings changes every 500ms
165- Future .delayed (const Duration (milliseconds: 500 ), () async {
166- if (mounted) {
167- final newSettings = await _settingsService.loadSettings ();
168- final tabsVisibilityChanged =
169- newSettings.showBatFilesTab != _currentSettings.showBatFilesTab ||
170- newSettings.showAppDrawerTab != _currentSettings.showAppDrawerTab ||
171- newSettings.loggingEnabled != _currentSettings.loggingEnabled;
172-
173- if (tabsVisibilityChanged) {
174- final currentTabs = _visibleTabLabelsFor (_currentSettings);
175- final currentTabLabel =
176- selectedIndex >= 0 && selectedIndex < currentTabs.length
177- ? currentTabs[selectedIndex]
178- : 'Home' ;
179-
180- final newTabs = _visibleTabLabelsFor (newSettings);
181- final newIndex = newTabs.indexOf (currentTabLabel);
182-
183- setState (() {
184- _currentSettings = newSettings;
185- selectedIndex = newIndex >= 0 ? newIndex : 0 ;
186- });
187- }
188- _startSettingsPolling ();
189- }
190- });
191- }
192-
193192 /// List of available pages in the application
194193 ///
195194 /// Index mapping (when Scripts tab is shown):
@@ -207,8 +206,11 @@ class _ScrcpyGuiAppState extends State<ScrcpyGuiApp> {
207206 List <Widget > get pages => [
208207 HomePage (
209208 panelOrder: _currentSettings.panelOrder,
210- onNavigateToSettings: () =>
211- setState (() => selectedIndex = pages.length - 1 ),
209+ onNavigateToSettings: () {
210+ final tabs = _visibleTabLabelsFor (_currentSettings);
211+ final idx = tabs.indexOf ('Settings' );
212+ if (idx >= 0 ) setState (() => selectedIndex = idx);
213+ },
212214 ),
213215 const FavoritesPage (),
214216 if (_currentSettings.showAppDrawerTab) const AppDrawerPage (),
@@ -235,13 +237,14 @@ class _ScrcpyGuiAppState extends State<ScrcpyGuiApp> {
235237 showAppDrawerTab: _currentSettings.showAppDrawerTab,
236238 showLogsTab: _currentSettings.loggingEnabled,
237239 onItemSelected: (index) {
238- // Clear command builder when leaving Home page (index 0)
240+ final notifier = Provider .of <CommandNotifier >(
241+ context,
242+ listen: false ,
243+ );
239244 if (selectedIndex == 0 && index != 0 ) {
240- final commandService = Provider .of <CommandBuilderService >(
241- context,
242- listen: false ,
243- );
244- commandService.resetToDefaults ();
245+ notifier.reset ();
246+ } else if (index == 0 && selectedIndex != 0 ) {
247+ notifier.loadDefault ();
245248 }
246249 setState (() => selectedIndex = index);
247250 },
0 commit comments