From 9fe25b9bd385aaded003e39a0ae2ee7dea9b8c27 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 26 Jun 2024 20:32:34 +0300 Subject: [PATCH] finished adding tasks and removing them , added error handling --- .../device_manager_state.dart | 6 +- .../bloc/create_scene/create_scene_bloc.dart | 48 +++++ .../bloc/create_scene/create_scene_event.dart | 36 ++++ .../bloc/create_scene/create_scene_state.dart | 16 +- lib/features/scene/helper/scene_helper.dart | 194 +++++++++++------- .../scene/model/scene_static_function.dart | 66 +++--- lib/features/scene/repo/scene_repo.dart | 16 ++ .../scene/view/create_scene_view.dart | 15 +- .../scene/view/device_functions_view.dart | 100 ++++++--- ...l_devices.dart => scene_rooms_tabbar.dart} | 11 +- ...e_add_tasks.dart => scene_tasks_view.dart} | 45 ++-- .../scene/widgets/alert_dialog_countdown.dart | 6 +- .../widgets/alert_dialog_functions_body.dart | 54 +++-- .../alert_dialog_temperature_body.dart | 18 +- .../if_then_containers/then_added_tasks.dart | 99 +++++++++ .../if_then_containers/then_container.dart | 23 +++ lib/my_app.dart | 8 +- lib/navigation/router.dart | 8 +- lib/services/api/devices_api.dart | 6 +- lib/utils/context_extension.dart | 6 +- pubspec.lock | 6 +- pubspec.yaml | 49 ++--- 22 files changed, 605 insertions(+), 231 deletions(-) create mode 100644 lib/features/scene/repo/scene_repo.dart rename lib/features/scene/view/{scene_control_devices.dart => scene_rooms_tabbar.dart} (88%) rename lib/features/scene/view/{scene_add_tasks.dart => scene_tasks_view.dart} (70%) create mode 100644 lib/features/scene/widgets/if_then_containers/then_added_tasks.dart diff --git a/lib/features/devices/bloc/device_manager_bloc/device_manager_state.dart b/lib/features/devices/bloc/device_manager_bloc/device_manager_state.dart index d9780a8..35295a4 100644 --- a/lib/features/devices/bloc/device_manager_bloc/device_manager_state.dart +++ b/lib/features/devices/bloc/device_manager_bloc/device_manager_state.dart @@ -1,7 +1,7 @@ import 'package:equatable/equatable.dart'; import 'package:syncrow_app/features/devices/model/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; -import 'package:syncrow_app/features/devices/model/functions.dart'; +import 'package:syncrow_app/features/devices/model/function_model.dart'; class DeviceManagerState extends Equatable { final bool loading; @@ -11,7 +11,7 @@ class DeviceManagerState extends Equatable { final bool categoryChanged; final bool deviceSelected; final bool functionsLoading; - final FunctionsEntity? deviceFunctions; + final FunctionModel? deviceFunctions; const DeviceManagerState({ required this.loading, @@ -45,7 +45,7 @@ class DeviceManagerState extends Equatable { bool? categoryChanged, bool? deviceSelected, bool? functionsLoading, - FunctionsEntity? deviceFunctions, + FunctionModel? deviceFunctions, }) { return DeviceManagerState( loading: loading ?? this.loading, diff --git a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart index f3b03e4..413cfbe 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_bloc.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_bloc.dart @@ -2,6 +2,8 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:syncrow_app/features/devices/model/device_control_model.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; part 'create_scene_event.dart'; part 'create_scene_state.dart'; @@ -9,5 +11,51 @@ part 'create_scene_state.dart'; class CreateSceneBloc extends Bloc { CreateSceneBloc() : super(CreateSceneInitial()) { on((event, emit) => null as FutureOr); + on(_onAddSceneTask); + on(_selectedValue); + on(_removeTaskById); + } + + List tasksList = []; + String selectedValue = ''; + + FutureOr _onAddSceneTask( + AddTaskEvent event, Emitter emit) { + tasksList.add( + SceneStaticFunction( + operationName: event.operation, + deviceName: event.deviceName, + icon: event.icon, + code: event.deviceControlModel.code ?? '', + deviceId: event.deviceId, + operationalValues: [ + SceneOperationalValue( + value: event.deviceControlModel.value, + icon: '', + ), + ], + ), + ); + emit(AddSceneTask(tasksList: tasksList)); + } + + FutureOr _selectedValue( + SelectedValueEvent event, Emitter emit) { + selectedValue = event.value; + emit(SelectedTaskValueState(value: event.value)); + } + + FutureOr _removeTaskById( + RemoveTaskEvent event, Emitter emit) { + emit(CreateSceneLoading()); + + for (var element in tasksList) { + if (element.uniqueCustomId == event.taskId) { + tasksList.remove(element); + + emit(AddSceneTask(tasksList: tasksList)); + break; + } + } } } diff --git a/lib/features/scene/bloc/create_scene/create_scene_event.dart b/lib/features/scene/bloc/create_scene/create_scene_event.dart index 80ee709..a91843a 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_event.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_event.dart @@ -7,4 +7,40 @@ sealed class CreateSceneEvent extends Equatable { List get props => []; } +class AddTaskEvent extends CreateSceneEvent { + final DeviceControlModel deviceControlModel; + final String deviceId; + final String icon; + final String operation; + final String deviceName; + const AddTaskEvent({ + required this.deviceControlModel, + required this.deviceId, + required this.icon, + required this.operation, + required this.deviceName, + }); + + @override + List get props => + [deviceControlModel, deviceId, deviceName, icon, operation]; +} + +class SelectedValueEvent extends CreateSceneEvent { + final String value; + + const SelectedValueEvent({required this.value}); + + @override + List get props => [value]; +} + +class RemoveTaskEvent extends CreateSceneEvent { + final String taskId; + + const RemoveTaskEvent({required this.taskId}); + + @override + List get props => [taskId]; +} diff --git a/lib/features/scene/bloc/create_scene/create_scene_state.dart b/lib/features/scene/bloc/create_scene/create_scene_state.dart index f3bb61e..241c04a 100644 --- a/lib/features/scene/bloc/create_scene/create_scene_state.dart +++ b/lib/features/scene/bloc/create_scene/create_scene_state.dart @@ -2,7 +2,7 @@ part of 'create_scene_bloc.dart'; sealed class CreateSceneState extends Equatable { const CreateSceneState(); - + @override List get props => []; } @@ -11,4 +11,18 @@ final class CreateSceneInitial extends CreateSceneState {} class CreateSceneLoading extends CreateSceneState {} +class AddSceneTask extends CreateSceneState { + final List tasksList; + const AddSceneTask({required this.tasksList}); + @override + List get props => [tasksList]; +} + +class SelectedTaskValueState extends CreateSceneState { + final String value; + const SelectedTaskValueState({required this.value}); + + @override + List get props => [value]; +} diff --git a/lib/features/scene/helper/scene_helper.dart b/lib/features/scene/helper/scene_helper.dart index ccfc555..859e9b5 100644 --- a/lib/features/scene/helper/scene_helper.dart +++ b/lib/features/scene/helper/scene_helper.dart @@ -5,27 +5,40 @@ import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; mixin SceneHelper { - List getFunctionsWithIcons( - {DeviceType? type, required List functions}) { + List getFunctionsWithIcons({ + DeviceType? type, + required List functions, + required String deviceId, + required String deviceName, + }) { switch (type) { case DeviceType.LightBulb: - return lightBulbFunctions(functions); + return lightBulbFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.CeilingSensor: - return ceilingSensorFunctions(functions); + return ceilingSensorFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.WallSensor: - return wallSensorFunctions(functions); + return wallSensorFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.AC: - return acFunctions(functions); + return acFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.DoorLock: - return doorLockFunctions(functions); + return doorLockFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.Curtain: - return curtainFunctions(functions); + return curtainFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.ThreeGang: - return threeGangFunctions(functions); + return threeGangFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); case DeviceType.Gateway: - return gatewayFunctions(functions); + return gatewayFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); default: - return lightBulbFunctions(functions); + return lightBulbFunctions( + functions: functions, deviceId: deviceId, deviceName: deviceName); } } @@ -54,32 +67,36 @@ mixin SceneHelper { /// presence sensor List ceilingSensorFunctions( - List functions) { + {required List functions, + required String deviceId, + required String deviceName}) { return [ SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsSensitivityFunction, - name: 'Sensitivity', + operationName: 'Sensitivity', code: 'sensitivity', operationalValues: [ - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "1"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "2"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "3"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "4"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "5"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "6"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "7"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "8"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "9"), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSensitivityOperationIcon, value: "10"), ], ), @@ -87,165 +104,204 @@ mixin SceneHelper { } } -List curtainFunctions(List functions) { +List curtainFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return []; } -List doorLockFunctions(List functions) { +List doorLockFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return []; } -List wallSensorFunctions(List functions) { +List wallSensorFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return []; } -List lightBulbFunctions(List functions) { +List lightBulbFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return []; } -List gatewayFunctions(List functions) { +List gatewayFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return []; } -List threeGangFunctions(List functions) { +List threeGangFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return [ SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsAcPower, - name: 'Light 1 Switch', + operationName: 'Light 1 Switch', code: 'switch_1', operationalValues: [ - StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), - StaticFunctionOperationHelper( - icon: Assets.assetsAcPowerOFF, value: "OFF"), - StaticFunctionOperationHelper( + SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"), + SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"), + SceneOperationalValue( icon: Assets.assetsSceneRefresh, value: "Reverse Switch"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsAcPower, - name: 'Light 2 Switch', + operationName: 'Light 2 Switch', code: 'switch_2', operationalValues: [ - StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), - StaticFunctionOperationHelper( - icon: Assets.assetsAcPowerOFF, value: "OFF"), - StaticFunctionOperationHelper( + SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"), + SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"), + SceneOperationalValue( icon: Assets.assetsSceneRefresh, value: "Reverse Switch"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsAcPower, - name: 'Light 3 Switch', + operationName: 'Light 3 Switch', code: 'switch_3', operationalValues: [ - StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), - StaticFunctionOperationHelper( - icon: Assets.assetsAcPowerOFF, value: "OFF"), - StaticFunctionOperationHelper( + SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"), + SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"), + SceneOperationalValue( icon: Assets.assetsSceneRefresh, value: "Reverse Switch"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsLightCountdown, - name: 'Light 1 CountDown', + operationName: 'Light 1 CountDown', code: 'countdown_1', operationalValues: [ - StaticFunctionOperationHelper(icon: '', value: "12610"), + SceneOperationalValue(icon: '', value: "0"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsLightCountdown, - name: 'Light 2 CountDown', + operationName: 'Light 2 CountDown', code: 'countdown_1', operationalValues: [ - StaticFunctionOperationHelper(icon: '', value: "0"), + SceneOperationalValue(icon: '', value: "0"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsLightCountdown, - name: 'Light 3 CountDown', + operationName: 'Light 3 CountDown', code: 'countdown_1', operationalValues: [ - StaticFunctionOperationHelper(icon: '', value: "0"), + SceneOperationalValue(icon: '', value: "0"), ], ), ]; } /// smart ac thermostat -List acFunctions(List functions) { +List acFunctions( + {required List functions, + required String deviceId, + required String deviceName}) { return [ SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsAcPower, - name: 'Power', + operationName: 'Power', code: 'switch', operationalValues: [ - StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), - StaticFunctionOperationHelper( - icon: Assets.assetsAcPowerOFF, value: "OFF"), + SceneOperationalValue(icon: Assets.assetsAcPower, value: "ON"), + SceneOperationalValue(icon: Assets.assetsAcPowerOFF, value: "OFF"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsFreezing, - name: 'Mode', + operationName: 'Mode', code: 'mode', operationalValues: [ - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsAcCooling, value: AcValuesEnums.Cooling.name, ), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsAcHeating, value: AcValuesEnums.Heating.name, ), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsFanSpeed, value: AcValuesEnums.Ventilation.name, ), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsTempreture, - name: 'Set Temperature', + operationName: 'Set Temperature', code: 'temp_set', operationalValues: [ - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsCelsiusDegrees, value: "COOL TO"), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsFanSpeed, - name: 'Fan Speed', + operationName: 'Fan Speed', code: 'level', operationalValues: [ - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsAcFanLow, value: ValueACRange.LOW.name, ), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsAcFanMiddle, value: ValueACRange.MIDDLE.name, ), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsAcFanHigh, value: ValueACRange.HIGH.name, ), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsAcFanAuto, value: ValueACRange.AUTO.name, ), ], ), SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, icon: Assets.assetsChildLock, - name: 'Child Lock', + operationName: 'Child Lock', code: 'child_lock', operationalValues: [ - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSceneChildLock, value: 'Lock', ), - StaticFunctionOperationHelper( + SceneOperationalValue( icon: Assets.assetsSceneChildUnlock, value: 'Unlock', ), diff --git a/lib/features/scene/model/scene_static_function.dart b/lib/features/scene/model/scene_static_function.dart index b073516..730cc41 100644 --- a/lib/features/scene/model/scene_static_function.dart +++ b/lib/features/scene/model/scene_static_function.dart @@ -1,51 +1,65 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; +import 'package:uuid/uuid.dart'; class SceneStaticFunction { final String icon; - final String name; + final String deviceName; final String code; - final List operationalValues; + final List operationalValues; + final String deviceId; + final String operationName; + final String uniqueCustomId; SceneStaticFunction({ required this.icon, - required this.name, + required this.deviceName, required this.code, required this.operationalValues, - }); + required this.deviceId, + required this.operationName, + }) : uniqueCustomId = const Uuid().v4(); SceneStaticFunction copyWith({ String? icon, String? name, String? code, - List? operationalValues, + List? operationalValues, + String? deviceId, + String? operationName, }) { return SceneStaticFunction( icon: icon ?? this.icon, - name: name ?? this.name, + deviceName: name ?? this.deviceName, code: code ?? this.code, operationalValues: operationalValues ?? this.operationalValues, + deviceId: deviceId ?? this.deviceId, + operationName: operationName ?? this.operationName, ); } Map toMap() { return { 'icon': icon, - 'name': name, + 'name': deviceName, 'code': code, 'operationalValues': operationalValues.map((x) => x.toMap()).toList(), + 'deviceId': deviceId, + 'operationName': operationName }; } factory SceneStaticFunction.fromMap(Map map) { return SceneStaticFunction( icon: map['icon'] ?? '', - name: map['name'] ?? '', + deviceName: map['name'] ?? '', code: map['code'] ?? '', - operationalValues: List.from( - map['operationalValues'] - ?.map((x) => StaticFunctionOperationHelper.fromMap(x))), + operationalValues: List.from( + map['operationalValues']?.map((x) => SceneOperationalValue.fromMap(x)), + ), + deviceId: map['deviceId'] ?? '', + operationName: map['operationName'] ?? '', ); } @@ -56,7 +70,7 @@ class SceneStaticFunction { @override String toString() { - return 'SceneStaticFunction(icon: $icon, name: $name, code: $code, operationalValues: $operationalValues)'; + return 'SceneStaticFunction(icon: $icon, name: $deviceName, code: $code, operationalValues: $operationalValues, deviceId: $deviceId, operationName: $operationName)'; } @override @@ -65,34 +79,38 @@ class SceneStaticFunction { return other is SceneStaticFunction && other.icon == icon && - other.name == name && + other.deviceName == deviceName && other.code == code && - listEquals(other.operationalValues, operationalValues); + other.operationName == operationName && + listEquals(other.operationalValues, operationalValues) && + other.deviceId == deviceId; } @override int get hashCode { return icon.hashCode ^ - name.hashCode ^ + deviceName.hashCode ^ code.hashCode ^ + deviceId.hashCode ^ + operationName.hashCode ^ operationalValues.hashCode; } } -class StaticFunctionOperationHelper { +class SceneOperationalValue { final String icon; final String value; - StaticFunctionOperationHelper({ + SceneOperationalValue({ required this.icon, required this.value, }); - StaticFunctionOperationHelper copyWith({ + SceneOperationalValue copyWith({ String? icon, String? value, }) { - return StaticFunctionOperationHelper( + return SceneOperationalValue( icon: icon ?? this.icon, value: value ?? this.value, ); @@ -105,8 +123,8 @@ class StaticFunctionOperationHelper { }; } - factory StaticFunctionOperationHelper.fromMap(Map map) { - return StaticFunctionOperationHelper( + factory SceneOperationalValue.fromMap(Map map) { + return SceneOperationalValue( icon: map['icon'] ?? '', value: map['value'] ?? '', ); @@ -114,8 +132,8 @@ class StaticFunctionOperationHelper { String toJson() => json.encode(toMap()); - factory StaticFunctionOperationHelper.fromJson(String source) => - StaticFunctionOperationHelper.fromMap(json.decode(source)); + factory SceneOperationalValue.fromJson(String source) => + SceneOperationalValue.fromMap(json.decode(source)); @override String toString() => @@ -125,7 +143,7 @@ class StaticFunctionOperationHelper { bool operator ==(Object other) { if (identical(this, other)) return true; - return other is StaticFunctionOperationHelper && + return other is SceneOperationalValue && other.icon == icon && other.value == value; } diff --git a/lib/features/scene/repo/scene_repo.dart b/lib/features/scene/repo/scene_repo.dart new file mode 100644 index 0000000..eaa7705 --- /dev/null +++ b/lib/features/scene/repo/scene_repo.dart @@ -0,0 +1,16 @@ +import 'package:syncrow_app/features/devices/model/device_control_model.dart'; +import 'package:syncrow_app/services/api/devices_api.dart'; + +class SceneRepo { + Future deviceControl({ + required DeviceControlModel controlModel, + required String deviceId, + }) async { + final response = await DevicesAPI.controlDevice(controlModel, deviceId); + if (response['success'] == true) { + return true; + } else { + return false; + } + } +} diff --git a/lib/features/scene/view/create_scene_view.dart b/lib/features/scene/view/create_scene_view.dart index afc8de5..7bf6db9 100644 --- a/lib/features/scene/view/create_scene_view.dart +++ b/lib/features/scene/view/create_scene_view.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; @@ -27,11 +29,14 @@ class CreateSceneView extends StatelessWidget { titleString: StringsManager.tapToRun, subtitleString: StringsManager.turnOffAllLights, ), - onTap: () => Navigator.pushNamed( - context, - Routes.sceneTasksRoute, - arguments: CreateSceneEnum.tabToRun, - ), + onTap: () { + Navigator.pushNamed( + context, + Routes.sceneTasksRoute, + arguments: CreateSceneEnum.tabToRun, + ); + context.read().tasksList.clear(); + }, ), DefaultContainer( width: double.infinity, diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index fd5fe91..541092d 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.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/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/helper/scene_helper.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/widgets/alert_dialog_countdown.dart'; @@ -10,6 +13,7 @@ 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/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -29,14 +33,22 @@ class DeviceFunctionsView extends StatelessWidget with SceneHelper { List functions = []; if (device.functions.isNotEmpty) { functions = getFunctionsWithIcons( - type: device.productType, functions: device.functions); + type: device.productType, + functions: device.functions, + deviceId: device.uuid ?? '', + deviceName: device.name ?? '', + ); } return DefaultScaffold( title: getTitle(type: device.productType), actions: [ TextButton( - onPressed: () {}, + onPressed: () { + Navigator.popUntil(context, (route) { + return route.settings.name == Routes.sceneTasksRoute; + }); + }, child: BodyMedium( text: 'Save', fontWeight: FontWeight.normal, @@ -81,38 +93,60 @@ class DeviceFunctionsView extends StatelessWidget with SceneHelper { child: Column( mainAxisSize: MainAxisSize.min, children: [ - SceneListTile( - iconsSize: 32, - minLeadingWidth: 20, - assetPath: functions[index].icon, - titleString: functions[index].name, - trailingWidget: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - /// selected value or the default value - // BodyMedium(text: ), - Icon( - Icons.arrow_forward_ios_rounded, - color: ColorsManager.greyColor, - size: 16, + BlocBuilder( + builder: (context, state) { + return SceneListTile( + iconsSize: 32, + minLeadingWidth: 20, + assetPath: functions[index].icon, + titleString: functions[index].operationName, + trailingWidget: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + /// selected value or the default value + // BodyMedium(text: ), + Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + size: 16, + ), + ], ), - ], - ), - onPressed: () { - context.customAlertDialog( - alertBody: functions[index].code == 'temp_set' - ? AlertDialogTemperatureBody( - index: index, functions: functions) - : functions[index].code.contains('countdown') - ? AlertDialogCountdown( - durationValue: functions[index] - .operationalValues - .first - .value) - : AlertDialogFunctionsOperationsBody( - index: index, functions: functions), - title: functions[index].name, - onConfirm: () {}, + onPressed: () { + context.customAlertDialog( + alertBody: functions[index].code == 'temp_set' + ? AlertDialogTemperatureBody( + index: index, functions: functions) + : functions[index].code.contains('countdown') + ? AlertDialogCountdown( + durationValue: functions[index] + .operationalValues + .first + .value) + : AlertDialogFunctionsOperationsBody( + index: index, functions: functions), + title: functions[index].operationName, + onConfirm: () { + final selectedValue = context + .read() + .selectedValue; + context + .read() + .add(AddTaskEvent( + deviceControlModel: DeviceControlModel( + deviceId: device.uuid, + code: functions[index].code, + value: selectedValue, + ), + deviceId: device.uuid ?? '', + operation: functions[index].operationName, + icon: device.icon ?? '', + deviceName: device.name ?? '', + )); + Navigator.pop(context); + }, + ); + }, ); }, ), diff --git a/lib/features/scene/view/scene_control_devices.dart b/lib/features/scene/view/scene_rooms_tabbar.dart similarity index 88% rename from lib/features/scene/view/scene_control_devices.dart rename to lib/features/scene/view/scene_rooms_tabbar.dart index 090f381..62bacde 100644 --- a/lib/features/scene/view/scene_control_devices.dart +++ b/lib/features/scene/view/scene_rooms_tabbar.dart @@ -12,15 +12,16 @@ import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; -class SceneControlDevicesView extends StatefulWidget { - const SceneControlDevicesView({super.key}); +class SceneRoomsTabBarDevicesView extends StatefulWidget { + const SceneRoomsTabBarDevicesView({super.key}); @override - State createState() => - _SceneControlDevicesViewState(); + State createState() => + _SceneRoomsTabBarDevicesViewState(); } -class _SceneControlDevicesViewState extends State +class _SceneRoomsTabBarDevicesViewState + extends State with SingleTickerProviderStateMixin { late final TabController _tabController; List? rooms = []; diff --git a/lib/features/scene/view/scene_add_tasks.dart b/lib/features/scene/view/scene_tasks_view.dart similarity index 70% rename from lib/features/scene/view/scene_add_tasks.dart rename to lib/features/scene/view/scene_tasks_view.dart index 5843323..5c8f1f2 100644 --- a/lib/features/scene/view/scene_add_tasks.dart +++ b/lib/features/scene/view/scene_tasks_view.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/widgets/if_then_containers/if_container.dart'; import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_button.dart'; @@ -12,8 +10,8 @@ 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/strings_manager.dart'; -class SceneAddTasksView extends StatelessWidget { - const SceneAddTasksView({super.key}); +class SceneTasksView extends StatelessWidget { + const SceneTasksView({super.key}); @override Widget build(BuildContext context) { @@ -36,27 +34,24 @@ class SceneAddTasksView extends StatelessWidget { ], child: Stack( children: [ - SingleChildScrollView( - child: BlocProvider( - create: (context) => CreateSceneBloc(), - child: const Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: 24, - ), - // IF - IFDefaultContainer(), - SizedBox( - height: 8, - ), - // THEN - ThenDefaultContainer(), - SizedBox( - height: 100, - ), - ], - ), + const SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 24, + ), + // IF + IFDefaultContainer(), + SizedBox( + height: 8, + ), + // THEN + ThenDefaultContainer(), + SizedBox( + height: 100, + ), + ], ), ), Positioned( diff --git a/lib/features/scene/widgets/alert_dialog_countdown.dart b/lib/features/scene/widgets/alert_dialog_countdown.dart index 6feadfa..455ae98 100644 --- a/lib/features/scene/widgets/alert_dialog_countdown.dart +++ b/lib/features/scene/widgets/alert_dialog_countdown.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; - +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; class AlertDialogCountdown extends StatefulWidget { const AlertDialogCountdown({super.key, required this.durationValue}); @@ -29,6 +30,9 @@ class _AlertDialogCountdownState extends State { setState(() { durationInSeconds = newDuration.inSeconds; }); + context + .read() + .add(SelectedValueEvent(value: newDuration.inSeconds.toString())); }, ), ); diff --git a/lib/features/scene/widgets/alert_dialog_functions_body.dart b/lib/features/scene/widgets/alert_dialog_functions_body.dart index 679060a..52fa50b 100644 --- a/lib/features/scene/widgets/alert_dialog_functions_body.dart +++ b/lib/features/scene/widgets/alert_dialog_functions_body.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; @@ -27,26 +29,38 @@ class _AlertDialogFunctionsOperationsBodyState mainAxisSize: MainAxisSize.min, children: [ ...widget.functions[widget.index].operationalValues.map( - (operation) => SceneListTile( - iconsSize: 25, - minLeadingWidth: 15, - padding: const EdgeInsets.symmetric(horizontal: 16), - assetPath: operation.icon, - titleString: operation.value, - textAlign: TextAlign.start, - trailingWidget: Radio( - value: operation.value, - groupValue: groupValue, - onChanged: (value) { - setState(() { - groupValue = value; - }); - }, - ), - onPressed: () { - setState(() { - groupValue = operation.value; - }); + (operation) => BlocBuilder( + builder: (context, state) { + return SceneListTile( + iconsSize: 25, + minLeadingWidth: 15, + padding: const EdgeInsets.symmetric(horizontal: 16), + assetPath: operation.icon, + titleString: operation.value, + textAlign: TextAlign.start, + trailingWidget: Radio( + value: operation.value, + groupValue: (state is SelectedTaskValueState) + ? state.value + : groupValue, + onChanged: (value) { + setState(() { + groupValue = value; + }); + context + .read() + .add(SelectedValueEvent(value: value!)); + }, + ), + onPressed: () { + setState(() { + groupValue = operation.value; + }); + context + .read() + .add(SelectedValueEvent(value: groupValue!)); + }, + ); }, ), ), diff --git a/lib/features/scene/widgets/alert_dialog_temperature_body.dart b/lib/features/scene/widgets/alert_dialog_temperature_body.dart index df80d43..5aeb430 100644 --- a/lib/features/scene/widgets/alert_dialog_temperature_body.dart +++ b/lib/features/scene/widgets/alert_dialog_temperature_body.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; @@ -24,7 +26,7 @@ class AlertDialogTemperatureBody extends StatefulWidget { class _AlertDialogTemperatureBodyState extends State { - double temperature = 16; + int temperature = 24; @override Widget build(BuildContext context) { return ListTile( @@ -32,8 +34,13 @@ class _AlertDialogTemperatureBodyState leading: IconButton( onPressed: () { setState(() { - temperature--; + if (temperature > 20) { + temperature--; + } }); + context + .read() + .add(SelectedValueEvent(value: temperature.toString())); }, icon: const Icon( Icons.remove, @@ -69,8 +76,13 @@ class _AlertDialogTemperatureBodyState trailing: IconButton( onPressed: () { setState(() { - temperature++; + if (temperature < 30) { + temperature++; + } }); + context + .read() + .add(SelectedValueEvent(value: temperature.toString())); }, icon: const Icon( Icons.add, diff --git a/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart new file mode 100644 index 0000000..063c3ce --- /dev/null +++ b/lib/features/scene/widgets/if_then_containers/then_added_tasks.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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'; + +class ThenAddedTasksContainer extends StatelessWidget { + const ThenAddedTasksContainer({ + super.key, + required this.taskList, + }); + + final SceneStaticFunction taskList; + + @override + Widget build(BuildContext context) { + String operationValue = ''; + if (taskList.code.contains('countdown')) { + final duration = Duration( + seconds: + int.tryParse(taskList.operationalValues.first.value.toString()) ?? + 0); + operationValue = + "${duration.inHours}h ${duration.inMinutes.remainder(60)}m "; + } else { + operationValue = taskList.operationalValues.first.value.toString(); + } + return DefaultContainer( + padding: EdgeInsets.zero, + child: Dismissible( + key: Key(taskList.uniqueCustomId.toString()), + background: Container( + padding: const EdgeInsets.only(right: 10), + alignment: AlignmentDirectional.centerEnd, + decoration: const ShapeDecoration( + color: Color(0xFFFF0000), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + bottomRight: Radius.circular(20), + ), + ), + ), + child: SvgPicture.asset( + Assets.assetsDeleteIcon, + width: 20, + height: 22, + ), + ), + direction: DismissDirection.endToStart, + onDismissed: (direction) { + String removeFunctionById = taskList.uniqueCustomId; + + context + .read() + .add(RemoveTaskEvent(taskId: removeFunctionById)); + + String removeFunction = + "${taskList.operationName} with value ${taskList.operationalValues.first.value}"; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('$removeFunction removed')), + ); + }, + child: SceneListTile( + padding: EdgeInsets.zero, + assetPath: taskList.icon, + iconsSize: 32, + titleWidget: BodyMedium( + text: taskList.deviceName, + style: context.bodyMedium.copyWith( + fontWeight: FontWeight.bold, + ), + ), + subtitleWidget: Row( + children: [ + BodyMedium( + text: "${taskList.operationName}: ", + fontColor: ColorsManager.secondaryTextColor, + fontWeight: FontWeight.normal, + ), + BodyMedium( + text: operationValue, + fontColor: ColorsManager.secondaryTextColor, + fontWeight: FontWeight.normal, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/features/scene/widgets/if_then_containers/then_container.dart b/lib/features/scene/widgets/if_then_containers/then_container.dart index fd701de..86aca2b 100644 --- a/lib/features/scene/widgets/if_then_containers/then_container.dart +++ b/lib/features/scene/widgets/if_then_containers/then_container.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; +import 'package:syncrow_app/features/scene/widgets/if_then_containers/then_added_tasks.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/scene/widgets/bottom_sheet_widget.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; @@ -48,6 +49,28 @@ class ThenDefaultContainer extends StatelessWidget { const LightDivider(), BlocBuilder( builder: (context, state) { + if (state is AddSceneTask) { + final taskLists = state.tasksList; + if (taskLists.isNotEmpty) { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: taskLists.length, + itemBuilder: (context, index) { + return ThenAddedTasksContainer( + taskList: taskLists[index], + ); + }, + ); + } + return SceneListTile( + titleString: '+ Add Task', + textAlign: TextAlign.center, + onPressed: () => context.customBottomSheet( + child: const CustomBottomSheetWidget(), + ), + ); + } return SceneListTile( titleString: '+ Add Task', textAlign: TextAlign.center, diff --git a/lib/my_app.dart b/lib/my_app.dart index 46ae999..eb399ad 100644 --- a/lib/my_app.dart +++ b/lib/my_app.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart'; +import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/navigation/navigation_service.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; @@ -19,8 +20,11 @@ class MyApp extends StatelessWidget { MediaQuery.sizeOf(context).height * Constants.appBarHeightPercentage; Constants.bottomNavBarHeight = MediaQuery.sizeOf(context).height * Constants.bottomNavBarHeightPercentage; - return BlocProvider( - create: (context) => AuthCubit(), + return MultiBlocProvider( + providers: [ + BlocProvider(create: (context) => AuthCubit()), + BlocProvider(create: (context) => CreateSceneBloc()) + ], child: MaterialApp( navigatorKey: NavigationService.navigatorKey, scaffoldMessengerKey: NavigationService.snackbarKey, diff --git a/lib/navigation/router.dart b/lib/navigation/router.dart index 2d5e3ea..cb36f6d 100644 --- a/lib/navigation/router.dart +++ b/lib/navigation/router.dart @@ -14,8 +14,8 @@ import 'package:syncrow_app/features/menu/view/widgets/profile/profile_view.dart import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart'; import 'package:syncrow_app/features/scene/view/device_functions_view.dart'; -import 'package:syncrow_app/features/scene/view/scene_add_tasks.dart'; -import 'package:syncrow_app/features/scene/view/scene_control_devices.dart'; +import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; +import 'package:syncrow_app/features/scene/view/scene_rooms_tabbar.dart'; import 'package:syncrow_app/features/scene/view/scene_view.dart'; import 'package:syncrow_app/features/splash/view/splash_view.dart'; import 'routing_constants.dart'; @@ -72,7 +72,7 @@ class Router { builder: (_) => const CreateUnitView(), settings: settings); case Routes.sceneTasksRoute: return MaterialPageRoute( - builder: (_) => const SceneAddTasksView(), settings: settings); + builder: (_) => const SceneTasksView(), settings: settings); case Routes.sceneControlDevicesRoute: return MaterialPageRoute( builder: (_) => MultiBlocProvider( @@ -87,7 +87,7 @@ class Router { ..add(const TabChanged(selectedIndex: 0, roomId: '-1')), ), ], - child: const SceneControlDevicesView(), + child: const SceneRoomsTabBarDevicesView(), ), settings: settings); case Routes.deviceFunctionsRoute: diff --git a/lib/services/api/devices_api.dart b/lib/services/api/devices_api.dart index 29eb9cd..7b53bda 100644 --- a/lib/services/api/devices_api.dart +++ b/lib/services/api/devices_api.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:syncrow_app/features/devices/model/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; -import 'package:syncrow_app/features/devices/model/functions.dart'; +import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/services/api/api_links_endpoints.dart'; import 'package:syncrow_app/services/api/http_service.dart'; @@ -57,12 +57,12 @@ class DevicesAPI { } /// Get Device Functions - static Future deviceFunctions(String deviceId) async { + static Future deviceFunctions(String deviceId) async { final response = await _httpService.get( path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { - final functions = FunctionsEntity.fromJson(json); + final functions = FunctionModel.fromJson(json); return functions; }, ); diff --git a/lib/utils/context_extension.dart b/lib/utils/context_extension.dart index 77d6a50..df6143a 100644 --- a/lib/utils/context_extension.dart +++ b/lib/utils/context_extension.dart @@ -50,7 +50,7 @@ extension ContextExtension on BuildContext { void customAlertDialog( {required Widget alertBody, required String title, - required Function()? onConfirm}) { + required VoidCallback onConfirm}) { showDialog( context: this, builder: (BuildContext context) { @@ -98,7 +98,7 @@ extension ContextExtension on BuildContext { Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - InkWell( + GestureDetector( onTap: () { Navigator.pop(context); }, @@ -115,7 +115,7 @@ extension ContextExtension on BuildContext { width: 1, color: ColorsManager.greyColor, ), - InkWell( + GestureDetector( onTap: onConfirm, child: Center( child: BodyMedium( diff --git a/pubspec.lock b/pubspec.lock index 75ce64d..8f7b6d8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -907,13 +907,13 @@ packages: source: hosted version: "3.1.1" uuid: - dependency: transitive + dependency: "direct main" description: name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "4.3.3" + version: "4.4.0" vector_graphics: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a50acf6..7e8dac3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,6 @@ name: syncrow_app -description: This is the mobile application project, developed with Flutter for Syncrow IOT Project. +description: This is the mobile application project, developed with Flutter for + Syncrow IOT Project. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: "none" # Remove this line if you wish to publish to pub.dev @@ -10,44 +11,39 @@ environment: sdk: ">=3.0.6 <4.0.0" dependencies: + cached_network_image: ^3.3.1 + cupertino_icons: ^1.0.6 + dio: ^5.4.1 + equatable: ^2.0.5 + firebase_analytics: ^10.8.7 + firebase_core: ^2.25.5 + firebase_crashlytics: ^3.4.16 + fl_chart: ^0.66.2 flutter: sdk: flutter - - #UI Packages - cupertino_icons: ^1.0.6 - shared_preferences: ^2.2.2 flutter_animated_dialog: ^2.0.1 - flutter_svg: ^2.0.10+1 - fl_chart: ^0.66.2 - sleek_circular_slider: ^2.0.1 - - # Utility Packages - flutter_secure_storage: ^9.0.0 - cached_network_image: ^3.3.1 - flutter_dotenv: ^5.1.0 - # noinspection YAMLSchemaValidation - intl: ^0.19.0 - get_it: ^7.6.7 - url_launcher: ^6.2.5 - dio: ^5.4.1 - flutter_localization: ^0.2.0 flutter_bloc: ^8.1.4 - firebase_core: ^2.25.5 - firebase_analytics: ^10.8.7 - firebase_crashlytics: ^3.4.16 - smooth_page_indicator: ^1.1.0 + flutter_dotenv: ^5.1.0 + flutter_localization: ^0.2.0 + flutter_secure_storage: ^9.0.0 + flutter_svg: ^2.0.10+1 + get_it: ^7.6.7 html: ^0.15.4 - equatable: ^2.0.5 + intl: ^0.19.0 onesignal_flutter: ^5.2.0 permission_handler: ^11.3.1 pin_code_fields: ^8.0.1 share_plus: ^9.0.0 - + shared_preferences: ^2.2.2 + sleek_circular_slider: ^2.0.1 + smooth_page_indicator: ^1.1.0 + url_launcher: ^6.2.5 + uuid: ^4.4.0 dev_dependencies: + flutter_lints: ^3.0.1 flutter_test: sdk: flutter - flutter_lints: ^3.0.1 flutter_assets: assets_path: assets/ @@ -78,7 +74,6 @@ flutter: - family: Aftika fonts: - asset: assets/fonts/AftikaRegular.ttf - # # - family: Trajan Pro # fonts: # - asset: fonts/TrajanPro.ttf