From f25b4dbf6d5b19db7ff41ad0b4575ddab7097a6a Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Wed, 16 Apr 2025 15:52:56 +0300 Subject: [PATCH] implement `SceneDevicesBodyTabBar` for improved tab management in `SceneDevicesBody`. --- .../scene_devices/scene_devices_body.dart | 63 ++++++++----------- .../scene_devices_body_tab_bar.dart | 46 ++++++++++++++ 2 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 lib/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart diff --git a/lib/features/scene/widgets/scene_devices/scene_devices_body.dart b/lib/features/scene/widgets/scene_devices/scene_devices_body.dart index 51ad9e6..1a89142 100644 --- a/lib/features/scene/widgets/scene_devices/scene_devices_body.dart +++ b/lib/features/scene/widgets/scene_devices/scene_devices_body.dart @@ -7,11 +7,9 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart' import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart'; import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_list.dart'; import 'package:syncrow_app/features/shared_widgets/app_loading_indicator.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; -import 'package:syncrow_app/utils/context_extension.dart'; -import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class SceneDevicesBody extends StatelessWidget { const SceneDevicesBody({ @@ -25,47 +23,27 @@ class SceneDevicesBody extends StatelessWidget { @override Widget build(BuildContext context) { - final routeArguments = - ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?; - final deviceStatusChangesScene = CreateSceneEnum.deviceStatusChanges.name; - final sceneType = routeArguments?.sceneType; - final isAutomationDeviceStatus = sceneType == deviceStatusChangesScene; - return BlocBuilder( builder: (context, state) { return Column( mainAxisSize: MainAxisSize.min, children: [ - TabBar( - controller: tabController, - dividerColor: Colors.transparent, - indicatorColor: Colors.transparent, - isScrollable: true, - tabAlignment: TabAlignment.start, - tabs: rooms.map((e) { - final isStateTabSelected = state is TabSelected; - final isSelected = isStateTabSelected && state.roomId == e.id; - return Tab( - child: BodyLarge( - text: e.name ?? '', - textAlign: TextAlign.start, - style: context.bodyLarge.copyWith( - color: isSelected - ? ColorsManager.textPrimaryColor - : ColorsManager.textPrimaryColor.withValues( - alpha: 0.2, - ), - ), - ), - ); - }).toList(), + SceneDevicesBodyTabBar( + tabController: tabController, + rooms: rooms, + selectedRoomId: state is TabSelected ? state.roomId : '-1', ), Expanded( child: TabBarView( physics: const NeverScrollableScrollPhysics(), controller: tabController, children: rooms - .map((e) => _buildRoomTab(e, context, isAutomationDeviceStatus)) + .map( + (room) => _buildRoomTab( + room, + _isAutomationDeviceStatus(context), + ), + ) .toList(), ), ), @@ -75,9 +53,16 @@ class SceneDevicesBody extends StatelessWidget { ); } + bool _isAutomationDeviceStatus(BuildContext context) { + final routeArguments = + ModalRoute.of(context)?.settings.arguments as SceneSettingsRouteArguments?; + final deviceStatusChangesScene = CreateSceneEnum.deviceStatusChanges.name; + final sceneType = routeArguments?.sceneType; + return sceneType == deviceStatusChangesScene; + } + Widget _buildRoomTab( SubSpaceModel room, - BuildContext context, bool isAutomationDeviceStatus, ) { return BlocBuilder( @@ -96,12 +81,14 @@ class SceneDevicesBody extends StatelessWidget { ), }; + final invalidWidgetEntry = MapEntry( + true, + Center(child: Text('This subspace has no devices')), + ); + final validWidgetEntry = widgets.entries.firstWhere( (entry) => entry.key == true, - orElse: () => MapEntry( - true, - Center(child: Text('This subspace has no devices')), - ), + orElse: () => invalidWidgetEntry, ); return validWidgetEntry.value; diff --git a/lib/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart b/lib/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart new file mode 100644 index 0000000..744a0ff --- /dev/null +++ b/lib/features/scene/widgets/scene_devices/scene_devices_body_tab_bar.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/devices/model/subspace_model.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class SceneDevicesBodyTabBar extends StatelessWidget { + const SceneDevicesBodyTabBar({ + required this.tabController, + required this.rooms, + required this.selectedRoomId, + super.key, + }); + + final String selectedRoomId; + + final TabController tabController; + final List rooms; + + @override + Widget build(BuildContext context) { + return TabBar( + controller: tabController, + dividerColor: Colors.transparent, + indicatorColor: Colors.transparent, + isScrollable: true, + tabAlignment: TabAlignment.start, + tabs: rooms.map((e) { + final isSelected = selectedRoomId == e.id; + return Tab( + child: BodyLarge( + text: e.name ?? '', + textAlign: TextAlign.start, + style: context.bodyLarge.copyWith( + color: isSelected + ? ColorsManager.textPrimaryColor + : ColorsManager.textPrimaryColor.withValues( + alpha: 0.2, + ), + ), + ), + ); + }).toList(), + ); + } +}