Compare commits

..

13 Commits

Author SHA1 Message Date
21c336360c revert 2024-09-06 10:40:45 +04:00
fee34703bd revert back 2024-09-06 10:33:39 +04:00
a92676d6a4 revert back to dev 2024-09-06 10:32:02 +04:00
8c5cf2c04e dialog 2024-09-06 10:25:54 +04:00
1f02f66916 changed stack to column 2024-09-06 10:20:52 +04:00
3ea089425c revert back change 2024-09-06 10:07:14 +04:00
77d2f54352 revert back dev 2024-09-02 13:38:49 +04:00
cff66bb653 revert back to dev 2024-09-02 13:35:25 +04:00
022ba53f5d Revert back to dev 2024-09-02 13:34:16 +04:00
bf69399af2 Merge remote-tracking branch 'origin/dev' into bugfix/SP-292 2024-09-02 13:27:08 +04:00
a72fc0b466 Added dialogue for success message 2024-09-02 13:25:58 +04:00
df13840a65 asset added of success icon 2024-09-02 13:25:33 +04:00
032a28d47a setting up the dependencies 2024-08-29 15:54:27 +04:00
20 changed files with 660 additions and 501 deletions

View File

@ -0,0 +1,14 @@
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 284">
<g id="Group">
<g id="Group_2">
<path id="Vector" d="M37.8033 16.3571C37.2313 15.7851 36.3039 15.785 35.7318 16.3572L21.5532 30.5356L14.2681 23.2508C13.6962 22.6788 12.7686 22.6787 12.1966 23.2509C11.6246 23.8229 11.6246 24.7504 12.1966 25.3224L20.5174 33.643C20.8034 33.9291 21.1783 34.072 21.5531 34.072C21.928 34.072 22.3029 33.9291 22.5888 33.6429L37.8033 18.4287C38.3754 17.8567 38.3754 16.9292 37.8033 16.3571Z" fill="white"/>
</g>
</g>
<g id="Group_3">
<g id="Group_4">
<path id="Vector_2" d="M42.6776 7.32236C37.9558 2.60049 31.6776 0 25 0C18.3223 0 12.0442 2.60049 7.32236 7.32236C2.60039 12.0443 0 18.3224 0 25C0 31.6778 2.60039 37.9559 7.32236 42.6777C12.0441 47.3996 18.3223 50 25 50C31.6777 50 37.9558 47.3996 42.6776 42.6777C47.3995 37.9559 50 31.6778 50 25C50 18.3224 47.3995 12.0443 42.6776 7.32236ZM25 47.0703C12.8304 47.0703 2.92969 37.1696 2.92969 25C2.92969 12.8304 12.8304 2.92969 25 2.92969C37.1696 2.92969 47.0703 12.8304 47.0703 25C47.0703 37.1696 37.1696 47.0703 25 47.0703Z" fill="white"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -241,14 +241,16 @@ class AuthCubit extends Cubit<AuthState> {
} }
} }
reSendOtp() async { Future<bool> reSendOtp() async {
try { try {
emit(AuthLoading()); emit(AuthLoading());
await AuthenticationAPI.sendOtp( await AuthenticationAPI.sendOtp(
body: {'email': email, 'type': 'VERIFICATION'}); body: {'email': email, 'type': 'VERIFICATION'});
emit(ResendOtpSuccess()); emit(ResendOtpSuccess());
return true;
} catch (_) { } catch (_) {
emit(AuthLoginError(message: 'Something went wrong')); emit(AuthLoginError(message: 'Something went wrong'));
return false;
} }
} }

View File

