push 3G glass switches

This commit is contained in:
ashrafzarkanisala
2024-10-04 17:40:52 +03:00
parent 7661f54427
commit 47f1a9a6cd
12 changed files with 690 additions and 64 deletions

View File

@ -16,6 +16,8 @@ import 'package:syncrow_web/pages/device_managment/main_door_sensor/view/main_do
import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/view/one_gang_glass_batch_control_view.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/view/three_gang_glass_switch_batch_control_view.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/view/three_gang_glass_switch_control_view.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_device_control.dart';
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/view/two_gang_glass_switch_batch_control_view.dart';
@ -52,10 +54,10 @@ mixin RouteControlsBasedCode {
return TwoGangGlassSwitchControlView(
deviceId: device.uuid!,
);
// case '3GT':
// return LivingRoomClassSwitchControlView(
// deviceId: device.uuid!,
// );
case '3GT':
return ThreeGangGlassSwitchControlView(
deviceId: device.uuid!,
);
case 'GW':
return GateWayControlsView(
gatewayId: device.uuid!,
@ -121,6 +123,10 @@ mixin RouteControlsBasedCode {
return TwoGangGlassSwitchBatchControlView(
deviceIds: devices.where((e) => (e.productType == '2GT')).map((e) => e.uuid!).toList(),
);
case '3GT':
return ThreeGangGlassSwitchBatchControlView(
deviceIds: devices.where((e) => (e.productType == '3GT')).map((e) => e.uuid!).toList(),
);
case 'GW':
return GatewayBatchControlView(
gatewayIds: devices.where((e) => (e.productType == 'GW')).map((e) => e.uuid!).toList(),

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/models/once_gang_glass_status_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class OneGangGlassSwitchControlView extends StatelessWidget with HelperResponsiveLayout {
@ -65,6 +66,24 @@ class OneGangGlassSwitchControlView extends StatelessWidget with HelperResponsiv
);
},
),
ToggleWidget(
value: false,
code: '',
deviceId: deviceId,
label: 'Preferences',
icon: Assets.preferences,
onChange: (value) {},
showToggle: false,
),
ToggleWidget(
value: false,
code: '',
deviceId: deviceId,
label: 'Scheduling',
icon: Assets.scheduling,
onChange: (value) {},
showToggle: false,
),
],
);
}

View File

@ -1,5 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
@ -13,6 +12,7 @@ class ToggleWidget extends StatelessWidget {
final String? icon;
final Widget? labelWidget;
final Function(dynamic value) onChange;
final bool showToggle;
const ToggleWidget({
super.key,
@ -23,6 +23,7 @@ class ToggleWidget extends StatelessWidget {
required this.onChange,
this.icon,
this.labelWidget,
this.showToggle = true,
});
@override
@ -62,16 +63,17 @@ class ToggleWidget extends StatelessWidget {
fit: BoxFit.contain,
),
)),
Container(
height: 20,
width: 35,
padding: const EdgeInsets.only(right: 16, top: 10),
child: CupertinoSwitch(
value: value,
activeColor: ColorsManager.dialogBlueTitle,
onChanged: onChange,
if (showToggle)
Container(
height: 20,
width: 35,
padding: const EdgeInsets.only(right: 16, top: 10),
child: CupertinoSwitch(
value: value,
activeColor: ColorsManager.dialogBlueTitle,
onChanged: onChange,
),
),
),
],
),
),

View File

@ -0,0 +1,174 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/models/three_gang_glass_switch.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';
part 'three_gang_glass_switch_event.dart';
part 'three_gang_glass_switch_state.dart';
class ThreeGangGlassSwitchBloc extends Bloc<ThreeGangGlassSwitchEvent, ThreeGangGlassSwitchState> {
ThreeGangGlassStatusModel deviceStatus;
Timer? _timer;
ThreeGangGlassSwitchBloc({required String deviceId})
: deviceStatus = ThreeGangGlassStatusModel(
uuid: deviceId,
switch1: false,
countDown1: 0,
switch2: false,
countDown2: 0,
switch3: false,
countDown3: 0),
super(ThreeGangGlassSwitchInitial()) {
on<ThreeGangGlassSwitchFetchDeviceEvent>(_onFetchDeviceStatus);
on<ThreeGangGlassSwitchControl>(_onControl);
on<ThreeGangGlassSwitchBatchControl>(_onBatchControl);
on<ThreeGangGlassSwitchFetchBatchStatusEvent>(_onFetchBatchStatus);
on<ThreeGangGlassFactoryReset>(_onFactoryReset);
}
Future<void> _onFetchDeviceStatus(
ThreeGangGlassSwitchFetchDeviceEvent event, Emitter<ThreeGangGlassSwitchState> emit) async {
emit(ThreeGangGlassSwitchLoading());
try {
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
deviceStatus = ThreeGangGlassStatusModel.fromJson(event.deviceId, status.status);
emit(ThreeGangGlassSwitchStatusLoaded(deviceStatus));
} catch (e) {
emit(ThreeGangGlassSwitchError(e.toString()));
}
}
Future<void> _onControl(ThreeGangGlassSwitchControl event, Emitter<ThreeGangGlassSwitchState> emit) async {
final oldValue = _getValueByCode(event.code);
_updateLocalValue(event.code, event.value);
emit(ThreeGangGlassSwitchStatusLoaded(deviceStatus));
await _runDebounce(
deviceId: event.deviceId,
code: event.code,
value: event.value,
oldValue: oldValue,
emit: emit,
isBatch: false,
);
}
Future<void> _onBatchControl(ThreeGangGlassSwitchBatchControl event, Emitter<ThreeGangGlassSwitchState> emit) async {
final oldValue = _getValueByCode(event.code);
_updateLocalValue(event.code, event.value);
emit(ThreeGangGlassSwitchBatchStatusLoaded(deviceStatus));
await _runDebounce(
deviceId: event.deviceIds,
code: event.code,
value: event.value,
oldValue: oldValue,
emit: emit,
isBatch: true,
);
}
Future<void> _onFetchBatchStatus(
ThreeGangGlassSwitchFetchBatchStatusEvent event, Emitter<ThreeGangGlassSwitchState> emit) async {
emit(ThreeGangGlassSwitchLoading());
try {
final status = await DevicesManagementApi().getBatchStatus(event.deviceIds);
deviceStatus = ThreeGangGlassStatusModel.fromJson(event.deviceIds.first, status.status);
emit(ThreeGangGlassSwitchBatchStatusLoaded(deviceStatus));
} catch (e) {
emit(ThreeGangGlassSwitchError(e.toString()));
}
}
Future<void> _onFactoryReset(ThreeGangGlassFactoryReset event, Emitter<ThreeGangGlassSwitchState> emit) async {
emit(ThreeGangGlassSwitchLoading());
try {
final response = await DevicesManagementApi().factoryReset(event.factoryReset, event.deviceId);
if (!response) {
emit(ThreeGangGlassSwitchError('Failed'));
} else {
emit(ThreeGangGlassSwitchStatusLoaded(deviceStatus));
}
} catch (e) {
emit(ThreeGangGlassSwitchError(e.toString()));
}
}
Future<void> _runDebounce({
required dynamic deviceId,
required String code,
required bool value,
required bool oldValue,
required Emitter<ThreeGangGlassSwitchState> emit,
required bool isBatch,
}) async {
late String id;
if (deviceId is List) {
id = deviceId.first;
} else {
id = deviceId;
}
if (_timer != null) {
_timer!.cancel();
}
_timer = Timer(const Duration(milliseconds: 500), () async {
try {
late bool response;
if (isBatch) {
response = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
} else {
response = await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
}
if (!response) {
_revertValueAndEmit(id, code, oldValue, emit);
}
} catch (e) {
_revertValueAndEmit(id, code, oldValue, emit);
}
});
}
void _revertValueAndEmit(String deviceId, String code, bool oldValue, Emitter<ThreeGangGlassSwitchState> emit) {
_updateLocalValue(code, oldValue);
emit(ThreeGangGlassSwitchStatusLoaded(deviceStatus));
}
void _updateLocalValue(String code, bool value) {
if (code == 'switch_1') {
deviceStatus = deviceStatus.copyWith(switch1: value);
} else if (code == 'switch_2') {
deviceStatus = deviceStatus.copyWith(switch2: value);
} else if (code == 'switch_3') {
deviceStatus = deviceStatus.copyWith(switch3: value);
}
}
bool _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 false;
}
}
@override
Future<void> close() {
_timer?.cancel();
return super.close();
}
}

View File

