mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-17 02:25:16 +00:00
connected all devices
This commit is contained in:
@ -16,6 +16,7 @@ import 'package:syncrow_app/features/devices/view/widgets/lights/lights_view.dar
|
|||||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/doors_list_view.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/doors_list_view.dart';
|
||||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
import 'package:syncrow_app/services/api/home_management_api.dart';
|
||||||
import 'package:syncrow_app/services/api/network_exception.dart';
|
import 'package:syncrow_app/services/api/network_exception.dart';
|
||||||
import 'package:syncrow_app/services/api/spaces_api.dart';
|
import 'package:syncrow_app/services/api/spaces_api.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
@ -289,6 +290,9 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
|
|
||||||
fetchDevicesByRoomId(String? roomId) async {
|
fetchDevicesByRoomId(String? roomId) async {
|
||||||
if (roomId == null) return;
|
if (roomId == null) return;
|
||||||
|
if (roomId == '-1') {
|
||||||
|
return fetchAllDevices();
|
||||||
|
}
|
||||||
|
|
||||||
emitSafe(GetDevicesLoading());
|
emitSafe(GetDevicesLoading());
|
||||||
int roomIndex = HomeCubit.getInstance()
|
int roomIndex = HomeCubit.getInstance()
|
||||||
@ -316,6 +320,16 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fetchAllDevices() async {
|
||||||
|
emitSafe(GetDevicesLoading());
|
||||||
|
try {
|
||||||
|
final allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||||
|
emitSafe(GetDevicesSuccess(allDevices));
|
||||||
|
} catch (e) {
|
||||||
|
emitSafe(GetDevicesError(e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fetchDevicesStatues(String deviceUuid, int roomIndex, {String? code}) async {
|
fetchDevicesStatues(String deviceUuid, int roomIndex, {String? code}) async {
|
||||||
emitSafe(GetDeviceStatusLoading(code: code));
|
emitSafe(GetDeviceStatusLoading(code: code));
|
||||||
int deviceIndex = HomeCubit.getInstance()
|
int deviceIndex = HomeCubit.getInstance()
|
||||||
|
@ -5,7 +5,8 @@ import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart
|
|||||||
class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
|
class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
|
||||||
TabBarBloc() : super(const Initial()) {
|
TabBarBloc() : super(const Initial()) {
|
||||||
on<TabChanged>((event, emit) {
|
on<TabChanged>((event, emit) {
|
||||||
emit(TabSelected(event.tabIndex));
|
emit(TabSelected(
|
||||||
|
selectedTabIndex: event.selectedIndex, roomId: event.roomId));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ abstract class TabBarEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TabChanged extends TabBarEvent {
|
class TabChanged extends TabBarEvent {
|
||||||
final int tabIndex;
|
final int selectedIndex;
|
||||||
const TabChanged(this.tabIndex);
|
final String roomId;
|
||||||
|
const TabChanged({required this.selectedIndex, required this.roomId});
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,6 @@ class Initial extends TabBarState {
|
|||||||
|
|
||||||
class TabSelected extends TabBarState {
|
class TabSelected extends TabBarState {
|
||||||
final int selectedTabIndex;
|
final int selectedTabIndex;
|
||||||
const TabSelected(this.selectedTabIndex);
|
final String roomId;
|
||||||
|
const TabSelected({required this.roomId, required this.selectedTabIndex});
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
|||||||
class CreateSceneView extends StatelessWidget {
|
class CreateSceneView extends StatelessWidget {
|
||||||
const CreateSceneView({super.key});
|
const CreateSceneView({super.key});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
@ -42,11 +41,7 @@ class CreateSceneView extends StatelessWidget {
|
|||||||
titleString: StringsManager.whenDeviceStatusChanges,
|
titleString: StringsManager.whenDeviceStatusChanges,
|
||||||
subtitle: StringsManager.whenUnusualActivityIsDetected,
|
subtitle: StringsManager.whenUnusualActivityIsDetected,
|
||||||
),
|
),
|
||||||
onTap: () => Navigator.pushNamed(
|
onTap: () {},
|
||||||
context,
|
|
||||||
Routes.sceneTasksRoute,
|
|
||||||
arguments: CreateSceneEnum.deviceStatusChanges,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -5,16 +5,11 @@ import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
|||||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
|
import 'package:syncrow_app/features/scene/view/widgets/scene_devices/scene_devices_body.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/widgets/scene_list_tile.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
|
||||||
|
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||||
|
|
||||||
class SceneControlDevicesView extends StatefulWidget {
|
class SceneControlDevicesView extends StatefulWidget {
|
||||||
@ -32,17 +27,29 @@ class _SceneControlDevicesViewState extends State<SceneControlDevicesView>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
rooms = HomeCubit.getInstance().selectedSpace!.rooms!;
|
rooms = HomeCubit.getInstance().selectedSpace?.rooms;
|
||||||
|
rooms?.insert(
|
||||||
|
0,
|
||||||
|
RoomModel(
|
||||||
|
name: 'All Devices', devices: [], id: '-1', type: SpaceType.Room));
|
||||||
|
|
||||||
_tabController =
|
_tabController =
|
||||||
TabController(length: rooms!.length, vsync: this, initialIndex: 0);
|
TabController(length: rooms!.length, vsync: this, initialIndex: 0);
|
||||||
_tabController.addListener(_handleTabSelection);
|
_tabController.addListener(_handleTabSwitched);
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleTabSelection() {
|
void _handleTabSwitched() {
|
||||||
if (_tabController.indexIsChanging) {
|
if (_tabController.indexIsChanging) {
|
||||||
context.read<TabBarBloc>().add(TabChanged(_tabController.index));
|
final value = _tabController.index;
|
||||||
|
|
||||||
|
/// select tab
|
||||||
|
context.read<TabBarBloc>().add(
|
||||||
|
TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
|
||||||
|
|
||||||
|
/// fetch devices
|
||||||
|
context.read<DevicesCubit>().fetchDevicesByRoomId(rooms![value].id!);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,125 +65,7 @@ class _SceneControlDevicesViewState extends State<SceneControlDevicesView>
|
|||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: StringsManager.createScene,
|
title: StringsManager.createScene,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: BlocProvider(
|
child: SceneDevicesBody(tabController: _tabController, rooms: rooms),
|
||||||
create: (context) => DevicesCubit.getInstance(),
|
|
||||||
//TODO: remove the future builder for the first room call
|
|
||||||
//TODO: and replace it from a bloc call
|
|
||||||
child: FutureBuilder(
|
|
||||||
future: DevicesCubit.getInstance()
|
|
||||||
.fetchDevicesByRoomId(rooms![0].id!),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text(snapshot.error.toString());
|
|
||||||
} else {
|
|
||||||
return SceneDevicesBody(
|
|
||||||
tabController: _tabController, rooms: rooms);
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SceneDevicesBody extends StatelessWidget {
|
|
||||||
const SceneDevicesBody({
|
|
||||||
super.key,
|
|
||||||
required TabController tabController,
|
|
||||||
required this.rooms,
|
|
||||||
}) : _tabController = tabController;
|
|
||||||
|
|
||||||
final TabController _tabController;
|
|
||||||
final List<RoomModel>? rooms;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return BlocBuilder<TabBarBloc, TabBarState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
TabBar(
|
|
||||||
controller: _tabController,
|
|
||||||
dividerColor: Colors.transparent,
|
|
||||||
indicatorColor: Colors.transparent,
|
|
||||||
tabs: List.generate(rooms!.length, (index) {
|
|
||||||
return Tab(
|
|
||||||
child: BodyLarge(
|
|
||||||
text: rooms![index].name ?? '',
|
|
||||||
style: context.bodyLarge.copyWith(
|
|
||||||
color: (state is TabSelected) &&
|
|
||||||
state.selectedTabIndex == index
|
|
||||||
? ColorsManager.textPrimaryColor
|
|
||||||
: ColorsManager.textPrimaryColor.withOpacity(0.2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
isScrollable: true,
|
|
||||||
onTap: (value) {
|
|
||||||
DevicesCubit.getInstance()
|
|
||||||
.fetchDevicesByRoomId(rooms![value].id!);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: TabBarView(
|
|
||||||
controller: _tabController,
|
|
||||||
children: rooms!
|
|
||||||
.map((e) => BlocBuilder<DevicesCubit, DevicesState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
if (state is GetDevicesLoading) {
|
|
||||||
return const Center(
|
|
||||||
child: CircularProgressIndicator());
|
|
||||||
} else if (state is GetDevicesSuccess) {
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: state.devices!.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final device = state.devices![index];
|
|
||||||
return DefaultContainer(
|
|
||||||
child: SceneListTile(
|
|
||||||
minLeadingWidth: 40,
|
|
||||||
leadingWidget: Image.network(
|
|
||||||
device.icon ?? '',
|
|
||||||
errorBuilder:
|
|
||||||
(context, error, stackTrace) =>
|
|
||||||
Image.asset(
|
|
||||||
Assets.assetsIconsLogo,
|
|
||||||
width: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
titleWidget: BodyMedium(
|
|
||||||
text: device.name ?? '',
|
|
||||||
style: context.titleSmall.copyWith(
|
|
||||||
color:
|
|
||||||
ColorsManager.secondaryTextColor,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailingWidget: const Icon(
|
|
||||||
Icons.arrow_forward_ios_rounded,
|
|
||||||
size: 16,
|
|
||||||
weight: 0.2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else if (state is GetDevicesError) {
|
|
||||||
return Center(child: Text(state.errorMsg));
|
|
||||||
}
|
|
||||||
return const SizedBox();
|
|
||||||
},
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||||
|
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/view/widgets/scene_list_tile.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
|
||||||
|
import 'package:syncrow_app/generated/assets.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({
|
||||||
|
super.key,
|
||||||
|
required TabController tabController,
|
||||||
|
required this.rooms,
|
||||||
|
}) : _tabController = tabController;
|
||||||
|
|
||||||
|
final TabController _tabController;
|
||||||
|
final List<RoomModel>? rooms;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<TabBarBloc, TabBarState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
/// Tab bar
|
||||||
|
TabBar(
|
||||||
|
controller: _tabController,
|
||||||
|
dividerColor: Colors.transparent,
|
||||||
|
indicatorColor: Colors.transparent,
|
||||||
|
tabs: [
|
||||||
|
...rooms!.map((e) => Tab(
|
||||||
|
child: BodyLarge(
|
||||||
|
text: e.name ?? '',
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: context.bodyLarge.copyWith(
|
||||||
|
color: (state is TabSelected) && state.roomId == e.id
|
||||||
|
? ColorsManager.textPrimaryColor
|
||||||
|
: ColorsManager.textPrimaryColor.withOpacity(0.2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
isScrollable: true,
|
||||||
|
tabAlignment: TabAlignment.start,
|
||||||
|
),
|
||||||
|
|
||||||
|
/// Tab bar view
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
controller: _tabController,
|
||||||
|
children: rooms!
|
||||||
|
.map((e) => BlocBuilder<DevicesCubit, DevicesState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is GetDevicesLoading) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator());
|
||||||
|
} else if (state is GetDevicesSuccess) {
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: state.devices!.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final device = state.devices![index];
|
||||||
|
return DefaultContainer(
|
||||||
|
child: SceneListTile(
|
||||||
|
minLeadingWidth: 40,
|
||||||
|
leadingWidget: Image.network(
|
||||||
|
device.icon ?? '',
|
||||||
|
errorBuilder:
|
||||||
|
(context, error, stackTrace) =>
|
||||||
|
Image.asset(
|
||||||
|
Assets.assetsIconsLogo,
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
titleWidget: BodyMedium(
|
||||||
|
text: device.name ?? '',
|
||||||
|
style: context.titleSmall.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager.secondaryTextColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailingWidget: const Icon(
|
||||||
|
Icons.arrow_forward_ios_rounded,
|
||||||
|
size: 16,
|
||||||
|
weight: 0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else if (state is GetDevicesError) {
|
||||||
|
return Center(child: Text(state.errorMsg));
|
||||||
|
}
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
|
import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
|
||||||
import 'package:syncrow_app/features/auth/view/otp_view.dart';
|
import 'package:syncrow_app/features/auth/view/otp_view.dart';
|
||||||
import 'package:syncrow_app/features/auth/view/login_view.dart';
|
import 'package:syncrow_app/features/auth/view/login_view.dart';
|
||||||
import 'package:syncrow_app/features/auth/view/sign_up_view.dart';
|
import 'package:syncrow_app/features/auth/view/sign_up_view.dart';
|
||||||
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||||
import 'package:syncrow_app/features/layout/view/layout_view.dart';
|
import 'package:syncrow_app/features/layout/view/layout_view.dart';
|
||||||
import 'package:syncrow_app/features/menu/view/menu_view.dart';
|
import 'package:syncrow_app/features/menu/view/menu_view.dart';
|
||||||
import 'package:syncrow_app/features/menu/view/widgets/create_home/create_home_view.dart';
|
import 'package:syncrow_app/features/menu/view/widgets/create_home/create_home_view.dart';
|
||||||
@ -72,8 +74,15 @@ class Router {
|
|||||||
builder: (_) => const SceneAddTasksView(), settings: settings);
|
builder: (_) => const SceneAddTasksView(), settings: settings);
|
||||||
case Routes.sceneControlDevicesRoute:
|
case Routes.sceneControlDevicesRoute:
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider(
|
builder: (_) => MultiBlocProvider(
|
||||||
create: (context) => TabBarBloc()..add(const TabChanged(0)),
|
providers: [
|
||||||
|
BlocProvider<TabBarBloc>(
|
||||||
|
create: (BuildContext context) => TabBarBloc()
|
||||||
|
..add(const TabChanged(selectedIndex: 0, roomId: '')),
|
||||||
|
),
|
||||||
|
BlocProvider<DevicesCubit>(
|
||||||
|
create: (context) => DevicesCubit.getInstance()),
|
||||||
|
],
|
||||||
child: const SceneControlDevicesView(),
|
child: const SceneControlDevicesView(),
|
||||||
),
|
),
|
||||||
settings: settings);
|
settings: settings);
|
||||||
|
Reference in New Issue
Block a user