@ -8,6 +8,7 @@ import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart'; import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/auth/view/create_new_password.dart'; import 'package:syncrow_app/features/auth/view/create_new_password.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart'; import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/success_dialog.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/navigation/routing_constants.dart';
@ -40,13 +41,19 @@ class _OtpViewState extends State<OtpView> {
_lifecycleEventHandler = LifecycleEventHandler( _lifecycleEventHandler = LifecycleEventHandler(
resumeCallBack: () async { resumeCallBack: () async {
SharedPreferencesHelper.saveBoolToSP('timeStampSaved', false); SharedPreferencesHelper.saveBoolToSP('timeStampSaved', false);
String timeStampInBackground = await SharedPreferencesHelper.readStringFromSP('timeStamp'); String timeStampInBackground =
int savedCounter = await SharedPreferencesHelper.readIntFromSP('savedCounter'); await SharedPreferencesHelper.readStringFromSP('timeStamp');
int savedCounter =
await SharedPreferencesHelper.readIntFromSP('savedCounter');
DateTime currentTime = DateTime.now(); DateTime currentTime = DateTime.now();
int differenceInSeconds = timeStampInBackground.isNotEmpty int differenceInSeconds = timeStampInBackground.isNotEmpty
? currentTime.difference(DateTime.parse(timeStampInBackground)).inSeconds ? currentTime
.difference(DateTime.parse(timeStampInBackground))
.inSeconds
: 0; : 0;
remainingSec = differenceInSeconds > savedCounter ? 0 : savedCounter - differenceInSeconds; remainingSec = differenceInSeconds > savedCounter
? 0
: savedCounter - differenceInSeconds;
timerStarted = true; timerStarted = true;
startTimer(remainingSec ?? 0); startTimer(remainingSec ?? 0);
return; return;
@ -75,7 +82,8 @@ class _OtpViewState extends State<OtpView> {
} }
handleTimerOnBackground() async { handleTimerOnBackground() async {
bool timeStampSaved = await SharedPreferencesHelper.readBoolFromSP('timeStampSaved') ?? false; bool timeStampSaved =
await SharedPreferencesHelper.readBoolFromSP('timeStampSaved') ?? false;
if (!timeStampSaved) { if (!timeStampSaved) {
final dateInString = DateTime.now().toString(); final dateInString = DateTime.now().toString();
SharedPreferencesHelper.saveIntToSP('savedCounter', remainingSec ?? 0); SharedPreferencesHelper.saveIntToSP('savedCounter', remainingSec ?? 0);
@ -115,7 +123,8 @@ class _OtpViewState extends State<OtpView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String maskedEmail = AuthCubit.get(context).maskEmail(AuthCubit.get(context).email); String maskedEmail =
AuthCubit.get(context).maskEmail(AuthCubit.get(context).email);
return BlocConsumer<AuthCubit, AuthState>( return BlocConsumer<AuthCubit, AuthState>(
listener: (context, state) { listener: (context, state) {
if (state is AuthOtpSuccess) { if (state is AuthOtpSuccess) {
@ -199,7 +208,10 @@ class _OtpViewState extends State<OtpView> {
child: RichText( child: RichText(
text: TextSpan( text: TextSpan(
text: 'We have sent the verification code to', text: 'We have sent the verification code to',
style: Theme.of(context).textTheme.titleSmall!.copyWith( style: Theme.of(context)
.textTheme
.titleSmall!
.copyWith(
color: Colors.white, color: Colors.white,
fontWeight: FontsManager.regular, fontWeight: FontsManager.regular,
fontSize: 14, fontSize: 14,
@ -207,7 +219,10 @@ class _OtpViewState extends State<OtpView> {
children: [ children: [
TextSpan( TextSpan(
text: ' $maskedEmail', text: ' $maskedEmail',
style: Theme.of(context).textTheme.titleSmall!.copyWith( style: Theme.of(context)
.textTheme
.titleSmall!
.copyWith(
color: Colors.black, color: Colors.black,
fontWeight: FontsManager.bold, fontWeight: FontsManager.bold,
fontSize: 14, fontSize: 14,
@ -215,7 +230,10 @@ class _OtpViewState extends State<OtpView> {
), ),
TextSpan( TextSpan(
text: ' change email?', text: ' change email?',
style: Theme.of(context).textTheme.titleSmall!.copyWith( style: Theme.of(context)
.textTheme
.titleSmall!
.copyWith(
color: const Color(0xFF87C7FF), color: const Color(0xFF87C7FF),
fontWeight: FontsManager.regular, fontWeight: FontsManager.regular,
fontSize: 14, fontSize: 14,
@ -239,7 +257,8 @@ class _OtpViewState extends State<OtpView> {
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
autoFocus: true, autoFocus: true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
animationDuration: const Duration(milliseconds: 30), animationDuration:
const Duration(milliseconds: 30),
beforeTextPaste: (text) { beforeTextPaste: (text) {
// Allow pasting only if all characters are numeric // Allow pasting only if all characters are numeric
return int.tryParse(text!) != null; return int.tryParse(text!) != null;
@ -262,18 +281,27 @@ class _OtpViewState extends State<OtpView> {
errorBorderWidth: 1, errorBorderWidth: 1,
borderWidth: 1, borderWidth: 1,
errorBorderColor: Colors.red, errorBorderColor: Colors.red,
activeColor: state is AuthLoginError ? Colors.red : Colors.white, activeColor: state is AuthLoginError
inactiveColor: ? Colors.red
state is AuthLoginError ? Colors.red : Colors.white, : Colors.white,
activeFillColor: inactiveColor: state is AuthLoginError
state is AuthLoginError ? Colors.red : Colors.white, ? Colors.red
inactiveFillColor: : Colors.white,
state is AuthLoginError ? Colors.red : Colors.white, activeFillColor: state is AuthLoginError
selectedFillColor: ? Colors.red
state is AuthLoginError ? Colors.red : Colors.white, : Colors.white,
inactiveFillColor: state is AuthLoginError
? Colors.red
: Colors.white,
selectedFillColor: state is AuthLoginError
? Colors.red
: Colors.white,
disabledColor: Colors.white, disabledColor: Colors.white,
fieldHeight: 56, fieldHeight: 56,
fieldWidth: MediaQuery.sizeOf(context).width > 340 ? 40 : 20, fieldWidth:
MediaQuery.sizeOf(context).width > 340
? 40
: 20,
// fieldWidth: 40, // fieldWidth: 40,
selectedColor: Colors.white, selectedColor: Colors.white,
shape: PinCodeFieldShape.box, shape: PinCodeFieldShape.box,
@ -295,10 +323,12 @@ class _OtpViewState extends State<OtpView> {
isDone: state is AuthLoginSuccess, isDone: state is AuthLoginSuccess,
isLoading: state is AuthLoading, isLoading: state is AuthLoading,
customButtonStyle: ButtonStyle( customButtonStyle: ButtonStyle(
backgroundColor: MaterialStateProperty.all( backgroundColor:
MaterialStateProperty.all(
Colors.black.withOpacity(.25), Colors.black.withOpacity(.25),
), ),
foregroundColor: MaterialStateProperty.all( foregroundColor:
MaterialStateProperty.all(
Colors.white, Colors.white,
), ),
), ),
@ -307,7 +337,8 @@ class _OtpViewState extends State<OtpView> {
), ),
onPressed: () { onPressed: () {
if ((state is! AuthLoading)) { if ((state is! AuthLoading)) {
AuthCubit.get(context).verifyOtp(widget.isForgetPage); AuthCubit.get(context)
.verifyOtp(widget.isForgetPage);
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
} }
}, },
@ -321,10 +352,12 @@ class _OtpViewState extends State<OtpView> {
isDone: state is AuthLoginSuccess, isDone: state is AuthLoginSuccess,
isLoading: state is AuthLoading, isLoading: state is AuthLoading,
customButtonStyle: ButtonStyle( customButtonStyle: ButtonStyle(
backgroundColor: MaterialStateProperty.all( backgroundColor:
MaterialStateProperty.all(
Colors.black.withOpacity(.25), Colors.black.withOpacity(.25),
), ),
foregroundColor: MaterialStateProperty.all( foregroundColor:
MaterialStateProperty.all(
Colors.white, Colors.white,
), ),
), ),
@ -341,8 +374,20 @@ class _OtpViewState extends State<OtpView> {
return; return;
} }
if ((state is! AuthLoading)) { if ((state is! AuthLoading)) {
await AuthCubit.get(context).reSendOtp(); bool success = await AuthCubit.get(context)
.reSendOtp();
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
if(success){
showDialog(
context: context,
builder: (_) => SuccessDialog(
key: ValueKey('SuccessDialog'),
message: 'New OTP sent!',));
}
Future.delayed(Duration(seconds: 2),
() {
Navigator.of(context).pop();
});
} }
}, },
), ),

View File

@ -1,184 +0,0 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
double curtainWidth = 270;
double curtainOpeningSpace = 195;
double blindHeight = 310;
double blindOpeningSpace = 245;
double openPercentage = 0;
bool isMoving = false;
final String curtainId;
CurtainBloc(
this.curtainId,
) : super(CurtainInitial()) {
on<InitCurtain>(_fetchStatus);
on<OpenCurtain>(_onOpenCurtain);
on<CloseCurtain>(_onCloseCurtain);
on<PauseCurtain>(_onPauseCurtain);
}
Future<void> _onOpenCurtain(
OpenCurtain event,
Emitter<CurtainState> emit) async {
isMoving = true;
while (openPercentage < 100.0) {
if (state is CurtainsClosing) {
_pauseCurtain(emit);
break;
}
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
if (isMoving) {
await Future.delayed(const Duration(milliseconds: 200), () async {
openPercentage += 10.0;
event.deviceType == DeviceType.Curtain
? curtainWidth -= curtainOpeningSpace / 10
: blindHeight -= blindOpeningSpace / 10;
if (openPercentage >= 100.0) {
_pauseCurtain(emit);
}
});
if (openPercentage >=100.0) {
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: curtainId,
code: 'control',
value: 'close',
),
curtainId,
);
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: curtainId,
code: 'percent_control',
value: 100,
),
curtainId,
);
}
} else {
_pauseCurtain(emit);
break;
}
}
}
Future<void> _onCloseCurtain(
CloseCurtain event, Emitter<CurtainState> emit) async {
isMoving = true;
while (openPercentage > 0.0) {
if (state is CurtainsOpening) {
_pauseCurtain(emit);
break;
}
emit(CurtainsClosing(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
if (isMoving) {
await Future.delayed(const Duration(milliseconds: 200), () async {
openPercentage -= 10.0;
event.deviceType == DeviceType.Curtain
? curtainWidth += curtainOpeningSpace / 10
: blindHeight += blindOpeningSpace / 10;
if (openPercentage <= 0.0) {
_pauseCurtain(emit);
}
});
if (openPercentage == 0.0) {
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: curtainId,
code: 'percent_control',
value: 0,
),
curtainId,
);
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: curtainId,
code: 'control',
value: 'open',
),
curtainId,
);
}
} else {
_pauseCurtain(emit);
break;
}
}
}
Future<void> _onPauseCurtain(
PauseCurtain event, Emitter<CurtainState> emit) async {
_pauseCurtain(emit);
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: curtainId,
code: 'control',
value: 'stop',
),
curtainId,
);
await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: curtainId,
code: 'percent_control',
value: openPercentage.ceil(),
),
curtainId,
);
}
Future<void> _pauseCurtain(Emitter<CurtainState> emit) async {
isMoving = false;
emit(CurtainsPaused(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
}
void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async {
try {
emit(CurtainLoadingState());
// Fetch the status from the API
var response = await DevicesAPI.getDeviceStatus(curtainId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
// Get the open percentage from the response
openPercentage = double.tryParse(statusModelList[1].value.toString())!;
// Calculate curtain width and blind height based on the open percentage
if (openPercentage != null) {
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
}
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
} catch (e) {
emit(FailedState());
return;
}
}
}

View File

@ -1,34 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
abstract class CurtainEvent extends Equatable {
const CurtainEvent();
@override
List<Object?> get props => [];
}
class OpenCurtain extends CurtainEvent {
final DeviceType deviceType;
const OpenCurtain(this.deviceType);
@override
List<Object?> get props => [deviceType];
}
class CloseCurtain extends CurtainEvent {
final DeviceType deviceType;
const CloseCurtain(this.deviceType);
@override
List<Object?> get props => [deviceType];
}
class InitCurtain extends CurtainEvent {}
class PauseCurtain extends CurtainEvent {}
class useCurtainEvent extends CurtainEvent {}

View File

@ -1,76 +0,0 @@
// curtain_state.dart
import 'package:equatable/equatable.dart';
abstract class CurtainState extends Equatable {
const CurtainState();
@override
List<Object?> get props => [];
}
class CurtainInitial extends CurtainState {}
class UpdateCurtain extends CurtainState {
final double curtainWidth;
final double blindHeight;
final double openPercentage;
const UpdateCurtain({
required this.curtainWidth,
required this.blindHeight,
required this.openPercentage,
});
@override
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
}
class FailedState extends CurtainState {}
class CurtainLoadingState extends CurtainState {}
class CurtainsOpening extends CurtainState {
final double curtainWidth;
final double blindHeight;
final double openPercentage;
const CurtainsOpening({
required this.curtainWidth,
required this.blindHeight,
required this.openPercentage,
});
@override
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
}
class CurtainsClosing extends CurtainState {
final double curtainWidth;
final double blindHeight;
final double openPercentage;
const CurtainsClosing({
required this.curtainWidth,
required this.blindHeight,
required this.openPercentage,
});
@override
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
}
class CurtainsPaused extends CurtainState {
final double curtainWidth;
final double blindHeight;
final double openPercentage;
const CurtainsPaused({
required this.curtainWidth,
required this.blindHeight,
required this.openPercentage,
});
@override
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
}

View File

@ -87,10 +87,10 @@ class DevicesCubit extends Cubit<DevicesState> {
return const DoorsListView(); return const DoorsListView();
case DeviceType.Curtain: case DeviceType.Curtain:
return const CurtainListView(); return const CurtainListView();
// case DeviceType.ThreeGang: // case DeviceType.ThreeGang:
// return const ThreeGangSwitchesView(); // return const ThreeGangSwitchesView();
// case DeviceType.Gateway: // case DeviceType.Gateway:
// return const GateWayView(); // return const GateWayView();
default: default:
return null; return null;
} }
@ -308,10 +308,10 @@ class DevicesCubit extends Cubit<DevicesState> {
emitSafe(GetDevicesLoading()); emitSafe(GetDevicesLoading());
int roomIndex = int roomIndex =
HomeCubit.getInstance().selectedSpace!.rooms!.indexWhere((element) => element.id == roomId); HomeCubit.getInstance().selectedSpace!.rooms!.indexWhere((element) => element.id == roomId);
try { try {
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices = HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices =
await DevicesAPI.getDevicesByRoomId(roomId); await DevicesAPI.getDevicesByRoomId(roomId);
} catch (e) { } catch (e) {
emitSafe(GetDevicesError(e.toString())); emitSafe(GetDevicesError(e.toString()));
return; return;
@ -397,7 +397,87 @@ class DevicesCubit extends Cubit<DevicesState> {
// } // }
// } // }
//////////////////////////////////CURTAINS//////////////////////////////////////
double curtainWidth = 270;
double curtainOpeningSpace = 195;
double blindWindowHight = 310;
double blindOpeningSpace = 245;
double _openPercentage = 0;
bool isMoving = false;
openCurtain(DeviceType type) async {
if (state is CurtainsIsOpening) {
return;
}
isMoving = true;
while (_openPercentage < 100.0) {
if (state is CurtainsIsClosing) {
//listen to interruption by the closing process
pauseCurtain();
break;
}
emit(CurtainsIsOpening());
if (isMoving) {
await Future.delayed(const Duration(milliseconds: 200), () {
_openPercentage += 10.0;
//25.5 is the 10% of the curtain opening space, its used to update the
// animated container of thecurtain
type == DeviceType.Curtain
? curtainWidth -= curtainOpeningSpace / 10
: blindWindowHight -= blindOpeningSpace / 10;
if (_openPercentage >= 100.0) {
pauseCurtain();
}
});
} else {
pauseCurtain();
break;
}
}
}
closeCurtain(DeviceType type) async {
if (state is CurtainsIsClosing) {
return;
}
isMoving = true;
while (_openPercentage > 0.0) {
if (state is CurtainsIsOpening) {
// interrupted by the opening process
pauseCurtain();
break;
}
emit(CurtainsIsClosing());
if (isMoving) {
await Future.delayed(const Duration(milliseconds: 200), () {
_openPercentage -= 10.0;
//25.5 is the 10% of the curtain opening space, its used to update the
type == DeviceType.Curtain
? curtainWidth += curtainOpeningSpace / 10
: blindWindowHight += 24.5;
if (_openPercentage <= 0.0) {
pauseCurtain();
}
});
} else {
pauseCurtain();
break;
}
}
}
pauseCurtain() {
isMoving = false;
emit(CurtainsStopped());
}
} }
enum LightMode { enum LightMode {

View File

@ -54,7 +54,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
bool isStartEndTime = true; bool isStartEndTime = true;
DateTime? startTime; DateTime? startTime;
DateTime? endTime; DateTime? endTime;
int unlockRequest = 0;
List<TemporaryPassword>? temporaryPasswords = []; List<TemporaryPassword>? temporaryPasswords = [];
List<OfflinePasswordModel>? oneTimePasswords = []; List<OfflinePasswordModel>? oneTimePasswords = [];
List<OfflinePasswordModel>? timeLimitPasswords = []; List<OfflinePasswordModel>? timeLimitPasswords = [];
@ -129,7 +128,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} }
_doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) { _doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) {
unlockRequest = deviceStatus.unlockRequest;
emit(UpdateState(smartDoorModel: deviceStatus)); emit(UpdateState(smartDoorModel: deviceStatus));
} }

View File

@ -0,0 +1,163 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class BlindsView extends StatelessWidget {
const BlindsView({
super.key,
this.blind,
});
final DeviceModel? blind;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return DefaultScaffold(
title: blind?.name ?? 'Blinds',
child: Column(
children: [
Column(
children: [
Stack(
alignment: Alignment.topCenter,
children: [
Container(
height: 340,
width: 365,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesWindow,
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 15, bottom: 10),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.linear,
height: DevicesCubit.get(context).blindWindowHight,
width: 270,
child: Stack(
children: List.generate(
25,
(index) {
double spacing = DevicesCubit.get(context)
.blindWindowHight /
24;
double topPosition = index * spacing;
return AnimatedPositioned(
duration: const Duration(milliseconds: 200),
curve: Curves.linear,
top: topPosition,
child: SizedBox(
height: 10,
width: 270,
child: Image.asset(
Assets.assetsImagesHorizintalBlade,
fit: BoxFit.fill,
),
),
);
},
),
),
),
),
],
),
const SizedBox(height: 80),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DecoratedBox(
decoration:
BoxDecoration(shape: BoxShape.circle, boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(3, 3),
),
]),
child: InkWell(
overlayColor:
MaterialStateProperty.all(Colors.transparent),
onTap: () {
// DevicesCubit.get(context).setHight(false);
DevicesCubit.get(context).openCurtain(
blind?.productType! ?? DeviceType.Blind);
},
child: Image.asset(
Assets.assetsImagesUp,
width: 60,
height: 60,
),
),
),
DecoratedBox(
decoration:
BoxDecoration(shape: BoxShape.circle, boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(3, 3),
),
]),
child: InkWell(
overlayColor:
MaterialStateProperty.all(Colors.transparent),
onTap: () {
DevicesCubit.get(context).pauseCurtain();
},
child: Image.asset(
Assets.assetsImagesPause,
width: 60,
height: 60,
),
),
),
DecoratedBox(
decoration:
BoxDecoration(shape: BoxShape.circle, boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(3, 3),
),
]),
child: InkWell(
overlayColor:
MaterialStateProperty.all(Colors.transparent),
onTap: () {
DevicesCubit.get(context).closeCurtain(
blind?.productType! ?? DeviceType.Blind);
},
child: Image.asset(
Assets.assetsImagesDown,
width: 60,
height: 60,
),
),
),
],
),
],
),
],
),
);
},
),
);
}
}

View File

@ -0,0 +1,83 @@
// import 'package:flutter/material.dart';
// import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
// import 'package:syncrow_app/generated2/assets.dart';
// class BlindsBottons extends StatelessWidget {
// const BlindsBottons({
// super.key,
// });
// @override
// Widget build(BuildContext context) {
// return Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// children: [
// DecoratedBox(
// decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
// BoxShadow(
// color: Colors.grey.withOpacity(0.5),
// spreadRadius: 1,
// blurRadius: 5,
// offset: const Offset(3, 3),
// ),
// ]),
// child: InkWell(
// overlayColor: MaterialStateProperty.all(Colors.transparent),
// onTap: () {
// // DevicesCubit.get(context).setHight(false);
// DevicesCubit.get(context).closeCurtain();
// },
// child: Image.asset(
// Assets.assetsImagesUp,
// width: 60,
// height: 60,
// ),
// ),
// ),
// DecoratedBox(
// decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
// BoxShadow(
// color: Colors.grey.withOpacity(0.5),
// spreadRadius: 1,
// blurRadius: 5,
// offset: const Offset(3, 3),
// ),
// ]),
// child: InkWell(
// overlayColor: MaterialStateProperty.all(Colors.transparent),
// onTap: () {
// // DevicesCubit.get(context).setHight(false);
// },
// child: Image.asset(
// Assets.assetsImagesPause,
// width: 60,
// height: 60,
// ),
// ),
// ),
// DecoratedBox(
// decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
// BoxShadow(
// color: Colors.grey.withOpacity(0.5),
// spreadRadius: 1,
// blurRadius: 5,
// offset: const Offset(3, 3),
// ),
// ]),
// child: InkWell(
// overlayColor: MaterialStateProperty.all(Colors.transparent),
// onTap: () {
// // DevicesCubit.get(context).setHight(true);
// DevicesCubit.get(context).openCurtain();
// },
// child: Image.asset(
// Assets.assetsImagesDown,
// width: 60,
// height: 60,
// ),
// ),
// ),
// ],
// );
// }
// }

View File

@ -1,73 +1,114 @@
part of "curtain_view.dart";
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/generated/assets.dart';
class CurtainButtons extends StatelessWidget { class CurtainButtons extends StatelessWidget {
const CurtainButtons({super.key, required this.curtain}); const CurtainButtons({super.key, required this.curtain});
final DeviceModel curtain; final DeviceModel curtain;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
_buildButton( Stack(
onTap: () => context.read<CurtainBloc>().add(OpenCurtain(curtain.productType!)), alignment: Alignment.center,
iconPath: Assets.assetsIconsCurtainsIconOpenCurtain, children: [
), DecoratedBox(
_buildButton( decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
onTap: () => context.read<CurtainBloc>().add(PauseCurtain()), BoxShadow(
iconPath: Assets.assetsImagesPause, color: Colors.grey.withOpacity(0.5),
isSvg: false, spreadRadius: 1,
), blurRadius: 5,
_buildButton( offset: const Offset(3, 3),
onTap: () => context.read<CurtainBloc>().add(CloseCurtain(curtain.productType!)), ),
iconPath: Assets.assetsIconsCurtainsIconCloseCurtain, ]),
), child: InkWell(
], overlayColor: MaterialStateProperty.all(Colors.transparent),
); onTap: () {
} DevicesCubit.get(context).openCurtain(curtain.productType!);
},
Widget _buildButton({ child: const SizedBox.square(
required VoidCallback onTap, dimension: 60,
required String iconPath, ),
bool isSvg = true,
}) {
return Stack(
alignment: Alignment.center,
children: [
DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(3, 3),
), ),
], ),
), Padding(
padding: const EdgeInsets.only(right: 5, bottom: 5),
child: InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: () {
DevicesCubit.get(context).openCurtain(curtain.productType!);
},
child: SvgPicture.asset(
Assets.assetsIconsCurtainsIconOpenCurtain,
width: 110,
height: 110,
),
),
)
],
),
DecoratedBox(
decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(3, 3),
),
]),
child: InkWell( child: InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent), overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: onTap, onTap: () {
child: const SizedBox.square(dimension: 60), DevicesCubit.get(context).pauseCurtain();
},
child: Image.asset(
Assets.assetsImagesPause,
width: 60,
height: 60,
),
), ),
), ),
Padding( Stack(
padding: const EdgeInsets.only(right: 5, bottom: 5), alignment: Alignment.center,
child: InkWell( children: [
overlayColor: MaterialStateProperty.all(Colors.transparent), DecoratedBox(
onTap: onTap, decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
child: isSvg BoxShadow(
? SvgPicture.asset(iconPath, width: 110, height: 110) color: Colors.grey.withOpacity(0.5),
: Image.asset(iconPath, width: 60, height: 60), spreadRadius: 1,
), blurRadius: 5,
offset: const Offset(3, 3),
),
]),
child: const SizedBox.square(
dimension: 60,
),
// InkWell(
// overlayColor: MaterialStateProperty.all(Colors.transparent),
// onTap: () {
// DevicesCubit.get(context).closeCurtain(curtain.productType!);
// },
// child: SvgPicture.asset(
// Assets.assetsIconsCurtainsIconCloseCurtain,
// width: 60,
// height: 60,
// ),
// ),
),
Padding(
padding: const EdgeInsets.only(right: 5, bottom: 5),
child: InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: () {
DevicesCubit.get(context).closeCurtain(curtain.productType!);
},
child: SvgPicture.asset(
Assets.assetsIconsCurtainsIconCloseCurtain,
width: 110,
height: 110,
),
),
)
],
), ),
], ],
); );