@ -0,0 +1,50 @@
part of 'three_gang_glass_switch_bloc.dart';
@immutable
abstract class ThreeGangGlassSwitchEvent {}
class ThreeGangGlassSwitchFetchDeviceEvent extends ThreeGangGlassSwitchEvent {
final String deviceId;
ThreeGangGlassSwitchFetchDeviceEvent(this.deviceId);
}
class ThreeGangGlassSwitchControl extends ThreeGangGlassSwitchEvent {
final String deviceId;
final String code;
final bool value;
ThreeGangGlassSwitchControl({
required this.deviceId,
required this.code,
required this.value,
});
}
class ThreeGangGlassSwitchBatchControl extends ThreeGangGlassSwitchEvent {
final List<String> deviceIds;
final String code;
final bool value;
ThreeGangGlassSwitchBatchControl({
required this.deviceIds,
required this.code,
required this.value,
});
}
class ThreeGangGlassSwitchFetchBatchStatusEvent extends ThreeGangGlassSwitchEvent {
final List<String> deviceIds;
ThreeGangGlassSwitchFetchBatchStatusEvent(this.deviceIds);
}
class ThreeGangGlassFactoryReset extends ThreeGangGlassSwitchEvent {
final String deviceId;
final FactoryResetModel factoryReset;
ThreeGangGlassFactoryReset({
required this.deviceId,
required this.factoryReset,
});
}

View File

@ -0,0 +1,32 @@
part of 'three_gang_glass_switch_bloc.dart';
@immutable
abstract class ThreeGangGlassSwitchState {}
class ThreeGangGlassSwitchInitial extends ThreeGangGlassSwitchState {}
class ThreeGangGlassSwitchLoading extends ThreeGangGlassSwitchState {}
class ThreeGangGlassSwitchStatusLoaded extends ThreeGangGlassSwitchState {
final ThreeGangGlassStatusModel status;
ThreeGangGlassSwitchStatusLoaded(this.status);
}
class ThreeGangGlassSwitchError extends ThreeGangGlassSwitchState {
final String message;
ThreeGangGlassSwitchError(this.message);
}
class ThreeGangGlassSwitchBatchStatusLoaded extends ThreeGangGlassSwitchState {
final ThreeGangGlassStatusModel status;
ThreeGangGlassSwitchBatchStatusLoaded(this.status);
}
class ThreeGangGlassSwitchBatchControlError extends ThreeGangGlassSwitchState {
final String message;
ThreeGangGlassSwitchBatchControlError(this.message);
}

View File

@ -0,0 +1,87 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
class ThreeGangGlassStatusModel {
final String uuid;
final bool switch1;
final int countDown1;
final bool switch2;
final int countDown2;
final bool switch3;
final int countDown3;
ThreeGangGlassStatusModel({
required this.uuid,
required this.switch1,
required this.countDown1,
required this.switch2,
required this.countDown2,
required this.switch3,
required this.countDown3,
});
factory ThreeGangGlassStatusModel.fromJson(String id, List<Status> jsonList) {
late bool switch1;
late int countDown1;
late bool switch2;
late int countDown2;
late bool switch3;
late int countDown3;
for (var status in jsonList) {
switch (status.code) {
case 'switch_1':
switch1 = status.value ?? false;
break;
case 'countdown_1':
countDown1 = status.value ?? 0;
break;
case 'switch_2':
switch2 = status.value ?? false;
break;
case 'countdown_2':
countDown2 = status.value ?? 0;
break;
case 'switch_3':
switch3 = status.value ?? false;
break;
case 'countdown_3':
countDown3 = status.value ?? 0;
break;
}
}
return ThreeGangGlassStatusModel(
uuid: id,
switch1: switch1,
countDown1: countDown1,
switch2: switch2,
countDown2: countDown2,
switch3: switch3,
countDown3: countDown3,
);
}
ThreeGangGlassStatusModel copyWith({
String? uuid,
bool? switch1,
int? countDown1,
bool? switch2,
int? countDown2,
bool? switch3,
int? countDown3,
}) {
return ThreeGangGlassStatusModel(
uuid: uuid ?? this.uuid,
switch1: switch1 ?? this.switch1,
countDown1: countDown1 ?? this.countDown1,
switch2: switch2 ?? this.switch2,
countDown2: countDown2 ?? this.countDown2,
switch3: switch3 ?? this.switch3,
countDown3: countDown3 ?? this.countDown3,
);
}
@override
String toString() =>
'ThreeGangGlassStatusModel(uuid: $uuid, switch1: $switch1, countDown1: $countDown1, switch2: $switch2, countDown2: $countDown2, switch3: $switch3, countDown3: $countDown3)';
}

View File

