mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
push living room refactor
This commit is contained in:
@ -12,7 +12,7 @@ mixin RouteControlsBasedCode {
|
||||
switch (device.productType) {
|
||||
case '3G':
|
||||
return LivingRoomDeviceControl(
|
||||
device: device,
|
||||
deviceId: device.uuid!,
|
||||
);
|
||||
case 'GW':
|
||||
return GateWayControls(
|
||||
|
@ -11,7 +11,8 @@ import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presen
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class CeilingSensorControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
class CeilingSensorControls extends StatelessWidget
|
||||
with HelperResponsiveLayout {
|
||||
const CeilingSensorControls({super.key, required this.device});
|
||||
|
||||
final AllDevicesModel device;
|
||||
@ -21,8 +22,8 @@ class CeilingSensorControls extends StatelessWidget with HelperResponsiveLayout
|
||||
final isLarge = isLargeScreenSize(context);
|
||||
final isMedium = isMediumScreenSize(context);
|
||||
return BlocProvider(
|
||||
create: (context) =>
|
||||
CeilingSensorBloc(deviceId: device.uuid ?? '')..add(CeilingInitialEvent()),
|
||||
create: (context) => CeilingSensorBloc(deviceId: device.uuid ?? '')
|
||||
..add(CeilingInitialEvent()),
|
||||
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
||||
builder: (context, state) {
|
||||
if (state is CeilingLoadingInitialState) {
|
||||
@ -86,14 +87,17 @@ class CeilingSensorControls extends StatelessWidget with HelperResponsiveLayout
|
||||
),
|
||||
),
|
||||
PresenceUpdateData(
|
||||
value: (state.ceilingSensorModel.noBodyTime.toDouble() / 3600).roundToDouble(),
|
||||
value:
|
||||
(state.ceilingSensorModel.noBodyTime.toDouble() / 3600)
|
||||
.roundToDouble(),
|
||||
title: 'Nobody Time:',
|
||||
minValue: 0,
|
||||
maxValue: 300000,
|
||||
steps: 5000,
|
||||
description: 'hr',
|
||||
action: (int value) =>
|
||||
context.read<CeilingSensorBloc>().add(CeilingChangeValueEvent(
|
||||
action: (int value) => context
|
||||
.read<CeilingSensorBloc>()
|
||||
.add(CeilingChangeValueEvent(
|
||||
code: 'none_body_time',
|
||||
value: value,
|
||||
))),
|
||||
|
@ -34,7 +34,7 @@ class GateWayControls extends StatelessWidget with HelperResponsiveLayout {
|
||||
: isMedium
|
||||
? 2
|
||||
: 1,
|
||||
mainAxisExtent: 150,
|
||||
mainAxisExtent: 133,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 12,
|
||||
),
|
||||
|
@ -1,15 +1,21 @@
|
||||
import 'dart:async';
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/models/living_room_model.dart';
|
||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||
|
||||
part 'living_room_event.dart';
|
||||
part 'living_room_state.dart';
|
||||
|
||||
class LivingRoomBloc extends Bloc<LivingRoomEvent, LivingRoomState> {
|
||||
LivingRoomBloc() : super(LivingRoomInitial()) {
|
||||
late LivingRoomStatusModel deviceStatus;
|
||||
final String deviceId;
|
||||
Timer? _timer;
|
||||
|
||||
LivingRoomBloc({required this.deviceId}) : super(LivingRoomInitial()) {
|
||||
on<LivingRoomFetchDeviceStatus>(_onFetchDeviceStatus);
|
||||
on<LivingRoomControl>(_livingRoomControl);
|
||||
}
|
||||
@ -20,7 +26,9 @@ class LivingRoomBloc extends Bloc<LivingRoomEvent, LivingRoomState> {
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
emit(LivingRoomDeviceStatusLoaded(status));
|
||||
deviceStatus =
|
||||
LivingRoomStatusModel.fromJson(event.deviceId, status.status);
|
||||
emit(LivingRoomDeviceStatusLoaded(deviceStatus));
|
||||
} catch (e) {
|
||||
emit(LivingRoomDeviceManagementError(e.toString()));
|
||||
}
|
||||
@ -28,22 +36,84 @@ class LivingRoomBloc extends Bloc<LivingRoomEvent, LivingRoomState> {
|
||||
|
||||
FutureOr<void> _livingRoomControl(
|
||||
LivingRoomControl event, Emitter<LivingRoomState> emit) async {
|
||||
emit(LivingRoomControlLoading());
|
||||
try {
|
||||
final status = Status(code: event.code, value: event.value);
|
||||
final response =
|
||||
await DevicesManagementApi().deviceControl(event.deviceId, status);
|
||||
final oldValue = _getValueByCode(event.code);
|
||||
|
||||
if (response) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
final newStatus =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
emit(LivingRoomDeviceStatusLoaded(newStatus));
|
||||
} else {
|
||||
emit(const LivingRoomControlError('Failed to control the device.'));
|
||||
_updateLocalValue(event.code, event.value);
|
||||
|
||||
emit(LivingRoomDeviceStatusLoaded(deviceStatus));
|
||||
|
||||
await _runDebounce(
|
||||
deviceId: event.deviceId,
|
||||
code: event.code,
|
||||
value: event.value,
|
||||
oldValue: oldValue,
|
||||
emit: emit,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _runDebounce({
|
||||
required String deviceId,
|
||||
required String code,
|
||||
required dynamic value,
|
||||
required dynamic oldValue,
|
||||
required Emitter<LivingRoomState> emit,
|
||||
}) async {
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(seconds: 1), () async {
|
||||
try {
|
||||
final response = await DevicesManagementApi()
|
||||
.deviceControl(deviceId, Status(code: code, value: value));
|
||||
if (!response) {
|
||||
_revertValueAndEmit(deviceId, code, oldValue, emit);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(LivingRoomControlError('Error controlling the device: $e'));
|
||||
_revertValueAndEmit(deviceId, code, oldValue, emit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _revertValueAndEmit(String deviceId, String code, dynamic oldValue,
|
||||
Emitter<LivingRoomState> emit) {
|
||||
_updateLocalValue(code, oldValue);
|
||||
emit(LivingRoomDeviceStatusLoaded(deviceStatus));
|
||||
emit(const LivingRoomControlError('Failed to control the device.'));
|
||||
}
|
||||
|
||||
void _updateLocalValue(String code, dynamic value) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(switch1: value);
|
||||
}
|
||||
break;
|
||||
case 'switch_2':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(switch2: value);
|
||||
}
|
||||
break;
|
||||
case 'switch_3':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(switch3: value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
emit(LivingRoomDeviceStatusLoaded(deviceStatus));
|
||||
}
|
||||
|
||||
dynamic _getValueByCode(String code) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
return deviceStatus.switch1;
|
||||
case 'switch_2':
|
||||
return deviceStatus.switch2;
|
||||
case 'switch_3':
|
||||
return deviceStatus.switch3;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ final class LivingRoomInitial extends LivingRoomState {}
|
||||
class LivingRoomDeviceStatusLoading extends LivingRoomState {}
|
||||
|
||||
class LivingRoomDeviceStatusLoaded extends LivingRoomState {
|
||||
final DeviceStatus status;
|
||||
final LivingRoomStatusModel status;
|
||||
|
||||
const LivingRoomDeviceStatusLoaded(this.status);
|
||||
|
||||
@ -29,8 +29,6 @@ class LivingRoomDeviceManagementError extends LivingRoomState {
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
|
||||
class LivingRoomControlSuccess extends LivingRoomState {}
|
||||
|
||||
class LivingRoomControlError extends LivingRoomState {
|
||||
final String message;
|
||||
|
||||
@ -39,5 +37,3 @@ class LivingRoomControlError extends LivingRoomState {
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
|
||||
class LivingRoomControlLoading extends LivingRoomState {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/control_list/cieling_light.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/control_list/spot_light.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/control_list/wall_light.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/widgets/cieling_light.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/widgets/spot_light.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/widgets/wall_light.dart';
|
||||
|
||||
mixin LivingRoomHelper {
|
||||
Widget livingRoomControlWidgets(
|
||||
|
@ -0,0 +1,56 @@
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
|
||||
class LivingRoomStatusModel {
|
||||
final String uuid;
|
||||
final bool switch1;
|
||||
final bool switch2;
|
||||
final bool switch3;
|
||||
|
||||
LivingRoomStatusModel({
|
||||
required this.uuid,
|
||||
required this.switch1,
|
||||
required this.switch2,
|
||||
required this.switch3,
|
||||
});
|
||||
|
||||
factory LivingRoomStatusModel.fromJson(String id, List<Status> jsonList) {
|
||||
late bool switch1;
|
||||
late bool switch2;
|
||||
late bool switch3;
|
||||
|
||||
for (var status in jsonList) {
|
||||
switch (status.code) {
|
||||
case 'switch_1':
|
||||
switch1 = status.value ?? false; // default to false if null
|
||||
break;
|
||||
case 'switch_2':
|
||||
switch2 = status.value ?? false; // default to false if null
|
||||
break;
|
||||
case 'switch_3':
|
||||
switch3 = status.value ?? false; // default to false if null
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return LivingRoomStatusModel(
|
||||
uuid: id,
|
||||
switch1: switch1,
|
||||
switch2: switch2,
|
||||
switch3: switch3,
|
||||
);
|
||||
}
|
||||
|
||||
LivingRoomStatusModel copyWith({
|
||||
String? uuid,
|
||||
bool? switch1,
|
||||
bool? switch2,
|
||||
bool? switch3,
|
||||
}) {
|
||||
return LivingRoomStatusModel(
|
||||
uuid: uuid ?? this.uuid,
|
||||
switch1: switch1 ?? this.switch1,
|
||||
switch2: switch2 ?? this.switch2,
|
||||
switch3: switch3 ?? this.switch3,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,30 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/bloc/living_room_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/helper/living_room_helper.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/models/living_room_model.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/widgets/living_toggle_widget.dart';
|
||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||
|
||||
class LivingRoomDeviceControl extends StatelessWidget with LivingRoomHelper {
|
||||
const LivingRoomDeviceControl({super.key, required this.device});
|
||||
class LivingRoomDeviceControl extends StatelessWidget
|
||||
with HelperResponsiveLayout {
|
||||
final String deviceId;
|
||||
|
||||
final AllDevicesModel device;
|
||||
const LivingRoomDeviceControl({super.key, required this.deviceId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) =>
|
||||
LivingRoomBloc()..add(LivingRoomFetchDeviceStatus(device.uuid!)),
|
||||
create: (context) => LivingRoomBloc(deviceId: deviceId)
|
||||
..add(LivingRoomFetchDeviceStatus(deviceId)),
|
||||
child: BlocBuilder<LivingRoomBloc, LivingRoomState>(
|
||||
builder: (context, state) {
|
||||
if (state is LivingRoomDeviceStatusLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is LivingRoomDeviceStatusLoaded) {
|
||||
return _buildStatusControls(state.status.status);
|
||||
} else if ((state is LivingRoomDeviceManagementError) ||
|
||||
(state is LivingRoomControlError)) {
|
||||
return const Center(child: Text('Error fetching status'));
|
||||
return _buildStatusControls(context, state.status);
|
||||
} else if (state is LivingRoomDeviceManagementError ||
|
||||
state is LivingRoomControlError) {
|
||||
return Center(child: Text(state.toString()));
|
||||
} else {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
@ -33,32 +33,44 @@ class LivingRoomDeviceControl extends StatelessWidget with LivingRoomHelper {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatusControls(List<Status> statuses) {
|
||||
return GridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
Widget _buildStatusControls(
|
||||
BuildContext context, LivingRoomStatusModel status) {
|
||||
final isLarge = isLargeScreenSize(context);
|
||||
final isMedium = isMediumScreenSize(context);
|
||||
return GridView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: isLarge
|
||||
? 3
|
||||
: isMedium
|
||||
? 2
|
||||
: 1,
|
||||
mainAxisExtent: 133,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 12,
|
||||
),
|
||||
itemCount: 3,
|
||||
itemBuilder: (context, index) {
|
||||
final status = statuses[index];
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||
border: Border.all(color: ColorsManager.boxDivider),
|
||||
children: [
|
||||
ToggleWidget(
|
||||
value: status.switch1,
|
||||
code: 'switch_1',
|
||||
deviceId: deviceId,
|
||||
label: 'Wall Light',
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: livingRoomControlWidgets(
|
||||
value: status.value, code: status.code, deviceId: device.uuid!),
|
||||
);
|
||||
},
|
||||
ToggleWidget(
|
||||
value: status.switch2,
|
||||
code: 'switch_2',
|
||||
deviceId: deviceId,
|
||||
label: 'Ceiling Light',
|
||||
),
|
||||
ToggleWidget(
|
||||
value: status.switch3,
|
||||
code: 'switch_3',
|
||||
deviceId: deviceId,
|
||||
label: 'Spotlight',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/living_room_switch/bloc/living_room_bloc.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class ToggleWidget extends StatelessWidget {
|
||||
final bool value;
|
||||
final String code;
|
||||
final String deviceId;
|
||||
final String label;
|
||||
|
||||
const ToggleWidget({
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.code,
|
||||
required this.deviceId,
|
||||
required this.label,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: ColorsManager.greyColor.withOpacity(0.2),
|
||||
border: Border.all(color: ColorsManager.boxDivider),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ClipOval(
|
||||
child: Container(
|
||||
color: ColorsManager.whiteColors,
|
||||
child: SvgPicture.asset(
|
||||
Assets.lightPulp,
|
||||
width: 60,
|
||||
height: 60,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
width: 35,
|
||||
child: CupertinoSwitch(
|
||||
value: value,
|
||||
activeColor: ColorsManager.dialogBlueTitle,
|
||||
onChanged: (newValue) {
|
||||
context.read<LivingRoomBloc>().add(
|
||||
LivingRoomControl(
|
||||
deviceId: deviceId,
|
||||
code: code,
|
||||
value: newValue,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user