mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-11-27 19:44:54 +00:00
@ -26,7 +26,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
bool oneGangGroup = false;
|
bool oneGangGroup = false;
|
||||||
List<DeviceModel> devicesList = [];
|
List<DeviceModel> devicesList = [];
|
||||||
|
|
||||||
OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) {
|
OneGangBloc({required this.oneGangId, required this.switchCode})
|
||||||
|
: super(InitialState()) {
|
||||||
on<InitialEvent>(_fetchOneGangStatus);
|
on<InitialEvent>(_fetchOneGangStatus);
|
||||||
on<OneGangUpdated>(_oneGangUpdated);
|
on<OneGangUpdated>(_oneGangUpdated);
|
||||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||||
@ -49,7 +50,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
on<GroupAllOffEvent>(_groupAllOff);
|
on<GroupAllOffEvent>(_groupAllOff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
|
void _fetchOneGangStatus(
|
||||||
|
InitialEvent event, Emitter<OneGangState> emit) async {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
try {
|
try {
|
||||||
var response = await DevicesAPI.getDeviceStatus(oneGangId);
|
var response = await DevicesAPI.getDeviceStatus(oneGangId);
|
||||||
@ -68,18 +70,21 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
|
|
||||||
_listenToChanges() {
|
_listenToChanges() {
|
||||||
try {
|
try {
|
||||||
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneGangId');
|
DatabaseReference ref =
|
||||||
|
FirebaseDatabase.instance.ref('device-status/$oneGangId');
|
||||||
Stream<DatabaseEvent> stream = ref.onValue;
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
stream.listen((DatabaseEvent event) async {
|
stream.listen((DatabaseEvent event) async {
|
||||||
if (_timer != null) {
|
if (_timer != null) {
|
||||||
await Future.delayed(const Duration(seconds: 2));
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
}
|
}
|
||||||
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
Map<dynamic, dynamic> usersMap =
|
||||||
|
event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
List<StatusModel> statusList = [];
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
usersMap['status'].forEach((element) {
|
usersMap['status'].forEach((element) {
|
||||||
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
statusList
|
||||||
|
.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
});
|
});
|
||||||
|
|
||||||
deviceStatus = OneGangModel.fromJson(statusList);
|
deviceStatus = OneGangModel.fromJson(statusList);
|
||||||
@ -94,7 +99,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
emit(UpdateState(oneGangModel: deviceStatus));
|
emit(UpdateState(oneGangModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
|
void _changeFirstSwitch(
|
||||||
|
ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
|
||||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
deviceStatus.firstSwitch = !event.value;
|
deviceStatus.firstSwitch = !event.value;
|
||||||
@ -119,17 +125,20 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _changeSliding(ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
|
void _changeSliding(
|
||||||
|
ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
|
||||||
emit(ChangeSlidingSegmentState(value: event.value));
|
emit(ChangeSlidingSegmentState(value: event.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setCounterValue(SetCounterValue event, Emitter<OneGangState> emit) async {
|
void _setCounterValue(
|
||||||
|
SetCounterValue event, Emitter<OneGangState> emit) async {
|
||||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||||
int seconds = 0;
|
int seconds = 0;
|
||||||
try {
|
try {
|
||||||
seconds = event.duration.inSeconds;
|
seconds = event.duration.inSeconds;
|
||||||
final response = await DevicesAPI.controlDevice(
|
final response = await DevicesAPI.controlDevice(
|
||||||
DeviceControlModel(deviceId: oneGangId, code: event.deviceCode, value: seconds),
|
DeviceControlModel(
|
||||||
|
deviceId: oneGangId, code: event.deviceCode, value: seconds),
|
||||||
oneGangId);
|
oneGangId);
|
||||||
|
|
||||||
if (response['success'] ?? false) {
|
if (response['success'] ?? false) {
|
||||||
@ -152,7 +161,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _getCounterValue(GetCounterEvent event, Emitter<OneGangState> emit) async {
|
void _getCounterValue(
|
||||||
|
GetCounterEvent event, Emitter<OneGangState> emit) async {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
try {
|
try {
|
||||||
var response = await DevicesAPI.getDeviceStatus(oneGangId);
|
var response = await DevicesAPI.getDeviceStatus(oneGangId);
|
||||||
@ -241,7 +251,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
deviceId: oneGangId,
|
deviceId: oneGangId,
|
||||||
);
|
);
|
||||||
List<dynamic> jsonData = response;
|
List<dynamic> jsonData = response;
|
||||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
listSchedule =
|
||||||
|
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||||
emit(InitialState());
|
emit(InitialState());
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
@ -252,12 +263,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
|
|
||||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||||
if (dateTime == null) return null;
|
if (dateTime == null) return null;
|
||||||
DateTime dateTimeWithoutSeconds =
|
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||||
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
|
dateTime.day, dateTime.hour, dateTime.minute);
|
||||||
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future toggleChange(ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
|
Future toggleChange(
|
||||||
|
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
final response = await DevicesAPI.changeSchedule(
|
final response = await DevicesAPI.changeSchedule(
|
||||||
@ -276,7 +288,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
|
Future deleteSchedule(
|
||||||
|
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
final response = await DevicesAPI.deleteSchedule(
|
final response = await DevicesAPI.deleteSchedule(
|
||||||
@ -296,8 +309,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggleCreateSchedule(
|
||||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
|
ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
createSchedule = !createSchedule;
|
createSchedule = !createSchedule;
|
||||||
selectedDays.clear();
|
selectedDays.clear();
|
||||||
@ -326,7 +339,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
|
|
||||||
int selectedTabIndex = 0;
|
int selectedTabIndex = 0;
|
||||||
|
|
||||||
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneGangState> emit) {
|
void toggleSelectedIndex(
|
||||||
|
ToggleSelectedEvent event, Emitter<OneGangState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
selectedTabIndex = event.index;
|
selectedTabIndex = event.index;
|
||||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||||
@ -335,7 +349,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
List<GroupOneGangModel> groupOneGangList = [];
|
List<GroupOneGangModel> groupOneGangList = [];
|
||||||
bool allSwitchesOn = true;
|
bool allSwitchesOn = true;
|
||||||
|
|
||||||
void _fetchOneGangWizardStatus(InitialWizardEvent event, Emitter<OneGangState> emit) async {
|
void _fetchOneGangWizardStatus(
|
||||||
|
InitialWizardEvent event, Emitter<OneGangState> emit) async {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
try {
|
try {
|
||||||
devicesList = [];
|
devicesList = [];
|
||||||
@ -345,7 +360,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
|
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
|
||||||
|
|
||||||
for (int i = 0; i < devicesList.length; i++) {
|
for (int i = 0; i < devicesList.length; i++) {
|
||||||
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
var response =
|
||||||
|
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||||
List<StatusModel> statusModelList = [];
|
List<StatusModel> statusModelList = [];
|
||||||
for (var status in response['status']) {
|
for (var status in response['status']) {
|
||||||
statusModelList.add(StatusModel.fromJson(status));
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
@ -366,15 +382,16 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
|
emit(UpdateGroupState(
|
||||||
|
oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(error: e.toString()));
|
emit(FailedState(error: e.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _changeFirstWizardSwitch(
|
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||||
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneGangState> emit) async {
|
Emitter<OneGangState> emit) async {
|
||||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
bool allSwitchesValue = true;
|
bool allSwitchesValue = true;
|
||||||
@ -387,7 +404,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
|
emit(UpdateGroupState(
|
||||||
|
oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
|
||||||
|
|
||||||
final response = await DevicesAPI.deviceBatchController(
|
final response = await DevicesAPI.deviceBatchController(
|
||||||
code: 'switch_1',
|
code: 'switch_1',
|
||||||
@ -415,7 +433,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
|
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
|
||||||
|
|
||||||
// Get a list of all device IDs
|
// Get a list of all device IDs
|
||||||
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
|
List<String> allDeviceIds =
|
||||||
|
groupOneGangList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
// First call for switch_1
|
// First call for switch_1
|
||||||
final response = await DevicesAPI.deviceBatchController(
|
final response = await DevicesAPI.deviceBatchController(
|
||||||
@ -447,7 +466,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
|||||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
|
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
|
||||||
|
|
||||||
// Get a list of all device IDs
|
// Get a list of all device IDs
|
||||||
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
|
List<String> allDeviceIds =
|
||||||
|
groupOneGangList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
// First call for switch_1
|
// First call for switch_1
|
||||||
final response = await DevicesAPI.deviceBatchController(
|
final response = await DevicesAPI.deviceBatchController(
|
||||||
|
|||||||
551
lib/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart
Normal file
551
lib/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart
Normal file
@ -0,0 +1,551 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
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/one_touch_bloc/one_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.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_one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/schedule_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/helpers/snack_bar.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
|
||||||
|
final String oneTouchId;
|
||||||
|
final String switchCode;
|
||||||
|
OneTouchModel deviceStatus = OneTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off);
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
bool oneTouchGroup = false;
|
||||||
|
List<DeviceModel> devicesList = [];
|
||||||
|
|
||||||
|
OneTouchBloc({required this.oneTouchId, required this.switchCode})
|
||||||
|
: super(InitialState()) {
|
||||||
|
on<InitialEvent>(_fetchOneTouchStatus);
|
||||||
|
on<OneTouchUpdated>(_oneTouchUpdated);
|
||||||
|
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||||
|
on<ChangeSlidingSegment>(_changeSliding);
|
||||||
|
on<SetCounterValue>(_setCounterValue);
|
||||||
|
on<GetCounterEvent>(_getCounterValue);
|
||||||
|
on<TickTimer>(_onTickTimer);
|
||||||
|
on<OnClose>(_onClose);
|
||||||
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
|
on<ScheduleSave>(saveSchedule);
|
||||||
|
on<GetScheduleEvent>(getSchedule);
|
||||||
|
on<ToggleScheduleEvent>(toggleChange);
|
||||||
|
on<DeleteScheduleEvent>(deleteSchedule);
|
||||||
|
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||||
|
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||||
|
on<InitialWizardEvent>(_fetchOneTouchWizardStatus);
|
||||||
|
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||||
|
on<GroupAllOnEvent>(_groupAllOn);
|
||||||
|
on<GroupAllOffEvent>(_groupAllOff);
|
||||||
|
on<ChangeStatusEvent>(_changeStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fetchOneTouchStatus(
|
||||||
|
InitialEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = OneTouchModel.fromJson(statusModelList);
|
||||||
|
emit(UpdateState(oneTouchModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref =
|
||||||
|
FirebaseDatabase.instance.ref('device-status/$oneTouchId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) async {
|
||||||
|
if (_timer != null) {
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
Map<dynamic, dynamic> usersMap =
|
||||||
|
event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList
|
||||||
|
.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = OneTouchModel.fromJson(statusList);
|
||||||
|
if (!isClosed) {
|
||||||
|
add(OneTouchUpdated());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_oneTouchUpdated(OneTouchUpdated event, Emitter<OneTouchState> emit) {
|
||||||
|
emit(UpdateState(oneTouchModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeFirstSwitch(
|
||||||
|
ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
deviceStatus.firstSwitch = !event.value;
|
||||||
|
emit(UpdateState(oneTouchModel: deviceStatus));
|
||||||
|
if (_timer != null) {
|
||||||
|
_timer!.cancel();
|
||||||
|
}
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: oneTouchGroup ? event.deviceId : oneTouchId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: !event.value),
|
||||||
|
oneTouchGroup ? event.deviceId : oneTouchId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeSliding(
|
||||||
|
ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(ChangeSlidingSegmentState(value: event.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCounterValue(
|
||||||
|
SetCounterValue event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||||
|
int seconds = 0;
|
||||||
|
try {
|
||||||
|
seconds = event.duration.inSeconds;
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: oneTouchId, code: event.deviceCode, value: seconds),
|
||||||
|
oneTouchId);
|
||||||
|
|
||||||
|
if (response['success'] ?? false) {
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown = seconds;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit(const FailedState(error: 'Something went wrong'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (seconds > 0) {
|
||||||
|
_onStartTimer(seconds);
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getCounterValue(
|
||||||
|
GetCounterEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = OneTouchModel.fromJson(statusModelList);
|
||||||
|
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.firstCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onClose(OnClose event, Emitter<OneTouchState> emit) {
|
||||||
|
_timer?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onStartTimer(int seconds) {
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
add(TickTimer(seconds - timer.tick));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTickTimer(TickTimer event, Emitter<OneTouchState> emit) {
|
||||||
|
if (event.remainingTime > 0) {
|
||||||
|
emit(TimerRunInProgress(event.remainingTime));
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, String>> days = [
|
||||||
|
{"day": "Sun", "key": "Sun"},
|
||||||
|
{"day": "Mon", "key": "Mon"},
|
||||||
|
{"day": "Tue", "key": "Tue"},
|
||||||
|
{"day": "Wed", "key": "Wed"},
|
||||||
|
{"day": "Thu", "key": "Thu"},
|
||||||
|
{"day": "Fri", "key": "Fri"},
|
||||||
|
{"day": "Sat", "key": "Sat"},
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<void> saveSchedule(
|
||||||
|
ScheduleSave event,
|
||||||
|
Emitter<OneTouchState> emit,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
if (selectedDays.isNotEmpty) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
await DevicesAPI.postSchedule(
|
||||||
|
category: switchCode,
|
||||||
|
deviceId: oneTouchId,
|
||||||
|
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||||
|
code: switchCode,
|
||||||
|
value: toggleSchedule,
|
||||||
|
days: selectedDays);
|
||||||
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
emit(SaveSchedule());
|
||||||
|
|
||||||
|
add(const ToggleCreateScheduleEvent(index: 1));
|
||||||
|
} else {
|
||||||
|
CustomSnackBar.displaySnackBar('Please select days');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getSchedule(
|
||||||
|
GetScheduleEvent event,
|
||||||
|
Emitter<OneTouchState> emit,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.getSchedule(
|
||||||
|
category: switchCode,
|
||||||
|
deviceId: oneTouchId,
|
||||||
|
);
|
||||||
|
List<dynamic> jsonData = response;
|
||||||
|
listSchedule =
|
||||||
|
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||||
|
emit(InitialState());
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||||
|
if (dateTime == null) return null;
|
||||||
|
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||||
|
dateTime.day, dateTime.hour, dateTime.minute);
|
||||||
|
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future toggleChange(
|
||||||
|
ToggleScheduleEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.changeSchedule(
|
||||||
|
scheduleId: event.id, deviceUuid: oneTouchId, enable: event.toggle);
|
||||||
|
if (response == true) {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
toggleSchedule = event.toggle;
|
||||||
|
return toggleSchedule;
|
||||||
|
}
|
||||||
|
emit(IsToggleState(onOff: toggleSchedule));
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future deleteSchedule(
|
||||||
|
DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.deleteSchedule(
|
||||||
|
scheduleId: event.id,
|
||||||
|
deviceUuid: oneTouchId,
|
||||||
|
);
|
||||||
|
if (response == true) {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
return toggleSchedule;
|
||||||
|
}
|
||||||
|
emit(IsToggleState(onOff: toggleSchedule));
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleCreateSchedule(
|
||||||
|
ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
createSchedule = !createSchedule;
|
||||||
|
selectedDays.clear();
|
||||||
|
selectedTime = DateTime.now();
|
||||||
|
emit(UpdateCreateScheduleState(createSchedule));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool toggleSchedule = true;
|
||||||
|
List<String> selectedDays = [];
|
||||||
|
bool createSchedule = false;
|
||||||
|
List<ScheduleModel> listSchedule = [];
|
||||||
|
DateTime? selectedTime = DateTime.now();
|
||||||
|
Future<void> toggleDaySelection(
|
||||||
|
ToggleDaySelectionEvent event,
|
||||||
|
Emitter<OneTouchState> emit,
|
||||||
|
) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
if (selectedDays.contains(event.key)) {
|
||||||
|
selectedDays.remove(event.key);
|
||||||
|
} else {
|
||||||
|
selectedDays.add(event.key);
|
||||||
|
}
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
add(ChangeSlidingSegment(value: 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int selectedTabIndex = 0;
|
||||||
|
|
||||||
|
void toggleSelectedIndex(
|
||||||
|
ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
selectedTabIndex = event.index;
|
||||||
|
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GroupOneTouchModel> groupOneTouchList = [];
|
||||||
|
bool allSwitchesOn = true;
|
||||||
|
|
||||||
|
void _fetchOneTouchWizardStatus(
|
||||||
|
InitialWizardEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
devicesList = [];
|
||||||
|
groupOneTouchList = [];
|
||||||
|
allSwitchesOn = true;
|
||||||
|
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||||
|
HomeCubit.getInstance().selectedSpace?.id ?? '', '1GT');
|
||||||
|
|
||||||
|
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 = OneTouchModel.fromJson(statusModelList);
|
||||||
|
groupOneTouchList.add(GroupOneTouchModel(
|
||||||
|
deviceId: devicesList[i].uuid ?? '',
|
||||||
|
deviceName: devicesList[i].name ?? '',
|
||||||
|
firstSwitch: deviceStatus.firstSwitch,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupOneTouchList.isNotEmpty) {
|
||||||
|
groupOneTouchList.firstWhere((element) {
|
||||||
|
if (!element.firstSwitch) {
|
||||||
|
allSwitchesOn = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||||
|
Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
bool allSwitchesValue = true;
|
||||||
|
groupOneTouchList.forEach((element) {
|
||||||
|
if (element.deviceId == event.deviceId) {
|
||||||
|
element.firstSwitch = !event.value;
|
||||||
|
}
|
||||||
|
if (!element.firstSwitch) {
|
||||||
|
allSwitchesValue = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
final response = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_1',
|
||||||
|
devicesUuid: [event.deviceId],
|
||||||
|
value: !event.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _groupAllOn(GroupAllOnEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||||
|
for (int i = 0; i < groupOneTouchList.length; i++) {
|
||||||
|
groupOneTouchList[i].firstSwitch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the state with updated values
|
||||||
|
emit(
|
||||||
|
UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
|
||||||
|
|
||||||
|
// Get a list of all device IDs
|
||||||
|
List<String> allDeviceIds =
|
||||||
|
groupOneTouchList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
|
// First call for switch_1
|
||||||
|
final response1 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_1', // Controls first switch for all devices
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: true, // true (on) or false (off) depending on the event value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Second call for switch_2
|
||||||
|
final response2 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_2', // Controls second switch for all devices
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: true, // true (on) or false (off) depending on the event value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if either response is unsuccessful, then reset to initial state
|
||||||
|
if (!response1['success'] || !response2['success']) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// In case of an error, delay and reset the screen to initial state
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _groupAllOff(GroupAllOffEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||||
|
for (int i = 0; i < groupOneTouchList.length; i++) {
|
||||||
|
groupOneTouchList[i].firstSwitch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the state with updated values
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
oneTouchList: groupOneTouchList, allSwitches: false));
|
||||||
|
|
||||||
|
// Get a list of all device IDs
|
||||||
|
List<String> allDeviceIds =
|
||||||
|
groupOneTouchList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
|
// First call for switch_1
|
||||||
|
final response1 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_1', // Controls first switch for all devices
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: true, // true (on) or false (off) depending on the event value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Second call for switch_2
|
||||||
|
final response2 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_2', // Controls second switch for all devices
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: true, // true (on) or false (off) depending on the event value
|
||||||
|
);
|
||||||
|
// Check if either response is unsuccessful, then reset to initial state
|
||||||
|
if (!response1['success'] || !response2['success']) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// In case of an error, delay and reset the screen to initial state
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String statusSelected = '';
|
||||||
|
String optionSelected = '';
|
||||||
|
|
||||||
|
Future<void> _changeStatus(
|
||||||
|
ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
|
||||||
|
final Map<String, Map<String, String>> controlMap = {
|
||||||
|
"relay_status": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
"light_mode": {
|
||||||
|
'Off': 'none',
|
||||||
|
'On/Off Status': 'relay',
|
||||||
|
'Switch Position': 'pos',
|
||||||
|
},
|
||||||
|
"relay_status_1": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
final selectedControl = controlMap[optionSelected]?[statusSelected];
|
||||||
|
if (selectedControl != null) {
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: oneTouchId, code: optionSelected, value: selectedControl),
|
||||||
|
oneTouchId,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
print('Invalid statusSelected or optionSelected');
|
||||||
|
}
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
148
lib/features/devices/bloc/one_touch_bloc/one_touch_event.dart
Normal file
148
lib/features/devices/bloc/one_touch_bloc/one_touch_event.dart
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
abstract class OneTouchEvent extends Equatable {
|
||||||
|
const OneTouchEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class OneTouchUpdated extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class InitialEvent extends OneTouchEvent {
|
||||||
|
final bool groupScreen;
|
||||||
|
const InitialEvent({required this.groupScreen});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [groupScreen];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeFirstSwitchStatusEvent extends OneTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSecondSwitchStatusEvent extends OneTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeSecondSwitchStatusEvent(
|
||||||
|
{required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AllOffEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class AllOnEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class GroupAllOnEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class GroupAllOffEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class ChangeSlidingSegment extends OneTouchEvent {
|
||||||
|
final int value;
|
||||||
|
const ChangeSlidingSegment({required this.value});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetCounterEvent extends OneTouchEvent {
|
||||||
|
final String deviceCode;
|
||||||
|
const GetCounterEvent({required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetCounterValue extends OneTouchEvent {
|
||||||
|
final Duration duration;
|
||||||
|
final String deviceCode;
|
||||||
|
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration, deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartTimer extends OneTouchEvent {
|
||||||
|
final int duration;
|
||||||
|
|
||||||
|
const StartTimer(this.duration);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TickTimer extends OneTouchEvent {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TickTimer(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StopTimer extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class OnClose extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class InitialWizardEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
//------------------- Schedule ----------=---------
|
||||||
|
class GetScheduleEvent extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class ScheduleSave extends OneTouchEvent {}
|
||||||
|
|
||||||
|
class ToggleScheduleEvent extends OneTouchEvent {
|
||||||
|
final String id;
|
||||||
|
final bool toggle;
|
||||||
|
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [toggle, id];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleDaySelectionEvent extends OneTouchEvent {
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
const ToggleDaySelectionEvent({required this.key});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [key];
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteScheduleEvent extends OneTouchEvent {
|
||||||
|
final String id;
|
||||||
|
const DeleteScheduleEvent({required this.id});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleSelectedEvent extends OneTouchEvent {
|
||||||
|
final int index;
|
||||||
|
const ToggleSelectedEvent({required this.index});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleCreateScheduleEvent extends OneTouchEvent {
|
||||||
|
final int index;
|
||||||
|
const ToggleCreateScheduleEvent({required this.index});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeFirstWizardSwitchStatusEvent extends OneTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeFirstWizardSwitchStatusEvent(
|
||||||
|
{required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeStatusEvent extends OneTouchEvent {
|
||||||
|
final String deviceId;
|
||||||
|
final BuildContext context;
|
||||||
|
const ChangeStatusEvent({this.deviceId = '',required this.context});
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class OneTouchState extends Equatable {
|
||||||
|
const OneTouchState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialState extends OneTouchState {}
|
||||||
|
|
||||||
|
class LoadingInitialState extends OneTouchState {}
|
||||||
|
|
||||||
|
class UpdateState extends OneTouchState {
|
||||||
|
final OneTouchModel oneTouchModel;
|
||||||
|
const UpdateState({required this.oneTouchModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [oneTouchModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingNewSate extends OneTouchState {
|
||||||
|
final OneTouchModel oneTouchModel;
|
||||||
|
const LoadingNewSate({required this.oneTouchModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [OneTouchModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateGroupState extends OneTouchState {
|
||||||
|
final List<GroupOneTouchModel> oneTouchList;
|
||||||
|
final bool allSwitches;
|
||||||
|
|
||||||
|
const UpdateGroupState({required this.oneTouchList, required this.allSwitches});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [oneTouchList, allSwitches];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FailedState extends OneTouchState {
|
||||||
|
final String error;
|
||||||
|
|
||||||
|
const FailedState({required this.error});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [error];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSlidingSegmentState extends OneTouchState {
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
const ChangeSlidingSegmentState({required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateTimerState extends OneTouchState {
|
||||||
|
final int seconds;
|
||||||
|
const UpdateTimerState({required this.seconds});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [seconds];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunInProgress extends OneTouchState {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TimerRunInProgress(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunComplete extends OneTouchState {}
|
||||||
|
|
||||||
|
class SaveSchedule extends OneTouchState {}
|
||||||
|
|
||||||
|
class IsToggleState extends OneTouchState {
|
||||||
|
final bool? onOff;
|
||||||
|
const IsToggleState({this.onOff});
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeTimeState extends OneTouchState {}
|
||||||
|
|
||||||
|
class UpdateCreateScheduleState extends OneTouchState {
|
||||||
|
final bool createSchedule;
|
||||||
|
UpdateCreateScheduleState(this.createSchedule);
|
||||||
|
}
|
||||||
748
lib/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart
Normal file
748
lib/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart
Normal file
@ -0,0 +1,748 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
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/three_touch_bloc/three_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.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_three_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
|
||||||
|
final String threeTouchId;
|
||||||
|
final String switchCode;
|
||||||
|
ThreeTouchModel deviceStatus = ThreeTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
secondSwitch: false,
|
||||||
|
thirdSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
secondCountDown: 0,
|
||||||
|
thirdCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off,
|
||||||
|
relay_status_2: status.off,
|
||||||
|
relay_status_3: status.off,
|
||||||
|
);
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
bool threeTouchGroup = false;
|
||||||
|
List<DeviceModel> devicesList = [];
|
||||||
|
List<GroupThreeTouchModel> groupThreeTouchList = [];
|
||||||
|
bool allSwitchesOn = true;
|
||||||
|
|
||||||
|
ThreeTouchBloc({required this.threeTouchId, required this.switchCode})
|
||||||
|
: super(InitialState()) {
|
||||||
|
on<InitialEvent>(_fetchThreeTouchStatus);
|
||||||
|
on<ThreeTouchUpdated>(_threeTouchUpdated);
|
||||||
|
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||||
|
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
|
||||||
|
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
||||||
|
on<AllOffEvent>(_allOff);
|
||||||
|
on<AllOnEvent>(_allOn);
|
||||||
|
on<ChangeSlidingSegment>(_changeSliding);
|
||||||
|
on<SetCounterValue>(_setCounterValue);
|
||||||
|
on<GetCounterEvent>(_getCounterValue);
|
||||||
|
on<TickTimer>(_onTickTimer);
|
||||||
|
on<OnClose>(_onClose);
|
||||||
|
on<GroupAllOnEvent>(_groupAllOn);
|
||||||
|
on<GroupAllOffEvent>(_groupAllOff);
|
||||||
|
|
||||||
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
|
on<ThreeTouchSave>(saveSchedule);
|
||||||
|
on<GetScheduleEvent>(getSchedule);
|
||||||
|
on<ToggleScheduleEvent>(toggleChange);
|
||||||
|
on<DeleteScheduleEvent>(deleteSchedule);
|
||||||
|
|
||||||
|
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||||
|
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||||
|
on<ChangeStatusEvent>(_changeStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fetchThreeTouchStatus(
|
||||||
|
InitialEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
threeTouchGroup = event.groupScreen;
|
||||||
|
if (threeTouchGroup) {
|
||||||
|
devicesList = [];
|
||||||
|
groupThreeTouchList = [];
|
||||||
|
allSwitchesOn = true;
|
||||||
|
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||||
|
HomeCubit.getInstance().selectedSpace?.id ?? '', '3GT');
|
||||||
|
|
||||||
|
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 = ThreeTouchModel.fromJson(statusModelList);
|
||||||
|
|
||||||
|
groupThreeTouchList.add(GroupThreeTouchModel(
|
||||||
|
deviceId: devicesList[i].uuid ?? '',
|
||||||
|
deviceName: devicesList[i].name ?? '',
|
||||||
|
firstSwitch: deviceStatus.firstSwitch,
|
||||||
|
secondSwitch: deviceStatus.secondSwitch,
|
||||||
|
thirdSwitch: deviceStatus.thirdSwitch));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupThreeTouchList.isNotEmpty) {
|
||||||
|
groupThreeTouchList.firstWhere((element) {
|
||||||
|
if (!element.firstSwitch ||
|
||||||
|
!element.secondSwitch ||
|
||||||
|
!element.thirdSwitch) {
|
||||||
|
allSwitchesOn = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
|
||||||
|
} else {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref =
|
||||||
|
FirebaseDatabase.instance.ref('device-status/$threeTouchId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) async {
|
||||||
|
if (_timer != null) {
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
Map<dynamic, dynamic> usersMap =
|
||||||
|
event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList
|
||||||
|
.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = ThreeTouchModel.fromJson(statusList);
|
||||||
|
if (!isClosed) {
|
||||||
|
add(ThreeTouchUpdated());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_threeTouchUpdated(ThreeTouchUpdated event, Emitter<ThreeTouchState> emit) {
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeFirstSwitch(
|
||||||
|
ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
if (threeTouchGroup) {
|
||||||
|
bool allSwitchesValue = true;
|
||||||
|
groupThreeTouchList.forEach((element) {
|
||||||
|
if (element.deviceId == event.deviceId) {
|
||||||
|
element.firstSwitch = !event.value;
|
||||||
|
}
|
||||||
|
if (!element.firstSwitch ||
|
||||||
|
!element.secondSwitch ||
|
||||||
|
!element.thirdSwitch) {
|
||||||
|
allSwitchesValue = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
threeTouchList: groupThreeTouchList,
|
||||||
|
allSwitches: allSwitchesValue));
|
||||||
|
} else {
|
||||||
|
deviceStatus.firstSwitch = !event.value;
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_timer != null) {
|
||||||
|
_timer!.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchGroup ? event.deviceId : threeTouchId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: !event.value),
|
||||||
|
threeTouchGroup ? event.deviceId : threeTouchId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event,
|
||||||
|
Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
if (threeTouchGroup) {
|
||||||
|
bool allSwitchesValue = true;
|
||||||
|
groupThreeTouchList.forEach((element) {
|
||||||
|
if (element.deviceId == event.deviceId) {
|
||||||
|
element.secondSwitch = !event.value;
|
||||||
|
}
|
||||||
|
if (!element.firstSwitch ||
|
||||||
|
!element.secondSwitch ||
|
||||||
|
!element.thirdSwitch) {
|
||||||
|
allSwitchesValue = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
threeTouchList: groupThreeTouchList,
|
||||||
|
allSwitches: allSwitchesValue));
|
||||||
|
} else {
|
||||||
|
deviceStatus.secondSwitch = !event.value;
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_timer != null) {
|
||||||
|
_timer!.cancel();
|
||||||
|
}
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchGroup ? event.deviceId : threeTouchId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: !event.value),
|
||||||
|
threeTouchGroup ? event.deviceId : threeTouchId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeThirdSwitch(
|
||||||
|
ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
if (threeTouchGroup) {
|
||||||
|
bool allSwitchesValue = true;
|
||||||
|
groupThreeTouchList.forEach((element) {
|
||||||
|
if (element.deviceId == event.deviceId) {
|
||||||
|
element.thirdSwitch = !event.value;
|
||||||
|
}
|
||||||
|
if (!element.firstSwitch ||
|
||||||
|
!element.secondSwitch ||
|
||||||
|
!element.thirdSwitch) {
|
||||||
|
allSwitchesValue = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
threeTouchList: groupThreeTouchList,
|
||||||
|
allSwitches: allSwitchesValue));
|
||||||
|
} else {
|
||||||
|
deviceStatus.thirdSwitch = !event.value;
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_timer != null) {
|
||||||
|
_timer!.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchGroup ? event.deviceId : threeTouchId,
|
||||||
|
code: 'switch_3',
|
||||||
|
value: !event.value),
|
||||||
|
threeTouchGroup ? event.deviceId : threeTouchId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _allOff(AllOffEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
|
||||||
|
try {
|
||||||
|
deviceStatus.firstSwitch = false;
|
||||||
|
deviceStatus.secondSwitch = false;
|
||||||
|
deviceStatus.thirdSwitch = false;
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
|
||||||
|
final response = await Future.wait([
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: deviceStatus.firstSwitch),
|
||||||
|
threeTouchId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: deviceStatus.secondSwitch),
|
||||||
|
threeTouchId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: 'switch_3',
|
||||||
|
value: deviceStatus.thirdSwitch),
|
||||||
|
threeTouchId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (response.every((element) => !element['success'])) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: false));
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _allOn(AllOnEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
|
||||||
|
try {
|
||||||
|
deviceStatus.firstSwitch = true;
|
||||||
|
deviceStatus.secondSwitch = true;
|
||||||
|
deviceStatus.thirdSwitch = true;
|
||||||
|
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||||
|
|
||||||
|
final response = await Future.wait([
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: deviceStatus.firstSwitch),
|
||||||
|
threeTouchId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: deviceStatus.secondSwitch),
|
||||||
|
threeTouchId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: 'switch_3',
|
||||||
|
value: deviceStatus.thirdSwitch),
|
||||||
|
threeTouchId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (response.every((element) => !element['success'])) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: false));
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _groupAllOn(GroupAllOnEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||||
|
groupThreeTouchList[i].firstSwitch = true;
|
||||||
|
groupThreeTouchList[i].secondSwitch = true;
|
||||||
|
groupThreeTouchList[i].thirdSwitch = true;
|
||||||
|
}
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
threeTouchList: groupThreeTouchList, allSwitches: true));
|
||||||
|
|
||||||
|
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||||
|
final response = await Future.wait([
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: groupThreeTouchList[i].deviceId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: true),
|
||||||
|
groupThreeTouchList[i].deviceId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: groupThreeTouchList[i].deviceId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: true),
|
||||||
|
groupThreeTouchList[i].deviceId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: groupThreeTouchList[i].deviceId,
|
||||||
|
code: 'switch_3',
|
||||||
|
value: true),
|
||||||
|
groupThreeTouchList[i].deviceId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (response.every((element) => !element['success'])) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _groupAllOff(
|
||||||
|
GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||||
|
groupThreeTouchList[i].firstSwitch = false;
|
||||||
|
groupThreeTouchList[i].secondSwitch = false;
|
||||||
|
groupThreeTouchList[i].thirdSwitch = false;
|
||||||
|
}
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
threeTouchList: groupThreeTouchList, allSwitches: false));
|
||||||
|
|
||||||
|
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||||
|
final response = await Future.wait([
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: groupThreeTouchList[i].deviceId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: false),
|
||||||
|
groupThreeTouchList[i].deviceId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: groupThreeTouchList[i].deviceId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: false),
|
||||||
|
groupThreeTouchList[i].deviceId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: groupThreeTouchList[i].deviceId,
|
||||||
|
code: 'switch_3',
|
||||||
|
value: false),
|
||||||
|
groupThreeTouchList[i].deviceId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (response.every((element) => !element['success'])) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent(groupScreen: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeSliding(
|
||||||
|
ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(ChangeSlidingSegmentState(value: event.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCounterValue(
|
||||||
|
SetCounterValue event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||||
|
int seconds = 0;
|
||||||
|
try {
|
||||||
|
seconds = event.duration.inSeconds;
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId, code: event.deviceCode, value: seconds),
|
||||||
|
threeTouchId);
|
||||||
|
|
||||||
|
if (response['success'] ?? false) {
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown = seconds;
|
||||||
|
} else if (event.deviceCode == 'countdown_2') {
|
||||||
|
deviceStatus.secondCountDown = seconds;
|
||||||
|
} else if (event.deviceCode == 'countdown_3') {
|
||||||
|
deviceStatus.thirdCountDown = seconds;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit(const FailedState(error: 'Something went wrong'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (seconds > 0) {
|
||||||
|
_onStartTimer(seconds);
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getCounterValue(
|
||||||
|
GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
|
||||||
|
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.firstCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||||
|
} else if (event.deviceCode == 'countdown_2') {
|
||||||
|
deviceStatus.secondCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.secondCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.secondCountDown));
|
||||||
|
} else if (event.deviceCode == 'countdown_3') {
|
||||||
|
deviceStatus.thirdCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.thirdCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.thirdCountDown));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onClose(OnClose event, Emitter<ThreeTouchState> emit) {
|
||||||
|
_timer?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onStartTimer(int seconds) {
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
add(TickTimer(seconds - timer.tick));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTickTimer(TickTimer event, Emitter<ThreeTouchState> emit) {
|
||||||
|
if (event.remainingTime > 0) {
|
||||||
|
emit(TimerRunInProgress(event.remainingTime));
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, String>> days = [
|
||||||
|
{"day": "Sun", "key": "Sun"},
|
||||||
|
{"day": "Mon", "key": "Mon"},
|
||||||
|
{"day": "Tue", "key": "Tue"},
|
||||||
|
{"day": "Wed", "key": "Wed"},
|
||||||
|
{"day": "Thu", "key": "Thu"},
|
||||||
|
{"day": "Fri", "key": "Fri"},
|
||||||
|
{"day": "Sat", "key": "Sat"},
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<void> toggleDaySelection(
|
||||||
|
ToggleDaySelectionEvent event,
|
||||||
|
Emitter<ThreeTouchState> emit,
|
||||||
|
) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
if (selectedDays.contains(event.key)) {
|
||||||
|
selectedDays.remove(event.key);
|
||||||
|
} else {
|
||||||
|
selectedDays.add(event.key);
|
||||||
|
}
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
add(ChangeSlidingSegment(value: 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveSchedule(
|
||||||
|
ThreeTouchSave event,
|
||||||
|
Emitter<ThreeTouchState> emit,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
if (selectedDays.isNotEmpty) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
await DevicesAPI.postSchedule(
|
||||||
|
category: switchCode,
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||||
|
code: switchCode,
|
||||||
|
value: toggleSchedule,
|
||||||
|
days: selectedDays);
|
||||||
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
emit(ThreeTouchSaveSchedule());
|
||||||
|
add(const ToggleCreateScheduleEvent(index: 1));
|
||||||
|
} else {
|
||||||
|
CustomSnackBar.displaySnackBar('Please select days');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getSchedule(
|
||||||
|
GetScheduleEvent event,
|
||||||
|
Emitter<ThreeTouchState> emit,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.getSchedule(
|
||||||
|
category: switchCode,
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
);
|
||||||
|
List<dynamic> jsonData = response;
|
||||||
|
listSchedule =
|
||||||
|
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||||
|
emit(InitialState());
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||||
|
if (dateTime == null) return null;
|
||||||
|
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||||
|
dateTime.day, dateTime.hour, dateTime.minute);
|
||||||
|
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future toggleChange(
|
||||||
|
ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.changeSchedule(
|
||||||
|
scheduleId: event.id, deviceUuid: threeTouchId, enable: event.toggle);
|
||||||
|
if (response == true) {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
toggleSchedule = event.toggle;
|
||||||
|
return toggleSchedule;
|
||||||
|
}
|
||||||
|
emit(IsToggleState(onOff: toggleSchedule));
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future deleteSchedule(
|
||||||
|
DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.deleteSchedule(
|
||||||
|
scheduleId: event.id,
|
||||||
|
deviceUuid: threeTouchId,
|
||||||
|
);
|
||||||
|
if (response == true) {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
return toggleSchedule;
|
||||||
|
}
|
||||||
|
emit(IsToggleState(onOff: toggleSchedule));
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleSelectedIndex(
|
||||||
|
ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
selectedTabIndex = event.index;
|
||||||
|
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleCreateSchedule(
|
||||||
|
ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
createSchedule = !createSchedule;
|
||||||
|
selectedDays.clear();
|
||||||
|
selectedTime = DateTime.now();
|
||||||
|
emit(UpdateCreateScheduleState(createSchedule));
|
||||||
|
}
|
||||||
|
|
||||||
|
int selectedTabIndex = 0;
|
||||||
|
bool toggleSchedule = true;
|
||||||
|
List<String> selectedDays = [];
|
||||||
|
bool createSchedule = false;
|
||||||
|
List<ScheduleModel> listSchedule = [];
|
||||||
|
DateTime? selectedTime = DateTime.now();
|
||||||
|
|
||||||
|
String statusSelected = '';
|
||||||
|
String optionSelected = '';
|
||||||
|
|
||||||
|
Future<void> _changeStatus(
|
||||||
|
ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final Map<String, Map<String, String>> controlMap = {
|
||||||
|
"relay_status": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
"light_mode": {
|
||||||
|
'Off': 'none',
|
||||||
|
'On/Off Status': 'relay',
|
||||||
|
'Switch Position': 'pos',
|
||||||
|
},
|
||||||
|
"relay_status_1": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
"relay_status_2": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
"relay_status_3": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
final selectedControl = controlMap[optionSelected]?[statusSelected];
|
||||||
|
if (selectedControl != null) {
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeTouchId,
|
||||||
|
code: optionSelected,
|
||||||
|
value: selectedControl),
|
||||||
|
threeTouchId,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
print('Invalid statusSelected or optionSelected');
|
||||||
|
}
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
abstract class ThreeTouchEvent extends Equatable {
|
||||||
|
const ThreeTouchEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingEvent extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class ThreeTouchUpdated extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class InitialEvent extends ThreeTouchEvent {
|
||||||
|
final bool groupScreen;
|
||||||
|
const InitialEvent({required this.groupScreen});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [groupScreen];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeFirstSwitchStatusEvent extends ThreeTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSecondSwitchStatusEvent extends ThreeTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeSecondSwitchStatusEvent(
|
||||||
|
{required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeThirdSwitchStatusEvent extends ThreeTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeThirdSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AllOffEvent extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class AllOnEvent extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class GroupAllOnEvent extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class GroupAllOffEvent extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class ChangeSlidingSegment extends ThreeTouchEvent {
|
||||||
|
final int value;
|
||||||
|
const ChangeSlidingSegment({required this.value});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetCounterEvent extends ThreeTouchEvent {
|
||||||
|
final String deviceCode;
|
||||||
|
const GetCounterEvent({required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetCounterValue extends ThreeTouchEvent {
|
||||||
|
final Duration duration;
|
||||||
|
final String deviceCode;
|
||||||
|
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration, deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartTimer extends ThreeTouchEvent {
|
||||||
|
final int duration;
|
||||||
|
|
||||||
|
const StartTimer(this.duration);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TickTimer extends ThreeTouchEvent {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TickTimer(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StopTimer extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class OnClose extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
//------------------- Schedule ----------=---------
|
||||||
|
class GetScheduleEvent extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class ThreeTouchSave extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class ToggleScheduleEvent extends ThreeTouchEvent {
|
||||||
|
final String id;
|
||||||
|
final bool toggle;
|
||||||
|
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [toggle, id];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleDaySelectionEvent extends ThreeTouchEvent {
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
const ToggleDaySelectionEvent({required this.key});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [key];
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeleteScheduleEvent extends ThreeTouchEvent {
|
||||||
|
final String id;
|
||||||
|
const DeleteScheduleEvent({required this.id});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleSelectedEvent extends ThreeTouchEvent {
|
||||||
|
final int index;
|
||||||
|
const ToggleSelectedEvent({required this.index});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleCreateScheduleEvent extends ThreeTouchEvent {
|
||||||
|
final int index;
|
||||||
|
const ToggleCreateScheduleEvent({required this.index});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialWizardDevises extends ThreeTouchEvent {}
|
||||||
|
|
||||||
|
class ChangeStatusEvent extends ThreeTouchEvent {
|
||||||
|
final String deviceId;
|
||||||
|
final BuildContext context;
|
||||||
|
const ChangeStatusEvent({this.deviceId = '', required this.context});
|
||||||
|
}
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_three_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||||
|
|
||||||
|
class ThreeTouchState extends Equatable {
|
||||||
|
const ThreeTouchState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialState extends ThreeTouchState {}
|
||||||
|
|
||||||
|
class LoadingInitialState extends ThreeTouchState {}
|
||||||
|
|
||||||
|
class UpdateState extends ThreeTouchState {
|
||||||
|
final ThreeTouchModel threeTouchModel;
|
||||||
|
const UpdateState({required this.threeTouchModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [threeTouchModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingNewSate extends ThreeTouchState {
|
||||||
|
final ThreeTouchModel threeTouchModel;
|
||||||
|
const LoadingNewSate({required this.threeTouchModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [threeTouchModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateGroupState extends ThreeTouchState {
|
||||||
|
final List<GroupThreeTouchModel> threeTouchList;
|
||||||
|
final bool allSwitches;
|
||||||
|
|
||||||
|
const UpdateGroupState(
|
||||||
|
{required this.threeTouchList, required this.allSwitches});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [threeTouchList, allSwitches];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FailedState extends ThreeTouchState {
|
||||||
|
final String error;
|
||||||
|
|
||||||
|
const FailedState({required this.error});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [error];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSlidingSegmentState extends ThreeTouchState {
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
const ChangeSlidingSegmentState({required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateTimerState extends ThreeTouchState {
|
||||||
|
final int seconds;
|
||||||
|
const UpdateTimerState({required this.seconds});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [seconds];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunInProgress extends ThreeTouchState {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TimerRunInProgress(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunComplete extends ThreeTouchState {}
|
||||||
|
|
||||||
|
class ThreeTouchSaveSchedule extends ThreeTouchState {}
|
||||||
|
|
||||||
|
class IsToggleState extends ThreeTouchState {
|
||||||
|
final bool? onOff;
|
||||||
|
const IsToggleState({this.onOff});
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeTimeState extends ThreeTouchState {}
|
||||||
|
|
||||||
|
class UpdateCreateScheduleState extends ThreeTouchState {
|
||||||
|
final bool createSchedule;
|
||||||
|
UpdateCreateScheduleState(this.createSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeStateSetting extends ThreeTouchState {
|
||||||
|
const ChangeStateSetting();
|
||||||
|
}
|
||||||
687
lib/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart
Normal file
687
lib/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart
Normal file
@ -0,0 +1,687 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
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/two_touch_bloc/two_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.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_two_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
|
||||||
|
final String twoTouchId;
|
||||||
|
final String switchCode;
|
||||||
|
TwoTouchModel deviceStatus = TwoTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
secondSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
secondCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off,
|
||||||
|
relay_status_2: status.off,
|
||||||
|
);
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
bool twoTouchGroup = false;
|
||||||
|
List<DeviceModel> devicesList = [];
|
||||||
|
List<GroupTwoTouchModel> groupTwoTouchList = [];
|
||||||
|
bool allSwitchesOn = true;
|
||||||
|
bool toggleSchedule = true;
|
||||||
|
List<String> selectedDays = [];
|
||||||
|
|
||||||
|
bool createSchedule = false;
|
||||||
|
List<ScheduleModel> listSchedule = [];
|
||||||
|
|
||||||
|
TwoTouchBloc({required this.twoTouchId, required this.switchCode})
|
||||||
|
: super(InitialState()) {
|
||||||
|
on<InitialEvent>(_fetchTwoTouchStatus);
|
||||||
|
on<TwoTouchUpdated>(_twoTouchUpdated);
|
||||||
|
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||||
|
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
|
||||||
|
on<AllOffEvent>(_allOff);
|
||||||
|
on<AllOnEvent>(_allOn);
|
||||||
|
on<ChangeSlidingSegment>(_changeSliding);
|
||||||
|
on<SetCounterValue>(_setCounterValue);
|
||||||
|
on<GetCounterEvent>(_getCounterValue);
|
||||||
|
on<TickTimer>(_onTickTimer);
|
||||||
|
on<OnClose>(_onClose);
|
||||||
|
on<GroupAllOnEvent>(_groupAllOn);
|
||||||
|
on<GroupAllOffEvent>(_groupAllOff);
|
||||||
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
|
on<TwoTouchSave>(saveSchedule);
|
||||||
|
on<GetScheduleEvent>(getSchedule);
|
||||||
|
on<ToggleScheduleEvent>(toggleRepeat);
|
||||||
|
on<DeleteScheduleEvent>(deleteSchedule);
|
||||||
|
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||||
|
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||||
|
on<InitialWizardEvent>(_fetchTwoTouchWizardStatus);
|
||||||
|
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||||
|
on<ChangeSecondWizardSwitchStatusEvent>(_changeSecondWizardSwitch);
|
||||||
|
on<ChangeStatusEvent>(_changeStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? selectedTime = DateTime.now();
|
||||||
|
|
||||||
|
int selectedTabIndex = 0;
|
||||||
|
|
||||||
|
void toggleSelectedIndex(
|
||||||
|
ToggleSelectedEvent event, Emitter<TwoTouchState> emit) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
selectedTabIndex = event.index;
|
||||||
|
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleCreateSchedule(
|
||||||
|
ToggleCreateScheduleEvent event, Emitter<TwoTouchState> emit) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
createSchedule = !createSchedule;
|
||||||
|
selectedDays.clear();
|
||||||
|
selectedTime = DateTime.now();
|
||||||
|
emit(UpdateCreateScheduleState(createSchedule));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fetchTwoTouchStatus(
|
||||||
|
InitialEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(twoTouchId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = TwoTouchModel.fromJson(statusModelList);
|
||||||
|
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref =
|
||||||
|
FirebaseDatabase.instance.ref('device-status/$twoTouchId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) async {
|
||||||
|
if (_timer != null) {
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
Map<dynamic, dynamic> usersMap =
|
||||||
|
event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList
|
||||||
|
.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = TwoTouchModel.fromJson(statusList);
|
||||||
|
if (!isClosed) {
|
||||||
|
add(TwoTouchUpdated());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_twoTouchUpdated(TwoTouchUpdated event, Emitter<TwoTouchState> emit) {
|
||||||
|
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeFirstSwitch(
|
||||||
|
ChangeFirstSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
deviceStatus.firstSwitch = !event.value;
|
||||||
|
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||||
|
if (_timer != null) {
|
||||||
|
_timer!.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId, code: 'switch_1', value: !event.value),
|
||||||
|
twoTouchId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeSecondSwitch(
|
||||||
|
ChangeSecondSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
deviceStatus.secondSwitch = !event.value;
|
||||||
|
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||||
|
if (_timer != null) {
|
||||||
|
_timer!.cancel();
|
||||||
|
}
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId, code: 'switch_2', value: !event.value),
|
||||||
|
twoTouchId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _allOff(AllOffEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
|
||||||
|
try {
|
||||||
|
deviceStatus.firstSwitch = false;
|
||||||
|
deviceStatus.secondSwitch = false;
|
||||||
|
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||||
|
|
||||||
|
final response = await Future.wait([
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: deviceStatus.firstSwitch),
|
||||||
|
twoTouchId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: deviceStatus.secondSwitch),
|
||||||
|
twoTouchId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (response.every((element) => !element['success'])) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _allOn(AllOnEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
deviceStatus.firstSwitch = true;
|
||||||
|
deviceStatus.secondSwitch = true;
|
||||||
|
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||||
|
final response = await Future.wait([
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: deviceStatus.firstSwitch),
|
||||||
|
twoTouchId),
|
||||||
|
DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: deviceStatus.secondSwitch),
|
||||||
|
twoTouchId),
|
||||||
|
]);
|
||||||
|
if (response.every((element) => !element['success'])) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(const InitialEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _groupAllOn(GroupAllOnEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < groupTwoTouchList.length; i++) {
|
||||||
|
groupTwoTouchList[i].firstSwitch = true;
|
||||||
|
groupTwoTouchList[i].secondSwitch = true;
|
||||||
|
}
|
||||||
|
emit(
|
||||||
|
UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: true));
|
||||||
|
List<String> allDeviceIds =
|
||||||
|
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
|
final response1 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_1',
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
final response2 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_2',
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response1['failedResults'].toString() != '[]' ||
|
||||||
|
response2['failedResults'].toString() != '[]') {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _groupAllOff(GroupAllOffEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < groupTwoTouchList.length; i++) {
|
||||||
|
groupTwoTouchList[i].firstSwitch = false;
|
||||||
|
groupTwoTouchList[i].secondSwitch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
twoTouchList: groupTwoTouchList, allSwitches: false));
|
||||||
|
|
||||||
|
List<String> allDeviceIds =
|
||||||
|
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
|
final response1 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_1',
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final response2 = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_2',
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response1['failedResults'].toString() != '[]' ||
|
||||||
|
response2['failedResults'].toString() != '[]') {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeSliding(
|
||||||
|
ChangeSlidingSegment event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(ChangeSlidingSegmentState(value: event.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCounterValue(
|
||||||
|
SetCounterValue event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
int seconds = 0;
|
||||||
|
try {
|
||||||
|
seconds = event.duration.inSeconds;
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId, code: event.deviceCode, value: seconds),
|
||||||
|
twoTouchId);
|
||||||
|
|
||||||
|
if (response['success'] ?? false) {
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown = seconds;
|
||||||
|
} else if (event.deviceCode == 'countdown_2') {
|
||||||
|
deviceStatus.secondCountDown = seconds;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit(const FailedState(error: 'Something went wrong'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (seconds > 0) {
|
||||||
|
_onStartTimer(seconds);
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getCounterValue(
|
||||||
|
GetCounterEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(twoTouchId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = TwoTouchModel.fromJson(statusModelList);
|
||||||
|
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.firstCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||||
|
} else if (event.deviceCode == 'countdown_2') {
|
||||||
|
deviceStatus.secondCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.secondCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.secondCountDown));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onClose(OnClose event, Emitter<TwoTouchState> emit) {
|
||||||
|
_timer?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onStartTimer(int seconds) {
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
add(TickTimer(seconds - timer.tick));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTickTimer(TickTimer event, Emitter<TwoTouchState> emit) {
|
||||||
|
if (event.remainingTime > 0) {
|
||||||
|
emit(TimerRunInProgress(event.remainingTime));
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, String>> days = [
|
||||||
|
{"day": "Sun", "key": "Sun"},
|
||||||
|
{"day": "Mon", "key": "Mon"},
|
||||||
|
{"day": "Tue", "key": "Tue"},
|
||||||
|
{"day": "Wed", "key": "Wed"},
|
||||||
|
{"day": "Thu", "key": "Thu"},
|
||||||
|
{"day": "Fri", "key": "Fri"},
|
||||||
|
{"day": "Sat", "key": "Sat"},
|
||||||
|
];
|
||||||
|
|
||||||
|
Future<void> toggleDaySelection(
|
||||||
|
ToggleDaySelectionEvent event,
|
||||||
|
Emitter<TwoTouchState> emit,
|
||||||
|
) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
if (selectedDays.contains(event.key)) {
|
||||||
|
selectedDays.remove(event.key);
|
||||||
|
} else {
|
||||||
|
selectedDays.add(event.key);
|
||||||
|
}
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveSchedule(
|
||||||
|
TwoTouchSave event,
|
||||||
|
Emitter<TwoTouchState> emit,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
if (selectedDays.isNotEmpty) {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
await DevicesAPI.postSchedule(
|
||||||
|
category: switchCode,
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||||
|
code: switchCode,
|
||||||
|
value: toggleSchedule,
|
||||||
|
days: selectedDays);
|
||||||
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
emit(TwoTouchSaveSchedule());
|
||||||
|
add(const ToggleCreateScheduleEvent(index: 1));
|
||||||
|
// toggleCreateSchedule();
|
||||||
|
} else {
|
||||||
|
CustomSnackBar.displaySnackBar('Please select days');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getSchedule(
|
||||||
|
GetScheduleEvent event,
|
||||||
|
Emitter<TwoTouchState> emit,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.getSchedule(
|
||||||
|
category: switchCode,
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
);
|
||||||
|
List<dynamic> jsonData = response;
|
||||||
|
listSchedule =
|
||||||
|
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||||
|
emit(InitialState());
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||||
|
if (dateTime == null) return null;
|
||||||
|
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||||
|
dateTime.day, dateTime.hour, dateTime.minute);
|
||||||
|
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future toggleRepeat(
|
||||||
|
ToggleScheduleEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.changeSchedule(
|
||||||
|
scheduleId: event.id, deviceUuid: twoTouchId, enable: event.toggle);
|
||||||
|
if (response == true) {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
toggleSchedule = event.toggle;
|
||||||
|
return toggleSchedule;
|
||||||
|
}
|
||||||
|
emit(IsToggleState(onOff: toggleSchedule));
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future deleteSchedule(
|
||||||
|
DeleteScheduleEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final response = await DevicesAPI.deleteSchedule(
|
||||||
|
scheduleId: event.id,
|
||||||
|
deviceUuid: twoTouchId,
|
||||||
|
);
|
||||||
|
if (response == true) {
|
||||||
|
add(GetScheduleEvent());
|
||||||
|
return toggleSchedule;
|
||||||
|
}
|
||||||
|
emit(IsToggleState(onOff: toggleSchedule));
|
||||||
|
add(const ChangeSlidingSegment(value: 1));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fetchTwoTouchWizardStatus(
|
||||||
|
InitialWizardEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
devicesList = [];
|
||||||
|
groupTwoTouchList = [];
|
||||||
|
allSwitchesOn = true;
|
||||||
|
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||||
|
HomeCubit.getInstance().selectedSpace?.id ?? '', '2GT');
|
||||||
|
|
||||||
|
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 = TwoTouchModel.fromJson(statusModelList);
|
||||||
|
|
||||||
|
groupTwoTouchList.add(GroupTwoTouchModel(
|
||||||
|
deviceId: devicesList[i].uuid ?? '',
|
||||||
|
deviceName: devicesList[i].name ?? '',
|
||||||
|
firstSwitch: deviceStatus.firstSwitch,
|
||||||
|
secondSwitch: deviceStatus.secondSwitch,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupTwoTouchList.isNotEmpty) {
|
||||||
|
groupTwoTouchList.firstWhere((element) {
|
||||||
|
if (!element.firstSwitch || !element.secondSwitch) {
|
||||||
|
allSwitchesOn = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesOn));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||||
|
Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
bool allSwitchesValue = true;
|
||||||
|
groupTwoTouchList.forEach((element) {
|
||||||
|
if (element.deviceId == event.deviceId) {
|
||||||
|
element.firstSwitch = !event.value;
|
||||||
|
}
|
||||||
|
if (!element.firstSwitch || !element.secondSwitch) {
|
||||||
|
allSwitchesValue = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
|
||||||
|
|
||||||
|
List<String> allDeviceIds =
|
||||||
|
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||||
|
final response = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_1',
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: !event.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response['failedResults'].toString() != '[]') {
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
|
||||||
|
Emitter<TwoTouchState> emit) async {
|
||||||
|
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
bool allSwitchesValue = true;
|
||||||
|
groupTwoTouchList.forEach((element) {
|
||||||
|
if (element.deviceId == event.deviceId) {
|
||||||
|
element.secondSwitch = !event.value;
|
||||||
|
}
|
||||||
|
if (!element.firstSwitch || !element.secondSwitch) {
|
||||||
|
allSwitchesValue = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
List<String> allDeviceIds =
|
||||||
|
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||||
|
|
||||||
|
emit(UpdateGroupState(
|
||||||
|
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
|
||||||
|
|
||||||
|
final response = await DevicesAPI.deviceBatchController(
|
||||||
|
code: 'switch_2',
|
||||||
|
devicesUuid: allDeviceIds,
|
||||||
|
value: !event.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response['failedResults'].toString() != '[]') {
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
add(InitialWizardEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String statusSelected = '';
|
||||||
|
String optionSelected = '';
|
||||||
|
|
||||||
|
Future<void> _changeStatus(
|
||||||
|
ChangeStatusEvent event, Emitter<TwoTouchState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
final Map<String, Map<String, String>> controlMap = {
|
||||||
|
"relay_status": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
"light_mode": {
|
||||||
|
'Off': 'none',
|
||||||
|
'On/Off Status': 'relay',
|
||||||
|
'Switch Position': 'pos',
|
||||||
|
},
|
||||||
|
"relay_status_1": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
"relay_status_2": {
|
||||||
|
'Power On': 'power_on',
|
||||||
|
'Power Off': 'power_off',
|
||||||
|
'Restart Memory': 'last',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
final selectedControl = controlMap[optionSelected]?[statusSelected];
|
||||||
|
if (selectedControl != null) {
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: twoTouchId,
|
||||||
|
code: optionSelected,
|
||||||
|
value: selectedControl),
|
||||||
|
twoTouchId,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
print('Invalid statusSelected or optionSelected');
|
||||||
|
}
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
162
lib/features/devices/bloc/two_touch_bloc/two_touch_event.dart
Normal file
162
lib/features/devices/bloc/two_touch_bloc/two_touch_event.dart
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
abstract class TwoTouchEvent extends Equatable {
|
||||||
|
const TwoTouchEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class TwoTouchUpdated extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class TwoTouchSave extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class ToggleScheduleEvent extends TwoTouchEvent {
|
||||||
|
final String id;
|
||||||
|
final bool toggle;
|
||||||
|
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [toggle, id];
|
||||||
|
}
|
||||||
|
|
||||||
|
class errorMessage extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class ToggleDaySelectionEvent extends TwoTouchEvent {
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
const ToggleDaySelectionEvent({required this.key});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [key];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialEvent extends TwoTouchEvent {
|
||||||
|
const InitialEvent();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeFirstSwitchStatusEvent extends TwoTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSecondSwitchStatusEvent extends TwoTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeSecondSwitchStatusEvent(
|
||||||
|
{required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AllOffEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class AllOnEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class GroupAllOnEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class GroupAllOffEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeSlidingSegment extends TwoTouchEvent {
|
||||||
|
final int value;
|
||||||
|
const ChangeSlidingSegment({required this.value});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetCounterEvent extends TwoTouchEvent {
|
||||||
|
final String deviceCode;
|
||||||
|
const GetCounterEvent({required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetCounterValue extends TwoTouchEvent {
|
||||||
|
final Duration duration;
|
||||||
|
final String deviceCode;
|
||||||
|
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration, deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartTimer extends TwoTouchEvent {
|
||||||
|
final int duration;
|
||||||
|
|
||||||
|
const StartTimer(this.duration);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TickTimer extends TwoTouchEvent {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TickTimer(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StopTimer extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class OnClose extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class GetScheduleEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class DeleteScheduleEvent extends TwoTouchEvent {
|
||||||
|
final String id;
|
||||||
|
const DeleteScheduleEvent({required this.id});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TabChangedEvent extends TwoTouchEvent {
|
||||||
|
final int index;
|
||||||
|
TabChangedEvent({required this.index});
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleSelectedEvent extends TwoTouchEvent {
|
||||||
|
final int index;
|
||||||
|
const ToggleSelectedEvent({required this.index});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleCreateScheduleEvent extends TwoTouchEvent {
|
||||||
|
final int index;
|
||||||
|
const ToggleCreateScheduleEvent({required this.index});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialWizardEvent extends TwoTouchEvent {}
|
||||||
|
|
||||||
|
class ChangeFirstWizardSwitchStatusEvent extends TwoTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeFirstWizardSwitchStatusEvent(
|
||||||
|
{required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSecondWizardSwitchStatusEvent extends TwoTouchEvent {
|
||||||
|
final bool value;
|
||||||
|
final String deviceId;
|
||||||
|
const ChangeSecondWizardSwitchStatusEvent(
|
||||||
|
{required this.value, this.deviceId = ''});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value, deviceId];
|
||||||
|
}
|
||||||
|
class ChangeStatusEvent extends TwoTouchEvent {
|
||||||
|
final String deviceId;
|
||||||
|
final BuildContext context;
|
||||||
|
const ChangeStatusEvent({this.deviceId = '',required this.context});
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_two_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||||
|
|
||||||
|
class TwoTouchState extends Equatable {
|
||||||
|
const TwoTouchState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialState extends TwoTouchState {}
|
||||||
|
|
||||||
|
class TwoTouchSaveSchedule extends TwoTouchState {}
|
||||||
|
|
||||||
|
class ChangeTimeState extends TwoTouchState {}
|
||||||
|
|
||||||
|
class LoadingInitialState extends TwoTouchState {}
|
||||||
|
|
||||||
|
class UpdateState extends TwoTouchState {
|
||||||
|
final TwoTouchModel twoTouchModel;
|
||||||
|
const UpdateState({required this.twoTouchModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [TwoTouchModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingNewSate extends TwoTouchState {
|
||||||
|
final TwoTouchModel twoTouchModel;
|
||||||
|
const LoadingNewSate({required this.twoTouchModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [TwoTouchModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateGroupState extends TwoTouchState {
|
||||||
|
final List<GroupTwoTouchModel> twoTouchList;
|
||||||
|
final bool allSwitches;
|
||||||
|
|
||||||
|
const UpdateGroupState({required this.twoTouchList, required this.allSwitches});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [twoTouchList, allSwitches];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FailedState extends TwoTouchState {
|
||||||
|
final String error;
|
||||||
|
|
||||||
|
const FailedState({required this.error});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [error];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeSlidingSegmentState extends TwoTouchState {
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
const ChangeSlidingSegmentState({required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateTimerState extends TwoTouchState {
|
||||||
|
final int seconds;
|
||||||
|
const UpdateTimerState({required this.seconds});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [seconds];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunInProgress extends TwoTouchState {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TimerRunInProgress(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunComplete extends TwoTouchState {}
|
||||||
|
|
||||||
|
class IsToggleState extends TwoTouchState {
|
||||||
|
final bool? onOff;
|
||||||
|
const IsToggleState({this.onOff});
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateCreateScheduleState extends TwoTouchState {
|
||||||
|
final bool createSchedule;
|
||||||
|
UpdateCreateScheduleState(this.createSchedule);
|
||||||
|
}
|
||||||
@ -67,4 +67,7 @@ Map<DeviceType, String> deviceTypeIconMap = {
|
|||||||
DeviceType.WH: Assets.waterHeaterIcon,
|
DeviceType.WH: Assets.waterHeaterIcon,
|
||||||
DeviceType.DS: Assets.doorSensorIcon,
|
DeviceType.DS: Assets.doorSensorIcon,
|
||||||
DeviceType.Other: Assets.assetsIconsAC,
|
DeviceType.Other: Assets.assetsIconsAC,
|
||||||
|
DeviceType.OneTouch: Assets.oneGang,
|
||||||
|
DeviceType.TowTouch: Assets.twoGang,
|
||||||
|
DeviceType.ThreeTouch: Assets.assetsIconsGang,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -66,6 +66,12 @@ class DeviceModel {
|
|||||||
tempIcon = Assets.waterHeaterIcon;
|
tempIcon = Assets.waterHeaterIcon;
|
||||||
} else if (type == DeviceType.DS) {
|
} else if (type == DeviceType.DS) {
|
||||||
tempIcon = Assets.doorSensorIcon;
|
tempIcon = Assets.doorSensorIcon;
|
||||||
|
} else if (type == DeviceType.OneTouch) {
|
||||||
|
tempIcon = Assets.oneGang;
|
||||||
|
} else if (type == DeviceType.TowTouch) {
|
||||||
|
tempIcon = Assets.twoGang;
|
||||||
|
} else if (type == DeviceType.ThreeTouch) {
|
||||||
|
tempIcon = Assets.assetsIcons3GangSwitch;
|
||||||
} else {
|
} else {
|
||||||
tempIcon = Assets.assetsIconsLogo;
|
tempIcon = Assets.assetsIconsLogo;
|
||||||
}
|
}
|
||||||
|
|||||||
11
lib/features/devices/model/group_one_touch_model.dart
Normal file
11
lib/features/devices/model/group_one_touch_model.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class GroupOneTouchModel {
|
||||||
|
final String deviceId;
|
||||||
|
final String deviceName;
|
||||||
|
bool firstSwitch;
|
||||||
|
|
||||||
|
GroupOneTouchModel({
|
||||||
|
required this.deviceId,
|
||||||
|
required this.deviceName,
|
||||||
|
required this.firstSwitch,
|
||||||
|
});
|
||||||
|
}
|
||||||
15
lib/features/devices/model/group_three_touch_model.dart
Normal file
15
lib/features/devices/model/group_three_touch_model.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class GroupThreeTouchModel {
|
||||||
|
final String deviceId;
|
||||||
|
final String deviceName;
|
||||||
|
bool firstSwitch;
|
||||||
|
bool secondSwitch;
|
||||||
|
bool thirdSwitch;
|
||||||
|
|
||||||
|
GroupThreeTouchModel({
|
||||||
|
required this.deviceId,
|
||||||
|
required this.deviceName,
|
||||||
|
required this.firstSwitch,
|
||||||
|
required this.secondSwitch,
|
||||||
|
required this.thirdSwitch,
|
||||||
|
});
|
||||||
|
}
|
||||||
13
lib/features/devices/model/group_two_touch_model.dart
Normal file
13
lib/features/devices/model/group_two_touch_model.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
class GroupTwoTouchModel {
|
||||||
|
final String deviceId;
|
||||||
|
final String deviceName;
|
||||||
|
bool firstSwitch;
|
||||||
|
bool secondSwitch;
|
||||||
|
|
||||||
|
GroupTwoTouchModel({
|
||||||
|
required this.deviceId,
|
||||||
|
required this.deviceName,
|
||||||
|
required this.firstSwitch,
|
||||||
|
required this.secondSwitch,
|
||||||
|
});
|
||||||
|
}
|
||||||
50
lib/features/devices/model/one_touch_model.dart
Normal file
50
lib/features/devices/model/one_touch_model.dart
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class OneTouchModel {
|
||||||
|
bool firstSwitch;
|
||||||
|
int firstCountDown;
|
||||||
|
status relay;
|
||||||
|
lightStatus light_mode;
|
||||||
|
status relay_status_1;
|
||||||
|
|
||||||
|
OneTouchModel(
|
||||||
|
{required this.firstSwitch,
|
||||||
|
required this.firstCountDown,
|
||||||
|
required this.light_mode,
|
||||||
|
required this.relay,
|
||||||
|
required this.relay_status_1
|
||||||
|
});
|
||||||
|
|
||||||
|
factory OneTouchModel.fromJson(List<StatusModel> jsonList) {
|
||||||
|
late bool _switch;
|
||||||
|
late int _count;
|
||||||
|
late String _relay;
|
||||||
|
late String _light_mode;
|
||||||
|
late String relay_status_1;
|
||||||
|
|
||||||
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
|
if (jsonList[i].code == 'switch_1') {
|
||||||
|
_switch = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'countdown_1') {
|
||||||
|
_count = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status') {
|
||||||
|
_relay = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'light_mode') {
|
||||||
|
_light_mode = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status_1') {
|
||||||
|
relay_status_1 = jsonList[i].value ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OneTouchModel(
|
||||||
|
firstSwitch: _switch,
|
||||||
|
firstCountDown: _count,
|
||||||
|
light_mode: lightStatusExtension.fromString(_light_mode) ,
|
||||||
|
relay: StatusExtension.fromString(_relay ) ,
|
||||||
|
relay_status_1: StatusExtension.fromString(relay_status_1 )
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
81
lib/features/devices/model/three_touch_model.dart
Normal file
81
lib/features/devices/model/three_touch_model.dart
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class ThreeTouchModel {
|
||||||
|
bool firstSwitch;
|
||||||
|
bool secondSwitch;
|
||||||
|
bool thirdSwitch;
|
||||||
|
int firstCountDown;
|
||||||
|
int secondCountDown;
|
||||||
|
int thirdCountDown;
|
||||||
|
status relay;
|
||||||
|
lightStatus light_mode;
|
||||||
|
status relay_status_1;
|
||||||
|
status relay_status_2;
|
||||||
|
status relay_status_3;
|
||||||
|
|
||||||
|
ThreeTouchModel(
|
||||||
|
{required this.firstSwitch,
|
||||||
|
required this.secondSwitch,
|
||||||
|
required this.thirdSwitch,
|
||||||
|
required this.firstCountDown,
|
||||||
|
required this.secondCountDown,
|
||||||
|
required this.thirdCountDown,
|
||||||
|
required this.light_mode,
|
||||||
|
required this.relay,
|
||||||
|
required this.relay_status_1,
|
||||||
|
required this.relay_status_2,
|
||||||
|
required this.relay_status_3});
|
||||||
|
|
||||||
|
factory ThreeTouchModel.fromJson(List<StatusModel> jsonList) {
|
||||||
|
late bool _firstSwitch;
|
||||||
|
late bool _secondSwitch;
|
||||||
|
late bool _thirdSwitch;
|
||||||
|
late int _firstCount;
|
||||||
|
late int _secondCount;
|
||||||
|
late int _thirdCount;
|
||||||
|
late String _relay;
|
||||||
|
late String _light_mode;
|
||||||
|
late String _relay_status_1;
|
||||||
|
late String _relay_status_2;
|
||||||
|
late String _relay_status_3;
|
||||||
|
|
||||||
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
|
if (jsonList[i].code == 'switch_1') {
|
||||||
|
_firstSwitch = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'switch_2') {
|
||||||
|
_secondSwitch = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'switch_3') {
|
||||||
|
_thirdSwitch = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'countdown_1') {
|
||||||
|
_firstCount = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'countdown_2') {
|
||||||
|
_secondCount = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'countdown_3') {
|
||||||
|
_thirdCount = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status') {
|
||||||
|
_relay = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'light_mode') {
|
||||||
|
_light_mode = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status_1') {
|
||||||
|
_relay_status_1 = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status_2') {
|
||||||
|
_relay_status_2 = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status_3') {
|
||||||
|
_relay_status_3 = jsonList[i].value ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ThreeTouchModel(
|
||||||
|
firstSwitch: _firstSwitch,
|
||||||
|
secondSwitch: _secondSwitch,
|
||||||
|
thirdSwitch: _thirdSwitch,
|
||||||
|
firstCountDown: _firstCount,
|
||||||
|
secondCountDown: _secondCount,
|
||||||
|
thirdCountDown: _thirdCount,
|
||||||
|
light_mode: lightStatusExtension.fromString(_light_mode),
|
||||||
|
relay: StatusExtension.fromString(_relay),
|
||||||
|
relay_status_1: StatusExtension.fromString(_relay_status_1),
|
||||||
|
relay_status_2: StatusExtension.fromString(_relay_status_2),
|
||||||
|
relay_status_3: StatusExtension.fromString(_relay_status_3));
|
||||||
|
}
|
||||||
|
}
|
||||||
63
lib/features/devices/model/two_touch_model.dart
Normal file
63
lib/features/devices/model/two_touch_model.dart
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class TwoTouchModel {
|
||||||
|
bool firstSwitch;
|
||||||
|
bool secondSwitch;
|
||||||
|
int firstCountDown;
|
||||||
|
int secondCountDown;
|
||||||
|
status relay;
|
||||||
|
lightStatus light_mode;
|
||||||
|
status relay_status_1;
|
||||||
|
status relay_status_2;
|
||||||
|
|
||||||
|
TwoTouchModel(
|
||||||
|
{required this.firstSwitch,
|
||||||
|
required this.secondSwitch,
|
||||||
|
required this.firstCountDown,
|
||||||
|
required this.secondCountDown,
|
||||||
|
required this.light_mode,
|
||||||
|
required this.relay,
|
||||||
|
required this.relay_status_1,
|
||||||
|
required this.relay_status_2});
|
||||||
|
|
||||||
|
factory TwoTouchModel.fromJson(List<StatusModel> jsonList) {
|
||||||
|
late bool _firstSwitch;
|
||||||
|
late bool _secondSwitch;
|
||||||
|
late int _firstCount;
|
||||||
|
late int _secondCount;
|
||||||
|
late String _relay;
|
||||||
|
late String _light_mode;
|
||||||
|
late String _relay_status_1;
|
||||||
|
late String _relay_status_2;
|
||||||
|
|
||||||
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
|
if (jsonList[i].code == 'switch_1') {
|
||||||
|
_firstSwitch = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'switch_2') {
|
||||||
|
_secondSwitch = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'countdown_1') {
|
||||||
|
_firstCount = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'countdown_2') {
|
||||||
|
_secondCount = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status') {
|
||||||
|
_relay = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'light_mode') {
|
||||||
|
_light_mode = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status_1') {
|
||||||
|
_relay_status_1 = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'relay_status_2') {
|
||||||
|
_relay_status_2 = jsonList[i].value ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TwoTouchModel(
|
||||||
|
firstSwitch: _firstSwitch,
|
||||||
|
secondSwitch: _secondSwitch,
|
||||||
|
firstCountDown: _firstCount,
|
||||||
|
secondCountDown: _secondCount,
|
||||||
|
light_mode: lightStatusExtension.fromString(_light_mode),
|
||||||
|
relay: StatusExtension.fromString(_relay),
|
||||||
|
relay_status_1: StatusExtension.fromString(_relay_status_1),
|
||||||
|
relay_status_2: StatusExtension.fromString(_relay_status_2));
|
||||||
|
}
|
||||||
|
}
|
||||||
88
lib/features/devices/view/widgets/circular_button.dart
Normal file
88
lib/features/devices/view/widgets/circular_button.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class CircularButton extends StatelessWidget {
|
||||||
|
const CircularButton({
|
||||||
|
super.key,
|
||||||
|
required this.device,
|
||||||
|
required this.label,
|
||||||
|
required this.onTap,
|
||||||
|
required this.icons,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
final String label;
|
||||||
|
final Function()? onTap;
|
||||||
|
final IconData icons;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Card(
|
||||||
|
elevation: 3,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[300],
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: label == 'All On'
|
||||||
|
? BodySmall(
|
||||||
|
text: "On",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
)
|
||||||
|
: label == 'All Off'
|
||||||
|
? BodySmall(
|
||||||
|
text: "Off",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
icons,
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
size: 25,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(
|
||||||
|
// text: "Timer",
|
||||||
|
text: label,
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,9 +19,11 @@ class OneGangWizard extends StatelessWidget {
|
|||||||
List<GroupOneGangModel> groupOneGangModel = [];
|
List<GroupOneGangModel> groupOneGangModel = [];
|
||||||
|
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
|
title: 'Lights',
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
OneGangBloc(switchCode: '', oneGangId: device?.uuid ?? '')..add(InitialWizardEvent()),
|
OneGangBloc(switchCode: '', oneGangId: device?.uuid ?? '')
|
||||||
|
..add(InitialWizardEvent()),
|
||||||
child: BlocBuilder<OneGangBloc, OneGangState>(
|
child: BlocBuilder<OneGangBloc, OneGangState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
bool allSwitchesOn = false;
|
bool allSwitchesOn = false;
|
||||||
@ -32,8 +34,10 @@ class OneGangWizard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return state is LoadingInitialState
|
return state is LoadingInitialState
|
||||||
? const Center(
|
? const Center(
|
||||||
child:
|
child: DefaultContainer(
|
||||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
)
|
)
|
||||||
: OneGangList(
|
: OneGangList(
|
||||||
oneGangList: groupOneGangModel,
|
oneGangList: groupOneGangModel,
|
||||||
|
|||||||
@ -0,0 +1,69 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_one_touch_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 OneTouchList extends StatelessWidget {
|
||||||
|
const OneTouchList(
|
||||||
|
{super.key, required this.oneTouchList, required this.allSwitches});
|
||||||
|
|
||||||
|
final List<GroupOneTouchModel> oneTouchList;
|
||||||
|
final bool allSwitches;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const BodySmall(text: 'All Lights'),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: allSwitches,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<OneTouchBloc>(context).add(GroupAllOnEvent());
|
||||||
|
},
|
||||||
|
secondAction: () {
|
||||||
|
BlocProvider.of<OneTouchBloc>(context).add(GroupAllOffEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
itemCount: oneTouchList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(text: oneTouchList[index].deviceName),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: oneTouchList[index].firstSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<OneTouchBloc>(context).add(
|
||||||
|
ChangeFirstWizardSwitchStatusEvent(
|
||||||
|
value: oneTouchList[index].firstSwitch,
|
||||||
|
deviceId: oneTouchList[index].deviceId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,221 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/circular_button.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_setting.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_timer_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.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_small.dart';
|
||||||
|
import 'package:syncrow_app/generated/assets.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/font_manager.dart';
|
||||||
|
|
||||||
|
class OneTouchScreen extends StatelessWidget {
|
||||||
|
const OneTouchScreen({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: device != null
|
||||||
|
? DeviceAppbar(
|
||||||
|
deviceName: device!.name!,
|
||||||
|
deviceUuid: device!.uuid!,
|
||||||
|
)
|
||||||
|
: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: BodyLarge(
|
||||||
|
text: device?.name ?? 'Lights',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constants.defaultPadding,
|
||||||
|
right: Constants.defaultPadding,
|
||||||
|
bottom: Constants.bottomNavBarHeight,
|
||||||
|
),
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) => OneTouchBloc(
|
||||||
|
switchCode: 'switch_1', oneTouchId: device?.uuid ?? '')
|
||||||
|
..add(const InitialEvent(groupScreen: false)),
|
||||||
|
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
OneTouchModel oneTouchModel = OneTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off);
|
||||||
|
|
||||||
|
List<GroupOneTouchModel> groupOneTouchModel = [];
|
||||||
|
bool allSwitchesOn = false;
|
||||||
|
|
||||||
|
if (state is LoadingNewSate) {
|
||||||
|
oneTouchModel = state.oneTouchModel;
|
||||||
|
} else if (state is UpdateState) {
|
||||||
|
oneTouchModel = state.oneTouchModel;
|
||||||
|
} else if (state is UpdateGroupState) {
|
||||||
|
groupOneTouchModel = state.oneTouchList;
|
||||||
|
allSwitchesOn = state.allSwitches;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
BlocProvider.of<OneTouchBloc>(context).add(
|
||||||
|
InitialEvent(
|
||||||
|
groupScreen:
|
||||||
|
device != null ? false : true));
|
||||||
|
},
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Expanded(child: SizedBox.shrink()),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
GangSwitch(
|
||||||
|
threeGangSwitch: device!,
|
||||||
|
value:
|
||||||
|
oneTouchModel.firstSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<
|
||||||
|
OneTouchBloc>(
|
||||||
|
context)
|
||||||
|
.add(ChangeFirstSwitchStatusEvent(
|
||||||
|
value: oneTouchModel
|
||||||
|
.firstSwitch));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(
|
||||||
|
width: 70,
|
||||||
|
child: BodySmall(
|
||||||
|
text: " Entrance Light",
|
||||||
|
fontColor: ColorsManager
|
||||||
|
.textPrimaryColor,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.access_time,
|
||||||
|
label: 'Timer',
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context,
|
||||||
|
animation1,
|
||||||
|
animation2) =>
|
||||||
|
TimerScheduleScreen(
|
||||||
|
switchCode:
|
||||||
|
'switch_1',
|
||||||
|
device: device!,
|
||||||
|
deviceCode:
|
||||||
|
'countdown_1',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 30,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.settings,
|
||||||
|
label: 'Setting',
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context,
|
||||||
|
animation1,
|
||||||
|
animation2) =>
|
||||||
|
OneTouchSetting(
|
||||||
|
device: device,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Expanded(child: SizedBox())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,311 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.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/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class OneTouchSetting extends StatelessWidget {
|
||||||
|
const OneTouchSetting({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Setting',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
OneTouchBloc(switchCode: '', oneTouchId: device?.uuid ?? '')
|
||||||
|
..add(const InitialEvent(groupScreen: false)),
|
||||||
|
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final oneTouchBloc = BlocProvider.of<OneTouchBloc>(context);
|
||||||
|
OneTouchModel? oneTouchModel = OneTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off);
|
||||||
|
|
||||||
|
// if (state is UpdateState) {
|
||||||
|
// oneTouchModel = state.oneTouchModel;
|
||||||
|
// }
|
||||||
|
if (state is UpdateState) {
|
||||||
|
oneTouchModel = state.oneTouchModel;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
child: DefaultContainer(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
oneTouchBloc.optionSelected =
|
||||||
|
'relay_status';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel: oneTouchBloc
|
||||||
|
.deviceStatus.relay.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
oneTouchBloc.add(ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
oneTouchBloc.add(const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: oneTouchBloc
|
||||||
|
.deviceStatus.relay.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
oneTouchBloc.optionSelected =
|
||||||
|
'light_mode';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
oneTouchModel!.light_mode.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
oneTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Indicator Status',
|
||||||
|
label1: 'Off',
|
||||||
|
label2: 'On/Off Status',
|
||||||
|
label3: 'Switch Position',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
oneTouchBloc.add(const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Indicator Status',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: oneTouchModel
|
||||||
|
.light_mode.value,
|
||||||
|
fontColor: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
oneTouchBloc.optionSelected =
|
||||||
|
'relay_status_1';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
oneTouchModel!
|
||||||
|
.relay_status_1.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
oneTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status 1',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
oneTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
oneTouchBloc.add(const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status 1',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: oneTouchModel
|
||||||
|
.relay_status_1.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,296 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.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';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class TimerScheduleScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
final String deviceCode;
|
||||||
|
final String switchCode;
|
||||||
|
const TimerScheduleScreen(
|
||||||
|
{required this.device,
|
||||||
|
required this.deviceCode,
|
||||||
|
required this.switchCode,
|
||||||
|
super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
OneTouchBloc(switchCode: switchCode, oneTouchId: device.uuid ?? '')
|
||||||
|
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||||
|
..add(GetScheduleEvent()),
|
||||||
|
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final oneTouchBloc = BlocProvider.of<OneTouchBloc>(context);
|
||||||
|
Duration duration = Duration.zero;
|
||||||
|
int countNum = 0;
|
||||||
|
if (state is UpdateTimerState) {
|
||||||
|
countNum = state.seconds;
|
||||||
|
} else if (state is TimerRunInProgress) {
|
||||||
|
countNum = state.remainingTime;
|
||||||
|
} else if (state is TimerRunComplete) {
|
||||||
|
countNum = 0;
|
||||||
|
} else if (state is LoadingNewSate) {
|
||||||
|
countNum = 0;
|
||||||
|
}
|
||||||
|
return PopScope(
|
||||||
|
canPop: false,
|
||||||
|
onPopInvoked: (didPop) {
|
||||||
|
if (!didPop) {
|
||||||
|
oneTouchBloc.add(OnClose());
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: 2,
|
||||||
|
child: DefaultScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
oneTouchBloc.createSchedule == true
|
||||||
|
? TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
oneTouchBloc.add(ScheduleSave());
|
||||||
|
},
|
||||||
|
child: const Text('Save'))
|
||||||
|
: oneTouchBloc.selectedTabIndex == 1
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
// oneTouchBloc.toggleCreateSchedule();
|
||||||
|
oneTouchBloc.add(
|
||||||
|
const ToggleCreateScheduleEvent(
|
||||||
|
index: 1));
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
decoration: const ShapeDecoration(
|
||||||
|
color: ColorsManager.onPrimaryColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(30)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
onTap: (value) {
|
||||||
|
if (value == 0) {
|
||||||
|
if (oneTouchBloc.createSchedule ==
|
||||||
|
true) {
|
||||||
|
// oneTouchBloc.toggleCreateSchedule();
|
||||||
|
oneTouchBloc.add(
|
||||||
|
const ToggleCreateScheduleEvent(
|
||||||
|
index: 0));
|
||||||
|
}
|
||||||
|
oneTouchBloc.add(
|
||||||
|
const ToggleSelectedEvent(
|
||||||
|
index: 0));
|
||||||
|
} else {
|
||||||
|
oneTouchBloc.add(
|
||||||
|
const ToggleSelectedEvent(
|
||||||
|
index: 1));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indicatorColor:
|
||||||
|
Colors.white, // Customize the indicator
|
||||||
|
dividerHeight: 0,
|
||||||
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
|
indicator: const ShapeDecoration(
|
||||||
|
color: ColorsManager.slidingBlueColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(20)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
child: BodySmall(
|
||||||
|
text: 'Countdown',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
child: Text(
|
||||||
|
'Schedule',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
physics:
|
||||||
|
const NeverScrollableScrollPhysics(), // Disable swiping
|
||||||
|
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
countNum > 0
|
||||||
|
? BodyLarge(
|
||||||
|
text: _formatDuration(
|
||||||
|
countNum),
|
||||||
|
fontColor: ColorsManager
|
||||||
|
.slidingBlueColor,
|
||||||
|
fontSize: 40,
|
||||||
|
)
|
||||||
|
: CupertinoTimerPicker(
|
||||||
|
mode:
|
||||||
|
CupertinoTimerPickerMode
|
||||||
|
.hm,
|
||||||
|
onTimerDurationChanged:
|
||||||
|
(Duration
|
||||||
|
newDuration) {
|
||||||
|
duration = newDuration;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (state
|
||||||
|
is LoadingNewSate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (countNum > 0) {
|
||||||
|
oneTouchBloc.add(
|
||||||
|
SetCounterValue(
|
||||||
|
deviceCode:
|
||||||
|
deviceCode,
|
||||||
|
duration: Duration
|
||||||
|
.zero));
|
||||||
|
} else if (duration !=
|
||||||
|
Duration.zero) {
|
||||||
|
oneTouchBloc.add(
|
||||||
|
SetCounterValue(
|
||||||
|
deviceCode:
|
||||||
|
deviceCode,
|
||||||
|
duration:
|
||||||
|
duration));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
countNum > 0
|
||||||
|
? Assets.pauseIcon
|
||||||
|
: Assets.playIcon)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
child: oneTouchBloc.createSchedule ==
|
||||||
|
true
|
||||||
|
? CreateSchedule(
|
||||||
|
onToggleChanged: (bool isOn) {
|
||||||
|
oneTouchBloc.toggleSchedule =
|
||||||
|
isOn;
|
||||||
|
},
|
||||||
|
onDateTimeChanged:
|
||||||
|
(DateTime dateTime) {
|
||||||
|
oneTouchBloc.selectedTime =
|
||||||
|
dateTime;
|
||||||
|
},
|
||||||
|
days: oneTouchBloc.days,
|
||||||
|
selectDays: (List<String>
|
||||||
|
selectedDays) {
|
||||||
|
oneTouchBloc.selectedDays =
|
||||||
|
selectedDays;
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 10),
|
||||||
|
child: ScheduleListView(
|
||||||
|
listSchedule: oneTouchBloc
|
||||||
|
.listSchedule, // Pass the schedule list here
|
||||||
|
onDismissed: (scheduleId) {
|
||||||
|
oneTouchBloc.listSchedule
|
||||||
|
.removeWhere((schedule) =>
|
||||||
|
schedule
|
||||||
|
.scheduleId ==
|
||||||
|
scheduleId);
|
||||||
|
oneTouchBloc.add(
|
||||||
|
DeleteScheduleEvent(
|
||||||
|
id: scheduleId));
|
||||||
|
},
|
||||||
|
onToggleSchedule:
|
||||||
|
(scheduleId, isEnabled) {
|
||||||
|
oneTouchBloc.add(
|
||||||
|
ToggleScheduleEvent(
|
||||||
|
id: scheduleId,
|
||||||
|
toggle: isEnabled,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _formatDuration(int seconds) {
|
||||||
|
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
|
||||||
|
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
|
||||||
|
final secs = (seconds % 60).toString().padLeft(2, '0');
|
||||||
|
return '$hours:$minutes:$secs';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||||
|
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_gang_list.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
|
||||||
|
class OneTouchWizard extends StatelessWidget {
|
||||||
|
const OneTouchWizard({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<GroupOneTouchModel> groupOneTouchModel = [];
|
||||||
|
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Lights',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
OneTouchBloc(switchCode: '', oneTouchId: device?.uuid ?? '')
|
||||||
|
..add(InitialWizardEvent()),
|
||||||
|
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
bool allSwitchesOn = false;
|
||||||
|
|
||||||
|
if (state is UpdateGroupState) {
|
||||||
|
groupOneTouchModel = state.oneTouchList;
|
||||||
|
allSwitchesOn = state.allSwitches;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: OneTouchList(
|
||||||
|
oneTouchList: groupOneTouchModel,
|
||||||
|
allSwitches: allSwitchesOn,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
230
lib/features/devices/view/widgets/restart_status_dialog.dart
Normal file
230
lib/features/devices/view/widgets/restart_status_dialog.dart
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.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/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class RestartStatusDialog extends StatefulWidget {
|
||||||
|
final String label1;
|
||||||
|
final String label2;
|
||||||
|
final String label3;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
final Function(String)? onTapLabel1;
|
||||||
|
final Function(String)? onTapLabel2;
|
||||||
|
final Function(String)? onTapLabel3;
|
||||||
|
final Function()? cancelTab;
|
||||||
|
final Function()? confirmTab;
|
||||||
|
|
||||||
|
final String? initialSelectedLabel;
|
||||||
|
|
||||||
|
RestartStatusDialog({
|
||||||
|
required this.label1,
|
||||||
|
required this.label2,
|
||||||
|
required this.label3,
|
||||||
|
required this.title,
|
||||||
|
this.onTapLabel1,
|
||||||
|
this.onTapLabel2,
|
||||||
|
this.onTapLabel3,
|
||||||
|
required this.cancelTab,
|
||||||
|
required this.confirmTab,
|
||||||
|
this.initialSelectedLabel,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_RestartStatusDialogState createState() => _RestartStatusDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RestartStatusDialogState extends State<RestartStatusDialog> {
|
||||||
|
late String _selectedOption;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_selectedOption = widget.initialSelectedLabel ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
BodyLarge(
|
||||||
|
text: widget.title,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 15, right: 15),
|
||||||
|
child: Divider(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 15, right: 15),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildCheckboxOption(
|
||||||
|
label: widget.label1,
|
||||||
|
onTap: widget.onTapLabel1,
|
||||||
|
),
|
||||||
|
_buildCheckboxOption(
|
||||||
|
label: widget.label2,
|
||||||
|
onTap: widget.onTapLabel2,
|
||||||
|
),
|
||||||
|
_buildCheckboxOption(
|
||||||
|
label: widget.label3,
|
||||||
|
onTap: widget.onTapLabel3,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
right: BorderSide(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
top: BorderSide(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
child: SizedBox(
|
||||||
|
child: InkWell(
|
||||||
|
onTap: widget.cancelTab,
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
left: BorderSide(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
top: BorderSide(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: widget.confirmTab,
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Confirm',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorsManager.primaryColor,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCheckboxOption(
|
||||||
|
{required String label, Function(String)? onTap}) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 10, top: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
text: label,
|
||||||
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
CircularCheckbox(
|
||||||
|
value: _selectedOption == label,
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
if (value == true) {
|
||||||
|
setState(() {
|
||||||
|
_selectedOption = label;
|
||||||
|
});
|
||||||
|
if (onTap != null) {
|
||||||
|
onTap(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircularCheckbox extends StatefulWidget {
|
||||||
|
final bool value;
|
||||||
|
final ValueChanged<bool?> onChanged;
|
||||||
|
|
||||||
|
CircularCheckbox({required this.value, required this.onChanged});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CircularCheckboxState createState() => _CircularCheckboxState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CircularCheckboxState extends State<CircularCheckbox> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
widget.onChanged(!widget.value);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: widget.value
|
||||||
|
? ColorsManager.primaryColorWithOpacity.withOpacity(0.01)
|
||||||
|
: Colors.grey,
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
|
color: widget.value
|
||||||
|
? ColorsManager.primaryColorWithOpacity
|
||||||
|
: Colors.transparent,
|
||||||
|
),
|
||||||
|
width: 24.0,
|
||||||
|
height: 24.0,
|
||||||
|
child: widget.value
|
||||||
|
? const Icon(
|
||||||
|
Icons.check,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 16.0,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,10 @@ import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_senso
|
|||||||
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_Interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_interface.dart';
|
||||||
@ -164,6 +167,26 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
|||||||
PageRouteBuilder(
|
PageRouteBuilder(
|
||||||
pageBuilder: (context, animation1, animation2) =>
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
DoorSensorScreen(device: device)));
|
DoorSensorScreen(device: device)));
|
||||||
|
|
||||||
|
case DeviceType.OneTouch:
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
OneTouchScreen(device: device)));
|
||||||
|
|
||||||
|
case DeviceType.TowTouch:
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
TwoTouchInterface(touchSwitch: device)));
|
||||||
|
case DeviceType.ThreeTouch:
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
ThreeTouchInterface(touchSwitch: device)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,10 @@ class ThreeGangWizard extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
|
title: 'Lights',
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) => ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
|
create: (context) =>
|
||||||
|
ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
|
||||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||||
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -31,8 +33,10 @@ class ThreeGangWizard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return state is LoadingInitialState
|
return state is LoadingInitialState
|
||||||
? const Center(
|
? const Center(
|
||||||
child:
|
child: DefaultContainer(
|
||||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
)
|
)
|
||||||
: ThreeGangList(
|
: ThreeGangList(
|
||||||
threeGangList: groupThreeGangModel,
|
threeGangList: groupThreeGangModel,
|
||||||
|
|||||||
@ -0,0 +1,56 @@
|
|||||||
|
// import 'package:flutter/material.dart';
|
||||||
|
// // import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
// import 'package:flutter_svg/svg.dart';
|
||||||
|
// // import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/two_gang_bloc.dart';
|
||||||
|
// // import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/two_gang_state.dart';
|
||||||
|
// import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
// import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
// import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
// class GangSwitch extends StatelessWidget {
|
||||||
|
// const GangSwitch(
|
||||||
|
// {super.key, required this.threeGangSwitch, required this.value, required this.action});
|
||||||
|
|
||||||
|
// final DeviceModel threeGangSwitch;
|
||||||
|
// final bool value;
|
||||||
|
// final Function action;
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// return InkWell(
|
||||||
|
// overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||||
|
// onTap: () {
|
||||||
|
// action();
|
||||||
|
// // var tempControl = DeviceControlModel(
|
||||||
|
// // deviceId: control.deviceId, code: control.code!, value: !control.value!);
|
||||||
|
// // DevicesCubit.getInstance().deviceControl(
|
||||||
|
// // tempControl,
|
||||||
|
// // control.deviceId!,
|
||||||
|
// // );
|
||||||
|
// },
|
||||||
|
// child: Stack(
|
||||||
|
// alignment: value ? Alignment.topCenter : Alignment.bottomCenter,
|
||||||
|
// children: [
|
||||||
|
// Container(
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// borderRadius: const BorderRadius.all(Radius.circular(100.0)),
|
||||||
|
// color: value ? ColorsManager.primaryColorWithOpacity : ColorsManager.switchOffColor,
|
||||||
|
// ),
|
||||||
|
// width: 60,
|
||||||
|
// height: 115,
|
||||||
|
// ),
|
||||||
|
// Padding(
|
||||||
|
// padding: const EdgeInsets.all(5.0),
|
||||||
|
// child: SizedBox.square(
|
||||||
|
// dimension: 60,
|
||||||
|
// child: SvgPicture.asset(
|
||||||
|
// value ? Assets.assetsIconsLightSwitchOn : Assets.assetsIconsLightSwitchOff,
|
||||||
|
// fit: BoxFit.fill,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@ -0,0 +1,186 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/timer_screen.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_small.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';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class ScheduleScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
const ScheduleScreen({required this.device, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 48,
|
||||||
|
),
|
||||||
|
DefaultContainer(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder:
|
||||||
|
(context, animation1, animation2) =>
|
||||||
|
TimerScheduleScreen(
|
||||||
|
switchCode: "switch_1",
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_1',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Bedside Light",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder:
|
||||||
|
(context, animation1, animation2) =>
|
||||||
|
TimerScheduleScreen(
|
||||||
|
switchCode: "switch_2",
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_2',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Ceiling Light",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder:
|
||||||
|
(context, animation1, animation2) =>
|
||||||
|
TimerScheduleScreen(
|
||||||
|
switchCode: "switch_3",
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_3',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Spotlight",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/generated/assets.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/font_manager.dart';
|
||||||
|
|
||||||
|
class ThreeTouchInterface extends StatelessWidget {
|
||||||
|
const ThreeTouchInterface({super.key, this.touchSwitch});
|
||||||
|
|
||||||
|
final DeviceModel? touchSwitch;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: touchSwitch != null
|
||||||
|
? DeviceAppbar(
|
||||||
|
deviceName: touchSwitch!.name!,
|
||||||
|
deviceUuid: touchSwitch!.uuid!,
|
||||||
|
)
|
||||||
|
: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: BodyLarge(
|
||||||
|
text: touchSwitch?.name ?? 'Lights',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constants.defaultPadding,
|
||||||
|
right: Constants.defaultPadding,
|
||||||
|
bottom: Constants.bottomNavBarHeight,
|
||||||
|
),
|
||||||
|
child: ThreeTouchScreen(device: touchSwitch),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_three_touch_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 ThreeTouchList extends StatelessWidget {
|
||||||
|
const ThreeTouchList({super.key, required this.threeTouchList, required this.allSwitches});
|
||||||
|
|
||||||
|
final List<GroupThreeTouchModel> threeTouchList;
|
||||||
|
final bool allSwitches;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const BodySmall(text: 'All Lights'),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: allSwitches,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context).add(GroupAllOnEvent());
|
||||||
|
},
|
||||||
|
secondAction: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context).add(GroupAllOffEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
itemCount: threeTouchList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(text: '${threeTouchList[index].deviceName} beside light'),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: threeTouchList[index].firstSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context).add(ChangeFirstSwitchStatusEvent(
|
||||||
|
value: threeTouchList[index].firstSwitch,
|
||||||
|
deviceId: threeTouchList[index].deviceId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(text: '${threeTouchList[index].deviceName} ceiling light'),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: threeTouchList[index].secondSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context).add(ChangeSecondSwitchStatusEvent(
|
||||||
|
value: threeTouchList[index].secondSwitch,
|
||||||
|
deviceId: threeTouchList[index].deviceId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(text: '${threeTouchList[index].deviceName} spotlight'),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: threeTouchList[index].thirdSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context).add(ChangeThirdSwitchStatusEvent(
|
||||||
|
value: threeTouchList[index].thirdSwitch,
|
||||||
|
deviceId: threeTouchList[index].deviceId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,228 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.dart';
|
||||||
|
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/circular_button.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/schedule_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_setting.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class ThreeTouchScreen extends StatelessWidget {
|
||||||
|
const ThreeTouchScreen({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
ThreeTouchBloc(switchCode: '', threeTouchId: device?.uuid ?? '')
|
||||||
|
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||||
|
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
ThreeTouchModel threeTouchModel = ThreeTouchModel(
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off,
|
||||||
|
relay_status_2: status.off,
|
||||||
|
relay_status_3: status.off,
|
||||||
|
firstSwitch: false,
|
||||||
|
secondSwitch: false,
|
||||||
|
thirdSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
secondCountDown: 0,
|
||||||
|
thirdCountDown: 0);
|
||||||
|
|
||||||
|
if (state is LoadingNewSate) {
|
||||||
|
threeTouchModel = state.threeTouchModel;
|
||||||
|
} else if (state is UpdateState) {
|
||||||
|
threeTouchModel = state.threeTouchModel;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context).add(InitialEvent(
|
||||||
|
groupScreen: device != null ? false : true));
|
||||||
|
},
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Expanded(child: SizedBox.shrink()),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
GangSwitch(
|
||||||
|
threeGangSwitch: device!,
|
||||||
|
value: threeTouchModel.firstSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context)
|
||||||
|
.add(ChangeFirstSwitchStatusEvent(
|
||||||
|
value: threeTouchModel
|
||||||
|
.firstSwitch));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(
|
||||||
|
width: 70,
|
||||||
|
child: BodySmall(
|
||||||
|
text: "Bedside Light",
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textPrimaryColor,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
GangSwitch(
|
||||||
|
threeGangSwitch: device!,
|
||||||
|
value: threeTouchModel.secondSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>( context) .add(
|
||||||
|
ChangeSecondSwitchStatusEvent(
|
||||||
|
value: threeTouchModel
|
||||||
|
.secondSwitch));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(
|
||||||
|
width: 70,
|
||||||
|
child: BodySmall(
|
||||||
|
text: "Ceiling Light",
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textPrimaryColor,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
GangSwitch(
|
||||||
|
threeGangSwitch: device!,
|
||||||
|
value: threeTouchModel.thirdSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(
|
||||||
|
context)
|
||||||
|
.add(ChangeThirdSwitchStatusEvent(
|
||||||
|
value: threeTouchModel
|
||||||
|
.thirdSwitch));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(
|
||||||
|
width: 70,
|
||||||
|
child: BodySmall(
|
||||||
|
text: "Spotlight",
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textPrimaryColor,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.u_turn_left,
|
||||||
|
label: "All On",
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context)
|
||||||
|
.add(AllOnEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.access_time,
|
||||||
|
label: "Timer",
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1,
|
||||||
|
animation2) =>
|
||||||
|
ScheduleScreen(
|
||||||
|
device: device!,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.access_time,
|
||||||
|
label: "Setting",
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1,
|
||||||
|
animation2) =>
|
||||||
|
ThreeTouchSetting(
|
||||||
|
device: device,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.u_turn_left,
|
||||||
|
label: "All Off",
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<ThreeTouchBloc>(context)
|
||||||
|
.add(AllOffEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(child: SizedBox())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,501 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.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/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class ThreeTouchSetting extends StatelessWidget {
|
||||||
|
const ThreeTouchSetting({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Setting',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
ThreeTouchBloc(switchCode: '', threeTouchId: device?.uuid ?? '')
|
||||||
|
..add(InitialEvent(groupScreen: false)),
|
||||||
|
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final threeTouchBloc = BlocProvider.of<ThreeTouchBloc>(context);
|
||||||
|
ThreeTouchModel deviceStatus = ThreeTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
secondSwitch: false,
|
||||||
|
thirdSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
secondCountDown: 0,
|
||||||
|
thirdCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off,
|
||||||
|
relay_status_2: status.off,
|
||||||
|
relay_status_3: status.off,
|
||||||
|
);
|
||||||
|
if (state is LoadingNewSate) {
|
||||||
|
deviceStatus = state.threeTouchModel;
|
||||||
|
} else if (state is UpdateState) {
|
||||||
|
deviceStatus = state.threeTouchModel;
|
||||||
|
}
|
||||||
|
// if (state is ChangeStateSetting) {
|
||||||
|
// // Navigator.of(context).pop(true);
|
||||||
|
// threeTouchBloc
|
||||||
|
// .add(InitialSettingDevises(id: device?.uuid ?? ''));
|
||||||
|
// }
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
child: DefaultContainer(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
threeTouchBloc.optionSelected =
|
||||||
|
'relay_status';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel: threeTouchBloc
|
||||||
|
.deviceStatus.relay.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
InitialEvent(groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: threeTouchBloc
|
||||||
|
.deviceStatus.relay.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
threeTouchBloc.optionSelected =
|
||||||
|
'light_mode';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel: threeTouchBloc
|
||||||
|
.deviceStatus.light_mode.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Indicator Status',
|
||||||
|
label1: 'Off',
|
||||||
|
label2: 'On/Off Status',
|
||||||
|
label3: 'Switch Position',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
InitialEvent(groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Indicator Status',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: threeTouchBloc.deviceStatus
|
||||||
|
.light_mode.value,
|
||||||
|
fontColor: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
threeTouchBloc.optionSelected =
|
||||||
|
'relay_status_1';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
threeTouchBloc.deviceStatus
|
||||||
|
.relay_status_1.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status 1',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status 1',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: threeTouchBloc
|
||||||
|
.deviceStatus
|
||||||
|
.relay_status_1
|
||||||
|
.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
threeTouchBloc.optionSelected =
|
||||||
|
'relay_status_2';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
threeTouchBloc.deviceStatus
|
||||||
|
.relay_status_2.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status 2',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status 2',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: threeTouchBloc
|
||||||
|
.deviceStatus
|
||||||
|
.relay_status_2
|
||||||
|
.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
threeTouchBloc.optionSelected =
|
||||||
|
'relay_status_3';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
threeTouchBloc.deviceStatus
|
||||||
|
.relay_status_3.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status 3',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
threeTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const InitialEvent(
|
||||||
|
groupScreen: false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status 3',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: threeTouchBloc
|
||||||
|
.deviceStatus
|
||||||
|
.relay_status_3
|
||||||
|
.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_three_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_list.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
|
||||||
|
class ThreeTouchWizard extends StatelessWidget {
|
||||||
|
const ThreeTouchWizard({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Lights',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
ThreeTouchBloc(switchCode: '', threeTouchId: device?.uuid ?? '')
|
||||||
|
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||||
|
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
List<GroupThreeTouchModel> groupThreeTouchModel = [];
|
||||||
|
bool allSwitchesOn = false;
|
||||||
|
|
||||||
|
if (state is UpdateGroupState) {
|
||||||
|
groupThreeTouchModel = state.threeTouchList;
|
||||||
|
allSwitchesOn = state.allSwitches;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ThreeTouchList(
|
||||||
|
threeTouchList: groupThreeTouchModel,
|
||||||
|
allSwitches: allSwitchesOn,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
320
lib/features/devices/view/widgets/three_touch/timer_screen.dart
Normal file
320
lib/features/devices/view/widgets/three_touch/timer_screen.dart
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.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';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class TimerScheduleScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
final String deviceCode;
|
||||||
|
final String switchCode;
|
||||||
|
const TimerScheduleScreen(
|
||||||
|
{required this.device,
|
||||||
|
required this.deviceCode,
|
||||||
|
required this.switchCode,
|
||||||
|
super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) => ThreeTouchBloc(
|
||||||
|
switchCode: switchCode, threeTouchId: device.uuid ?? '')
|
||||||
|
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||||
|
..add(GetScheduleEvent()),
|
||||||
|
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final threeTouchBloc = BlocProvider.of<ThreeTouchBloc>(context);
|
||||||
|
Duration duration = Duration.zero;
|
||||||
|
int countNum = 0;
|
||||||
|
if (state is UpdateTimerState) {
|
||||||
|
countNum = state.seconds;
|
||||||
|
} else if (state is TimerRunInProgress) {
|
||||||
|
countNum = state.remainingTime;
|
||||||
|
} else if (state is TimerRunComplete) {
|
||||||
|
countNum = 0;
|
||||||
|
} else if (state is LoadingNewSate) {
|
||||||
|
countNum = 0;
|
||||||
|
}
|
||||||
|
return PopScope(
|
||||||
|
canPop: false,
|
||||||
|
onPopInvoked: (didPop) {
|
||||||
|
if (!didPop) {
|
||||||
|
threeTouchBloc.add(OnClose());
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: 2,
|
||||||
|
child: DefaultScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
threeTouchBloc.createSchedule == true
|
||||||
|
? TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
threeTouchBloc.add(ThreeTouchSave());
|
||||||
|
},
|
||||||
|
child: const Text('Save'))
|
||||||
|
: threeTouchBloc.selectedTabIndex == 1
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
// oneTouchBloc.toggleCreateSchedule();
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const ToggleCreateScheduleEvent(
|
||||||
|
index: 1));
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
decoration: const ShapeDecoration(
|
||||||
|
color: ColorsManager.onPrimaryColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(30)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
// onTap: (value) {
|
||||||
|
// if (value == 0) {
|
||||||
|
// if (threeTouchBloc.createSchedule ==
|
||||||
|
// true) {
|
||||||
|
// threeTouchBloc.toggleCreateSchedule();
|
||||||
|
// }
|
||||||
|
// threeTouchBloc.toggleSelectedIndex(0);
|
||||||
|
// } else {
|
||||||
|
// threeTouchBloc.toggleSelectedIndex(1);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
|
onTap: (value) {
|
||||||
|
if (value == 0) {
|
||||||
|
if (threeTouchBloc.createSchedule ==
|
||||||
|
true) {
|
||||||
|
// oneTouchBloc.toggleCreateSchedule();
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const ToggleCreateScheduleEvent(
|
||||||
|
index: 0));
|
||||||
|
}
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const ToggleSelectedEvent(
|
||||||
|
index: 0));
|
||||||
|
} else {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
const ToggleSelectedEvent(
|
||||||
|
index: 1));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indicatorColor: Colors.white,
|
||||||
|
dividerHeight: 0,
|
||||||
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
|
indicator: const ShapeDecoration(
|
||||||
|
color: ColorsManager.slidingBlueColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(20)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
child: BodySmall(
|
||||||
|
text: 'Countdown',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
child: Text(
|
||||||
|
'Schedule',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
physics: const NeverScrollableScrollPhysics(), // Disable swiping
|
||||||
|
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
countNum > 0
|
||||||
|
? BodyLarge(
|
||||||
|
text: _formatDuration(
|
||||||
|
countNum),
|
||||||
|
fontColor: ColorsManager
|
||||||
|
.slidingBlueColor,
|
||||||
|
fontSize: 40,
|
||||||
|
)
|
||||||
|
: CupertinoTimerPicker(
|
||||||
|
mode:
|
||||||
|
CupertinoTimerPickerMode
|
||||||
|
.hm,
|
||||||
|
onTimerDurationChanged:
|
||||||
|
(Duration
|
||||||
|
newDuration) {
|
||||||
|
duration = newDuration;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (state
|
||||||
|
is LoadingNewSate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (countNum > 0) {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
SetCounterValue(
|
||||||
|
deviceCode:
|
||||||
|
deviceCode,
|
||||||
|
duration: Duration
|
||||||
|
.zero));
|
||||||
|
} else if (duration !=
|
||||||
|
Duration.zero) {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
SetCounterValue(
|
||||||
|
deviceCode:
|
||||||
|
deviceCode,
|
||||||
|
duration:
|
||||||
|
duration));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
countNum > 0
|
||||||
|
? Assets.pauseIcon
|
||||||
|
: Assets.playIcon)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
child: threeTouchBloc.createSchedule ==
|
||||||
|
true
|
||||||
|
? CreateSchedule(
|
||||||
|
onToggleChanged: (bool isOn) {
|
||||||
|
threeTouchBloc.toggleSchedule =
|
||||||
|
isOn;
|
||||||
|
},
|
||||||
|
onDateTimeChanged:
|
||||||
|
(DateTime dateTime) {
|
||||||
|
threeTouchBloc.selectedTime =
|
||||||
|
dateTime;
|
||||||
|
},
|
||||||
|
days: threeTouchBloc.days,
|
||||||
|
selectDays: (List<String>
|
||||||
|
selectedDays) {
|
||||||
|
threeTouchBloc.selectedDays =
|
||||||
|
selectedDays;
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 10),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ScheduleListView(
|
||||||
|
listSchedule: threeTouchBloc
|
||||||
|
.listSchedule, // Pass the schedule list here
|
||||||
|
onDismissed:
|
||||||
|
(scheduleId) {
|
||||||
|
threeTouchBloc
|
||||||
|
.listSchedule
|
||||||
|
.removeWhere(
|
||||||
|
(schedule) =>
|
||||||
|
schedule
|
||||||
|
.scheduleId ==
|
||||||
|
scheduleId);
|
||||||
|
threeTouchBloc.add(
|
||||||
|
DeleteScheduleEvent(
|
||||||
|
id: scheduleId));
|
||||||
|
},
|
||||||
|
onToggleSchedule:
|
||||||
|
(scheduleId,
|
||||||
|
isEnabled) {
|
||||||
|
threeTouchBloc.add(
|
||||||
|
ToggleScheduleEvent(
|
||||||
|
id: scheduleId,
|
||||||
|
toggle: isEnabled,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _formatDuration(int seconds) {
|
||||||
|
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
|
||||||
|
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
|
||||||
|
final secs = (seconds % 60).toString().padLeft(2, '0');
|
||||||
|
return '$hours:$minutes:$secs';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,9 +19,11 @@ class TwoGangWizard extends StatelessWidget {
|
|||||||
List<GroupTwoGangModel> groupTwoGangModel = [];
|
List<GroupTwoGangModel> groupTwoGangModel = [];
|
||||||
|
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
|
title: 'Lights',
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
TwoGangBloc(switchCode: '', twoGangId: device?.uuid ?? '')..add(InitialWizardEvent()),
|
TwoGangBloc(switchCode: '', twoGangId: device?.uuid ?? '')
|
||||||
|
..add(InitialWizardEvent()),
|
||||||
child: BlocBuilder<TwoGangBloc, TwoGangState>(
|
child: BlocBuilder<TwoGangBloc, TwoGangState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
bool allSwitchesOn = false;
|
bool allSwitchesOn = false;
|
||||||
@ -32,8 +34,10 @@ class TwoGangWizard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return state is LoadingInitialState
|
return state is LoadingInitialState
|
||||||
? const Center(
|
? const Center(
|
||||||
child:
|
child: DefaultContainer(
|
||||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
)
|
)
|
||||||
: TwoGangList(
|
: TwoGangList(
|
||||||
twoGangList: groupTwoGangModel,
|
twoGangList: groupTwoGangModel,
|
||||||
|
|||||||
@ -0,0 +1,141 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_Touch/two_timer_screen.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_small.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';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class TwoTouchScheduleScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
const TwoTouchScheduleScreen({required this.device, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 48,
|
||||||
|
),
|
||||||
|
DefaultContainer(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_1',
|
||||||
|
switchCode:'switch_1' ,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Cove Light",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_2',
|
||||||
|
switchCode:'switch_2' ,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Chandelier",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,303 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.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';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class TimerScheduleScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
final String deviceCode;
|
||||||
|
final String switchCode;
|
||||||
|
const TimerScheduleScreen(
|
||||||
|
{required this.device,
|
||||||
|
required this.deviceCode,
|
||||||
|
required this.switchCode,
|
||||||
|
super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
TwoTouchBloc(switchCode: switchCode, twoTouchId: device.uuid ?? '')
|
||||||
|
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||||
|
..add(GetScheduleEvent()),
|
||||||
|
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final twoTouchBloc = BlocProvider.of<TwoTouchBloc>(context);
|
||||||
|
Duration duration = Duration.zero;
|
||||||
|
int countNum = 0;
|
||||||
|
if (state is UpdateTimerState) {
|
||||||
|
countNum = state.seconds;
|
||||||
|
} else if (state is TimerRunInProgress) {
|
||||||
|
countNum = state.remainingTime;
|
||||||
|
} else if (state is TimerRunComplete) {
|
||||||
|
countNum = 0;
|
||||||
|
} else if (state is LoadingNewSate) {
|
||||||
|
countNum = 0;
|
||||||
|
}
|
||||||
|
return PopScope(
|
||||||
|
canPop: false,
|
||||||
|
onPopInvoked: (didPop) {
|
||||||
|
if (!didPop) {
|
||||||
|
twoTouchBloc.add(OnClose());
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: 2,
|
||||||
|
child: DefaultScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
twoTouchBloc.createSchedule == true
|
||||||
|
? TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
twoTouchBloc.add(TwoTouchSave());
|
||||||
|
},
|
||||||
|
child: const Text('Save'))
|
||||||
|
: twoTouchBloc.selectedTabIndex == 1
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
// oneTouchBloc.toggleCreateSchedule();
|
||||||
|
twoTouchBloc.add(
|
||||||
|
const ToggleCreateScheduleEvent(
|
||||||
|
index: 1));
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
decoration: const ShapeDecoration(
|
||||||
|
color: ColorsManager.onPrimaryColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(30)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
onTap: (value) {
|
||||||
|
if (value == 0) {
|
||||||
|
if (twoTouchBloc.createSchedule ==
|
||||||
|
true) {
|
||||||
|
// oneTouchBloc.toggleCreateSchedule();
|
||||||
|
twoTouchBloc.add(
|
||||||
|
const ToggleCreateScheduleEvent(
|
||||||
|
index: 0));
|
||||||
|
}
|
||||||
|
twoTouchBloc.add(
|
||||||
|
const ToggleSelectedEvent(
|
||||||
|
index: 0));
|
||||||
|
} else {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
const ToggleSelectedEvent(
|
||||||
|
index: 1));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indicatorColor:
|
||||||
|
Colors.white, // Customize the indicator
|
||||||
|
dividerHeight: 0,
|
||||||
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
|
indicator: const ShapeDecoration(
|
||||||
|
color: ColorsManager.slidingBlueColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(20)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
child: BodySmall(
|
||||||
|
text: 'Countdown',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10),
|
||||||
|
child: Text(
|
||||||
|
'Schedule',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
physics: const NeverScrollableScrollPhysics(), // Disable swiping
|
||||||
|
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
countNum > 0
|
||||||
|
? BodyLarge(
|
||||||
|
text: _formatDuration(
|
||||||
|
countNum),
|
||||||
|
fontColor: ColorsManager
|
||||||
|
.slidingBlueColor,
|
||||||
|
fontSize: 40,
|
||||||
|
)
|
||||||
|
: CupertinoTimerPicker(
|
||||||
|
mode:
|
||||||
|
CupertinoTimerPickerMode
|
||||||
|
.hm,
|
||||||
|
onTimerDurationChanged:
|
||||||
|
(Duration
|
||||||
|
newDuration) {
|
||||||
|
duration = newDuration;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (state
|
||||||
|
is LoadingNewSate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (countNum > 0) {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
SetCounterValue(
|
||||||
|
deviceCode:
|
||||||
|
deviceCode,
|
||||||
|
duration: Duration
|
||||||
|
.zero));
|
||||||
|
} else if (duration !=
|
||||||
|
Duration.zero) {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
SetCounterValue(
|
||||||
|
deviceCode:
|
||||||
|
deviceCode,
|
||||||
|
duration:
|
||||||
|
duration));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
countNum > 0
|
||||||
|
? Assets.pauseIcon
|
||||||
|
: Assets.playIcon)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
child: twoTouchBloc.createSchedule ==
|
||||||
|
true
|
||||||
|
? CreateSchedule(
|
||||||
|
onToggleChanged: (bool isOn) {
|
||||||
|
twoTouchBloc.toggleSchedule =
|
||||||
|
isOn;
|
||||||
|
},
|
||||||
|
onDateTimeChanged:
|
||||||
|
(DateTime dateTime) {
|
||||||
|
twoTouchBloc.selectedTime =
|
||||||
|
dateTime;
|
||||||
|
},
|
||||||
|
days: twoTouchBloc.days,
|
||||||
|
selectDays: (List<String>
|
||||||
|
selectedDays) {
|
||||||
|
twoTouchBloc.selectedDays =
|
||||||
|
selectedDays;
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 10),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ScheduleListView(
|
||||||
|
listSchedule: twoTouchBloc
|
||||||
|
.listSchedule, // Pass the schedule list here
|
||||||
|
onDismissed:
|
||||||
|
(scheduleId) {
|
||||||
|
twoTouchBloc
|
||||||
|
.listSchedule
|
||||||
|
.removeWhere(
|
||||||
|
(schedule) =>
|
||||||
|
schedule
|
||||||
|
.scheduleId ==
|
||||||
|
scheduleId);
|
||||||
|
twoTouchBloc.add(
|
||||||
|
DeleteScheduleEvent(
|
||||||
|
id: scheduleId));
|
||||||
|
},
|
||||||
|
onToggleSchedule:
|
||||||
|
(scheduleId,
|
||||||
|
isEnabled) {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
ToggleScheduleEvent(
|
||||||
|
id: scheduleId,
|
||||||
|
toggle: isEnabled,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _formatDuration(int seconds) {
|
||||||
|
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
|
||||||
|
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
|
||||||
|
final secs = (seconds % 60).toString().padLeft(2, '0');
|
||||||
|
return '$hours:$minutes:$secs';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/generated/assets.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/font_manager.dart';
|
||||||
|
|
||||||
|
class TwoTouchInterface extends StatelessWidget {
|
||||||
|
const TwoTouchInterface({super.key, this.touchSwitch});
|
||||||
|
|
||||||
|
final DeviceModel? touchSwitch;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: touchSwitch != null
|
||||||
|
? DeviceAppbar(
|
||||||
|
deviceName: touchSwitch!.name!,
|
||||||
|
deviceUuid: touchSwitch!.uuid!,
|
||||||
|
)
|
||||||
|
: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: BodyLarge(
|
||||||
|
text: touchSwitch?.name ?? 'Lights',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: Constants.defaultPadding,
|
||||||
|
right: Constants.defaultPadding,
|
||||||
|
bottom: Constants.bottomNavBarHeight,
|
||||||
|
),
|
||||||
|
child: TwoTouchScreen(device: touchSwitch),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_two_touch_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 TwoTouchList extends StatelessWidget {
|
||||||
|
const TwoTouchList(
|
||||||
|
{super.key, required this.twoTouchList, required this.allSwitches});
|
||||||
|
|
||||||
|
final List<GroupTwoTouchModel> twoTouchList;
|
||||||
|
final bool allSwitches;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const BodySmall(text: 'All Lights'),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: allSwitches,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context).add(GroupAllOnEvent());
|
||||||
|
},
|
||||||
|
secondAction: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context).add(GroupAllOffEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
itemCount: twoTouchList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(text: twoTouchList[index].deviceName),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: twoTouchList[index].firstSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context).add(
|
||||||
|
ChangeFirstWizardSwitchStatusEvent(
|
||||||
|
value: twoTouchList[index].firstSwitch,
|
||||||
|
deviceId: twoTouchList[index].deviceId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodySmall(text: twoTouchList[index].deviceName),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
DevicesDefaultSwitch(
|
||||||
|
switchValue: twoTouchList[index].secondSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context).add(
|
||||||
|
ChangeSecondWizardSwitchStatusEvent(
|
||||||
|
value: twoTouchList[index].secondSwitch,
|
||||||
|
deviceId: twoTouchList[index].deviceId));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,333 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/circular_button.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_setting.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_schedule_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class TwoTouchScreen extends StatelessWidget {
|
||||||
|
const TwoTouchScreen({super.key, this.device, this.switchCode});
|
||||||
|
final DeviceModel? device;
|
||||||
|
final String? switchCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => TwoTouchBloc(
|
||||||
|
switchCode: switchCode ?? '', twoTouchId: device?.uuid ?? '')
|
||||||
|
..add(const InitialEvent()),
|
||||||
|
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
TwoTouchModel twoTouchModel = TwoTouchModel(
|
||||||
|
firstSwitch: false,
|
||||||
|
secondSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
secondCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off,
|
||||||
|
relay_status_2: status.off,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (state is LoadingNewSate) {
|
||||||
|
twoTouchModel = state.twoTouchModel;
|
||||||
|
} else if (state is UpdateState) {
|
||||||
|
twoTouchModel = state.twoTouchModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context)
|
||||||
|
.add(const InitialEvent());
|
||||||
|
},
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Expanded(child: SizedBox.shrink()),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
GangSwitch(
|
||||||
|
threeGangSwitch: device!,
|
||||||
|
value: twoTouchModel.firstSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context)
|
||||||
|
.add(ChangeFirstSwitchStatusEvent(
|
||||||
|
value: twoTouchModel
|
||||||
|
.firstSwitch));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(
|
||||||
|
width: 77,
|
||||||
|
child: BodySmall(
|
||||||
|
text: "Cove Light",
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textPrimaryColor,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
GangSwitch(
|
||||||
|
threeGangSwitch: device!,
|
||||||
|
value: twoTouchModel.secondSwitch,
|
||||||
|
action: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context)
|
||||||
|
.add(
|
||||||
|
ChangeSecondSwitchStatusEvent(
|
||||||
|
value: twoTouchModel
|
||||||
|
.secondSwitch));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(
|
||||||
|
width: 77,
|
||||||
|
child: BodySmall(
|
||||||
|
text: "Chandelier",
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textPrimaryColor,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.u_turn_left,
|
||||||
|
label: "All On",
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context)
|
||||||
|
.add(AllOnEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
// Column(
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
// children: [
|
||||||
|
|
||||||
|
// Card(
|
||||||
|
// elevation: 3,
|
||||||
|
// shape: RoundedRectangleBorder(
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(100),
|
||||||
|
// ),
|
||||||
|
// child: GestureDetector(
|
||||||
|
// onTap: () {
|
||||||
|
// BlocProvider.of<TwoTouchBloc>(
|
||||||
|
// context)
|
||||||
|
// .add(AllOnEvent());
|
||||||
|
// },
|
||||||
|
// child: Stack(
|
||||||
|
// alignment: Alignment.center,
|
||||||
|
// children: [
|
||||||
|
// Container(
|
||||||
|
// width: 60,
|
||||||
|
// height: 60,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: Colors.grey[300],
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(
|
||||||
|
// 100),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Container(
|
||||||
|
// width: 40,
|
||||||
|
// height: 40,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: Colors.white,
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(
|
||||||
|
// 100),
|
||||||
|
// ),
|
||||||
|
// child: Center(
|
||||||
|
// child: BodySmall(
|
||||||
|
// text: "On",
|
||||||
|
// style: context.bodyMedium
|
||||||
|
// .copyWith(
|
||||||
|
// color: ColorsManager
|
||||||
|
// .primaryColorWithOpacity,
|
||||||
|
// fontWeight:
|
||||||
|
// FontWeight
|
||||||
|
// .bold),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// BodySmall(
|
||||||
|
// text: "All On",
|
||||||
|
// style: context.bodyMedium.copyWith(
|
||||||
|
// color: ColorsManager.textPrimaryColor,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.access_time,
|
||||||
|
label: "Timer",
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1,
|
||||||
|
animation2) =>
|
||||||
|
TwoTouchScheduleScreen(
|
||||||
|
device: device!,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
// Column(
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
// children: [
|
||||||
|
// Card(
|
||||||
|
// elevation: 3,
|
||||||
|
// shape: RoundedRectangleBorder(
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(100),
|
||||||
|
// ),
|
||||||
|
// child: GestureDetector(
|
||||||
|
// onTap: () {
|
||||||
|
// Navigator.push(
|
||||||
|
// context,
|
||||||
|
// PageRouteBuilder(
|
||||||
|
// pageBuilder: (context,
|
||||||
|
// animation1,
|
||||||
|
// animation2) =>
|
||||||
|
// TwoTouchScheduleScreen(
|
||||||
|
// device: device!,
|
||||||
|
// )));
|
||||||
|
// },
|
||||||
|
// child: Stack(
|
||||||
|
// alignment: Alignment.center,
|
||||||
|
// children: [
|
||||||
|
// Container(
|
||||||
|
// width: 60,
|
||||||
|
// height: 60,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: Colors.grey[300],
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(
|
||||||
|
// 100),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Container(
|
||||||
|
// width: 40,
|
||||||
|
// height: 40,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: Colors.white,
|
||||||
|
// borderRadius:
|
||||||
|
// BorderRadius.circular(
|
||||||
|
// 100),
|
||||||
|
// ),
|
||||||
|
// child: Center(
|
||||||
|
// child: Icon(
|
||||||
|
// Icons.access_time,
|
||||||
|
// color: ColorsManager
|
||||||
|
// .primaryColorWithOpacity,
|
||||||
|
// size: 25,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// BodySmall(
|
||||||
|
// text: "Timer",
|
||||||
|
// style: context.bodyMedium.copyWith(
|
||||||
|
// color: ColorsManager.textPrimaryColor,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.access_time,
|
||||||
|
label: "Setting",
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1,
|
||||||
|
animation2) =>
|
||||||
|
TwoTouchSetting(
|
||||||
|
device: device,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
CircularButton(
|
||||||
|
device: device,
|
||||||
|
icons: Icons.access_time,
|
||||||
|
label: "All Off",
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<TwoTouchBloc>(context)
|
||||||
|
.add(AllOffEvent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(child: SizedBox())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,394 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.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/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class TwoTouchSetting extends StatelessWidget {
|
||||||
|
const TwoTouchSetting({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Setting',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
TwoTouchBloc(switchCode: '', twoTouchId: device?.uuid ?? '')
|
||||||
|
..add(const InitialEvent()),
|
||||||
|
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final twoTouchBloc = BlocProvider.of<TwoTouchBloc>(context);
|
||||||
|
TwoTouchModel? twoTouchModel = TwoTouchModel(
|
||||||
|
relay_status_2: status.off,
|
||||||
|
secondCountDown: 0,
|
||||||
|
secondSwitch: false,
|
||||||
|
firstSwitch: false,
|
||||||
|
firstCountDown: 0,
|
||||||
|
light_mode: lightStatus.off,
|
||||||
|
relay: status.off,
|
||||||
|
relay_status_1: status.off);
|
||||||
|
|
||||||
|
// if (state is UpdateState) {
|
||||||
|
// TwoTouchModel = state.TwoTouchModel;
|
||||||
|
// }
|
||||||
|
if (state is UpdateState) {
|
||||||
|
twoTouchModel = state.twoTouchModel;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
child: DefaultContainer(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
twoTouchBloc.optionSelected =
|
||||||
|
'relay_status';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
twoTouchModel!.relay.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
twoTouchBloc.add(ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
twoTouchBloc.add(const InitialEvent());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: twoTouchModel.relay.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
twoTouchBloc.optionSelected =
|
||||||
|
'light_mode';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
twoTouchModel!.light_mode.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Indicator Status',
|
||||||
|
label1: 'Off',
|
||||||
|
label2: 'On/Off Status',
|
||||||
|
label3: 'Switch Position',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
twoTouchBloc
|
||||||
|
.add(const InitialEvent());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Indicator Status',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: twoTouchBloc.deviceStatus
|
||||||
|
.light_mode.value,
|
||||||
|
fontColor: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
twoTouchBloc.optionSelected =
|
||||||
|
'relay_status_1';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
twoTouchModel!
|
||||||
|
.relay_status_1.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status 1',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
twoTouchBloc
|
||||||
|
.add(const InitialEvent());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status 1',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: twoTouchBloc.deviceStatus
|
||||||
|
.relay_status_1.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
bottom: 10, top: 10),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
twoTouchBloc.optionSelected =
|
||||||
|
'relay_status_2';
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return RestartStatusDialog(
|
||||||
|
initialSelectedLabel:
|
||||||
|
twoTouchModel!
|
||||||
|
.relay_status_2.value,
|
||||||
|
cancelTab: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
confirmTab: () {
|
||||||
|
twoTouchBloc.add(
|
||||||
|
ChangeStatusEvent(
|
||||||
|
deviceId: device!.uuid!,
|
||||||
|
context: context));
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
title: 'Restart Status 2',
|
||||||
|
label1: 'Power Off',
|
||||||
|
label2: 'Power On',
|
||||||
|
label3: 'Restart Memory',
|
||||||
|
onTapLabel1: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel2: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
onTapLabel3: (selected) {
|
||||||
|
twoTouchBloc.statusSelected =
|
||||||
|
selected;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
Future.delayed(
|
||||||
|
const Duration(seconds: 2),
|
||||||
|
() async {
|
||||||
|
twoTouchBloc
|
||||||
|
.add(const InitialEvent());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BodyLarge(
|
||||||
|
fontSize: 15,
|
||||||
|
text: 'Restart Status 2',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
fontSize: 13,
|
||||||
|
text: twoTouchBloc.deviceStatus
|
||||||
|
.relay_status_2.value,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.dart';
|
||||||
|
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/group_two_touch_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_list.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
|
||||||
|
class TwoTouchWizard extends StatelessWidget {
|
||||||
|
const TwoTouchWizard({super.key, this.device});
|
||||||
|
|
||||||
|
final DeviceModel? device;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<GroupTwoTouchModel> groupTwoTouchModel = [];
|
||||||
|
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Lights',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
TwoTouchBloc(switchCode: '', twoTouchId: device?.uuid ?? '')
|
||||||
|
..add(InitialWizardEvent()),
|
||||||
|
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
bool allSwitchesOn = false;
|
||||||
|
|
||||||
|
if (state is UpdateGroupState) {
|
||||||
|
groupTwoTouchModel = state.twoTouchList;
|
||||||
|
allSwitchesOn = state.allSwitches;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: TwoTouchList(
|
||||||
|
twoTouchList: groupTwoTouchModel,
|
||||||
|
allSwitches: allSwitchesOn,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,8 +3,11 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
import 'package:syncrow_app/features/devices/model/device_category_model.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/ACs/acs_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_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';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_wizard.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_wizard.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_wizard.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_wizard.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_wizard.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_wizard.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/water_heater/wh_wizard.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/water_heater/wh_wizard.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.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_large.dart';
|
||||||
@ -64,6 +67,30 @@ class WizardPage extends StatelessWidget {
|
|||||||
pageBuilder: (context, animation1, animation2) =>
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
const WHWizard()));
|
const WHWizard()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (groupsList[index].name == '1GT') {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
const OneTouchWizard()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupsList[index].name == '2GT') {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
const TwoTouchWizard()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupsList[index].name == '3GT') {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
const ThreeTouchWizard()));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: DefaultContainer(
|
child: DefaultContainer(
|
||||||
padding: const EdgeInsets.all(15),
|
padding: const EdgeInsets.all(15),
|
||||||
|
|||||||
@ -4,7 +4,10 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
|||||||
|
|
||||||
class DevicesDefaultSwitch extends StatelessWidget {
|
class DevicesDefaultSwitch extends StatelessWidget {
|
||||||
const DevicesDefaultSwitch(
|
const DevicesDefaultSwitch(
|
||||||
{super.key, required this.switchValue, required this.action, this.secondAction});
|
{super.key,
|
||||||
|
required this.switchValue,
|
||||||
|
required this.action,
|
||||||
|
this.secondAction});
|
||||||
|
|
||||||
final bool switchValue;
|
final bool switchValue;
|
||||||
final Function action;
|
final Function action;
|
||||||
@ -22,7 +25,9 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
height: 60,
|
height: 60,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: switchValue ? ColorsManager.primaryColor : Colors.white,
|
color: switchValue
|
||||||
|
? ColorsManager.switchButton.withOpacity(0.6)
|
||||||
|
: Colors.white,
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
topLeft: Radius.circular(15),
|
topLeft: Radius.circular(15),
|
||||||
bottomLeft: Radius.circular(15),
|
bottomLeft: Radius.circular(15),
|
||||||
@ -30,9 +35,10 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: BodyMedium(
|
child: BodyMedium(
|
||||||
|
fontSize: 14,
|
||||||
text: "ON",
|
text: "ON",
|
||||||
fontColor: switchValue ? Colors.white : null,
|
fontColor: switchValue ? Colors.white : null,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -50,7 +56,9 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
height: 60,
|
height: 60,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: switchValue ? Colors.white : ColorsManager.primaryColor,
|
color: switchValue
|
||||||
|
? Colors.white
|
||||||
|
: ColorsManager.switchButton.withOpacity(0.6),
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
topRight: Radius.circular(15),
|
topRight: Radius.circular(15),
|
||||||
bottomRight: Radius.circular(15),
|
bottomRight: Radius.circular(15),
|
||||||
@ -58,9 +66,10 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: BodyMedium(
|
child: BodyMedium(
|
||||||
|
fontSize: 14,
|
||||||
text: "OFF",
|
text: "OFF",
|
||||||
fontColor: switchValue ? null : Colors.white,
|
fontColor: switchValue ? null : Colors.white,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -33,10 +33,11 @@ class DevicesAPI {
|
|||||||
static Future<Map<String, dynamic>> controlDevice(
|
static Future<Map<String, dynamic>> controlDevice(
|
||||||
DeviceControlModel controlModel, String deviceId) async {
|
DeviceControlModel controlModel, String deviceId) async {
|
||||||
try {
|
try {
|
||||||
|
print(controlModel.toJson());
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.controlDevice.replaceAll('{deviceUuid}', deviceId),
|
path: ApiEndpoints.controlDevice.replaceAll('{deviceUuid}', deviceId),
|
||||||
body: controlModel.toJson(),
|
body: controlModel.toJson(),
|
||||||
showServerMessage: false,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
@ -72,7 +73,8 @@ class DevicesAPI {
|
|||||||
|
|
||||||
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId),
|
path: ApiEndpoints.deviceFunctionsStatus
|
||||||
|
.replaceAll('{deviceUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -82,7 +84,9 @@ class DevicesAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<Map<String, dynamic>> renamePass(
|
static Future<Map<String, dynamic>> renamePass(
|
||||||
{required String name, required String doorLockUuid, required String passwordId}) async {
|
{required String name,
|
||||||
|
required String doorLockUuid,
|
||||||
|
required String passwordId}) async {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.renamePassword
|
path: ApiEndpoints.renamePassword
|
||||||
.replaceAll('{doorLockUuid}', doorLockUuid)
|
.replaceAll('{doorLockUuid}', doorLockUuid)
|
||||||
@ -107,7 +111,8 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<DeviceModel>> getDeviceByGroupName(String unitId, String groupName) async {
|
static Future<List<DeviceModel>> getDeviceByGroupName(
|
||||||
|
String unitId, String groupName) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.devicesByGroupName
|
path: ApiEndpoints.devicesByGroupName
|
||||||
.replaceAll('{unitUuid}', unitId)
|
.replaceAll('{unitUuid}', unitId)
|
||||||
@ -146,7 +151,8 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
|
static Future<List<DeviceModel>> getDevicesByGatewayId(
|
||||||
|
String gatewayId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
|
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
@ -168,7 +174,8 @@ class DevicesAPI {
|
|||||||
String deviceId,
|
String deviceId,
|
||||||
) async {
|
) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.getTemporaryPassword
|
||||||
|
.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -179,7 +186,8 @@ class DevicesAPI {
|
|||||||
|
|
||||||
static Future getOneTimePasswords(String deviceId) async {
|
static Future getOneTimePasswords(String deviceId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.getOneTimeTemporaryPassword
|
||||||
|
.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -190,7 +198,8 @@ class DevicesAPI {
|
|||||||
|
|
||||||
static Future getTimeLimitPasswords(String deviceId) async {
|
static Future getTimeLimitPasswords(String deviceId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.getMultipleTimeTemporaryPassword
|
||||||
|
.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -215,10 +224,12 @@ class DevicesAPI {
|
|||||||
"invalidTime": invalidTime,
|
"invalidTime": invalidTime,
|
||||||
};
|
};
|
||||||
if (scheduleList != null) {
|
if (scheduleList != null) {
|
||||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
body["scheduleList"] =
|
||||||
|
scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||||
}
|
}
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.addTemporaryPassword
|
||||||
|
.replaceAll('{doorLockUuid}', deviceId),
|
||||||
body: body,
|
body: body,
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) => json,
|
expectedResponseModel: (json) => json,
|
||||||
@ -229,7 +240,8 @@ class DevicesAPI {
|
|||||||
static Future generateOneTimePassword({deviceId}) async {
|
static Future generateOneTimePassword({deviceId}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.addOneTimeTemporaryPassword
|
||||||
|
.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -241,10 +253,12 @@ class DevicesAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future generateMultiTimePassword({deviceId, effectiveTime, invalidTime}) async {
|
static Future generateMultiTimePassword(
|
||||||
|
{deviceId, effectiveTime, invalidTime}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.addMultipleTimeTemporaryPassword
|
||||||
|
.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
|
body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
|
|||||||
@ -5,7 +5,8 @@ abstract class ColorsManager {
|
|||||||
static const Color switchOffColor = Color(0x7F8D99AE);
|
static const Color switchOffColor = Color(0x7F8D99AE);
|
||||||
static const Color primaryColor = Color(0xFF0030CB);
|
static const Color primaryColor = Color(0xFF0030CB);
|
||||||
static const Color secondaryTextColor = Color(0xFF848484);
|
static const Color secondaryTextColor = Color(0xFF848484);
|
||||||
static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
|
static Color primaryColorWithOpacity =
|
||||||
|
const Color(0xFF023DFE).withOpacity(0.6);
|
||||||
static const Color onPrimaryColor = Colors.white;
|
static const Color onPrimaryColor = Colors.white;
|
||||||
static const Color secondaryColor = Color(0xFF023DFE);
|
static const Color secondaryColor = Color(0xFF023DFE);
|
||||||
static const Color onSecondaryColor = Color(0xFF023DFE);
|
static const Color onSecondaryColor = Color(0xFF023DFE);
|
||||||
@ -27,4 +28,5 @@ abstract class ColorsManager {
|
|||||||
static const Color red = Colors.red;
|
static const Color red = Colors.red;
|
||||||
static const Color graysColor = Color(0xffEBEBEB);
|
static const Color graysColor = Color(0xffEBEBEB);
|
||||||
static const Color textGray = Color(0xffD5D5D5);
|
static const Color textGray = Color(0xffD5D5D5);
|
||||||
|
static const Color switchButton = Color(0xff023DFE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,10 @@ enum DeviceType {
|
|||||||
WallSensor,
|
WallSensor,
|
||||||
WH,
|
WH,
|
||||||
DS,
|
DS,
|
||||||
|
OneTouch,
|
||||||
|
TowTouch,
|
||||||
|
ThreeTouch,
|
||||||
|
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +80,9 @@ Map<String, DeviceType> devicesTypesMap = {
|
|||||||
"CUR": DeviceType.Curtain,
|
"CUR": DeviceType.Curtain,
|
||||||
"WH": DeviceType.WH,
|
"WH": DeviceType.WH,
|
||||||
"DS": DeviceType.DS,
|
"DS": DeviceType.DS,
|
||||||
|
"1GT": DeviceType.OneTouch,
|
||||||
|
"2GT": DeviceType.TowTouch,
|
||||||
|
"3GT": DeviceType.ThreeTouch,
|
||||||
};
|
};
|
||||||
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||||
DeviceType.AC: [
|
DeviceType.AC: [
|
||||||
@ -284,13 +291,144 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
|||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'doorcontact_state',
|
code: 'doorcontact_state',
|
||||||
type: functionTypesMap['Raw'],
|
type: functionTypesMap['Raw'],
|
||||||
values: ValueModel.fromJson({})
|
values: ValueModel.fromJson({})),
|
||||||
),
|
|
||||||
FunctionModel(
|
FunctionModel(
|
||||||
code: 'battery_percentage',
|
code: 'battery_percentage',
|
||||||
type: functionTypesMap['Integer'],
|
type: functionTypesMap['Integer'],
|
||||||
values: ValueModel.fromJson({})
|
values: ValueModel.fromJson({})),
|
||||||
),
|
],
|
||||||
|
DeviceType.OneTouch: [
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_1',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_1',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'light_mode',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['none', 'relay', 'pos']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status_1',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
DeviceType.TowTouch: [
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_1',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_2',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_1',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_2',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'light_mode',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['none', 'relay', 'pos']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status_1',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status_2',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
|
||||||
|
DeviceType.ThreeTouch: [
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_1',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_2',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_3',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_1',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_2',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_3',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'light_mode',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['none', 'relay', 'pos']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status_1',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status_2',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'relay_status_3',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['power_off', 'power_on', 'last']
|
||||||
|
})),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -589,3 +727,67 @@ List<Map<String, Object>> members = [
|
|||||||
'role': MemberRole.FamilyMember,
|
'role': MemberRole.FamilyMember,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
enum status {
|
||||||
|
on,
|
||||||
|
off,
|
||||||
|
restart,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension StatusExtension on status {
|
||||||
|
String get value {
|
||||||
|
switch (this) {
|
||||||
|
case status.off:
|
||||||
|
return "Power Off";
|
||||||
|
case status.on:
|
||||||
|
return "Power On";
|
||||||
|
case status.restart:
|
||||||
|
return "Restart Memory";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static status fromString(String value) {
|
||||||
|
switch (value) {
|
||||||
|
case "power_off":
|
||||||
|
return status.off;
|
||||||
|
case "power_on":
|
||||||
|
return status.on;
|
||||||
|
case "last":
|
||||||
|
return status.restart;
|
||||||
|
default:
|
||||||
|
throw ArgumentError("Invalid access type: $value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum lightStatus {
|
||||||
|
off,
|
||||||
|
on_off,
|
||||||
|
switchPosition,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension lightStatusExtension on lightStatus {
|
||||||
|
String get value {
|
||||||
|
switch (this) {
|
||||||
|
case lightStatus.off:
|
||||||
|
return "Off";
|
||||||
|
case lightStatus.switchPosition:
|
||||||
|
return "On/Off Status";
|
||||||
|
case lightStatus.on_off:
|
||||||
|
return "Restart Memory";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static lightStatus fromString(String value) {
|
||||||
|
switch (value) {
|
||||||
|
case "none":
|
||||||
|
return lightStatus.off;
|
||||||
|
case "relay":
|
||||||
|
return lightStatus.switchPosition;
|
||||||
|
case "pos":
|
||||||
|
return lightStatus.on_off;
|
||||||
|
default:
|
||||||
|
throw ArgumentError("Invalid access type: $value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user