@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/models/three_gang_glass_switch.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperResponsiveLayout {
final List<String> deviceIds;
const ThreeGangGlassSwitchBatchControlView({required this.deviceIds, super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ThreeGangGlassSwitchBloc(deviceId: deviceIds.first)
..add(ThreeGangGlassSwitchFetchBatchStatusEvent(deviceIds)),
child: BlocBuilder<ThreeGangGlassSwitchBloc, ThreeGangGlassSwitchState>(
builder: (context, state) {
if (state is ThreeGangGlassSwitchLoading) {
return const Center(child: CircularProgressIndicator());
} else if (state is ThreeGangGlassSwitchBatchStatusLoaded) {
return _buildStatusControls(context, state.status);
} else if (state is ThreeGangGlassSwitchError) {
return const Center(child: Text('Error fetching status'));
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
Widget _buildStatusControls(BuildContext context, ThreeGangGlassStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context);
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
ToggleWidget(
value: status.switch1,
code: 'switch_1',
deviceId: deviceIds.first,
label: 'Glass Switch 1',
onChange: (value) {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassSwitchBatchControl(
deviceIds: deviceIds,
code: 'switch_1',
value: value,
),
);
},
),
ToggleWidget(
value: status.switch2,
code: 'switch_2',
deviceId: deviceIds.first,
label: 'Glass Switch 2',
onChange: (value) {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassSwitchBatchControl(
deviceIds: deviceIds,
code: 'switch_2',
value: value,
),
);
},
),
ToggleWidget(
value: status.switch3,
code: 'switch_3',
deviceId: deviceIds.first,
label: 'Glass Switch 3',
onChange: (value) {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassSwitchBatchControl(
deviceIds: deviceIds,
code: 'switch_3',
value: value,
),
);
},
),
FirmwareUpdateWidget(
deviceId: deviceIds.first,
version: 12, // adjust the version according to your requirement
),
FactoryResetWidget(
callFactoryReset: () {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassFactoryReset(
deviceId: status.uuid,
factoryReset: FactoryResetModel(devicesUuid: deviceIds),
),
);
},
),
],
);
}
}

View File

@ -0,0 +1,121 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import '../models/three_gang_glass_switch.dart';
class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperResponsiveLayout {
final String deviceId;
const ThreeGangGlassSwitchControlView({required this.deviceId, super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
ThreeGangGlassSwitchBloc(deviceId: deviceId)..add(ThreeGangGlassSwitchFetchDeviceEvent(deviceId)),
child: BlocBuilder<ThreeGangGlassSwitchBloc, ThreeGangGlassSwitchState>(
builder: (context, state) {
if (state is ThreeGangGlassSwitchLoading) {
return const Center(child: CircularProgressIndicator());
} else if (state is ThreeGangGlassSwitchStatusLoaded) {
return _buildStatusControls(context, state.status);
} else if (state is ThreeGangGlassSwitchError) {
return const Center(child: Text('Error fetching status'));
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
Widget _buildStatusControls(BuildContext context, ThreeGangGlassStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context);
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
ToggleWidget(
value: status.switch1,
code: 'switch_1',
deviceId: deviceId,
label: 'Wall Light',
onChange: (value) {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassSwitchControl(
deviceId: deviceId,
code: 'switch_1',
value: value,
),
);
},
),
ToggleWidget(
value: status.switch2,
code: 'switch_2',
deviceId: deviceId,
label: 'Ceiling Light',
onChange: (value) {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassSwitchControl(
deviceId: deviceId,
code: 'switch_2',
value: value,
),
);
},
),
ToggleWidget(
value: status.switch3,
code: 'switch_3',
deviceId: deviceId,
label: 'SpotLight',
onChange: (value) {
context.read<ThreeGangGlassSwitchBloc>().add(
ThreeGangGlassSwitchControl(
deviceId: deviceId,
code: 'switch_3',
value: value,
),
);
},
),
ToggleWidget(
value: false,
code: '',
deviceId: deviceId,
label: 'Preferences',
icon: Assets.preferences,
onChange: (value) {},
showToggle: false,
),
ToggleWidget(
value: false,
code: '',
deviceId: deviceId,
label: 'Scheduling',
icon: Assets.scheduling,
onChange: (value) {},
showToggle: false,
),
],
);
}
}

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class TwoGangGlassSwitchControlView extends StatelessWidget with HelperResponsiveLayout {
@ -80,6 +81,24 @@ class TwoGangGlassSwitchControlView extends StatelessWidget with HelperResponsiv
);
},
),
ToggleWidget(
value: false,
code: '',
deviceId: deviceId,
label: 'Preferences',
icon: Assets.preferences,
onChange: (value) {},
showToggle: false,
),
ToggleWidget(
value: false,
code: '',
deviceId: deviceId,
label: 'Scheduling',
icon: Assets.scheduling,
onChange: (value) {},
showToggle: false,
),
],
);
}