View File

@ -1,99 +1,86 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_buttons.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
part "curtain_buttons.dart";
class CurtainView extends StatelessWidget { class CurtainView extends StatelessWidget {
const CurtainView({super.key, required this.curtain}); const CurtainView({super.key, required this.curtain});
final DeviceModel curtain; final DeviceModel curtain;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => CurtainBloc(curtain.uuid!)..add(InitCurtain()), create: (context) => DevicesCubit.getInstance(),
child: BlocBuilder<CurtainBloc, CurtainState>( child: BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) { builder: (context, state) => DefaultScaffold(
double curtainWidth = 270; title: curtain.name,
double blindHeight = 310; child: Column(
if (state is CurtainsOpening) { children: [
curtainWidth = state.curtainWidth; Stack(
blindHeight = state.blindHeight; alignment: Alignment.centerLeft,
} else if (state is CurtainsClosing) { children: [
curtainWidth = state.curtainWidth; Container(
blindHeight = state.blindHeight; height: 340,
} else if (state is CurtainsPaused) { width: 365,
curtainWidth = state.curtainWidth; decoration: const BoxDecoration(
blindHeight = state.blindHeight; image: DecorationImage(
} image: AssetImage(
return DefaultScaffold( Assets.assetsImagesWindow,
title: curtain.name,
child: Column(
children: [
Stack(
alignment: Alignment.centerLeft,
children: [
Container(
height: 340,
width: 365,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesWindow,
),
), ),
), ),
), ),
Padding( ),
padding: const EdgeInsets.all(40), Padding(
child: AnimatedContainer( padding: const EdgeInsets.all(40),
duration: const Duration(milliseconds: 200), child: AnimatedContainer(
curve: Curves.linear, duration: const Duration(milliseconds: 200),
height: 310, curve: Curves.linear,
width: curtainWidth, height: 310,
child: Stack( width: DevicesCubit.getInstance().curtainWidth,
children: List.generate( child: Stack(
10, (index) { children: List.generate(
double spacing = curtainWidth / 9; 10,
double leftMostPosition = index * spacing; (index) {
return AnimatedPositioned( double spacing =
duration: const Duration(milliseconds: 200), DevicesCubit.getInstance().curtainWidth / 9;
curve: Curves.linear, double leftMostPosition = index * spacing;
left: leftMostPosition, return AnimatedPositioned(
child: SizedBox( duration: const Duration(milliseconds: 200),
height: 320, curve: Curves.linear,
width: 32, left: leftMostPosition,
child: SvgPicture.asset( child: SizedBox(
Assets.assetsIconsCurtainsIconVerticalBlade, height: 320,
fit: BoxFit.fill, width: 32,
), child: SvgPicture.asset(
Assets.assetsIconsCurtainsIconVerticalBlade,
fit: BoxFit.fill,
), ),
); ),
}, );
), },
), ),
), ),
), ),
Positioned( ),
Positioned(
top: 27, top: 27,
left: 43, left: 43,
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.assetsIconsCurtainsIconCurtainHolder, Assets.assetsIconsCurtainsIconCurtainHolder)),
), ],
), ),
], const SizedBox(height: 80),
), CurtainButtons(
const SizedBox(height: 80), curtain: curtain,
CurtainButtons(curtain: curtain), ),
], ],
), ),
); ),
},
), ),
); );
} }

View File

@ -66,7 +66,6 @@ class DevicesViewBody extends StatelessWidget {
const SizedBox( const SizedBox(
height: 10, height: 10,
), ),
Expanded( Expanded(
child: PageView( child: PageView(
controller: HomeCubit.getInstance().devicesPageController, controller: HomeCubit.getInstance().devicesPageController,

View File

@ -8,7 +8,6 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_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/curtains/curtain_view.dart';
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/wall_sensor/wall_sensor_interface.dart'; import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
@ -103,11 +102,6 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
// navigateToInterface(CeilingSensorInterface(ceilingSensor: device), context); // navigateToInterface(CeilingSensorInterface(ceilingSensor: device), context);
break; break;
case DeviceType.Curtain: case DeviceType.Curtain:
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
CurtainView(curtain: device,)));
break; break;
case DeviceType.Blind: case DeviceType.Blind:
break; break;

View File

@ -31,36 +31,47 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_animationController = AnimationController( _animationController = AnimationController(
vsync: this, vsync: this,
value: context.read<SmartDoorBloc>().unlockRequest > 0 ? 1 : 0, value: smartDoorModel.unlockRequest > 0 ? 1 : 0,
duration: Duration(seconds: context.read<SmartDoorBloc>().unlockRequest), duration: Duration(seconds: smartDoorModel.unlockRequest),
); );
if (context.read<SmartDoorBloc>().unlockRequest > 0) { if (smartDoorModel.unlockRequest > 0) {
_animationController.reverse(); _animationController.reverse();
} }
_animation = Tween<double>(begin: 0, end: 1).animate(_animationController) _animation = Tween<double>(begin: 0, end: 1).animate(_animationController)
..addListener(() { ..addListener(() {
// if (_animation.status == AnimationStatus.completed) {
// if (widget.doorLock.status
// .firstWhere((element) => element.code == 'normal_open_switch')
// .value !=
// true) {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: widget.doorLock.uuid, code: 'normal_open_switch', value: true),
// widget.doorLock.uuid ?? "");
// }
// BlocProvider.of<SmartDoorBloc>(context)
// .add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
// _animationController.reverse();
// }
// } else if (_animation.status == AnimationStatus.dismissed) {
// // if (widget.doorLock.status
// // .firstWhere((element) => element.code == 'normal_open_switch')
// // .value !=
// // false) {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: widget.doorLock.uuid, code: 'normal_open_switch', value: false),
// widget.doorLock.uuid ?? "");
// // }
// _animationController.forward();
// }
setState(() {}); setState(() {});
}); });
} }
@override
void didUpdateWidget(DoorLockButton oldWidget) {
super.didUpdateWidget(oldWidget);
if (_animationController.status == AnimationStatus.dismissed) {
if (context.read<SmartDoorBloc>().unlockRequest > 0) {
_animationController.value = 1;
_animationController.duration =
Duration(seconds: context.read<SmartDoorBloc>().unlockRequest);
_animationController.reverse();
}
}
}
@override @override
void dispose() { void dispose() {
_animationController.dispose(); _animationController.dispose();
@ -89,7 +100,7 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
// } else if (_animationController.status == AnimationStatus.reverse) { // } else if (_animationController.status == AnimationStatus.reverse) {
// _animationController.forward(); // _animationController.forward();
// } // }
if (context.read<SmartDoorBloc>().unlockRequest > 0) { if (smartDoorModel.unlockRequest > 0) {
BlocProvider.of<SmartDoorBloc>(context) BlocProvider.of<SmartDoorBloc>(context)
.add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch)); .add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
} }

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.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/font_manager.dart';
class SuccessDialog extends StatelessWidget {
final double dialogWidth;
final String message;
const SuccessDialog(
{super.key, this.dialogWidth = 160, required this.message});
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
child: Container(
width: dialogWidth,
height: 120,
decoration: BoxDecoration(
color: ColorsManager.blackColor.withOpacity(0.7),
borderRadius: BorderRadius.circular(15),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.assetsSuccessWhite,
width: 50,
height: 50,
),
const SizedBox(height: 20),
BodySmall(
text: message,
fontColor: ColorsManager.onPrimaryColor,
fontSize: FontSize.s16),
],
),
),
);
}
}

View File

@ -733,6 +733,10 @@ class Assets {
static const String playIcon = "assets/icons/play_ic.svg"; static const String playIcon = "assets/icons/play_ic.svg";
static const String gatewayIcon = "assets/icons/gateway_icon.svg"; static const String gatewayIcon = "assets/icons/gateway_icon.svg";
//assets/icons/success-white.svg
//assets for success white image
static const String assetsSuccessWhite ="assets/icons/success-white.svg";
/// Assets for assetsImagesAutomation /// Assets for assetsImagesAutomation
/// assets/images/automation.jpg /// assets/images/automation.jpg
static const String assetsImagesAutomation = "assets/images/automation.jpg"; static const String assetsImagesAutomation = "assets/images/automation.jpg";
@ -1029,4 +1033,5 @@ class Assets {
static const String assetsPresenceState = static const String assetsPresenceState =
"assets/icons/functions_icons/automation_functions/presence_state.svg"; "assets/icons/functions_icons/automation_functions/presence_state.svg";
} }

View File

@ -7,7 +7,9 @@ import 'package:syncrow_app/firebase_options.dart';
import 'package:syncrow_app/services/locator.dart'; import 'package:syncrow_app/services/locator.dart';
import 'package:syncrow_app/utils/bloc_observer.dart'; import 'package:syncrow_app/utils/bloc_observer.dart';
import 'package:syncrow_app/utils/helpers/localization_helpers.dart'; import 'package:syncrow_app/utils/helpers/localization_helpers.dart';
import 'my_app.dart'; import 'my_app.dart';
void main() { void main() {
//to observe the state of the blocs in the output console //to observe the state of the blocs in the output console
Bloc.observer = MyBlocObserver(); Bloc.observer = MyBlocObserver();

View File

@ -32,7 +32,6 @@ 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 {
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(),
@ -214,6 +213,7 @@ class DevicesAPI {
"effectiveTime": effectiveTime, "effectiveTime": effectiveTime,
"invalidTime": invalidTime, "invalidTime": invalidTime,
}; };
print('createPassword =$body');
if (scheduleList != null) { if (scheduleList != null) {
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList(); body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
} }

View File

@ -68,7 +68,6 @@ Map<String, DeviceType> devicesTypesMap = {
"DL": DeviceType.DoorLock, "DL": DeviceType.DoorLock,
"WPS": DeviceType.WallSensor, "WPS": DeviceType.WallSensor,
"3G": DeviceType.ThreeGang, "3G": DeviceType.ThreeGang,
"CUR": DeviceType.Curtain,
}; };
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = { Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
DeviceType.AC: [ DeviceType.AC: [
@ -175,21 +174,6 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
type: functionTypesMap['Integer'], type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})), values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
], ],
DeviceType.Curtain: [
FunctionModel(
code: 'control',
type: functionTypesMap['Enum'],
values: ValueModel.fromJson(
{"range": ["open","stop","close"]}
)
),
FunctionModel(
code: 'percent_control',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson(
{"unit": "%", "min": 0, "max": 100, "scale": 0, "step": 1})
),
],
}; };
enum TempModes { hot, cold, wind } enum TempModes { hot, cold, wind }