mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-10-23 11:47:56 +00:00
curtain wizard
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/curtain_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_curtain_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
@@ -22,9 +26,14 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
on<OpenCurtain>(_onOpenCurtain);
|
||||
on<CloseCurtain>(_onCloseCurtain);
|
||||
on<PauseCurtain>(_onPauseCurtain);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
on<InitialWizardEvent>(_fetchOneTouchWizardStatus);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
}
|
||||
|
||||
Future<void> _onOpenCurtain(OpenCurtain event, Emitter<CurtainState> emit) async {
|
||||
Future<void> _onOpenCurtain(
|
||||
OpenCurtain event, Emitter<CurtainState> emit) async {
|
||||
isMoving = true;
|
||||
while (openPercentage < 100.0) {
|
||||
if (state is CurtainsClosing) {
|
||||
@@ -71,7 +80,8 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onCloseCurtain(CloseCurtain event, Emitter<CurtainState> emit) async {
|
||||
Future<void> _onCloseCurtain(
|
||||
CloseCurtain event, Emitter<CurtainState> emit) async {
|
||||
isMoving = true;
|
||||
while (openPercentage > 0.0) {
|
||||
if (state is CurtainsOpening) {
|
||||
@@ -118,7 +128,8 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onPauseCurtain(PauseCurtain event, Emitter<CurtainState> emit) async {
|
||||
Future<void> _onPauseCurtain(
|
||||
PauseCurtain event, Emitter<CurtainState> emit) async {
|
||||
_pauseCurtain(emit);
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
@@ -172,4 +183,157 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<GroupCurtainModel> groupList = [];
|
||||
bool allSwitchesOn = true;
|
||||
List<DeviceModel> devicesList = [];
|
||||
CurtainModel deviceStatus = CurtainModel(
|
||||
control: 'stop',
|
||||
);
|
||||
void _fetchOneTouchWizardStatus(
|
||||
InitialWizardEvent event, Emitter<CurtainState> emit) async {
|
||||
emit(CurtainLoadingState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', 'CUR');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = CurtainModel.fromJson(statusModelList);
|
||||
groupList.add(GroupCurtainModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.control,
|
||||
percentControl: 0));
|
||||
}
|
||||
|
||||
if (groupList.isNotEmpty) {
|
||||
groupList.firstWhere((element) {
|
||||
print('object=====${element.firstSwitch}');
|
||||
if (element.firstSwitch == 'close') {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(
|
||||
UpdateGroupState(curtainList: groupList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(FailedState());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<CurtainState> emit) async {
|
||||
emit(LoadingNewSate(curtainModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
|
||||
// Update the firstSwitch value in the groupList based on the deviceId
|
||||
groupList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = event.value; // Set the new value from the event
|
||||
}
|
||||
if (element.firstSwitch != 'open') {
|
||||
allSwitchesValue = false; // Check if any switch is not 'open'
|
||||
}
|
||||
});
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'control',
|
||||
devicesUuid: [event.deviceId],
|
||||
value: event.value, // Use the value from the event
|
||||
);
|
||||
|
||||
emit(UpdateGroupState(
|
||||
curtainList: groupList, allSwitches: allSwitchesValue));
|
||||
|
||||
if (response['success']) {
|
||||
// Optionally add an initial event if needed.
|
||||
}
|
||||
} catch (_) {
|
||||
// Handle the error if needed.
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOn(GroupAllOnEvent event, Emitter<CurtainState> emit) async {
|
||||
emit(LoadingNewSate(curtainModel: deviceStatus));
|
||||
try {
|
||||
// Set all devices to 'open'
|
||||
for (int i = 0; i < groupList.length; i++) {
|
||||
groupList[i].firstSwitch = 'open';
|
||||
}
|
||||
|
||||
emit(UpdateGroupState(curtainList: groupList, allSwitches: true));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupList.map((device) => device.deviceId).toList();
|
||||
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'control',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: 'open', // Set the devices to 'open'
|
||||
);
|
||||
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'control',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: 'open',
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
// Handle retry or error if needed.
|
||||
}
|
||||
} catch (_) {
|
||||
emit(FailedState());
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
// Optionally add an initial event if needed.
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOff(GroupAllOffEvent event, Emitter<CurtainState> emit) async {
|
||||
emit(LoadingNewSate(curtainModel: deviceStatus));
|
||||
try {
|
||||
// Set all devices to 'close'
|
||||
for (int i = 0; i < groupList.length; i++) {
|
||||
groupList[i].firstSwitch = 'close';
|
||||
}
|
||||
|
||||
emit(UpdateGroupState(curtainList: groupList, allSwitches: false));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupList.map((device) => device.deviceId).toList();
|
||||
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'control',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: 'close', // Set the devices to 'close'
|
||||
);
|
||||
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'control',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: 'close',
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
// Handle retry or error if needed.
|
||||
}
|
||||
} catch (_) {
|
||||
emit(FailedState());
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
// Optionally add an initial event if needed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,21 @@ class CloseCurtain extends CurtainEvent {
|
||||
|
||||
class InitCurtain extends CurtainEvent {}
|
||||
class PauseCurtain extends CurtainEvent {}
|
||||
class useCurtainEvent extends CurtainEvent {}
|
||||
class useCurtainEvent extends CurtainEvent {}
|
||||
class InitialWizardEvent extends CurtainEvent {}
|
||||
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends CurtainEvent {
|
||||
final String value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class GroupAllOnEvent extends CurtainEvent {}
|
||||
|
||||
class GroupAllOffEvent extends CurtainEvent {}
|
||||
@@ -1,5 +1,7 @@
|
||||
// curtain_state.dart
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/curtain_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_curtain_model.dart';
|
||||
|
||||
abstract class CurtainState extends Equatable {
|
||||
const CurtainState();
|
||||
@@ -10,8 +12,9 @@ abstract class CurtainState extends Equatable {
|
||||
|
||||
class CurtainInitial extends CurtainState {}
|
||||
|
||||
class UpdateCurtain extends CurtainState {
|
||||
class LoadingInitialState extends CurtainState {}
|
||||
|
||||
class UpdateCurtain extends CurtainState {
|
||||
final double curtainWidth;
|
||||
final double blindHeight;
|
||||
final double openPercentage;
|
||||
@@ -73,4 +76,23 @@ class CurtainsPaused extends CurtainState {
|
||||
|
||||
@override
|
||||
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateGroupState extends CurtainState {
|
||||
final List<GroupCurtainModel> curtainList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState(
|
||||
{required this.curtainList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [curtainList, allSwitches];
|
||||
}
|
||||
|
||||
class LoadingNewSate extends CurtainState {
|
||||
final CurtainModel curtainModel;
|
||||
const LoadingNewSate({required this.curtainModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [curtainModel];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
|
||||
class CurtainModel {
|
||||
String control;
|
||||
|
||||
CurtainModel({
|
||||
required this.control,
|
||||
});
|
||||
|
||||
factory CurtainModel.fromJson(List<StatusModel> jsonList) {
|
||||
late String _control;
|
||||
|
||||
for (int i = 0; i < jsonList.length; i++) {
|
||||
if (jsonList[i].code == 'control') {
|
||||
_control = jsonList[i].value ?? false;
|
||||
}
|
||||
}
|
||||
return CurtainModel(
|
||||
control: _control,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,9 @@ class DevicesCategoryModel {
|
||||
: name = json['groupName'],
|
||||
// id = json['groupId'],
|
||||
type = devicesTypesMap[json['groupName']] ?? DeviceType.Other,
|
||||
icon = deviceTypeIconMap[devicesTypesMap[json['groupName']] ?? DeviceType.Other] ?? '',
|
||||
icon = deviceTypeIconMap[
|
||||
devicesTypesMap[json['groupName']] ?? DeviceType.Other] ??
|
||||
'',
|
||||
devices = [],
|
||||
isSelected = false;
|
||||
|
||||
@@ -65,8 +67,8 @@ Map<DeviceType, String> deviceTypeIconMap = {
|
||||
DeviceType.WH: Assets.waterHeaterIcon,
|
||||
DeviceType.DS: Assets.doorSensorIcon,
|
||||
DeviceType.Other: Assets.assetsIconsAC,
|
||||
DeviceType.OneTouch: Assets.oneGang,
|
||||
DeviceType.TowTouch: Assets.twoGang,
|
||||
DeviceType.ThreeTouch: Assets.assetsIconsGang,
|
||||
DeviceType.OneTouch: Assets.gang1touch,
|
||||
DeviceType.TowTouch: Assets.gang2touch,
|
||||
DeviceType.ThreeTouch: Assets.gang3touch,
|
||||
DeviceType.GarageDoor: Assets.garageIcon
|
||||
};
|
||||
|
||||
@@ -67,13 +67,13 @@ class DeviceModel {
|
||||
} else if (type == DeviceType.DS) {
|
||||
tempIcon = Assets.doorSensorIcon;
|
||||
} else if (type == DeviceType.OneTouch) {
|
||||
tempIcon = Assets.oneGang;
|
||||
tempIcon = Assets.gang1touch;
|
||||
} else if (type == DeviceType.TowTouch) {
|
||||
tempIcon = Assets.twoGang;
|
||||
tempIcon = Assets.gang2touch;
|
||||
} else if (type == DeviceType.GarageDoor) {
|
||||
tempIcon = Assets.garageIcon;
|
||||
} else if (type == DeviceType.ThreeTouch) {
|
||||
tempIcon = Assets.assetsIcons3GangSwitch;
|
||||
tempIcon = Assets.gang3touch;
|
||||
} else if (type == DeviceType.WaterLeak) {
|
||||
tempIcon = Assets.waterLeakIcon;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
class GroupCurtainModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
String firstSwitch;
|
||||
int percentControl;
|
||||
|
||||
GroupCurtainModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
required this.percentControl,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/group_curtain_model.dart';
|
||||
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
class CurtainsList extends StatelessWidget {
|
||||
const CurtainsList(
|
||||
{super.key, required this.curtainsList, required this.allSwitches});
|
||||
|
||||
final List<GroupCurtainModel> curtainsList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<CurtainBloc, CurtainState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const BodySmall(text: 'All Curtains'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: allSwitches,
|
||||
action: () {
|
||||
BlocProvider.of<CurtainBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<CurtainBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: curtainsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: curtainsList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: curtainsList[index].firstSwitch == 'open',
|
||||
action: () {
|
||||
// Toggle between 'open' and 'close' based on current value
|
||||
final newValue =
|
||||
curtainsList[index].firstSwitch == 'open'
|
||||
? 'close'
|
||||
: 'open';
|
||||
BlocProvider.of<CurtainBloc>(context).add(
|
||||
ChangeFirstWizardSwitchStatusEvent(
|
||||
value: newValue,
|
||||
deviceId: curtainsList[index].deviceId,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_curtain_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtains_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
class CurtainsWizard extends StatelessWidget {
|
||||
const CurtainsWizard({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<GroupCurtainModel> groupOneTouchModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Curtain',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
CurtainBloc(device?.uuid ?? '')..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<CurtainBloc, CurtainState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
if (state is UpdateGroupState) {
|
||||
groupOneTouchModel = state.curtainList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: CurtainsList(
|
||||
curtainsList: groupOneTouchModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtains_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garage_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_wizard.dart';
|
||||
@@ -100,6 +101,13 @@ class WizardPage extends StatelessWidget {
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const GarageWizard()));
|
||||
}
|
||||
if (groupsList[index].name == 'CUR') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const CurtainsWizard()));
|
||||
}
|
||||
},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(15),
|
||||
|
||||
@@ -1078,5 +1078,8 @@ class Assets {
|
||||
static const String waterLeakIcon = "assets/icons/waterleak_icon.svg";
|
||||
static const String leakDetectedIcon = "assets/icons/leak_detected.svg";
|
||||
static const String leakNormalIcon = "assets/icons/leak_normal_icon.svg";
|
||||
static const String gang1touch = "assets/icons/1gang_touch.svg";
|
||||
static const String gang2touch = "assets/icons/2gang_touch.svg";
|
||||
static const String gang3touch = "assets/icons/3gang_touch.svg";
|
||||
//leakNormalIcon
|
||||
}
|
||||
|
||||
@@ -384,13 +384,15 @@ class DevicesAPI {
|
||||
static Future deviceBatchController({
|
||||
List<String>? devicesUuid,
|
||||
String? code,
|
||||
bool? value,
|
||||
var value,
|
||||
}) async {
|
||||
print({"devicesUuid": devicesUuid, "code": code, "value": value});
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.controlBatch,
|
||||
body: {"devicesUuid": devicesUuid, "code": code, "value": value},
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('json-=-=-=-=-=-${json}');
|
||||
return json;
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user