diff --git a/lib/app_state.dart b/lib/app_state.dart index 89b6b31..9420813 100644 --- a/lib/app_state.dart +++ b/lib/app_state.dart @@ -422,7 +422,6 @@ class AppState extends ChangeNotifier with WidgetsBindingObserver { refreshDeviceIds.length, 0, refreshFilter, null, forceBackend: true) .catchError(( e) async { - _logger.e((e as Error).stackTrace); if (!Settings.getLocalMode()) { Toast.showToastNoContext( "Error refreshing device status, using cache"); diff --git a/lib/services/api_available.dart b/lib/services/api_available.dart index 1d0d25f..5d83c0b 100644 --- a/lib/services/api_available.dart +++ b/lib/services/api_available.dart @@ -29,7 +29,7 @@ class ApiAvailableService { ApiAvailableService._internal() { Connectivity().onConnectivityChanged.listen((event) { - final offline = event == ConnectivityResult.none; + final offline = event.contains(ConnectivityResult.none); if (offline != _offline) { _offline = offline; AppState().notifyListeners(); @@ -37,7 +37,7 @@ class ApiAvailableService { }); Timer.periodic(const Duration(seconds: 10), (timer) async { // not all connectivity changes are recognized, checking periodically - final offline = await Connectivity().checkConnectivity() == ConnectivityResult.none; + final offline = await Connectivity().checkConnectivity().then((value) => value.contains(ConnectivityResult.none)); if (offline != _offline) { _offline = offline; AppState().notifyListeners(); diff --git a/lib/services/device_commands.dart b/lib/services/device_commands.dart index 4621f6e..f2d0cf7 100644 --- a/lib/services/device_commands.dart +++ b/lib/services/device_commands.dart @@ -199,7 +199,7 @@ class DeviceCommandsService { try { retryRes = await _runCommands(cloudRetries, true, "", preferEventValue); } on DioException catch (e) { - _logger.e("Cant run cloud commands :${e.message!}"); + _logger.e("Cant run cloud commands :${e.message}"); retryRes = List.generate(cloudRetries.length, (index) => DeviceCommandResponse(502, e.toString())); } diff --git a/lib/shared/api_available_interceptor.dart b/lib/shared/api_available_interceptor.dart index cf8ba11..d243906 100644 --- a/lib/shared/api_available_interceptor.dart +++ b/lib/shared/api_available_interceptor.dart @@ -24,7 +24,7 @@ class ApiAvailableInterceptor extends Interceptor { factory ApiAvailableInterceptor() => _instance; - ApiAvailableInterceptor._internal() {} + ApiAvailableInterceptor._internal(); @override diff --git a/lib/widgets/tabs/device_tabs.dart b/lib/widgets/tabs/device_tabs.dart index 2b3e316..27cf8f6 100644 --- a/lib/widgets/tabs/device_tabs.dart +++ b/lib/widgets/tabs/device_tabs.dart @@ -199,21 +199,41 @@ class DeviceTabsState extends State with RestorationMixin { List _tabDisabled() { final state = AppState(); - return [ - false, - !SmartServiceService.isAvailable(), - state.deviceClasses.isEmpty && !DeviceClassesService.isAvailable(), - state.locations.isEmpty && !LocationService.isListAvailable(), - state.deviceGroups.isEmpty && !DeviceGroupsService.isListAvailable(), - state.networks.isEmpty && !NetworksService.isAvailable(), - false, - !SmartServiceService.isAvailable(), - false - ]; + final List disabledList = + List.generate(navItems.length, (index) => true); + navItems.forEach((navItem) { + switch (navItem.index) { + case tabLocations: + navItem.disabled = + state.locations.isEmpty && !LocationService.isListAvailable(); + break; + case tabGroups: + navItem.disabled = state.deviceGroups.isEmpty && + !DeviceGroupsService.isListAvailable(); + break; + case tabNetworks: + navItem.disabled = + state.networks.isEmpty && !NetworksService.isAvailable(); + break; + case tabClasses: + navItem.disabled = state.deviceClasses.isEmpty && + !DeviceClassesService.isAvailable(); + break; + case tabSmartServices: + navItem.disabled = !SmartServiceService.isAvailable(); + break; + case tabDashboard: + navItem.disabled = !SmartServiceService.isAvailable(); + default: + navItem.disabled = false; + } + disabledList[navItem.index] = navItem.disabled; + }); + return disabledList; } /// create BottomNavigationBar with items - PlatformNavBar _buildBottom(BuildContext context) { + PlatformNavBar _buildBottomNavBar(BuildContext context) { final disabled = _tabDisabled(); Color disabledColor; @@ -228,41 +248,41 @@ class DeviceTabsState extends State with RestorationMixin { if (Platform.isIOS) { navItems.forEach((navItem) { bottomBarItems.add(BottomNavigationBarItem( - tooltip: disabled[navItem.index] ? "Currently unavailable" : null, + tooltip: navItem.disabled ? "Currently unavailable" : null, icon: Icon(navItem.icon, key: _tabKeys[navItem.index], - color: disabled[navItem.index] ? disabledColor : null), + color: navItem.disabled ? disabledColor : null), label: navItem.name)); }); } else { navItems.forEach((navItem) { if (["Favorites", "Dashboard"].contains(navItem.name)) { bottomBarItems.add(BottomNavigationBarItem( - tooltip: disabled[navItem.index] ? "Currently unavailable" : null, + tooltip: navItem.disabled ? "Currently unavailable" : null, icon: Icon(navItem.icon, key: _tabKeys[navItem.index], - color: disabled[navItem.index] ? disabledColor : null), + color: navItem.disabled ? disabledColor : null), label: navItem.name)); } }); } return PlatformNavBar( - items: bottomBarItems, - currentIndex: _bottomBarIndex, - itemChanged: (i) { - if (disabled[i]) { - controller.index = _bottomBarIndex; - return; - } - setState(() { - _bottomBarIndex = i; - _navigationIndex = i; - _sidebarController.selectIndex(i); - }); - HapticFeedbackProxy.lightImpact(); - switchScreen(i, false); - }, + items: bottomBarItems, + currentIndex: _bottomBarIndex, + itemChanged: (i) { + if (disabled[i]) { + controller.index = _bottomBarIndex; + return; + } + setState(() { + _bottomBarIndex = i; + _navigationIndex = i; + _sidebarController.selectIndex(i); + }); + HapticFeedbackProxy.lightImpact(); + switchScreen(i, false); + }, ); } @@ -330,8 +350,7 @@ class DeviceTabsState extends State with RestorationMixin { )); } - - if (Settings.getFilterMode()){ + if (Settings.getFilterMode()) { populateAndShowFilterMenu(state, context, actions); } actions.addAll(MyAppBar.getDefaultActions(context)); @@ -347,10 +366,13 @@ class DeviceTabsState extends State with RestorationMixin { final List sidebarItems = []; navItems.forEach((navItem) { + if (navItem.disabled) { + return; + } sidebarItems.add(SidebarXItem( - icon: navItem.icon, label: navItem.name, + selectable: false, onTap: () { setState(() { _navigationIndex = navItem.index; @@ -366,9 +388,9 @@ class DeviceTabsState extends State with RestorationMixin { var backgroundColor = Colors.white; if (MyTheme.isDarkMode) { - selectorColor = MyTheme.appColor; - iconColor = Colors.white; - backgroundColor = const Color(0xFF424242); + selectorColor = MyTheme.appColor; + iconColor = Colors.white; + backgroundColor = const Color(0xFF424242); } final divider = Divider(color: textColor?.withOpacity(0.3), height: 1); @@ -493,7 +515,8 @@ class DeviceTabsState extends State with RestorationMixin { color: MyTheme.errorColor, ), SizedBox( - width: MediaQuery.textScalerOf(context).scale(1) * + width: MediaQuery.textScalerOf(context) + .scale(1) * 12, height: 0), const Text("not implemented") @@ -504,7 +527,7 @@ class DeviceTabsState extends State with RestorationMixin { cupertino: (context, _) => CupertinoPageScaffoldData(controller: controller), // if not used, changes to _bottomBarIndex are not reflected visually - bottomNavBar: _buildBottom(context), + bottomNavBar: _buildBottomNavBar(context), )))); }, ); @@ -512,7 +535,8 @@ class DeviceTabsState extends State with RestorationMixin { /// Populate and show filter menu /// uncomment to disable - void populateAndShowFilterMenu(AppState state, BuildContext context, List actions) { + void populateAndShowFilterMenu( + AppState state, BuildContext context, List actions) { if (_navigationIndex != tabGroups && _navigationIndex != tabSmartServices && _navigationIndex != tabDashboard) { @@ -542,39 +566,31 @@ class DeviceTabsState extends State with RestorationMixin { color: const Color(0x00000000), // required for ListTile child: ListView.builder( - itemCount: - state.deviceClasses.values.length, + itemCount: state.deviceClasses.values.length, itemBuilder: (context, i) { - final deviceClass = state - .deviceClasses.values - .elementAt(i); + final deviceClass = + state.deviceClasses.values.elementAt(i); return StatefulBuilder( - builder: (context, setState) => - ListTile( - trailing: PlatformSwitch( - onChanged: (checked) { - if (checked == true) { - filter.addDeviceClass( - deviceClass.id); - } else { - filter - .removeDeviceClass( - deviceClass.id); - } - setState(() {}); - }, - value: filter.deviceClassIds - ?.contains( - deviceClass - .id) ?? - false, - ), - title: - Text(deviceClass.name))); + builder: (context, setState) => ListTile( + trailing: PlatformSwitch( + onChanged: (checked) { + if (checked == true) { + filter.addDeviceClass( + deviceClass.id); + } else { + filter.removeDeviceClass( + deviceClass.id); + } + setState(() {}); + }, + value: filter.deviceClassIds + ?.contains( + deviceClass.id) ?? + false, + ), + title: Text(deviceClass.name))); }))), - actions: [ - filterOkAction - ], + actions: [filterOkAction], ), ))); } @@ -595,33 +611,28 @@ class DeviceTabsState extends State with RestorationMixin { child: ListView.builder( itemCount: state.locations.length, itemBuilder: (context, i) { - final location = - state.locations.elementAt(i); + final location = state.locations.elementAt(i); return StatefulBuilder( - builder: (context, setState) => - ListTile( - trailing: PlatformSwitch( - onChanged: (checked) { - setState(() { - if (checked == true) { - filter.addLocation( - location.id); - } else { - filter.removeLocation( - location.id); - } - }); - }, - value: filter.locationIds - ?.contains( - location.id) ?? - false, - ), - title: Text(location.name))); + builder: (context, setState) => ListTile( + trailing: PlatformSwitch( + onChanged: (checked) { + setState(() { + if (checked == true) { + filter + .addLocation(location.id); + } else { + filter.removeLocation( + location.id); + } + }); + }, + value: filter.locationIds + ?.contains(location.id) ?? + false, + ), + title: Text(location.name))); }))), - actions: [ - filterOkAction - ], + actions: [filterOkAction], ), ))); } @@ -645,34 +656,27 @@ class DeviceTabsState extends State with RestorationMixin { final deviceGroup = state.deviceGroups.elementAt(i); return StatefulBuilder( - builder: (context, setState) => - ListTile( - trailing: PlatformSwitch( - onChanged: (checked) { - setState(() { - if (checked == true) { - filter.addDeviceGroup( - deviceGroup.id); - } else { - filter - .removeDeviceGroup( - deviceGroup - .id); - } - }); - }, - value: filter.deviceGroupIds - ?.contains( - deviceGroup - .id) ?? - false, - ), - title: - Text(deviceGroup.name))); + builder: (context, setState) => ListTile( + trailing: PlatformSwitch( + onChanged: (checked) { + setState(() { + if (checked == true) { + filter.addDeviceGroup( + deviceGroup.id); + } else { + filter.removeDeviceGroup( + deviceGroup.id); + } + }); + }, + value: filter.deviceGroupIds + ?.contains( + deviceGroup.id) ?? + false, + ), + title: Text(deviceGroup.name))); }))), - actions: [ - filterOkAction - ], + actions: [filterOkAction], ), ))); } @@ -693,33 +697,27 @@ class DeviceTabsState extends State with RestorationMixin { child: ListView.builder( itemCount: state.networks.length, itemBuilder: (context, i) { - final network = - state.networks.elementAt(i); + final network = state.networks.elementAt(i); return StatefulBuilder( - builder: (context, setState) => - ListTile( - trailing: PlatformSwitch( - onChanged: (checked) { - setState(() { - if (checked == true) { - filter.addNetwork( - network.id); - } else { - filter.removeNetwork( - network.id); - } - }); - }, - value: filter.networkIds - ?.contains( - network.id) ?? - false, - ), - title: Text(network.name))); + builder: (context, setState) => ListTile( + trailing: PlatformSwitch( + onChanged: (checked) { + setState(() { + if (checked == true) { + filter.addNetwork(network.id); + } else { + filter.removeNetwork( + network.id); + } + }); + }, + value: filter.networkIds + ?.contains(network.id) ?? + false, + ), + title: Text(network.name))); }))), - actions: [ - filterOkAction - ], + actions: [filterOkAction], ), ))); } @@ -816,7 +814,6 @@ class DeviceTabsState extends State with RestorationMixin { @override String? get restorationId => "device_list"; - @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration( diff --git a/lib/widgets/tabs/nav.dart b/lib/widgets/tabs/nav.dart index 9b6f5ef..1323d80 100644 --- a/lib/widgets/tabs/nav.dart +++ b/lib/widgets/tabs/nav.dart @@ -42,5 +42,6 @@ class NavigationItem { String name; int index; IconData icon; + bool disabled = false; NavigationItem(this.name, this.index, this.icon); } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index e6b3e45..ec750d9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -189,10 +189,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: e9feae83b1849f61bad9f6f33ee00646e3410d54ce0821e02f262f9901dad3c9 + sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8 url: "https://pub.dev" source: hosted - version: "6.0.1" + version: "6.0.3" connectivity_plus_platform_interface: dependency: transitive description: @@ -1241,10 +1241,10 @@ packages: dependency: "direct main" description: name: sidebarx - sha256: "7042d64844b8e64ca5c17e70d89b49df35b54a26c015b90000da9741eab70bc0" + sha256: abe39d6db237fb8e25c600e8039ffab80fa7fe71acab03e9c378c31f912d2766 url: "https://pub.dev" source: hosted - version: "0.16.3" + version: "0.17.1" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 742724c..625ce07 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.0.313+313 +version: 0.0.314+314 environment: @@ -53,7 +53,7 @@ dependencies: mutex: ^3.1.0 openidconnect: ^1.0.28 openidconnect_platform_interface: ^1.0.15 - connectivity_plus: ^6.0.1 + connectivity_plus: ^6.0.3 crypto: ^3.0.2 fluttertoast: ^8.2.1 provider: ^6.0.5 @@ -83,7 +83,7 @@ dependencies: arrow_path: ^3.1.0 device_info_plus: ^10.0.1 #ory_kratos_client: 1.0.0 - sidebarx: ^0.16.2 + sidebarx: ^0.17.1 dev_dependencies: flutter_test: