Added latest changes from dev and solved conflicts

This commit is contained in:
Abdullah Alassaf
2024-06-30 16:27:42 +03:00
94 changed files with 4674 additions and 1442 deletions
+45 -51
View File
@@ -1,5 +1,4 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
@@ -22,6 +21,7 @@ import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
import 'package:syncrow_app/features/scene/view/scene_view.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
@@ -63,12 +63,9 @@ class HomeCubit extends Cubit<HomeState> {
selectedSpace = null;
selectedRoom = null;
pageIndex = 0;
OneSignal.User.pushSubscription
.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
OneSignal.Notifications.removePermissionObserver(
(permission) => oneSignalPermissionObserver);
OneSignal.Notifications.removeClickListener(
(event) => oneSignalClickListenerObserver);
OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
return super.close();
}
@@ -110,9 +107,7 @@ class HomeCubit extends Cubit<HomeState> {
return;
}
var userUuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
'';
var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
if (userUuid.isNotEmpty) {
await OneSignal.login(userUuid);
}
@@ -120,24 +115,21 @@ class HomeCubit extends Cubit<HomeState> {
await OneSignal.User.pushSubscription.optIn();
//this function will be called once a user is subscribed
oneSignalSubscriptionObserver =
OneSignal.User.pushSubscription.addObserver((state) async {
oneSignalSubscriptionObserver = OneSignal.User.pushSubscription.addObserver((state) async {
if (state.current.optedIn) {
await _sendSubscriptionId();
}
});
// Send the player id when a user allows notifications
oneSignalPermissionObserver =
OneSignal.Notifications.addPermissionObserver((state) async {
oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async {
await _sendSubscriptionId();
});
//check if the player id is sent, if not send it again
await _sendSubscriptionId();
oneSignalClickListenerObserver =
OneSignal.Notifications.addClickListener((event) async {
oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
//Once the user clicks on the notification
});
} catch (err) {
@@ -224,9 +216,7 @@ class HomeCubit extends Cubit<HomeState> {
Future<bool> joinAUnit(String code) async {
try {
var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
'';
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
Map<String, String> body = {'userUuid': uuid, 'inviteCode': code};
final success = await SpacesAPI.joinUnit(body);
@@ -280,30 +270,29 @@ class HomeCubit extends Cubit<HomeState> {
static Map<String, List<Widget>> appBarActions = {
'Dashboard': [
IconButton(
icon: const Icon(
Icons.add,
size: 25,
),
style: ButtonStyle(
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
Navigator.push(
NavigationService.navigatorKey.currentContext!,
CustomPageRoute(
builder: (context) => CurtainView(
curtain: DeviceModel(
name: "Curtain",
status: [StatusModel(code: "awd", value: 1)],
productType: DeviceType.Curtain,
),
),
),
);
},
),
// IconButton(
// icon: const Icon(
// Icons.add,
// size: 25,
// ),
// style: ButtonStyle(
// foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
// ),
// onPressed: () {
// Navigator.push(
// NavigationService.navigatorKey.currentContext!,
// CustomPageRoute(
// builder: (context) => CurtainView(
// curtain: DeviceModel(
// name: "Curtain",
// status: [StatusModel(code: "awd", value: 1)],
// productType: DeviceType.Curtain,
// ),
// ),
// ),
// );
// },
// ),
],
'Devices': [
//TODO: to be checked
@@ -345,8 +334,7 @@ class HomeCubit extends Cubit<HomeState> {
size: 32,
),
style: ButtonStyle(
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
Navigator.push(
@@ -363,8 +351,7 @@ class HomeCubit extends Cubit<HomeState> {
size: 28,
),
style: ButtonStyle(
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
@@ -397,8 +384,7 @@ class HomeCubit extends Cubit<HomeState> {
};
static var bottomNavItems = [
defaultBottomNavBarItem(
icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
@@ -421,10 +407,18 @@ class HomeCubit extends Cubit<HomeState> {
emitSafe(NavChangePage());
}
void updateDevice(String deviceId) async {
try {
final response = await DevicesAPI.firmwareDevice(deviceId: deviceId, firmwareVersion: '0');
if (response['success'] ?? false) {
CustomSnackBar.displaySnackBar('No updates available');
}
} catch (_) {}
}
}
BottomNavigationBarItem defaultBottomNavBarItem(
{required String icon, required String label}) {
BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
return BottomNavigationBarItem(
icon: SvgPicture.asset(icon),
activeIcon: SvgPicture.asset(
+45 -18
View File
@@ -8,7 +8,9 @@ import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/services/api/authentication_api.dart';
import 'package:syncrow_app/utils/helpers/shared_preferences_helper.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
part 'auth_state.dart';
class AuthCubit extends Cubit<AuthState> {
@@ -20,16 +22,19 @@ class AuthCubit extends Cubit<AuthState> {
String fullName = '';
String email = '';
String forgetPasswordEmail = '';
String signUpPassword = '';
String newPassword = '';
String maskedEmail = '';
String otpCode = '';
final loginFormKey = GlobalKey<FormState>();
final signUpFormKey = GlobalKey<FormState>();
final checkEmailFormKey = GlobalKey<FormState>();
final createNewPasswordKey = GlobalKey<FormState>();
bool isPasswordVisible = false;
bool showValidationMessage = false;
static GlobalKey<FormState> formKey = GlobalKey<FormState>();
void changePasswordVisibility() {
isPasswordVisible = !isPasswordVisible;
emit(AuthPasswordVisibilityChanged());
@@ -96,9 +101,15 @@ class AuthCubit extends Cubit<AuthState> {
String? reEnterPasswordCheck(String? value) {
passwordValidator(value);
if (signUpPassword == value) {
// if (signUpFormKey.currentState != null) {
// signUpFormKey.currentState!.save();
// }
return null;
} else {
return 'Passwords do not match';
}
}
String? reEnterPasswordCheckForgetPass(String? value) {
passwordValidator(value);
if (newPassword == value) {
return null;
} else {
return 'Passwords do not match';
@@ -226,26 +237,23 @@ class AuthCubit extends Cubit<AuthState> {
}
}
verifyOtp() async {
verifyOtp(bool isForgotPass) async {
emit(AuthLoginLoading());
try {
final response = await AuthenticationAPI.verifyPassCode(
body: {'email': email, 'type': 'VERIFICATION', 'otpCode': otpCode});
if (response['statusCode'] == 200) {
emailController.text = email;
passwordController.text = signUpPassword;
await login();
if (!isForgotPass) {
emailController.text = email;
passwordController.text = signUpPassword;
await login();
}
emit(AuthOtpSuccess());
} else {
emit(AuthLoginError(message: 'Something went wrong'));
}
// if (otpCode == '654321') {
// emit(AuthOtpSuccess());
// } else {
// emit(AuthLoginError(message: 'Otp is not correct'));
// }
} catch (failure) {
emit(AuthLoginError(message: failure.toString()));
emit(AuthLoginError(message: 'Something went wrong'));
return;
}
}
@@ -260,16 +268,25 @@ class AuthCubit extends Cubit<AuthState> {
(Route route) => false,
);
} catch (failure) {
emit(AuthLogoutError(message: failure.toString()));
emit(AuthLogoutError(message: 'Something went wrong'));
return;
}
}
getTokenAndValidate() async {
emit(AuthTokenLoading());
final value = await const FlutterSecureStorage().read(key: Token.loginAccessTokenKey);
const storage = FlutterSecureStorage();
final firstLaunch =
await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
if (value == null || value.isEmpty) {
if (firstLaunch) {
storage.deleteAll();
}
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
if (value.isEmpty) {
emit(AuthTokenError(message: "Token not found"));
return;
}
@@ -289,4 +306,14 @@ class AuthCubit extends Cubit<AuthState> {
emit(AuthTokenError(message: "Something went wrong"));
}
}
sendToForgetPassword({required String password}) async {
try {
emit(AuthForgetPassLoading());
await AuthenticationAPI.forgetPassword(email: email, password: password);
emit(AuthForgetPassSuccess());
} catch (_) {
emit(AuthForgetPassError(message: 'Something went wrong'));
}
}
}
+13
View File
@@ -51,3 +51,16 @@ class AuthTokenSuccess extends AuthSuccess {}
class AuthTokenError extends AuthError {
AuthTokenError({required super.message, super.code});
}
//ForgetPassword log states
class AuthForgetPassLoading extends AuthLoading {}
class AuthForgetPassSuccess extends AuthSuccess {}
class AuthForgetPassError extends AuthError {
AuthForgetPassError({required super.message, super.code});
}
@@ -0,0 +1,202 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/auth/view/otp_view.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:syncrow_app/utils/resource_manager/styles_manager.dart';
class checkEmailPage extends StatelessWidget {
const checkEmailPage({super.key});
@override
Widget build(BuildContext context) {
final formKey = AuthCubit.get(context).checkEmailFormKey;
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarBrightness: Brightness.light, statusBarIconBrightness: Brightness.light));
return BlocConsumer<AuthCubit, AuthState>(
listener: (context, state) {
if (state is AuthError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.message),
),
);
} else if (state is AuthSignUpSuccess) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const OtpView(
isForgetPage: true,
),
));
}
},
builder: (context, state) {
return Scaffold(
body: Stack(
children: [
Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
),
),
),
Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Assets.assetsImagesVector),
fit: BoxFit.cover,
opacity: 0.9,
),
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.only(
right: Constants.defaultPadding,
left: Constants.defaultPadding,
top: Constants.defaultPadding,
),
child: Form(
key: formKey,
child: SingleChildScrollView(
child: Center(
child: Column(
children: [
Center(
child: SvgPicture.asset(
Assets.assetsImagesLogo,
width: 160,
),
),
Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: MediaQuery.sizeOf(context).height / 5.5,
),
TitleMedium(
text: 'Forgot password?',
style: context.titleMedium.copyWith(
fontWeight: FontsManager.extraBold,
color: Colors.white,
),
),
const SizedBox(
height: 20,
),
const BodyMedium(
text: "Enter email address",
fontColor: Colors.white,
),
TextFormField(
textInputAction: TextInputAction.done,
keyboardType: TextInputType.text,
scrollPadding: EdgeInsets.zero,
autocorrect: false,
enableSuggestions: false,
autofillHints: const [AutofillHints.email],
validator: AuthCubit.get(context).emailAddressValidator,
onTapOutside: (event) {
FocusScope.of(context).unfocus();
},
onChanged: (value) {
AuthCubit.get(context).email = value;
},
decoration: defaultInputDecoration(context,
hint: "[email protected]"),
),
const SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: DefaultButton(
isDone: state is AuthLoginSuccess,
isLoading: state is AuthLoading,
customButtonStyle: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.black.withOpacity(.25),
),
foregroundColor: MaterialStateProperty.all(
Colors.white,
),
),
child: const Text(
'Send Code',
),
onPressed: () {
AuthCubit.get(context).showValidationMessage = true;
if (formKey.currentState!.validate()) {
if ((state is! AuthLoading)) {
AuthCubit.get(context).sendOtp();
FocusScope.of(context).unfocus();
}
}
},
),
),
],
),
Padding(
padding: EdgeInsets.only(
top: MediaQuery.sizeOf(context).height / 5.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
BodyLarge(
text: "Do you have an account? ",
style:
context.displaySmall.copyWith(color: Colors.white),
),
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: BodyLarge(
text: "Sign in",
style: context.displaySmall.copyWith(
color: Colors.black,
fontWeight: FontsManager.bold,
),
),
),
],
),
),
],
),
),
],
),
),
),
)),
)
],
),
);
},
);
}
}
@@ -0,0 +1,186 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_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/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:syncrow_app/utils/resource_manager/styles_manager.dart';
class CreateNewPasswordPage extends StatelessWidget {
const CreateNewPasswordPage({super.key,});
@override
Widget build(BuildContext context) {
final formKey = AuthCubit.get(context).createNewPasswordKey;
return BlocConsumer<AuthCubit, AuthState>(
listener: (context, state) {
if (state is AuthForgetPassSuccess) {
Navigator.of(context).pop();
}
},
builder: (context, state) {
return Scaffold(
body: Stack(
children: [
Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.symmetric(vertical: 24),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
),
),
),
Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Assets.assetsImagesVector),
fit: BoxFit.cover,
opacity: 0.9,
),
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.only(
right: Constants.defaultPadding,
left: Constants.defaultPadding,
top: Constants.defaultPadding,
),
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: SvgPicture.asset(
Assets.assetsImagesLogo,
width: 160,
),
),
const SizedBox(
height: 40,
),
TitleMedium(
text: 'Create new password',
style: context.titleMedium.copyWith(
fontWeight: FontsManager.extraBold,
color: Colors.white,
),
),
const SizedBox(
height: 20,
),
Form(
key: formKey,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 16),
const BodyMedium(
text: "Password",
fontColor: Colors.white,
),
TextFormField(
textInputAction: TextInputAction.done,
keyboardType: TextInputType.text,
scrollPadding: EdgeInsets.zero,
autocorrect: false,
autofillHints: const [AutofillHints.password],
validator: AuthCubit.get(context).passwordValidator,
onChanged: (value) {
AuthCubit.get(context).newPassword = value;
},
onTapOutside: (event) {
FocusScope.of(context).unfocus();
},
obscureText: !AuthCubit.get(context).isPasswordVisible,
decoration: defaultInputDecoration(context,
hint: "At least 8 characters"),
),
const SizedBox(height: 16),
const BodyMedium(
text: "Re-enter Password",
fontColor: Colors.white,
),
TextFormField(
autovalidateMode: AutovalidateMode.disabled,
textInputAction: TextInputAction.done,
keyboardType: TextInputType.text,
scrollPadding: EdgeInsets.zero,
autocorrect: false,
enableSuggestions: false,
autofillHints: const [AutofillHints.password],
onChanged: (value) {},
validator: AuthCubit.get(context).reEnterPasswordCheckForgetPass,
onTapOutside: (event) {
FocusScope.of(context).unfocus();
},
obscureText: !AuthCubit.get(context).isPasswordVisible,
decoration: defaultInputDecoration(context,
hint: "At least 8 characters"),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: DefaultButton(
isDone: state is AuthLoginSuccess,
isLoading: state is AuthLoading,
customButtonStyle: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.black.withOpacity(.25),
),
foregroundColor: MaterialStateProperty.all(
Colors.white,
),
),
child: const Text(
'Confirm',
),
onPressed: () {
AuthCubit.get(context).showValidationMessage = true;
if (formKey.currentState!.validate()) {
if ((state is! AuthForgetPassLoading)) {
AuthCubit.get(context).sendToForgetPassword(password:AuthCubit.get(context).newPassword);
FocusScope.of(context).unfocus();
}
}
},
),
),
],
)
],
),
),
),
],
),
),
),
),
)
],
),
);
},
);
}
}
+2 -1
View File
@@ -31,7 +31,8 @@ class LoginView extends StatelessWidget {
// content: Text(state.message),
// ),
// );
} else if (state is AuthLoginSuccess) {
}
else if (state is AuthLoginSuccess) {
Navigator.popAndPushNamed(context, Routes.homeRoute);
}
},
+12 -5
View File
@@ -6,6 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
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/view/create_new_password.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
@@ -17,7 +18,8 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class OtpView extends StatefulWidget {
const OtpView({super.key});
final bool isForgetPage;
const OtpView({super.key, this.isForgetPage = false});
@override
State<OtpView> createState() => _OtpViewState();
@@ -119,7 +121,13 @@ class _OtpViewState extends State<OtpView> {
if (state is AuthOtpSuccess) {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.popAndPushNamed(context, Routes.homeRoute);
widget.isForgetPage
? Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CreateNewPasswordPage(),
))
: Navigator.popAndPushNamed(context, Routes.homeRoute);
}
if (state is ResendOtpSuccess) {
startTimer(30);
@@ -190,8 +198,7 @@ class _OtpViewState extends State<OtpView> {
},
child: RichText(
text: TextSpan(
text:
'We have sent the verification codeWe have sent the verification code to',
text: 'We have sent the verification code to',
style: Theme.of(context).textTheme.titleSmall!.copyWith(
color: Colors.white,
fontWeight: FontsManager.regular,
@@ -300,7 +307,7 @@ class _OtpViewState extends State<OtpView> {
),
onPressed: () {
if ((state is! AuthLoading)) {
AuthCubit.get(context).verifyOtp();
AuthCubit.get(context).verifyOtp(widget.isForgetPage);
FocusScope.of(context).unfocus();
}
},
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/auth/view/check_email_page.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';
class ForgetPassword extends StatelessWidget {
@@ -15,7 +15,7 @@ class ForgetPassword extends StatelessWidget {
const Spacer(),
TextButton(
onPressed: () {
Navigator.popAndPushNamed(context, Routes.otpRoute);
Navigator.push(context, MaterialPageRoute(builder: (context) => const checkEmailPage(),));
},
child: BodyMedium(
text: "Forgot Password?",
@@ -85,10 +85,10 @@ class LoginForm extends StatelessWidget {
isDone: state is AuthLoginSuccess,
isLoading: state is AuthLoading,
customButtonStyle: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
backgroundColor: WidgetStateProperty.all(
Colors.black.withOpacity(.25),
),
foregroundColor: MaterialStateProperty.all(
foregroundColor: WidgetStateProperty.all(
Colors.white,
),
),
+180 -17
View File
@@ -1,4 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
@@ -10,34 +11,165 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
class ACsBloc extends Bloc<AcsEvent, AcsState> {
final String acId;
late DeviceModel deviceModel;
late AcStatusModel deviceStatus;
AcStatusModel deviceStatus = AcStatusModel(
acSwitch: true,
modeString: 'hot',
tempSet: 300,
currentTemp: 315,
fanSpeedsString: 'low',
childLock: false);
List<AcStatusModel> deviceStatusList = [];
List<DeviceModel> devicesList = [];
bool allAcsPage = false;
bool allAcsOn = true;
bool allTempSame = true;
int globalTemp = 25;
ACsBloc({required this.acId}) : super(AcsInitialState()) {
on<AcsInitial>(_fetchAcsStatus);
on<AcSwitch>(_changeAcSwitch);
on<IncreaseCoolToTemp>(_increaseCoolTo);
on<DecreaseCoolToTemp>(_decreaseCoolTo);
on<ChangeLock>(_changeLockValue);
on<ChangeAcMode>(_changeAcMode);
on<ChangeFanSpeed>(_changeFanSpeed);
on<ChangeAllSwitch>(_changeAllAcSwitch);
on<IncreaseAllTemp>(_increaseAllTemp);
on<DecreaseAllTemp>(_decreaseAllTemp);
}
void _fetchAcsStatus(AcsInitial event, Emitter<AcsState> emit) async {
emit(AcsLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(acId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
allAcsPage = event.allAcs;
if (event.allAcs) {
await _getAllAcs();
emit(GetAllAcsStatusState(
allAcsStatues: deviceStatusList,
allAcs: devicesList,
allOn: allAcsOn,
allTempSame: allTempSame,
temp: globalTemp));
} else {
var response = await DevicesAPI.getDeviceStatus(acId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = AcStatusModel.fromJson(statusModelList);
emit(GetAcStatusState(acStatusModel: deviceStatus));
}
deviceStatus = AcStatusModel.fromJson(statusModelList);
emit(GetAcStatusState(acStatusModel: deviceStatus));
} catch (e) {
emit(AcsFailedState(error: e.toString()));
return;
}
}
_getAllAcs() async {
deviceStatusList = [];
devicesList = [];
allAcsOn = true;
allTempSame = true;
devicesList = await DevicesAPI.getDeviceByGroupName(
HomeCubit.getInstance().selectedSpace?.id ?? '', 'AC');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatusList.add(AcStatusModel.fromJson(statusModelList));
}
if (deviceStatusList.isNotEmpty) {
int temp = deviceStatusList[0].tempSet;
deviceStatusList.firstWhere((element) {
if (!element.acSwitch) {
allAcsOn = false;
}
if (element.tempSet != temp) {
allTempSame = false;
}
return true;
});
if (allTempSame) {
globalTemp = temp;
}
}
}
void _changeAcSwitch(AcSwitch event, Emitter<AcsState> emit) async {
emit(AcChangeLoading(acStatusModel: deviceStatus));
final acSwitchValue = !event.acSwitch;
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: allAcsPage ? event.deviceId : acId, code: 'switch', value: acSwitchValue),
allAcsPage ? event.deviceId : acId);
if (response['success'] ?? false) {
deviceStatus.acSwitch = acSwitchValue;
}
} catch (_) {}
if (allAcsPage) {
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
} else {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
}
void _changeAllAcSwitch(ChangeAllSwitch event, Emitter<AcsState> emit) async {
emit(AcsLoadingState());
try {
if (deviceStatusList.length == devicesList.length) {
for (int i = 0; i < deviceStatusList.length; i++) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: devicesList[i].uuid, code: 'switch', value: event.value),
devicesList[i].uuid ?? '');
}
}
} catch (_) {}
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
}
void _increaseAllTemp(IncreaseAllTemp event, Emitter<AcsState> emit) async {
emit(AcsLoadingState());
try {
double tempValue = event.value + 0.5;
int value = (tempValue * 10).toInt();
if (deviceStatusList.length == devicesList.length) {
for (int i = 0; i < deviceStatusList.length; i++) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: devicesList[i].uuid, code: 'temp_set', value: value),
devicesList[i].uuid ?? '');
}
}
} catch (_) {}
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
}
void _decreaseAllTemp(DecreaseAllTemp event, Emitter<AcsState> emit) async {
emit(AcsLoadingState());
try {
double tempValue = event.value - 0.5;
int value = (tempValue * 10).toInt();
if (deviceStatusList.length == devicesList.length) {
for (int i = 0; i < deviceStatusList.length; i++) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: devicesList[i].uuid, code: 'temp_set', value: value),
devicesList[i].uuid ?? '');
}
}
} catch (_) {}
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
}
void _changeLockValue(ChangeLock event, Emitter<AcsState> emit) async {
emit(AcChangeLoading(acStatusModel: deviceStatus));
@@ -59,13 +191,20 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
int value = (tempValue * 10).toInt();
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: acId, code: 'temp_set', value: value), acId);
DeviceControlModel(
deviceId: allAcsPage ? event.deviceId : acId, code: 'temp_set', value: value),
allAcsPage ? event.deviceId : acId);
if (response['success'] ?? false) {
deviceStatus.tempSet = value;
}
} catch (_) {}
emit(AcModifyingState(acStatusModel: deviceStatus));
if (allAcsPage) {
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
} else {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
}
void _decreaseCoolTo(DecreaseCoolToTemp event, Emitter<AcsState> emit) async {
@@ -75,13 +214,20 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
int value = (tempValue * 10).toInt();
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: acId, code: 'temp_set', value: value), acId);
DeviceControlModel(
deviceId: allAcsPage ? event.deviceId : acId, code: 'temp_set', value: value),
allAcsPage ? event.deviceId : acId);
if (response['success'] ?? false) {
deviceStatus.tempSet = value;
}
} catch (_) {}
emit(AcModifyingState(acStatusModel: deviceStatus));
if (allAcsPage) {
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
} else {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
}
void _changeAcMode(ChangeAcMode event, Emitter<AcsState> emit) async {
@@ -89,14 +235,23 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
final tempMode = tempModesMap[getNextItem(tempModesMap, event.tempModes)]!;
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: acId, code: 'mode', value: getACModeString(tempMode)), acId);
DeviceControlModel(
deviceId: allAcsPage ? event.deviceId : acId,
code: 'mode',
value: getACModeString(tempMode)),
allAcsPage ? event.deviceId : acId);
if (response['success'] ?? false) {
deviceStatus.modeString = getACModeString(tempMode);
deviceStatus.acMode = AcStatusModel.getACMode(getACModeString(tempMode));
}
} catch (_) {}
emit(AcModifyingState(acStatusModel: deviceStatus));
if (allAcsPage) {
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
} else {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
}
void _changeFanSpeed(ChangeFanSpeed event, Emitter<AcsState> emit) async {
@@ -104,8 +259,11 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
final fanSpeed = event.fanSpeeds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: acId, code: 'level', value: getNextFanSpeedKey(fanSpeed)),
acId);
DeviceControlModel(
deviceId: allAcsPage ? event.deviceId : acId,
code: 'level',
value: getNextFanSpeedKey(fanSpeed)),
allAcsPage ? event.deviceId : acId);
try {
if (response['success'] ?? false) {
@@ -113,7 +271,12 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
deviceStatus.acFanSpeed = AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed));
}
} catch (_) {}
emit(AcModifyingState(acStatusModel: deviceStatus));
if (allAcsPage) {
await Future.delayed(const Duration(seconds: 1));
add(const AcsInitial(allAcs: true));
} else {
emit(AcModifyingState(acStatusModel: deviceStatus));
}
}
String getACModeString(TempModes value) {
@@ -10,40 +10,58 @@ abstract class AcsEvent extends Equatable {
class AcsLoading extends AcsEvent {}
class AcsInitial extends AcsEvent {}
class AcSwitch extends AcsEvent {
final bool acSwitch;
final String deviceId;
const AcSwitch({required this.acSwitch, this.deviceId = ''});
@override
List<Object> get props => [acSwitch, deviceId];
}
class AcsInitial extends AcsEvent {
final bool allAcs;
const AcsInitial({required this.allAcs});
@override
List<Object> get props => [allAcs];
}
class ACsChangeStatus extends AcsEvent {}
class IncreaseCoolToTemp extends AcsEvent {
final double value;
const IncreaseCoolToTemp({required this.value});
final String deviceId;
const IncreaseCoolToTemp({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value];
List<Object> get props => [value, deviceId];
}
class DecreaseCoolToTemp extends AcsEvent {
final double value;
const DecreaseCoolToTemp({required this.value});
final String deviceId;
const DecreaseCoolToTemp({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value];
List<Object> get props => [value, deviceId];
}
class ChangeAcMode extends AcsEvent {
final TempModes tempModes;
const ChangeAcMode({required this.tempModes});
final String deviceId;
const ChangeAcMode({required this.tempModes, this.deviceId = ''});
@override
List<Object> get props => [tempModes];
List<Object> get props => [tempModes, deviceId];
}
class ChangeFanSpeed extends AcsEvent {
final FanSpeeds fanSpeeds;
const ChangeFanSpeed({required this.fanSpeeds});
final String deviceId;
const ChangeFanSpeed({required this.fanSpeeds, this.deviceId = ''});
@override
List<Object> get props => [fanSpeeds];
List<Object> get props => [fanSpeeds, deviceId];
}
class ChangeLock extends AcsEvent {
@@ -53,3 +71,27 @@ class ChangeLock extends AcsEvent {
@override
List<Object> get props => [lockBool];
}
class ChangeAllSwitch extends AcsEvent {
final bool value;
const ChangeAllSwitch({required this.value});
@override
List<Object> get props => [value];
}
class IncreaseAllTemp extends AcsEvent {
final double value;
const IncreaseAllTemp({required this.value});
@override
List<Object> get props => [value];
}
class DecreaseAllTemp extends AcsEvent {
final double value;
const DecreaseAllTemp({required this.value});
@override
List<Object> get props => [value];
}
@@ -1,5 +1,6 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
abstract class AcsState extends Equatable {
const AcsState();
@@ -36,6 +37,24 @@ class GetAcStatusState extends AcsState {
List<Object> get props => [acStatusModel];
}
class GetAllAcsStatusState extends AcsState {
final List<AcStatusModel> allAcsStatues;
final List<DeviceModel> allAcs;
final bool allOn;
final bool allTempSame;
final int temp;
const GetAllAcsStatusState(
{required this.allAcsStatues,
required this.allAcs,
required this.allOn,
required this.allTempSame,
required this.temp});
@override
List<Object> get props => [allAcsStatues, allAcs, allAcs, allTempSame, temp];
}
class AcsFailedState extends AcsState {
final String error;
+9 -14
View File
@@ -30,6 +30,7 @@ class DevicesCubit extends Cubit<DevicesState> {
for (var room in HomeCubit.getInstance().selectedSpace!.rooms!) {
fetchDevicesByRoomId(room.id!);
}
fetchGroups(HomeCubit.getInstance().selectedSpace?.id ?? '');
}
}
@@ -53,7 +54,7 @@ class DevicesCubit extends Cubit<DevicesState> {
static DevicesCubit get(context) => BlocProvider.of(context);
static List<DevicesCategoryModel>? allCategories;
List<DevicesCategoryModel>? allCategories;
selectCategory(int index) {
for (var i = 0; i < allCategories!.length; i++) {
@@ -88,8 +89,8 @@ class DevicesCubit extends Cubit<DevicesState> {
return const CurtainListView();
// case DeviceType.ThreeGang:
// return const ThreeGangSwitchesView();
case DeviceType.Gateway:
return const GateWayView();
// case DeviceType.Gateway:
// return const GateWayView();
default:
return null;
}
@@ -306,10 +307,8 @@ class DevicesCubit extends Cubit<DevicesState> {
if (roomId == null) return;
emitSafe(GetDevicesLoading());
int roomIndex = HomeCubit.getInstance()
.selectedSpace!
.rooms!
.indexWhere((element) => element.id == roomId);
int roomIndex =
HomeCubit.getInstance().selectedSpace!.rooms!.indexWhere((element) => element.id == roomId);
try {
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices =
await DevicesAPI.getDevicesByRoomId(roomId);
@@ -317,8 +316,7 @@ class DevicesCubit extends Cubit<DevicesState> {
emitSafe(GetDevicesError(e.toString()));
return;
}
final devices =
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices;
final devices = HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices;
emitSafe(GetDevicesSuccess(devices));
//get status for each device
@@ -348,11 +346,8 @@ class DevicesCubit extends Cubit<DevicesState> {
emitSafe(GetDeviceStatusError(e.toString()));
return;
}
HomeCubit.getInstance()
.selectedSpace!
.rooms![roomIndex]
.devices![deviceIndex]
.status = statuses;
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices![deviceIndex].status =
statuses;
emitSafe(GetDeviceStatusSuccess(code: code));
}
@@ -0,0 +1,23 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_event.dart';
import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
class GatewayBloc extends Bloc<GatewayEvent, GatewayState> {
GatewayBloc() : super(GatewayInitialState()) {
on<GatewayInitial>(_fetchDevices);
}
void _fetchDevices(GatewayInitial event, Emitter<GatewayState> emit) async {
emit(GatewayLoadingState());
try {
List<DeviceModel> devicesList = await DevicesAPI.getDevicesByGatewayId(event.gatewayId);
emit(UpdateGatewayState(list: devicesList));
} catch (e) {
emit(ErrorState(message: e.toString()));
return;
}
}
}
@@ -0,0 +1,20 @@
import 'package:equatable/equatable.dart';
abstract class GatewayEvent extends Equatable {
const GatewayEvent();
@override
List<Object> get props => [];
}
class GatewayInitial extends GatewayEvent {
final String gatewayId;
const GatewayInitial({required this.gatewayId});
@override
List<Object> get props => [gatewayId];
}
class GatewayLoading extends GatewayEvent {}
class GatewayUpdateState extends GatewayEvent {}
@@ -0,0 +1,29 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
abstract class GatewayState extends Equatable {
const GatewayState();
@override
List<Object> get props => [];
}
class GatewayInitialState extends GatewayState {}
class GatewayLoadingState extends GatewayState {}
class UpdateGatewayState extends GatewayState {
final List<DeviceModel> list;
const UpdateGatewayState({required this.list});
@override
List<Object> get props => [list];
}
class ErrorState extends GatewayState {
final String message;
const ErrorState({required this.message});
@override
List<Object> get props => [message];
}
@@ -1,23 +1,39 @@
import 'dart:math';
import 'package:day_picker/model/day_in_week.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/model/create_temporary_password_model.dart';
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
final String deviceId;
late SmartDoorModel deviceStatus;
static String pageType = '';
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
on<InitialEvent>(_fetchSmartDoorStatus);
on<InitialPasswordsPage>(getTemporaryPasswords);
on<UpdateLockEvent>(_updateLock);
on<SavePasswordEvent>(savePassword);
on<ToggleRepeatEvent>(toggleRepeat);
on<SetStartEndTimeEvent>(setStartEndTime);
on<ChangeTimeEvent>(changeTime);
on<GeneratePasswordEvent>(generate7DigitNumber);
on<SelectTimeEvent>(selectTime);
on<DeletePasswordEvent>(deletePassword);
}
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingInitialState());
void _fetchSmartDoorStatus(
InitialEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getDeviceStatus(deviceId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
@@ -31,11 +47,76 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
void getTemporaryPasswords(
InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
pageType = event.type!;
var response = await DevicesAPI.getTemporaryPasswords(deviceId, pageType);
if (response is List) {
temporaryPasswords =
response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords = (response['data'] as List)
.map((item) => TemporaryPassword.fromJson(item))
.toList();
} else {
throw Exception("Unexpected response format");
}
emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
}
TextEditingController passwordController = TextEditingController();
TextEditingController passwordNameController = TextEditingController();
String effectiveTime = 'Select Time';
int? effectiveTimeTimeStamp;
String expirationTime = 'Select Time';
int? expirationTimeTimeStamp;
bool repeat = false;
bool isStartEndTime = true;
List<String>? selectedDay;
DateTime? startTime;
DateTime? endTime;
List<TemporaryPassword>? temporaryPasswords = [];
List<TemporaryPassword>? oneTimePasswords = [];
changeTime(ChangeTimeEvent event, Emitter<SmartDoorState> emit) {
emit(LoadingInitialState());
if (event.isStartEndTime == true) {
startTime = event.val;
} else {
endTime = event.val;
}
emit(changeTimeState());
}
bool toggleRepeat(ToggleRepeatEvent event, Emitter<SmartDoorState> emit) {
emit(LoadingInitialState());
repeat = !repeat;
emit(IsRepeatState());
return repeat;
}
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
emit(LoadingInitialState());
isStartEndTime = event.val;
emit(IsStartEndState());
return isStartEndTime;
}
void _updateLock(UpdateLockEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingNewSate(smartDoorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
DeviceControlModel(
deviceId: deviceId,
code: 'normal_open_switch',
value: !event.value),
deviceId);
if (response['success'] ?? false) {
@@ -44,4 +125,146 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
} catch (_) {}
emit(UpdateState(smartDoorModel: deviceStatus));
}
void generate7DigitNumber(GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingInitialState());
passwordController.clear();
Random random = Random();
int min = 1000000;
int max = 9999999;
passwordController.text = (min + random.nextInt(max - min + 1)).toString();
emit(GeneratePasswordState());
}
Future<void> selectTime(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
final DateTime? picked = await showDatePicker(
context: event.context,
initialDate: DateTime.now(),
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101),
);
if (picked != null) {
final TimeOfDay? timePicked = await showTimePicker(
context: event.context,
initialTime: TimeOfDay.now(),
);
if (timePicked != null) {
final selectedDateTime = DateTime(
picked.year,
picked.month,
picked.day,
timePicked.hour,
timePicked.minute,
);
if (event.isEffective) {
if (expirationTimeTimeStamp != null &&
selectedDateTime.millisecondsSinceEpoch >
expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
} else {
effectiveTime = selectedDateTime.toString();
effectiveTimeTimeStamp = selectedDateTime.millisecondsSinceEpoch;
}
} else {
if (effectiveTimeTimeStamp != null &&
selectedDateTime.millisecondsSinceEpoch <
effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
} else {
expirationTime = selectedDateTime.toString();
expirationTimeTimeStamp = selectedDateTime.millisecondsSinceEpoch;
}
}
emit(TimeSelectedState());
}
}
}
Future<void> savePassword(SavePasswordEvent event, Emitter<SmartDoorState> emit) async {
if (_validateInputs()) return;
try {
emit(LoadingSaveState());
var res = await DevicesAPI.createPassword(
pageType: pageType,
deviceId: deviceId,
effectiveTime: effectiveTimeTimeStamp.toString(),
invalidTime: expirationTimeTimeStamp.toString(),
name: passwordNameController.text,
password: passwordController.text,
scheduleList: [
if (repeat)
Schedule(
effectiveTime: getTimeOnly(startTime),
invalidTime: getTimeOnly(endTime).toString(),
workingDay: selectedDay!,
),
],
);
Navigator.of(event.context).pop(true);
CustomSnackBar.displaySnackBar('Save Successfully');
emit(SaveState());
} catch (_) {
}
}
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.deletePassword(
deviceId: deviceId, passwordId: event.passwordId)
.then((value) async {
add(InitialPasswordsPage(type: pageType));
});
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
}
bool _validateInputs() {
if (passwordController.text.length<7) {
CustomSnackBar.displaySnackBar('Password less than 7');
return true;
}
if (passwordController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password required');
return true;
}
if (passwordNameController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password name required');
return true;
}
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
CustomSnackBar.displaySnackBar('Select effective time');
return true;
}
if (expirationTime == 'Select Time' || expirationTimeTimeStamp == null) {
CustomSnackBar.displaySnackBar('Select expiration time');
return true;
}
if (repeat == true &&
(endTime == null || startTime == null || selectedDay == null)) {
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
return true;
}
return false;
}
List<DayInWeek> days = [
DayInWeek("S", dayKey: 'Sun'),
DayInWeek("M", dayKey: 'Mon'),
DayInWeek("T", dayKey: 'Tue'),
DayInWeek("W", dayKey: 'Wed'),
DayInWeek("T", dayKey: 'Thu'),
DayInWeek("F", dayKey: 'Fri'),
DayInWeek("S", dayKey: 'Sat'),
];
String getTimeOnly(DateTime? dateTime) {
if (dateTime == null) return '';
return DateFormat('HH:mm').format(dateTime);
}
}
@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
abstract class SmartDoorEvent extends Equatable {
const SmartDoorEvent();
@@ -8,6 +9,11 @@ abstract class SmartDoorEvent extends Equatable {
}
class InitialEvent extends SmartDoorEvent {}
class InitialPasswordsPage extends SmartDoorEvent {
final String? type;
const InitialPasswordsPage({ this.type});
}
class InitialOneTimePassword extends SmartDoorEvent {}
class UpdateLockEvent extends SmartDoorEvent {
final bool value;
@@ -15,3 +21,47 @@ class UpdateLockEvent extends SmartDoorEvent {
@override
List<Object> get props => [value];
}
class SavePasswordEvent extends SmartDoorEvent {
final BuildContext context;
const SavePasswordEvent({required this.context});
@override
List<Object> get props => [context];
}
class GeneratePasswordEvent extends SmartDoorEvent {}
class SelectTimeEvent extends SmartDoorEvent {
final BuildContext context;
final bool isEffective;
const SelectTimeEvent({required this.context,required this.isEffective});
@override
List<Object> get props => [context,isEffective];
}
class ToggleRepeatEvent extends SmartDoorEvent {}
class SetStartEndTimeEvent extends SmartDoorEvent {
final bool val;
const SetStartEndTimeEvent({required this.val});
@override
List<Object> get props => [val];
}
class DeletePasswordEvent extends SmartDoorEvent {
final String passwordId;
const DeletePasswordEvent({required this.passwordId});
@override
List<Object> get props => [passwordId];
}
class ChangeTimeEvent extends SmartDoorEvent {
final dynamic val;
final bool isStartEndTime;
const ChangeTimeEvent({required this.val,required this.isStartEndTime});
@override
List<Object> get props => [val,isStartEndTime];
}
@@ -1,5 +1,6 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
class SmartDoorState extends Equatable {
const SmartDoorState();
@@ -36,3 +37,17 @@ class FailedState extends SmartDoorState {
@override
List<Object> get props => [errorMessage];
}
class GeneratePasswordState extends SmartDoorState{}
class TimeSelectedState extends SmartDoorState{}
class IsRepeatState extends SmartDoorState{}
class IsStartEndState extends SmartDoorState{}
class changeStartTimeState extends SmartDoorState{}
class changeEndTimeState extends SmartDoorState{}
class changeTimeState extends SmartDoorState{}
class SaveState extends SmartDoorState{}
class LoadingSaveState extends SmartDoorState{}
class TemporaryPasswordsLoadedState extends SmartDoorState{
final List<TemporaryPassword> temporaryPassword;
const TemporaryPasswordsLoadedState({required this.temporaryPassword});
}
@@ -1,14 +1,29 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final String threeGangId;
late ThreeGangModel deviceStatus;
ThreeGangModel deviceStatus = ThreeGangModel(
firstSwitch: false,
secondSwitch: false,
thirdSwitch: false,
firstCountDown: 0,
secondCountDown: 0,
thirdCountDown: 0);
Timer? _timer;
bool threeGangGroup = false;
List<DeviceModel> devicesList = [];
List<GroupThreeGangModel> groupThreeGangList = [];
bool allSwitchesOn = true;
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
on<InitialEvent>(_fetchThreeGangStatus);
@@ -17,18 +32,60 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
on<AllOffEvent>(_allOff);
on<AllOnEvent>(_allOn);
on<ChangeSlidingSegment>(_changeSliding);
on<SetCounterValue>(_setCounterValue);
on<GetCounterEvent>(_getCounterValue);
on<TickTimer>(_onTickTimer);
on<OnClose>(_onClose);
on<GroupAllOnEvent>(_groupAllOn);
on<GroupAllOffEvent>(_groupAllOff);
}
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
threeGangGroup = event.groupScreen;
if (threeGangGroup) {
devicesList = [];
groupThreeGangList = [];
allSwitchesOn = true;
devicesList = await DevicesAPI.getDeviceByGroupName(
HomeCubit.getInstance().selectedSpace?.id ?? '', '3G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
groupThreeGangList.add(GroupThreeGangModel(
deviceId: devicesList[i].uuid ?? '',
deviceName: devicesList[i].name ?? '',
firstSwitch: deviceStatus.firstSwitch,
secondSwitch: deviceStatus.secondSwitch,
thirdSwitch: deviceStatus.thirdSwitch));
}
if (groupThreeGangList.isNotEmpty) {
groupThreeGangList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
} else {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus));
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
@@ -39,14 +96,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: 'switch_1', value: !event.value),
threeGangId);
DeviceControlModel(
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_1',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (response['success'] ?? false) {
deviceStatus.firstSwitch = !event.value;
}
} catch (_) {}
emit(UpdateState(threeGangModel: deviceStatus));
if (threeGangGroup) {
await Future.delayed(const Duration(seconds: 1));
add(const InitialEvent(groupScreen: true));
} else {
emit(UpdateState(threeGangModel: deviceStatus));
}
}
void _changeSecondSwitch(
@@ -54,28 +119,44 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: 'switch_2', value: !event.value),
threeGangId);
DeviceControlModel(
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_2',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (response['success'] ?? false) {
deviceStatus.secondSwitch = !event.value;
}
} catch (_) {}
emit(UpdateState(threeGangModel: deviceStatus));
if (threeGangGroup) {
await Future.delayed(const Duration(seconds: 1));
add(const InitialEvent(groupScreen: true));
} else {
emit(UpdateState(threeGangModel: deviceStatus));
}
}
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: 'switch_3', value: !event.value),
threeGangId);
DeviceControlModel(
deviceId: threeGangGroup ? event.deviceId : threeGangId,
code: 'switch_3',
value: !event.value),
threeGangGroup ? event.deviceId : threeGangId);
if (response['success'] ?? false) {
deviceStatus.thirdSwitch = !event.value;
}
} catch (_) {}
emit(UpdateState(threeGangModel: deviceStatus));
if (threeGangGroup) {
await Future.delayed(const Duration(seconds: 1));
add(const InitialEvent(groupScreen: true));
} else {
emit(UpdateState(threeGangModel: deviceStatus));
}
}
void _allOff(AllOffEvent event, Emitter<ThreeGangState> emit) async {
@@ -121,4 +202,140 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} catch (_) {}
emit(UpdateState(threeGangModel: deviceStatus));
}
void _groupAllOn(GroupAllOnEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
for (int i = 0; i < groupThreeGangList.length; i++) {
await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupThreeGangList[i].deviceId, code: 'switch_1', value: true),
groupThreeGangList[i].deviceId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupThreeGangList[i].deviceId, code: 'switch_2', value: true),
groupThreeGangList[i].deviceId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupThreeGangList[i].deviceId, code: 'switch_3', value: true),
groupThreeGangList[i].deviceId),
]);
}
} catch (_) {}
await Future.delayed(const Duration(seconds: 1));
add(const InitialEvent(groupScreen: true));
}
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
for (int i = 0; i < groupThreeGangList.length; i++) {
await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupThreeGangList[i].deviceId, code: 'switch_1', value: false),
groupThreeGangList[i].deviceId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupThreeGangList[i].deviceId, code: 'switch_2', value: false),
groupThreeGangList[i].deviceId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupThreeGangList[i].deviceId, code: 'switch_3', value: false),
groupThreeGangList[i].deviceId),
]);
}
} catch (_) {}
await Future.delayed(const Duration(seconds: 1));
add(const InitialEvent(groupScreen: true));
}
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: event.deviceCode, value: seconds),
threeGangId);
if (response['success'] ?? false) {
if (event.deviceCode == 'countdown_1') {
deviceStatus.firstCountDown = seconds;
} else if (event.deviceCode == 'countdown_2') {
deviceStatus.secondCountDown = seconds;
} else if (event.deviceCode == 'countdown_3') {
deviceStatus.thirdCountDown = seconds;
}
} else {
emit(const FailedState(error: 'Something went wrong'));
return;
}
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
if (seconds > 0) {
_onStartTimer(seconds);
} else {
_timer?.cancel();
emit(TimerRunComplete());
}
}
void _getCounterValue(GetCounterEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
if (event.deviceCode == 'countdown_1') {
deviceStatus.firstCountDown > 0
? _onStartTimer(deviceStatus.firstCountDown)
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
} else if (event.deviceCode == 'countdown_2') {
deviceStatus.secondCountDown > 0
? _onStartTimer(deviceStatus.secondCountDown)
: emit(UpdateTimerState(seconds: deviceStatus.secondCountDown));
} else if (event.deviceCode == 'countdown_3') {
deviceStatus.thirdCountDown > 0
? _onStartTimer(deviceStatus.thirdCountDown)
: emit(UpdateTimerState(seconds: deviceStatus.thirdCountDown));
}
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _onClose(OnClose event, Emitter<ThreeGangState> emit) {
_timer?.cancel();
}
void _onStartTimer(int seconds) {
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
add(TickTimer(seconds - timer.tick));
});
}
void _onTickTimer(TickTimer event, Emitter<ThreeGangState> emit) {
if (event.remainingTime > 0) {
emit(TimerRunInProgress(event.remainingTime));
} else {
_timer?.cancel();
emit(TimerRunComplete());
}
}
}
@@ -9,29 +9,85 @@ abstract class ThreeGangEvent extends Equatable {
class LoadingEvent extends ThreeGangEvent {}
class InitialEvent extends ThreeGangEvent {}
class InitialEvent extends ThreeGangEvent {
final bool groupScreen;
const InitialEvent({required this.groupScreen});
@override
List<Object> get props => [groupScreen];
}
class ChangeFirstSwitchStatusEvent extends ThreeGangEvent {
final bool value;
const ChangeFirstSwitchStatusEvent({required this.value});
final String deviceId;
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value];
List<Object> get props => [value, deviceId];
}
class ChangeSecondSwitchStatusEvent extends ThreeGangEvent {
final bool value;
const ChangeSecondSwitchStatusEvent({required this.value});
final String deviceId;
const ChangeSecondSwitchStatusEvent({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value];
List<Object> get props => [value, deviceId];
}
class ChangeThirdSwitchStatusEvent extends ThreeGangEvent {
final bool value;
const ChangeThirdSwitchStatusEvent({required this.value});
final String deviceId;
const ChangeThirdSwitchStatusEvent({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value];
List<Object> get props => [value, deviceId];
}
class AllOffEvent extends ThreeGangEvent {}
class AllOnEvent extends ThreeGangEvent {}
class GroupAllOnEvent extends ThreeGangEvent {}
class GroupAllOffEvent extends ThreeGangEvent {}
class ChangeSlidingSegment extends ThreeGangEvent {
final int value;
const ChangeSlidingSegment({required this.value});
@override
List<Object> get props => [value];
}
class GetCounterEvent extends ThreeGangEvent {
final String deviceCode;
const GetCounterEvent({required this.deviceCode});
@override
List<Object> get props => [deviceCode];
}
class SetCounterValue extends ThreeGangEvent {
final Duration duration;
final String deviceCode;
const SetCounterValue({required this.duration, required this.deviceCode});
@override
List<Object> get props => [duration, deviceCode];
}
class StartTimer extends ThreeGangEvent {
final int duration;
const StartTimer(this.duration);
@override
List<Object> get props => [duration];
}
class TickTimer extends ThreeGangEvent {
final int remainingTime;
const TickTimer(this.remainingTime);
@override
List<Object> get props => [remainingTime];
}
class StopTimer extends ThreeGangEvent {}
class OnClose extends ThreeGangEvent {}
@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
class ThreeGangState extends Equatable {
@@ -28,6 +29,16 @@ class LoadingNewSate extends ThreeGangState {
List<Object> get props => [threeGangModel];
}
class UpdateGroupState extends ThreeGangState {
final List<GroupThreeGangModel> threeGangList;
final bool allSwitches;
const UpdateGroupState({required this.threeGangList, required this.allSwitches});
@override
List<Object> get props => [threeGangList, allSwitches];
}
class FailedState extends ThreeGangState {
final String error;
@@ -36,3 +47,31 @@ class FailedState extends ThreeGangState {
@override
List<Object> get props => [error];
}
class ChangeSlidingSegmentState extends ThreeGangState {
final int value;
const ChangeSlidingSegmentState({required this.value});
@override
List<Object> get props => [value];
}
class UpdateTimerState extends ThreeGangState {
final int seconds;
const UpdateTimerState({required this.seconds});
@override
List<Object> get props => [seconds];
}
class TimerRunInProgress extends ThreeGangState {
final int remainingTime;
const TimerRunInProgress(this.remainingTime);
@override
List<Object> get props => [remainingTime];
}
class TimerRunComplete extends ThreeGangState {}
@@ -0,0 +1,68 @@
class CreateTemporaryPasswordModel{
final String name;
late final String password;
late final String effectiveTime;
late final String invalidTime;
List<Schedule>? scheduleList;
CreateTemporaryPasswordModel({
required this.name,
required this.password,
required this.effectiveTime,
required this.invalidTime,
this.scheduleList,
});
factory CreateTemporaryPasswordModel.fromJson(Map<String, dynamic> json) {
return CreateTemporaryPasswordModel(
name: json['name'],
password: json['password'],
effectiveTime: json['effectiveTime'],
invalidTime: json['invalidTime'],
scheduleList: (json['scheduleList'] as List)
.map((i) => Schedule.fromJson(i))
.toList(),
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'password': password,
'effectiveTime': effectiveTime,
'invalidTime': invalidTime,
'scheduleList': scheduleList!.map((i) => i.toJson()).toList(),
};
}
}
class Schedule {
final String effectiveTime;
final String invalidTime;
final List<String> workingDay;
Schedule({
required this.effectiveTime,
required this.invalidTime,
required this.workingDay,
});
factory Schedule.fromJson(Map<String, dynamic> json) {
return Schedule(
effectiveTime: json['effectiveTime'],
invalidTime: json['invalidTime'],
workingDay: List<String>.from(json['workingDay']),
);
}
Map<String, dynamic> toJson() {
return {
'effectiveTime': effectiveTime,
'invalidTime': invalidTime,
'workingDay': workingDay,
};
}
}
@@ -40,11 +40,9 @@ class DevicesCategoryModel {
DevicesCategoryModel.fromJson(Map<String, dynamic> json)
: name = json['groupName'],
id = json['groupId'],
type = devicesTypesMap[json['productType']] ?? DeviceType.Other,
icon = deviceTypeIconMap[
devicesTypesMap[json['productType']] ?? DeviceType.Other] ??
'',
// id = json['groupId'],
type = devicesTypesMap[json['groupName']] ?? DeviceType.Other,
icon = deviceTypeIconMap[devicesTypesMap[json['groupName']] ?? DeviceType.Other] ?? '',
devices = [],
isSelected = false;
+19 -19
View File
@@ -10,6 +10,7 @@ class DeviceModel {
String? model;
String? name;
String? icon;
String? type;
bool? isOnline;
List<StatusModel> status = [];
String? productName;
@@ -19,21 +20,21 @@ class DeviceModel {
DeviceType? productType;
bool isSelected = false;
late List<FunctionModel> functions;
DeviceModel({
this.activeTime,
// this.id,
this.localKey,
this.model,
this.name,
this.isOnline,
required this.status,
this.productName,
this.timeZone,
this.updateTime,
this.uuid,
this.productType,
this.icon,
}) {
DeviceModel(
{this.activeTime,
// this.id,
this.localKey,
this.model,
this.name,
this.isOnline,
required this.status,
this.productName,
this.timeZone,
this.updateTime,
this.uuid,
this.productType,
this.icon,
this.type}) {
functions = getFunctions(productType!);
}
@@ -43,8 +44,7 @@ class DeviceModel {
if (type == DeviceType.LightBulb) {
tempIcon = Assets.assetsIconsLight;
} else if (type == DeviceType.CeilingSensor ||
type == DeviceType.WallSensor) {
} else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
tempIcon = Assets.assetsIconsSensors;
} else if (type == DeviceType.AC) {
tempIcon = Assets.assetsIconsAC;
@@ -72,6 +72,7 @@ class DeviceModel {
updateTime: json['updateTime'],
uuid: json['uuid'],
productType: type,
type: json['productType'],
status: [],
);
}
@@ -92,6 +93,5 @@ class DeviceModel {
};
}
List<FunctionModel> getFunctions(DeviceType type) =>
devicesFunctionsMap[productType] ?? [];
List<FunctionModel> getFunctions(DeviceType type) => devicesFunctionsMap[productType] ?? [];
}
@@ -0,0 +1,15 @@
class GroupThreeGangModel {
final String deviceId;
final String deviceName;
final bool firstSwitch;
final bool secondSwitch;
final bool thirdSwitch;
GroupThreeGangModel({
required this.deviceId,
required this.deviceName,
required this.firstSwitch,
required this.secondSwitch,
required this.thirdSwitch,
});
}
@@ -0,0 +1,37 @@
class TemporaryPassword {
final int effectiveTime;
final int id;
final int invalidTime;
final String name;
final int phase;
final String phone;
final int sn;
final String timeZone;
final int type;
TemporaryPassword({
required this.effectiveTime,
required this.id,
required this.invalidTime,
required this.name,
required this.phase,
required this.phone,
required this.sn,
required this.timeZone,
required this.type,
});
factory TemporaryPassword.fromJson(Map<String, dynamic> json) {
return TemporaryPassword(
effectiveTime: json['effectiveTime'],
id: json['id'],
invalidTime: json['invalidTime'],
name: json['name'],
phase: json['phase'],
phone: json['phone'] ?? '',
sn: json['sn'],
timeZone: json['timeZone'] ?? '',
type: json['type'],
);
}
}
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_controls.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_temp_unit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
class AcInterface extends StatelessWidget {
const AcInterface({super.key, required this.ac});
@@ -24,6 +30,23 @@ class AcInterface extends StatelessWidget {
}
},
builder: (context, state) {
AcStatusModel statusModel = AcStatusModel(
acSwitch: true,
modeString: 'hot',
tempSet: 300,
currentTemp: 315,
fanSpeedsString: 'low',
childLock: false);
if (state is GetAcStatusState) {
statusModel = state.acStatusModel;
}
if (state is AcChangeLoading) {
statusModel = state.acStatusModel;
}
if (state is AcModifyingState) {
statusModel = state.acStatusModel;
}
return
// Scaffold(
// backgroundColor: ColorsManager.backgroundColor,
@@ -34,6 +57,28 @@ class AcInterface extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 20,
),
DefaultContainer(
height: 65,
padding: const EdgeInsets.all(15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyLarge(text: statusModel.acSwitch ? 'On' : 'Off'),
GestureDetector(
onTap: () {
BlocProvider.of<ACsBloc>(context)
.add(AcSwitch(acSwitch: statusModel.acSwitch));
},
child: SvgPicture.asset(Assets.acSwitchIcon))
],
),
),
const SizedBox(
height: 10,
),
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 380,
@@ -51,6 +96,7 @@ class AcInterface extends StatelessWidget {
),
child: AcInterfaceControls(
deviceModel: ac,
deviceStatus: statusModel,
),
),
],
@@ -4,45 +4,31 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_mode_control_unit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/generated/assets.dart';
class AcInterfaceControls extends StatelessWidget {
const AcInterfaceControls({
super.key,
required this.deviceModel,
});
const AcInterfaceControls({super.key, required this.deviceModel, required this.deviceStatus});
final DeviceModel deviceModel;
final AcStatusModel deviceStatus;
@override
Widget build(BuildContext context) {
return BlocBuilder<ACsBloc, AcsState>(
builder: (context, state) {
String lockIconName = Assets.assetsIconsLock;
bool lockValue = false;
if (state is GetAcStatusState) {
lockIconName =
state.acStatusModel.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock;
lockValue = state.acStatusModel.childLock;
}
if (state is AcChangeLoading) {
lockIconName =
state.acStatusModel.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock;
lockValue = state.acStatusModel.childLock;
}
if (state is AcModifyingState) {
lockIconName =
state.acStatusModel.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock;
lockValue = state.acStatusModel.childLock;
}
String lockIconName =
deviceStatus.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock;
return Column(
children: [
ACModeControlUnit(acDevice: deviceModel),
ACModeControlUnit(
acStatus: deviceStatus,
deviceId: deviceModel.uuid ?? '',
),
const SizedBox(height: 10),
Row(
children: [
@@ -61,7 +47,8 @@ class AcInterfaceControls extends StatelessWidget {
Flexible(
child: GestureDetector(
onTap: () {
BlocProvider.of<ACsBloc>(context).add(ChangeLock(lockBool: lockValue));
BlocProvider.of<ACsBloc>(context)
.add(ChangeLock(lockBool: deviceStatus.childLock));
},
child: DefaultContainer(
height: 55,
@@ -4,48 +4,41 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class ACModeControlUnit extends StatelessWidget {
const ACModeControlUnit({
super.key,
required this.acDevice,
required this.acStatus,
required this.deviceId,
});
final DeviceModel acDevice;
final AcStatusModel acStatus;
final String deviceId;
@override
Widget build(BuildContext context) {
return BlocBuilder<ACsBloc, AcsState>(
builder: (context, state) {
// FanSpeeds fanSpeed = FanSpeeds.middle;
// TempModes tempMode = TempModes.cold;
return Row(
children: [
Flexible(
child: GestureDetector(
onTap: () {
if (state is GetAcStatusState) {
if (state is! AcChangeLoading && state is! AcsLoadingState) {
BlocProvider.of<ACsBloc>(context)
.add(ChangeFanSpeed(fanSpeeds: state.acStatusModel.acFanSpeed));
} else if (state is AcModifyingState) {
BlocProvider.of<ACsBloc>(context)
.add(ChangeFanSpeed(fanSpeeds: state.acStatusModel.acFanSpeed));
.add(ChangeFanSpeed(fanSpeeds: acStatus.acFanSpeed, deviceId: deviceId));
}
// else if (state is AcModifyingState) {
// BlocProvider.of<ACsBloc>(context)
// .add(ChangeFanSpeed(fanSpeeds: state.acStatusModel.acFanSpeed));
// }
},
child: DefaultContainer(
height: 55,
child: Center(
child: state is GetAcStatusState
? SvgPicture.asset(fanSpeedsIconMap[state.acStatusModel.acFanSpeed]!)
: state is AcModifyingState
? SvgPicture.asset(fanSpeedsIconMap[state.acStatusModel.acFanSpeed]!)
: state is AcChangeLoading
? SvgPicture.asset(
fanSpeedsIconMap[state.acStatusModel.acFanSpeed]!)
: const CircularProgressIndicator()),
child: Center(child: SvgPicture.asset(fanSpeedsIconMap[acStatus.acFanSpeed]!)),
),
),
),
@@ -53,24 +46,22 @@ class ACModeControlUnit extends StatelessWidget {
Flexible(
child: GestureDetector(
onTap: () {
if (state is GetAcStatusState) {
// if (state is GetAcStatusState) {
// BlocProvider.of<ACsBloc>(context)
// .add(ChangeAcMode(tempModes: state.acStatusModel.acMode));
// } else if (state is AcModifyingState) {
// BlocProvider.of<ACsBloc>(context)
// .add(ChangeAcMode(tempModes: state.acStatusModel.acMode));
// }
if (state is! AcChangeLoading && state is! AcsLoadingState) {
BlocProvider.of<ACsBloc>(context)
.add(ChangeAcMode(tempModes: state.acStatusModel.acMode));
} else if (state is AcModifyingState) {
BlocProvider.of<ACsBloc>(context)
.add(ChangeAcMode(tempModes: state.acStatusModel.acMode));
.add(ChangeAcMode(tempModes: acStatus.acMode, deviceId: deviceId));
}
},
child: DefaultContainer(
height: 55,
child: Center(
child: state is GetAcStatusState
? SvgPicture.asset(tempModesIconMap[state.acStatusModel.acMode]!)
: state is AcModifyingState
? SvgPicture.asset(tempModesIconMap[state.acStatusModel.acMode]!)
: state is AcChangeLoading
? SvgPicture.asset(tempModesIconMap[state.acStatusModel.acMode]!)
: const CircularProgressIndicator(),
child: SvgPicture.asset(tempModesIconMap[acStatus.acMode]!),
),
),
),
@@ -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/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
@@ -11,12 +12,14 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/generated/assets.dart';
class ACTempWidget extends StatelessWidget {
const ACTempWidget(
this.deviceModel, {
const ACTempWidget({
required this.deviceModel,
required this.temp,
super.key,
});
final DeviceModel deviceModel;
final int temp;
@override
Widget build(BuildContext context) {
@@ -31,8 +34,11 @@ class ACTempWidget extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
// DevicesCubit.getInstance()
// .setACTemp(DeviceModel, DeviceModel.temperature - 0.5);
double tempC = temp / 10;
if (tempC > 20) {
BlocProvider.of<ACsBloc>(context)
.add(DecreaseCoolToTemp(value: tempC, deviceId: deviceModel.uuid ?? ''));
}
},
child: SvgPicture.asset(
Assets.assetsIconsMinus,
@@ -40,8 +46,7 @@ class ACTempWidget extends StatelessWidget {
),
),
BodyLarge(
// text: "${DeviceModel.temperature}° C",
text: '25 °C',
text: '${temp / 10} °C',
style: context.bodyLarge.copyWith(
color: ColorsManager.primaryColor.withOpacity(0.6),
fontSize: 23,
@@ -51,8 +56,11 @@ class ACTempWidget extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
// DevicesCubit.getInstance()
// .setACTemp(DeviceModel, DeviceModel.temperature + 0.5);
double tempC = temp / 10;
if (tempC < 30) {
BlocProvider.of<ACsBloc>(context)
.add(IncreaseCoolToTemp(value: tempC, deviceId: deviceModel.uuid ?? ''));
}
},
child: SvgPicture.asset(
Assets.assetsIconsPlus,
@@ -1,13 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/ac_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_mode_control_unit.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_temp_widget.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/universal_ac_temp.dart';
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
@@ -20,76 +22,87 @@ class ACsList extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<ACsBloc, AcsState>(
builder: (context, state) {
List<AcStatusModel> devicesStatuesList = [];
List<DeviceModel> devicesList = [];
bool allOn = false;
bool allTempSame = false;
int temperature = 20;
if (state is GetAllAcsStatusState) {
devicesStatuesList = state.allAcsStatues;
devicesList = state.allAcs;
allOn = state.allOn;
allTempSame = state.allTempSame;
temperature = state.temp;
}
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// universal AC controller
const SizedBox(height: 10),
const BodySmall(text: "All ACs"),
const SizedBox(height: 5),
// UniversalSwitch(
// category: DevicesCubit.getInstance().chosenCategory!,
// ),
const SizedBox(height: 10),
const UniversalACTemp(),
const SizedBox(height: 10),
child: state is AcChangeLoading || state is AcsLoadingState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// universal AC controller
const SizedBox(height: 10),
const BodySmall(text: "All ACs"),
const SizedBox(height: 5),
UniversalSwitch(
allOn: allOn,
),
const SizedBox(height: 10),
UniversalACTemp(
allTempSame: allTempSame,
temp: temperature,
),
const SizedBox(height: 10),
// other ACs controls
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
// itemCount: DevicesCubit.getInstance().chosenCategory!.devices!.length,
itemBuilder: (context, index) {
// DeviceModel ac = DevicesCubit.getInstance().chosenCategory!.devices![index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// BodySmall(
// text:
// DevicesCubit.getInstance().chosenCategory!.devices![index].name ??
// ""),
IconButton(
onPressed: () {
// DevicesCubit.getInstance().selectDevice(ac);
},
icon: const Icon(
Icons.arrow_forward_ios,
// other ACs controls
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
itemCount: devicesList.length,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
),
style: ButtonStyle(
padding: MaterialStateProperty.all(
const EdgeInsets.all(0),
),
iconSize: MaterialStateProperty.all(15),
alignment: Alignment.bottomRight,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
BodySmall(text: devicesList[index].name ?? ''),
],
),
),
],
),
const SizedBox(height: 5),
// DevicesDefaultSwitch(
// model: ac,
// ),
// const SizedBox(height: 10),
// ACTempWidget(
// ac,
// ),
// const SizedBox(height: 10),
// ACModeControlUnit(
// acDevice: ac,
// ),
const SizedBox(height: 10),
],
);
},
),
],
),
const SizedBox(height: 5),
DevicesDefaultSwitch(
switchValue: devicesStatuesList[index].acSwitch,
action: () {
BlocProvider.of<ACsBloc>(context).add(AcSwitch(
acSwitch: devicesStatuesList[index].acSwitch,
deviceId: devicesList[index].uuid ?? ''));
},
),
const SizedBox(height: 10),
ACTempWidget(
deviceModel: devicesList[index],
temp: devicesStatuesList[index].tempSet,
),
const SizedBox(height: 10),
ACModeControlUnit(
acStatus: devicesStatuesList[index],
deviceId: devicesList[index].uuid ?? '',
),
const SizedBox(height: 10),
],
);
},
),
],
),
);
},
);
@@ -7,7 +7,6 @@ import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_list.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/category_view_app_bar.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
@@ -15,6 +14,8 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import '../device_appbar.dart';
class ACsView extends StatelessWidget {
final DeviceModel? deviceModel;
const ACsView({this.deviceModel, super.key});
@@ -22,14 +23,10 @@ class ACsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '')..add(AcsInitial()),
create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '')
..add(AcsInitial(allAcs: deviceModel != null ? false : true)),
child: BlocBuilder<ACsBloc, AcsState>(
builder: (context, state) {
// BlocProvider.of<ACsBloc>(context).add(AcsInitial());
// DeviceModel? selectedAC;
// if (DevicesCubit.getInstance().getSelectedDevice() is DeviceModel) {
// selectedAC = DevicesCubit.getInstance().getSelectedDevice() as DeviceModel;
// }
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
@@ -39,15 +36,20 @@ class ACsView extends StatelessWidget {
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: deviceModel?.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
appBar: deviceModel != null
? DeviceAppbar(
deviceName: deviceModel!.name!,
deviceUuid: deviceModel!.uuid!,
)
: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: deviceModel?.name ?? "ACs",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
@@ -67,9 +69,10 @@ class ACsView extends StatelessWidget {
width: 50, height: 50, child: CircularProgressIndicator()),
)
: Container(
padding: const EdgeInsets.only(top: 25),
padding: const EdgeInsets.only(top: 40),
alignment: AlignmentDirectional.center,
child: deviceModel != null ? AcInterface(ac: deviceModel!) : ACsList(),
child:
deviceModel != null ? AcInterface(ac: deviceModel!) : const ACsList(),
),
),
),
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
@@ -10,9 +11,9 @@ import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class UniversalACTemp extends StatelessWidget {
const UniversalACTemp({
super.key,
});
const UniversalACTemp({super.key, required this.temp, required this.allTempSame});
final int temp;
final bool allTempSame;
@override
Widget build(BuildContext context) {
@@ -27,8 +28,10 @@ class UniversalACTemp extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
// DevicesCubit.getInstance()
// .setTempToAll(DevicesCubit.universalACTemp - .5);
double temperature = temp / 10;
if (temperature < 30) {
BlocProvider.of<ACsBloc>(context).add(DecreaseAllTemp(value: temperature));
}
},
child: SvgPicture.asset(
Assets.assetsIconsMinus,
@@ -36,8 +39,7 @@ class UniversalACTemp extends StatelessWidget {
),
),
BodyLarge(
// text: "${DevicesCubit.universalACTemp}° C",
text: '25 °C',
text: '${allTempSame ? temp / 10 : '-'} °C',
style: context.bodyLarge.copyWith(
color: ColorsManager.primaryColor.withOpacity(0.6),
fontSize: 23,
@@ -47,8 +49,10 @@ class UniversalACTemp extends StatelessWidget {
dimension: 24,
child: InkWell(
onTap: () {
// DevicesCubit.getInstance()
// .setTempToAll(DevicesCubit.universalACTemp + .5);
double temperature = temp / 10;
if (temperature > 20) {
BlocProvider.of<ACsBloc>(context).add(IncreaseAllTemp(value: temperature));
}
},
child: SvgPicture.asset(
Assets.assetsIconsPlus,
@@ -1,7 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_bloc.dart';
@@ -9,6 +7,8 @@ import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_ev
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
@@ -49,14 +49,9 @@ class CeilingSensorInterface extends StatelessWidget {
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: ceilingSensor.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
appBar: DeviceAppbar(
deviceName: ceilingSensor.name!,
deviceUuid: ceilingSensor.uuid!,
),
body: Container(
width: MediaQuery.sizeOf(context).width,
@@ -78,85 +73,85 @@ class CeilingSensorInterface extends StatelessWidget {
: SafeArea(
child: Column(
children: [
const Spacer(),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// InkWell(
// onTap: () {
// if ((ceilingSensor.isOnline ?? false) == false) {
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text(
// 'Device is offline',
// ),
// backgroundColor: Colors.red,
// ),
// );
// return;
// }
// String controlCode = 'sensitivity';
// showDialog(
// context: context,
// builder: (context) => ParameterControlDialog(
// title: 'Sensitivity',
// sensor: ceilingSensor,
// controlCode: controlCode,
// value: ceilingSensor.status
// .firstWhere((element) => element.code == controlCode)
// .value as int,
// min: ceilingSensor.functions
// .firstWhere((element) => element.code == controlCode)
// .values
// ?.min ??
// 0,
// max: ceilingSensor.functions
// .firstWhere((element) => element.code == controlCode)
// .values
// ?.max ??
// 0,
// ),
// );
// },
// child:
// ),
SvgPicture.asset(
ceilingSensorModel.presenceState.toLowerCase() == 'motion'
? Assets.assetsIconsPresenceSensorAssetsPresenceSensorMotion
: Assets.assetsIconsPresenceSensorAssetsPresence,
width: 100,
height: 100,
// colorFilter: ColorFilter.mode(
// (ceilingSensor.isOnline ?? false)
// ? ColorsManager.primaryColor
// : Colors.grey.withOpacity(0.9),
// BlendMode.srcIn,
// ),
),
const SizedBox(
height: 10,
),
BodyMedium(
text: StringHelpers.toTitleCase(ceilingSensorModel.presenceState),
// (ceilingSensor.isOnline ?? false)
// ? StringHelpers.toTitleCase(ceilingSensor.status
// .firstWhere((element) =>
// element.code == 'presence_state')
// .value
// .toString())
// : "Offline",
style: context.bodyMedium.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
const Spacer(),
SingleChildScrollView(
Expanded(
flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// InkWell(
// onTap: () {
// if ((ceilingSensor.isOnline ?? false) == false) {
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text(
// 'Device is offline',
// ),
// backgroundColor: Colors.red,
// ),
// );
// return;
// }
// String controlCode = 'sensitivity';
// showDialog(
// context: context,
// builder: (context) => ParameterControlDialog(
// title: 'Sensitivity',
// sensor: ceilingSensor,
// controlCode: controlCode,
// value: ceilingSensor.status
// .firstWhere((element) => element.code == controlCode)
// .value as int,
// min: ceilingSensor.functions
// .firstWhere((element) => element.code == controlCode)
// .values
// ?.min ??
// 0,
// max: ceilingSensor.functions
// .firstWhere((element) => element.code == controlCode)
// .values
// ?.max ??
// 0,
// ),
// );
// },
// child:
// ),
SvgPicture.asset(
ceilingSensorModel.presenceState.toLowerCase() == 'motion'
? Assets.assetsIconsPresenceSensorAssetsPresenceSensorMotion
: Assets.assetsIconsPresenceSensorAssetsPresence,
width: 100,
height: 100,
// colorFilter: ColorFilter.mode(
// (ceilingSensor.isOnline ?? false)
// ? ColorsManager.primaryColor
// : Colors.grey.withOpacity(0.9),
// BlendMode.srcIn,
// ),
),
const SizedBox(
height: 10,
),
BodyMedium(
text:
StringHelpers.toTitleCase(ceilingSensorModel.presenceState),
// (ceilingSensor.isOnline ?? false)
// ? StringHelpers.toTitleCase(ceilingSensor.status
// .firstWhere((element) =>
// element.code == 'presence_state')
// .value
// .toString())
// : "Offline",
style: context.bodyMedium.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
),
Expanded(
flex: 2,
child: ListView(
children: [
DefaultContainer(
padding: const EdgeInsets.symmetric(
@@ -165,19 +160,19 @@ class CeilingSensorInterface extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
const Flexible(child: BodySmall(text: 'Sports Para')),
Flexible(
child: BodyLarge(
Flexible(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const BodySmall(text: 'Sports Para'),
BodyLarge(
text: '0',
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
),
],
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
@@ -187,24 +182,23 @@ class CeilingSensorInterface extends StatelessWidget {
color: ColorsManager.greyColor,
),
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
const Flexible(
child: BodySmall(
text: 'Detection Range',
textOverflow: TextOverflow.ellipsis,
)),
Flexible(
child: BodyLarge(
Flexible(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const BodySmall(
text: 'Detection Range',
textOverflow: TextOverflow.ellipsis,
),
BodyLarge(
text: '0.0M',
textOverflow: TextOverflow.ellipsis,
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
),
],
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
@@ -214,24 +208,23 @@ class CeilingSensorInterface extends StatelessWidget {
color: ColorsManager.greyColor,
),
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
const Flexible(
child: BodySmall(
text: 'Movement',
textOverflow: TextOverflow.ellipsis,
)),
Flexible(
child: BodyLarge(
Flexible(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const BodySmall(
text: 'Movement',
textOverflow: TextOverflow.ellipsis,
),
BodyLarge(
text: 'none',
textOverflow: TextOverflow.ellipsis,
style: context.bodyLarge.copyWith(
fontWeight: FontsManager.bold,
),
),
),
],
],
),
),
],
)),
@@ -239,38 +232,81 @@ class CeilingSensorInterface extends StatelessWidget {
height: 15,
),
...List.generate(
ceilingSensorButtons.length,
ceilingSensorButtons().length,
(index) => DefaultContainer(
margin: const EdgeInsets.only(bottom: 5),
padding:
const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
onTap: () {
if (ceilingSensorButtons[index]['page'] != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ceilingSensorButtons[index]['page'] as Widget,
),
onTap: () async {
if (ceilingSensorButtons()[index]['title'] == 'Sensitivity') {
final result = await showDialog(
context: context,
builder: (context) {
return ParameterControlDialog(
title: ceilingSensorButtons()[index]['title']
.toString(),
sensor: ceilingSensor,
value: ceilingSensorModel.sensitivity,
min: 0,
max: 10,
);
},
);
if (result != null) {
BlocProvider.of<CeilingSensorBloc>(context).add(
ChangeValueEvent(
value: result, code: 'sensitivity'));
}
}
// if (ceilingSensorButtons[index]['page'] != null) {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) =>
// ceilingSensorButtons[index]['page'] as Widget,
// ),
// );
// }
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
ceilingSensorButtons[index]['icon'] as String,
// width: 30,
// height: 50,
Row(
children: [
SvgPicture.asset(
ceilingSensorButtons()[index]['icon'] as String,
// width: 30,
// height: 50,
),
const SizedBox(
width: 25,
),
BodyMedium(
text: ceilingSensorButtons()[index]['title']
as String,
style: context.bodyMedium.copyWith(
fontWeight: FontsManager.bold,
),
),
],
),
const SizedBox(
width: 25,
),
BodyMedium(
text: ceilingSensorButtons[index]['title'] as String,
style: context.bodyMedium.copyWith(
fontWeight: FontsManager.bold,
if (ceilingSensorButtons()[index]['withArrow'] == true)
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(ceilingSensorButtons(
sensitivity_val: ceilingSensorModel
.sensitivity
.toString())[index]['val']
.toString()),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
],
),
),
],
),
),
@@ -286,22 +322,53 @@ class CeilingSensorInterface extends StatelessWidget {
}),
);
}
}
var ceilingSensorButtons = [
{
'title': 'Parameter Settings',
'icon': Assets.assetsIconsPresenceSensorAssetsParameterSettings,
'page': null,
},
{
'title': 'Induction History',
'icon': Assets.assetsIconsPresenceSensorAssetsInductionRecording,
'page': null,
},
{
'title': 'Help Description',
'icon': Assets.assetsIconsPresenceSensorAssetsHelpDescription,
'page': null,
},
];
dynamic ceilingSensorButtons({
sensitivity_val = 0,
spaceType = 'Office',
maximumDistanceVal = '3.9m',
nobodyTimeVal = '1hr',
}) =>
[
{
'title': 'Space Type',
'icon': Assets.spaceTypeIcon,
'page': null,
'withArrow': true,
'val': spaceType
},
{
'title': 'Sensitivity',
'icon': Assets.sensitivityIcon,
'page': null,
'withArrow': true,
'val': sensitivity_val
},
{
'title': 'Maximum Distance',
'icon': Assets.maximumDistanceIcon,
'page': null,
'withArrow': true,
'val': maximumDistanceVal,
},
{
'title': 'Nobody Time',
'icon': Assets.assetsIconsPresenceSensorAssetsEmpty,
'page': null,
'withArrow': true,
'val': nobodyTimeVal,
},
{
'title': 'Induction History',
'icon': Assets.assetsIconsPresenceSensorAssetsInductionRecording,
'page': null,
'withArrow': false,
},
{
'title': 'Help Description',
'icon': Assets.assetsIconsPresenceSensorAssetsHelpDescription,
'page': null,
'withArrow': false,
},
];
}
@@ -6,7 +6,6 @@ class ParameterControlDialog extends StatefulWidget {
final int value;
final int min;
final int max;
final String controlCode;
const ParameterControlDialog({
super.key,
@@ -15,7 +14,6 @@ class ParameterControlDialog extends StatefulWidget {
required this.value,
required this.min,
required this.max,
required this.controlCode,
});
@override
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/view/widgets/popup_menu_widget.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class DeviceAppbar extends StatelessWidget implements PreferredSizeWidget {
final String deviceName;
final String deviceUuid;
final double appBarHeight = 56.0;
final void Function()? onPressed;
const DeviceAppbar({super.key, required this.deviceName, required this.deviceUuid,this.onPressed});
@override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: deviceName ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
actions: [
IconButton(onPressed: () {
showPopupMenu(context: context, items: [
PopupMenuItem(
onTap: () async {
HomeCubit.getInstance().updateDevice(deviceUuid);
},
value: 'Update',
child: const Text('Update'),
)
]);
}, icon: Icon(Icons.edit))
],
);
}
@override
Size get preferredSize => Size.fromHeight(appBarHeight);
}
@@ -41,7 +41,9 @@ class DevicesViewBody extends StatelessWidget {
HomeCubit.getInstance().devicesPageChanged(index);
},
children: [
const WizardPage(),
WizardPage(
groupsList: DevicesCubit.getInstance().allCategories ?? [],
),
if (HomeCubit.getInstance().selectedSpace != null)
if (HomeCubit.getInstance().selectedSpace!.rooms != null)
...HomeCubit.getInstance().selectedSpace!.rooms!.map(
@@ -1,10 +1,135 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_event.dart';
import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class GateWayView extends StatelessWidget {
const GateWayView({super.key});
final DeviceModel gatewayObj;
const GateWayView({required this.gatewayObj, super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
return BlocProvider(
create: (context) => GatewayBloc()..add(GatewayInitial(gatewayId: gatewayObj.uuid ?? '')),
child: BlocBuilder<GatewayBloc, GatewayState>(builder: (context, state) {
List<DeviceModel> devicesList = [];
if (state is UpdateGatewayState) {
devicesList = state.list;
}
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light,
),
child: Scaffold(
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar:DeviceAppbar(
deviceName: 'Gateway',
deviceUuid: gatewayObj.uuid!,
),
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.all(Constants.defaultPadding),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
opacity: 0.4,
),
),
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: MediaQuery.sizeOf(context).height * 0.3,
width: MediaQuery.sizeOf(context).width,
alignment: AlignmentDirectional.center,
child: Stack(children: [
SvgPicture.asset(
Assets.gatewayIcon,
width: 125,
height: 125,
),
Positioned(
right: 30,
top: 15,
child: Container(
width: 12,
height: 12,
decoration: const BoxDecoration(
color: ColorsManager.lightGreen,
shape: BoxShape.circle,
),
),
),
]),
),
if (devicesList.isEmpty && state is UpdateGatewayState)
Container(
width: MediaQuery.sizeOf(context).width,
alignment: AlignmentDirectional.center,
child: const BodyMedium(
text: 'No devices found',
fontSize: 15,
fontWeight: FontWeight.w700,
),
),
if (devicesList.isNotEmpty)
const BodyMedium(
text: 'Zigbee Devices',
fontSize: 15,
fontWeight: FontWeight.w700,
),
const SizedBox(
height: 10,
),
state is GatewayLoadingState
? Center(
child: Container(
margin: const EdgeInsets.only(top: 20),
height: 50,
width: 50,
child: const RefreshProgressIndicator()),
)
: Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
shrinkWrap: true,
itemCount: devicesList.length,
itemBuilder: (context, index) {
return RoomPageSwitch(device: devicesList[index]);
},
),
)
],
),
),
)));
}));
}
}
@@ -47,7 +47,10 @@ class LightsList extends StatelessWidget {
],
),
const SizedBox(height: 5),
DevicesDefaultSwitch(model: lights[index]),
DevicesDefaultSwitch(
switchValue: false,
action: () {},
),
const SizedBox(height: 10),
LightBrightness(light: lights[index]),
],
@@ -23,8 +23,8 @@ class LightsView extends StatelessWidget {
selectedLight = DevicesCubit.getInstance().getSelectedDevice() as DeviceModel;
}
List<DeviceModel> lights = [];
if (DevicesCubit.allCategories![1].devices != null) {
for (var device in DevicesCubit.allCategories![1].devices!) {
if (DevicesCubit.getInstance().allCategories![1].devices != null) {
for (var device in DevicesCubit.getInstance().allCategories![1].devices!) {
lights.add(device);
}
}
@@ -29,7 +29,7 @@ class LightsViewList extends StatelessWidget {
children: [
const BodySmall(text: "All Lights"),
UniversalSwitch(
category: DevicesCubit.allCategories![1],
allOn: false,
),
LightsList(lights: lights),
],
@@ -0,0 +1,11 @@
import 'package:flutter/material.dart';
void showPopupMenu(
{required BuildContext context, List<PopupMenuEntry<String>>? items}) async {
await showMenu(
context: context,
position: RelativeRect.fromLTRB( MediaQuery.of(context).size.width/2 , 100, 0, 0),
items: items!,
elevation: 8.0,
);
}
@@ -12,23 +12,19 @@ class RoomPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: room.devices!.length,
itemBuilder: (context, index) {
return RoomPageSwitch(device: room.devices![index]);
},
);
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: room.devices!.length,
itemBuilder: (context, index) {
return RoomPageSwitch(device: room.devices![index]);
},
),
);
@@ -3,20 +3,18 @@
/// This widget displays the icon and name of the device, along with a switch
/// to control its state. Tapping on the widget opens the device interface.
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.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/view/widgets/ACs/acs_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/wall_sensor/wall_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_interface.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
import 'package:syncrow_app/features/shared_widgets/custom_switch.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
@@ -31,46 +29,44 @@ class RoomPageSwitch extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InkWell(
return GestureDetector(
onTap: () {
showDeviceInterface(device, context);
},
child: DefaultContainer(
child: Padding(
padding: const EdgeInsets.only(top: 10, right: 10, left: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
device.icon!,
fit: BoxFit.contain,
),
CustomSwitch(
device: device,
),
],
),
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
child: BodyLarge(
text: device.name ?? "",
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
height: 0,
fontSize: 24,
color: Colors.grey,
),
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
device.icon!,
fit: BoxFit.contain,
),
// CustomSwitch(
// device: device,
// ),
],
),
Flexible(
child: FittedBox(
child: Text(
device.type ?? "",
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.grey,
),
),
),
],
),
),
],
),
),
);
@@ -117,6 +113,10 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
// navigateToInterface(DoorInterface(doorlock: device), context);
break;
case DeviceType.Gateway:
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => GateWayView(gatewayObj: device)));
break;
case DeviceType.LightBulb:
navigateToInterface(LightInterface(light: device), context);
@@ -33,9 +33,7 @@ class RoomsSlider extends StatelessWidget {
text: StringsManager.wizard,
style: context.titleMedium.copyWith(
fontSize: 25,
color: HomeCubit.getInstance().selectedRoom == null
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withOpacity(.2),
color: ColorsManager.textPrimaryColor,
),
),
),
@@ -46,20 +44,15 @@ class RoomsSlider extends StatelessWidget {
(room) => InkWell(
onTap: () {
HomeCubit.getInstance().roomSliderPageChanged(
HomeCubit.getInstance()
.selectedSpace!
.rooms!
.indexOf(room));
HomeCubit.getInstance().selectedSpace!.rooms!.indexOf(room));
},
child: TitleMedium(
text: room.name!,
style: context.titleMedium.copyWith(
fontSize: 25,
color:
HomeCubit.getInstance().selectedRoom == room
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor
.withOpacity(.2),
color: HomeCubit.getInstance().selectedRoom == room
? ColorsManager.textPrimaryColor
: ColorsManager.textPrimaryColor.withOpacity(.2),
),
),
),
@@ -0,0 +1,325 @@
import 'package:day_picker/day_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:time_picker_spinner/time_picker_spinner.dart';
class CreateTemporaryPassword extends StatelessWidget {
final String? deviceId;
final String? type;
const CreateTemporaryPassword({super.key,this.deviceId, this.type});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
listener: (context, state) {
if (state is FailedState) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMessage),
backgroundColor: Colors.red,
),
);
}
},
builder: (context, state) {
return DefaultScaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: const BodyLarge(
text: 'Create Password' ,
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
leading: IconButton(onPressed: () {
Navigator.of(context).pop('UpdatePage');
}, icon: const Icon(Icons.arrow_back)),
actions: [
TextButton(
onPressed: () {
BlocProvider.of<SmartDoorBloc>(context).add(SavePasswordEvent(context: context));
},
child: const Text('Save'))
],
),
child: state is LoadingInitialState?
const Center(child: CircularProgressIndicator()): SingleChildScrollView(
child:
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyMedium(
text:
'Save the password immediately. The password is not displayed in the app.',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
const SizedBox(
height: 20,
),
const BodyMedium(
text: '7-Digit Password',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
child: Row(
children: [
Expanded(
child: PinCodeTextField(
autoDisposeControllers: false,
keyboardType: TextInputType.phone,
length: 7,
enabled: true,
obscureText: false,
animationType: AnimationType.fade,
pinTheme: PinTheme(
shape: PinCodeFieldShape.underline,
fieldHeight: 45,
fieldWidth: 20,
activeFillColor: Colors.white,
disabledColor: Colors.grey,
activeColor: Colors.grey,
errorBorderColor: Colors.grey,
inactiveColor: Colors.grey,
inactiveFillColor: Colors.grey,
selectedColor: Colors.grey
),
animationDuration: Duration(milliseconds: 300),
backgroundColor: Colors.white,
enableActiveFill: false,
controller: BlocProvider.of<SmartDoorBloc>(context).passwordController,
appContext: context,
)),
const SizedBox(
width: 10,
),
InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context).add(GeneratePasswordEvent());
},
child: const BodyMedium(
text: 'Generate Randomly',
fontWeight: FontWeight.bold,
fontColor: ColorsManager.primaryColor,
))
],
),
),
BlocProvider.of<SmartDoorBloc>(context).passwordController.text.isNotEmpty?
TextButton(onPressed: () async {
await Clipboard.setData(ClipboardData(text: BlocProvider.of<SmartDoorBloc>(context).passwordController.text));
},
child: const Text('Copy')):SizedBox(),
const SizedBox(
height: 20,
),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: Column(
children: [
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Password Name',
fontWeight: FontWeight.normal,
),
trailing: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: TextFormField(
controller:
BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
decoration: const InputDecoration(
labelText: 'Enter The Name'),
)),
),
const Divider(color:Color(0xffEBEBEB),),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Effective Time',
fontWeight: FontWeight.normal,
),
trailing: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context)..add(SelectTimeEvent(context: context, isEffective: true));
// .selectTime(context, isEffective: true);
},
child: Text(
BlocProvider.of<SmartDoorBloc>(context).effectiveTime
),
)),
),
const Divider(color:Color(0xffEBEBEB),),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Expiration Time',
fontWeight: FontWeight.normal,
),
trailing: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context)..add(SelectTimeEvent(context: context, isEffective: false));
// BlocProvider.of<SmartDoorBloc>(context)
// .selectTime(context,
// isEffective: false);
},
child: Text(
BlocProvider.of<SmartDoorBloc>(context)
.expirationTime),
)),
),
),
],
)),
const SizedBox(
height: 20,
),
if(type=='Online Password')
DefaultContainer(
padding:
const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Repeat',
fontWeight: FontWeight.normal,
),
trailing: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value:
BlocProvider.of<SmartDoorBloc>(context).repeat,
onChanged: (value) {
BlocProvider.of<SmartDoorBloc>(context).add(ToggleRepeatEvent());
},
applyTheme: true,
)),
),
),
const SizedBox(
height: 20,
),
BlocProvider.of<SmartDoorBloc>(context).repeat
? DefaultContainer(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 5),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context).add(const SetStartEndTimeEvent(val: true));
},
child: BodyMedium(text: 'Start',fontColor:BlocProvider.of<SmartDoorBloc>(context).isStartEndTime==false? Colors.black:Colors.blue,fontSize: 18,),
),
InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context).add(const SetStartEndTimeEvent(val: false));
},
child: BodyMedium(text: 'End',fontColor:BlocProvider.of<SmartDoorBloc>(context).isStartEndTime? Colors.black:Colors.blue,fontSize: 18,),
)
],
),
),
const Divider(color:Color(0xffEBEBEB),),
Container(
height: 80,
child:
Container(
height: 90,
child:BlocProvider.of<SmartDoorBloc>(context).isStartEndTime? TimePickerSpinner(
time:
BlocProvider.of<SmartDoorBloc>(context).startTime,
is24HourMode: false,
itemHeight: 40,
normalTextStyle: const TextStyle(
fontSize: 24,
),
highlightedTextStyle: const TextStyle(
fontSize: 30, color: Colors.blue),
onTimeChange: (time) {
// BlocProvider.of<SmartDoorBloc>(context).changeTime(time, BlocProvider.of<SmartDoorBloc>(context).isStartEndTime);
BlocProvider.of<SmartDoorBloc>(context).add(ChangeTimeEvent(val: time, isStartEndTime: BlocProvider.of<SmartDoorBloc>(context).isStartEndTime));
},
): Container(
child: TimePickerSpinner(
time: BlocProvider.of<SmartDoorBloc>(context).endTime,
is24HourMode: false,
itemHeight: 40,
normalTextStyle: const TextStyle(
fontSize: 24,
),
highlightedTextStyle: const TextStyle(
fontSize: 30, color: Colors.blue),
onTimeChange: (time) {
BlocProvider.of<SmartDoorBloc>(context).add(ChangeTimeEvent(val: time, isStartEndTime: BlocProvider.of<SmartDoorBloc>(context).isStartEndTime));
// BlocProvider.of<SmartDoorBloc>(context).changeTime(time, BlocProvider.of<SmartDoorBloc>(context).isStartEndTime);
},
),
),
)
),
const Divider(color:Color(0xffEBEBEB),),
const SizedBox(height: 20),
SelectWeekDays(
width: MediaQuery.of(context).size.width / 1,
fontSize: 18,
fontWeight: FontWeight.w600,
days: BlocProvider.of<SmartDoorBloc>(context)
.days,
border: false,
selectedDayTextColor: Colors.black,
unSelectedDayTextColor: Colors.grey,
boxDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Colors.white),
onSelect: (values) {
BlocProvider.of<SmartDoorBloc>(context).selectedDay = values;
},
),
],
))
: SizedBox(),
const SizedBox(
height: 40,
)
],
),
),
);
}));
}
}
@@ -1,14 +1,14 @@
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/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
// import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
// import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
import 'package:syncrow_app/features/devices/model/device_control_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/smart_door_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
// import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.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';
@@ -85,7 +85,7 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
),
child: InkWell(
overlayColor:
MaterialStateProperty.all(ColorsManager.primaryColorWithOpacity.withOpacity(0.1)),
WidgetStateProperty.all(ColorsManager.primaryColorWithOpacity.withOpacity(0.1)),
borderRadius: BorderRadius.circular(999),
onTapDown: (details) {
if (_animationController.status == AnimationStatus.dismissed) {
@@ -114,7 +114,7 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
BoxShadow(
color: Colors.grey,
blurRadius: 18,
offset: Offset(6, 7),
// offset: Offset(6, 7),
blurStyle: BlurStyle.outer,
),
],
@@ -0,0 +1,135 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class DoorDialog extends StatefulWidget {
final String title;
final TemporaryPassword value;
const DoorDialog({
super.key,
required this.title,
required this.value,
});
@override
DoorDialogState createState() => DoorDialogState();
}
class DoorDialogState extends State<DoorDialog> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
final DateTime effectiveDateTime =
DateTime.fromMillisecondsSinceEpoch(widget.value.effectiveTime);
final DateTime expiredDateTime =
DateTime.fromMillisecondsSinceEpoch(widget.value.invalidTime);
final DateFormat formatter = DateFormat('HH:mm');
return Dialog(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
padding: const EdgeInsets.only(top: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
BodyMedium(
text: widget.title,
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontsManager.extraBold,
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 50,
),
child: Container(
height: 1,
width: double.infinity,
color: ColorsManager.greyColor,
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Effective Time :'),
Text(formatter.format(effectiveDateTime)),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Expired Time :'),
Text(formatter.format(expiredDateTime)),
],
),
],
),
),
Container(
height: 1,
width: double.infinity,
color: ColorsManager.greyColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InkWell(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: BodyMedium(
text: 'Cancel',
style: context.bodyMedium
.copyWith(color: ColorsManager.greyColor),
),
),
),
Container(
height: 50,
width: 1,
color: ColorsManager.greyColor,
),
InkWell(
onTap: () {
Navigator.pop(context, 'delete');
},
child: Center(
child: BodyMedium(
text: 'Delete Password',
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity),
),
),
),
],
)
],
),
),
);
}
}
@@ -3,15 +3,16 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/members_management_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/smart_linkage_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/temporary_password_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/unlocking_records_view.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
class DoorLockGrid extends StatelessWidget {
const DoorLockGrid({
super.key,
});
String uuid;
DoorLockGrid({
super.key,required this.uuid});
@override
Widget build(BuildContext context) {
@@ -28,10 +29,10 @@ class DoorLockGrid extends StatelessWidget {
itemBuilder: (context, index) => DefaultContainer(
onTap: () {
//TODO: remove checking after adding the pages
doorLockButtons[index]['page'] != null
doorLockButtons()[index]['page'] != null
? Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => doorLockButtons[index]['page'] as Widget,
builder: (context) => doorLockButtons(val: uuid)[index]['page'] as Widget,
),
)
: null;
@@ -43,7 +44,7 @@ class DoorLockGrid extends StatelessWidget {
ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
doorLockButtons[index]['image'] as String,
doorLockButtons()[index]['image'] as String,
),
),
const SizedBox(
@@ -52,7 +53,7 @@ class DoorLockGrid extends StatelessWidget {
Flexible(
child: FittedBox(
child: BodySmall(
text: doorLockButtons[index]['title'] as String,
text: doorLockButtons()[index]['title'] as String,
// doorLockButtons.keys.elementAt(index),
textAlign: TextAlign.center,
),
@@ -65,7 +66,7 @@ class DoorLockGrid extends StatelessWidget {
}
}
List<Map<String, dynamic>> doorLockButtons = [
List<Map<String, dynamic>> doorLockButtons({val}) => [
{
'title': 'Unlocking Records',
'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords,
@@ -79,7 +80,7 @@ List<Map<String, dynamic>> doorLockButtons = [
{
'title': 'Temporary Password',
'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword,
'page': null,
'page': TemporaryPasswordPage(deviceId:val) ,
},
{
'title': 'Smart Linkage',
@@ -6,6 +6,8 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_eve
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
import 'package:syncrow_app/features/devices/view/widgets/popup_menu_widget.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_button.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_grid.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
@@ -16,15 +18,16 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class DoorInterface extends StatelessWidget {
const DoorInterface({super.key, required this.doorLock});
DoorInterface({super.key, required this.doorLock});
final DeviceModel doorLock;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SmartDoorBloc(deviceId: doorLock.uuid ?? '')..add(InitialEvent()),
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
listener: (context, state) {
if (state is FailedState) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
@@ -68,14 +71,9 @@ class DoorInterface extends StatelessWidget {
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: doorLock.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
appBar: DeviceAppbar(
deviceName: doorLock.name!,
deviceUuid: doorLock.uuid!,
),
body: Container(
width: MediaQuery.sizeOf(context).width,
@@ -113,7 +111,8 @@ class DoorInterface extends StatelessWidget {
doorLock: doorLock,
smartDoorModel: smartDoorModel,
),
const DoorLockGrid(),
DoorLockGrid( uuid: doorLock.uuid!, ),
],
)
],
@@ -126,3 +125,4 @@ class DoorInterface extends StatelessWidget {
);
}
}
@@ -13,18 +13,46 @@ class DoorLockStatusBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
String batteryIc = Assets.assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn;
if (smartDoorModel.residualElectricity < 90) {
batteryIc = Assets.assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn;
} else if (smartDoorModel.residualElectricity < 10) {
batteryIc = Assets.assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn;
}
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(Assets.assetsIconsWifi),
SvgPicture.asset(batteryIc),
Transform.rotate(
angle: 1.5708, // 90 degrees in radians (π/2 or 1.5708)
child: Icon(
_getBatteryIcon(smartDoorModel.residualElectricity),
color: _getBatteryColor(smartDoorModel.residualElectricity),
size: 30,
),
),
],
);
}
IconData _getBatteryIcon(int batteryLevel) {
// if (batteryState == BatteryState.charging) {
// return Icons.battery_charging_full;
// } else
if (batteryLevel >= 80) {
return Icons.battery_full;
} else if (batteryLevel >= 60) {
return Icons.battery_4_bar;
} else if (batteryLevel >= 40) {
return Icons.battery_3_bar;
} else if (batteryLevel >= 20) {
return Icons.battery_2_bar;
} else {
return Icons.battery_alert;
}
}
Color _getBatteryColor(int batteryLevel) {
if (batteryLevel >= 80) {
return Colors.green;
} else if (batteryLevel >= 40) {
return Colors.yellowAccent;
} else {
return Colors.red;
}
}
}
@@ -0,0 +1,126 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/view/widgets/smart_door/view_temporary_password.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class TemporaryPasswordPage extends StatelessWidget {
final String? deviceId;
const TemporaryPasswordPage({super.key,this.deviceId});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Temporary Password',
child: Column(
children: [
const SizedBox(height: 10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyLarge(
text: 'Online Password',
fontWeight: FontWeight.normal,
fontColor: Color(0xfff999999),
),
const BodyMedium(
text: 'We recommend that you use the online password when the Wi-Fi network is stable.',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 10),
DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child:ListTile(
contentPadding: EdgeInsets.zero,
leading: SvgPicture.asset(
Assets.timeLimitedPasswordIcon),
title: const BodyMedium(
text: 'Time-Limited Password',
fontWeight: FontWeight.normal,
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewTemporaryPassword(deviceId:deviceId,type:'Online Password'),));
},
trailing: const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
),
),
],
),
const SizedBox(height: 10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyLarge(
text: 'Offline Password',
fontWeight: FontWeight.normal,
fontColor: Color(0xfff999999),
),
const BodyMedium(
text: 'WWe recommend that you use the offline password when the Wi-Fi is disconnected or in an unstable Wi-Fi environment.',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 10),
DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
child: Column(children: [
ListTile(
contentPadding: EdgeInsets.zero,
leading: SvgPicture.asset(Assets.oneTimePassword),
title:
const BodyMedium(
text: 'One-Time Password',
fontWeight: FontWeight.normal,
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewTemporaryPassword(deviceId:deviceId,type:'One-Time'),));
},
trailing: const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
),
const Divider( ),
ListTile(
contentPadding: EdgeInsets.zero,
leading: SvgPicture.asset(
Assets.timeLimitedPassword),
title: const BodyMedium(
text: 'Time-Limited Password',
fontWeight: FontWeight.normal,
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewTemporaryPassword(deviceId:deviceId,type:'Time-Limited'),));
},
trailing: const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
),
],)
),
],
),
const Spacer(),
],
),
);
}
}
@@ -0,0 +1,115 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'create_temporary_password.dart';
import 'door_dialog.dart';
class ViewTemporaryPassword extends StatelessWidget {
final String? deviceId;
final String? type;
const ViewTemporaryPassword({super.key, this.deviceId, this.type});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) =>
SmartDoorBloc(deviceId: deviceId!)..add(InitialPasswordsPage(type:type )),
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
listener: (context, state) {
if (state is FailedState) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMessage),
backgroundColor: Colors.red,
),
);
}
}, builder: (context, state) {
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
return DefaultScaffold(
title: 'Passwords',
actions: [
IconButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CreateTemporaryPassword(deviceId: deviceId, type: type),
)).then((result) {
if (result != null && result) {
smartDoorBloc.add(InitialPasswordsPage(type:type ));
}
});
},
icon: const Icon(Icons.add))
],
child: Builder(
builder: (context) {
return state is LoadingInitialState
? const Center(child: CircularProgressIndicator())
: Center(
child: smartDoorBloc.temporaryPasswords!.isNotEmpty
? ListView.builder(
itemCount: smartDoorBloc.temporaryPasswords!.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: DefaultContainer(
padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 10),
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: SvgPicture.asset(
Assets.timeLimitedPasswordIcon),
title: BodyMedium(
text:
'Password Name: ${smartDoorBloc.temporaryPasswords![index].name}',
fontWeight: FontWeight.normal,
),
onTap: () async {
final result = await showDialog(
context: context,
builder: (context) {
return DoorDialog(
title: 'Password Information',
value: smartDoorBloc.temporaryPasswords![index],
);
},
);
if(result=='delete'){
smartDoorBloc.add(DeletePasswordEvent(passwordId: smartDoorBloc.temporaryPasswords![index].id.toString()));
}
},
trailing: const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 15,
),
),
),
);
},
)
: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(Assets.noValidPasswords),
const SizedBox(
height: 10,
),
const BodyMedium(text: 'No Valid Passwords')
],
),
);
},
));
}));
}
}
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
// import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
// import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
@@ -0,0 +1,174 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/timer_screen.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class ScheduleScreen extends StatelessWidget {
final DeviceModel device;
const ScheduleScreen({required this.device, super.key});
@override
Widget build(BuildContext context) {
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light,
),
child: Scaffold(
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: const BodyLarge(
text: 'Schedule',
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
body: SafeArea(
child: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
opacity: 0.4,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 48,
),
DefaultContainer(
width: MediaQuery.sizeOf(context).width,
child: Column(
children: [
InkWell(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TimerScreen(
device: device,
deviceCode: 'countdown_1',
)));
},
child: Container(
padding:
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodySmall(
text: "Bedside Light",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
fontSize: 15,
fontWeight: FontWeight.w400,
),
),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 18,
)
],
),
),
),
const Divider(
color: ColorsManager.dividerColor,
),
InkWell(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TimerScreen(
device: device,
deviceCode: 'countdown_2',
)));
},
child: Container(
padding:
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodySmall(
text: "Ceiling Light",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
fontSize: 15,
fontWeight: FontWeight.w400,
),
),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 18,
)
],
),
),
),
const Divider(
color: ColorsManager.dividerColor,
),
InkWell(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TimerScreen(
device: device,
deviceCode: 'countdown_3',
)));
},
child: Container(
padding:
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodySmall(
text: "Spotlight",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
fontSize: 15,
fontWeight: FontWeight.w400,
),
),
const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.greyColor,
size: 18,
)
],
),
),
),
],
)),
],
),
),
),
));
}
}
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_screen.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
@@ -10,9 +10,9 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class ThreeGangInterface extends StatelessWidget {
const ThreeGangInterface({super.key, required this.gangSwitch});
const ThreeGangInterface({super.key, this.gangSwitch});
final DeviceModel gangSwitch;
final DeviceModel? gangSwitch;
@override
Widget build(BuildContext context) {
return AnnotatedRegion(
@@ -24,15 +24,20 @@ class ThreeGangInterface extends StatelessWidget {
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: gangSwitch.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
appBar: gangSwitch != null
? DeviceAppbar(
deviceName: gangSwitch!.name!,
deviceUuid: gangSwitch!.uuid!,
)
: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: gangSwitch?.name ?? 'Lights',
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
@@ -53,9 +58,7 @@ class ThreeGangInterface extends StatelessWidget {
right: Constants.defaultPadding,
bottom: Constants.bottomNavBarHeight,
),
child: ThreeGangScreen(
device: gangSwitch,
),
child: ThreeGangScreen(device: gangSwitch),
),
),
),
@@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class ThreeGangList extends StatelessWidget {
const ThreeGangList({super.key, required this.threeGangList, required this.allSwitches});
final List<GroupThreeGangModel> threeGangList;
final bool allSwitches;
@override
Widget build(BuildContext context) {
return BlocBuilder<ThreeGangBloc, ThreeGangState>(
builder: (context, state) {
return state is LoadingNewSate
? const Center(
child: DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 10),
const BodySmall(text: 'All Lights'),
const SizedBox(height: 5),
DevicesDefaultSwitch(
switchValue: allSwitches,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(GroupAllOnEvent());
},
secondAction: () {
BlocProvider.of<ThreeGangBloc>(context).add(GroupAllOffEvent());
},
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
itemCount: threeGangList.length,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
BodySmall(text: '${threeGangList[index].deviceName} beside light'),
const SizedBox(height: 5),
DevicesDefaultSwitch(
switchValue: threeGangList[index].firstSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeFirstSwitchStatusEvent(
value: threeGangList[index].firstSwitch,
deviceId: threeGangList[index].deviceId));
},
),
const SizedBox(height: 10),
BodySmall(text: '${threeGangList[index].deviceName} ceiling light'),
const SizedBox(height: 5),
DevicesDefaultSwitch(
switchValue: threeGangList[index].secondSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeSecondSwitchStatusEvent(
value: threeGangList[index].secondSwitch,
deviceId: threeGangList[index].deviceId));
},
),
const SizedBox(height: 10),
BodySmall(text: '${threeGangList[index].deviceName} spotlight'),
const SizedBox(height: 5),
DevicesDefaultSwitch(
switchValue: threeGangList[index].thirdSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeThirdSwitchStatusEvent(
value: threeGangList[index].thirdSwitch,
deviceId: threeGangList[index].deviceId));
},
),
],
);
},
),
],
),
);
},
);
}
}
@@ -4,25 +4,26 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_blo
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/schedule_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_list.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class ThreeGangScreen extends StatelessWidget {
const ThreeGangScreen({
super.key,
required this.device,
});
const ThreeGangScreen({super.key, this.device});
final DeviceModel device;
final DeviceModel? device;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ThreeGangBloc(threeGangId: device.uuid ?? '')..add(InitialEvent()),
create: (context) => ThreeGangBloc(threeGangId: device?.uuid ?? '')
..add(InitialEvent(groupScreen: device != null ? false : true)),
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
builder: (context, state) {
ThreeGangModel threeGangModel = ThreeGangModel(
@@ -32,327 +33,348 @@ class ThreeGangScreen extends StatelessWidget {
firstCountDown: 0,
secondCountDown: 0,
thirdCountDown: 0);
List<GroupThreeGangModel> groupThreeGangModel = [];
bool allSwitchesOn = false;
if (state is LoadingNewSate) {
threeGangModel = state.threeGangModel;
} else if (state is UpdateState) {
threeGangModel = state.threeGangModel;
} else if (state is UpdateGroupState) {
groupThreeGangModel = state.threeGangList;
allSwitchesOn = state.allSwitches;
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Expanded(child: SizedBox.shrink()),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
: device == null
? ThreeGangList(
threeGangList: groupThreeGangModel,
allSwitches: allSwitchesOn,
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Column(
children: [
GangSwitch(
threeGangSwitch: device,
value: threeGangModel.firstSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeFirstSwitchStatusEvent(
value: threeGangModel.firstSwitch));
},
// control: DeviceControlModel(
// deviceId: device.uuid,
// // code: 'switch_1',
// code: device.status[0].code,
// // value: true,
// value: device.status[0].value,
// ),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Bedside Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
Column(
children: [
GangSwitch(
threeGangSwitch: device,
value: threeGangModel.secondSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeSecondSwitchStatusEvent(
value: threeGangModel.secondSwitch));
},
// control: DeviceControlModel(
// // deviceId: 'bfe10693d4fd263206ocq9',
// // code: 'switch_2',
// // value: true,
// deviceId: device.uuid,
// code: device.status[1].code,
// value: device.status[1].value,
// ),
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Ceiling Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
Column(
children: [
GangSwitch(
threeGangSwitch: device,
value: threeGangModel.thirdSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeThirdSwitchStatusEvent(
value: threeGangModel.thirdSwitch));
},
),
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Spotlight",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
],
),
Expanded(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
const Expanded(child: SizedBox.shrink()),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_1',
// value: true,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_2',
// value: true,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_3',
// value: true,
// ),
// device.uuid!,
// );
BlocProvider.of<ThreeGangBloc>(context).add(AllOnEvent());
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "On",
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
GangSwitch(
threeGangSwitch: device!,
value: threeGangModel.firstSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeFirstSwitchStatusEvent(
value: threeGangModel.firstSwitch));
},
// control: DeviceControlModel(
// deviceId: device.uuid,
// // code: 'switch_1',
// code: device.status[0].code,
// // value: true,
// value: device.status[0].value,
// ),
),
const SizedBox(height: 10),
BodySmall(
text: "All On",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Bedside Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: Icon(
Icons.access_time,
color: ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
),
],
),
),
GangSwitch(
threeGangSwitch: device!,
value: threeGangModel.secondSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeSecondSwitchStatusEvent(
value: threeGangModel.secondSwitch));
},
// control: DeviceControlModel(
// // deviceId: 'bfe10693d4fd263206ocq9',
// // code: 'switch_2',
// // value: true,
// deviceId: device.uuid,
// code: device.status[1].code,
// value: device.status[1].value,
// ),
),
const SizedBox(height: 10),
BodySmall(
text: "Timer",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Ceiling Light",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_1',
// value: false,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_2',
// value: false,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_3',
// value: false,
// ),
// device.uuid!,
// );
BlocProvider.of<ThreeGangBloc>(context).add(AllOffEvent());
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "Off",
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
GangSwitch(
threeGangSwitch: device!,
value: threeGangModel.thirdSwitch,
action: () {
BlocProvider.of<ThreeGangBloc>(context).add(
ChangeThirdSwitchStatusEvent(
value: threeGangModel.thirdSwitch));
},
),
const SizedBox(height: 10),
BodySmall(
text: "All Off",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
const SizedBox(height: 20),
const SizedBox(
width: 70,
child: BodySmall(
text: "Spotlight",
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
],
),
),
),
],
);
Expanded(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_1',
// value: true,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_2',
// value: true,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_3',
// value: true,
// ),
// device.uuid!,
// );
BlocProvider.of<ThreeGangBloc>(context).add(AllOnEvent());
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "On",
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "All On",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
ScheduleScreen(
device: device!,
)));
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: Icon(
Icons.access_time,
color: ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "Timer",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
const SizedBox(
width: 20,
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_1',
// value: false,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_2',
// value: false,
// ),
// device.uuid!,
// );
// DevicesCubit.getInstance().deviceControl(
// DeviceControlModel(
// deviceId: device.uuid,
// code: 'switch_3',
// value: false,
// ),
// device.uuid!,
// );
BlocProvider.of<ThreeGangBloc>(context)
.add(AllOffEvent());
},
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(100),
),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: BodySmall(
text: "Off",
style: context.bodyMedium.copyWith(
color: ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
),
],
),
),
),
const SizedBox(height: 10),
BodySmall(
text: "All Off",
style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor,
),
),
],
),
],
),
),
),
],
);
},
),
);
@@ -0,0 +1,185 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class TimerScreen extends StatelessWidget {
final DeviceModel device;
final String deviceCode;
const TimerScreen({required this.device, required this.deviceCode, super.key});
@override
Widget build(BuildContext context) {
return AnnotatedRegion(
value: SystemUiOverlayStyle(
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light,
),
child: Scaffold(
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: const BodyLarge(
text: 'Schedule',
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
),
body: SafeArea(
child: BlocProvider(
create: (context) => ThreeGangBloc(threeGangId: device.uuid ?? '')
..add(GetCounterEvent(deviceCode: deviceCode)),
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
builder: (context, state) {
Duration duration = Duration.zero;
int countNum = 0;
int tabNum = 0;
if (state is UpdateTimerState) {
countNum = state.seconds;
} else if (state is TimerRunInProgress) {
countNum = state.remainingTime;
} else if (state is TimerRunComplete) {
countNum = 0;
} else if (state is LoadingNewSate) {
countNum = 0;
}
if (state is ChangeSlidingSegmentState) {
tabNum = state.value;
}
return PopScope(
canPop: false,
onPopInvoked: (didPop) {
if (!didPop) {
BlocProvider.of<ThreeGangBloc>(context).add(OnClose());
Navigator.pop(context);
}
},
child: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.all(24),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
opacity: 0.4,
),
),
child: state is LoadingInitialState || state is LoadingNewSate
? const Center(
child: DefaultContainer(
width: 50, height: 50, child: CircularProgressIndicator()),
)
: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: MediaQuery.sizeOf(context).width,
decoration: const ShapeDecoration(
color: ColorsManager.slidingBlueColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
child: CupertinoSlidingSegmentedControl<int>(
thumbColor: ColorsManager.slidingBlueColor,
onValueChanged: (value) {
BlocProvider.of<ThreeGangBloc>(context)
.add(ChangeSlidingSegment(value: value ?? 0));
},
groupValue:
state is ChangeSlidingSegmentState ? state.value : 0,
backgroundColor: Colors.white,
children: <int, Widget>{
0: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: BodySmall(
text: 'Countdown',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
1: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'Schedule',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
},
),
),
if (tabNum == 0)
countNum > 0
? BodyLarge(
text: _formatDuration(countNum),
fontColor: ColorsManager.slidingBlueColor,
fontSize: 40,
)
: CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.hm,
onTimerDurationChanged: (Duration newDuration) {
duration = newDuration;
},
),
if (tabNum == 0)
GestureDetector(
onTap: () {
if (state is LoadingNewSate) {
return;
}
if (countNum > 0) {
BlocProvider.of<ThreeGangBloc>(context).add(
SetCounterValue(
deviceCode: deviceCode,
duration: Duration.zero));
} else if (duration != Duration.zero) {
BlocProvider.of<ThreeGangBloc>(context).add(
SetCounterValue(
deviceCode: deviceCode, duration: duration));
}
},
child: SvgPicture.asset(
countNum > 0 ? Assets.pauseIcon : Assets.playIcon))
],
)));
},
),
),
),
),
);
}
String _formatDuration(int seconds) {
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
final secs = (seconds % 60).toString().padLeft(2, '0');
return '$hours:$minutes:$secs';
}
}
@@ -1,7 +1,8 @@
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_category_model.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
@@ -9,31 +10,27 @@ import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
class UniversalSwitch extends StatelessWidget {
const UniversalSwitch({
super.key,
required this.category,
required this.allOn,
});
final DevicesCategoryModel category;
final bool allOn;
@override
Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
return BlocBuilder<ACsBloc, AcsState>(
builder: (context, state) {
bool? status = category.devicesStatus;
// bool? status = category.devicesStatus;
return Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () {
DevicesCubit.getInstance().turnAllDevicesOn(category);
BlocProvider.of<ACsBloc>(context).add(const ChangeAllSwitch(value: true));
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: status != null
? status
? ColorsManager.primaryColor
: Colors.white
: Colors.white,
color: allOn ? ColorsManager.primaryColor : Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
bottomLeft: Radius.circular(15),
@@ -42,11 +39,7 @@ class UniversalSwitch extends StatelessWidget {
child: Center(
child: BodyMedium(
text: StringsManager.on,
fontColor: status != null
? status
? Colors.white
: null
: null,
fontColor: allOn ? Colors.white : null,
fontWeight: FontWeight.bold,
),
),
@@ -56,16 +49,12 @@ class UniversalSwitch extends StatelessWidget {
Expanded(
child: InkWell(
onTap: () {
DevicesCubit.getInstance().turnAllDevicesOff(category);
BlocProvider.of<ACsBloc>(context).add(const ChangeAllSwitch(value: false));
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: status != null
? status
? Colors.white
: ColorsManager.primaryColor
: Colors.white,
color: allOn ? Colors.white : ColorsManager.primaryColor,
borderRadius: const BorderRadius.only(
topRight: Radius.circular(15),
bottomRight: Radius.circular(15),
@@ -74,11 +63,7 @@ class UniversalSwitch extends StatelessWidget {
child: Center(
child: BodyMedium(
text: StringsManager.off,
fontColor: status != null
? status
? null
: Colors.white
: null,
fontColor: allOn ? null : Colors.white,
fontWeight: FontWeight.bold,
),
),
@@ -12,7 +12,7 @@ class ParametersList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Expanded(
flex: 7,
flex: 2,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -40,7 +40,6 @@ class ParametersList extends StatelessWidget {
builder: (context) => ParameterControlDialog(
title: 'Motion Detection Sensitivity',
sensor: wallSensor,
controlCode: controlCode,
value: presenceSensorsModel.motionSensitivity,
min: wallSensor.functions
.firstWhere((element) => element.code == controlCode)
@@ -54,6 +53,7 @@ class ParametersList extends StatelessWidget {
0,
),
);
print('result=== $result');
if (result != null) {
BlocProvider.of<WallSensorBloc>(context)
.add(ChangeValueEvent(value: result, code: controlCode));
@@ -92,7 +92,6 @@ class ParametersList extends StatelessWidget {
builder: (context) => ParameterControlDialog(
title: 'Motionless Detection Sensitivity',
sensor: wallSensor,
controlCode: controlCode,
value: presenceSensorsModel.motionlessSensitivity,
min: wallSensor.functions
.firstWhere((element) => element.code == controlCode)
@@ -141,13 +140,13 @@ class ParametersList extends StatelessWidget {
if ((wallSensor.isOnline ?? false) == false) {
return;
}
String controlCode = 'far_detection';
final result = await showDialog(
context: context,
builder: (context) => ParameterControlDialog(
title: 'Far Detection',
sensor: wallSensor,
controlCode: controlCode,
value: presenceSensorsModel.farDetection,
min: wallSensor.functions
.firstWhere((element) => element.code == controlCode)
@@ -10,7 +10,7 @@ class PresenceIndicator extends StatelessWidget {
// .value
// .toString();
return Expanded(
flex: 6,
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -8,6 +8,7 @@ import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_s
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_event.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/wall_sensor_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
@@ -56,14 +57,9 @@ class WallMountedInterface extends StatelessWidget {
backgroundColor: ColorsManager.backgroundColor,
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: BodyLarge(
text: deviceModel.name ?? "",
fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
appBar: DeviceAppbar(
deviceName: deviceModel.name!,
deviceUuid: deviceModel.uuid!,
),
body: Container(
width: MediaQuery.sizeOf(context).width,
@@ -1,17 +1,79 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:syncrow_app/features/devices/view/widgets/wizard_switches.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart';
class WizardPage extends StatelessWidget {
const WizardPage({
super.key,
});
final List<DevicesCategoryModel> groupsList;
const WizardPage({super.key, required this.groupsList});
@override
Widget build(BuildContext context) {
return const SingleChildScrollView(
child: WizartSwitches(),
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
shrinkWrap: true,
itemCount: groupsList.length,
itemBuilder: (_, index) {
return GestureDetector(
onTap: () {
if (groupsList[index].name == 'AC') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => const ACsView()));
}
if (groupsList[index].name == '3G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const ThreeGangInterface()));
}
},
child: DefaultContainer(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
groupsList[index].icon!,
fit: BoxFit.contain,
),
// CustomSwitch(
],
),
FittedBox(
fit: BoxFit.scaleDown,
child: BodyLarge(
text: groupsList[index].name!,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
height: 0,
fontSize: 20,
color: Colors.grey,
),
),
),
],
),
),
);
},
);
}
}
@@ -1,97 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
class WizartSwitches extends StatelessWidget {
const WizartSwitches({
super.key,
});
@override
Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return state is! DevicesLoading
? DevicesCubit.allCategories != null
? GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5,
),
padding: const EdgeInsets.only(top: 10),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: DevicesCubit.allCategories!.length,
itemBuilder: (_, index) {
return InkWell(
onTap: () {
// DevicesCubit.getInstance().selectCategory(index);
//Navigate to the chosen category view without animation
if (DevicesCubit.getInstance().chosenCategoryView ==
null) {
return;
}
Navigator.push(context,
CustomPageRoute(builder: (context) {
return DevicesCubit.getInstance()
.chosenCategoryView!;
}));
},
child: DefaultContainer(
child: Padding(
padding: const EdgeInsets.only(
top: 10, right: 10, left: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
DevicesCubit.allCategories![index].icon!,
fit: BoxFit.contain,
),
// CustomSwitch(
],
),
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
child: BodyLarge(
text: DevicesCubit
.allCategories![index].name!,
style: context.bodyLarge.copyWith(
fontWeight: FontWeight.bold,
height: 0,
fontSize: 24,
color: Colors.grey,
),
),
),
),
],
),
),
),
);
},
)
: const SizedBox.shrink()
: const Center(
child: CircularProgressIndicator(),
);
},
);
}
}
@@ -6,6 +6,7 @@ import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_even
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class AssignDeviceView extends StatelessWidget {
final String unitId;
@@ -16,77 +17,81 @@ class AssignDeviceView extends StatelessWidget {
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ManageUnitBloc()..add(FetchDevicesByRoomIdEvent(roomId: roomId)),
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(
listener: (context, state) {},
builder: (context, state) {
return DefaultScaffold(
title: 'Space Setting',
child: state is LoadingState
? const Center(child: RefreshProgressIndicator())
: state is FetchDeviceByRoomIdState
? Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
childAspectRatio: 1.0,
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(listener: (context, state) {
if (state is FetchDeviceByRoomIdState) {
if (state.allDevices.isEmpty) {
CustomSnackBar.displaySnackBar('You do not have the permission to assign devices');
Navigator.of(context).pop();
}
}
}, builder: (context, state) {
return DefaultScaffold(
title: 'Space Setting',
child: state is LoadingState
? const Center(child: RefreshProgressIndicator())
: state is FetchDeviceByRoomIdState
? Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
childAspectRatio: 1.0,
),
itemCount: state.allDevices.length,
itemBuilder: (context, index) {
return Container(
width: MediaQuery.sizeOf(context).width,
padding: const EdgeInsets.all(16),
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
itemCount: state.allDevices.length,
itemBuilder: (context, index) {
return Container(
width: MediaQuery.sizeOf(context).width,
padding: const EdgeInsets.all(16),
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
state.allDevices[index].icon!,
fit: BoxFit.contain,
),
GestureDetector(
onTap: () {
if (state.roomDevicesId[
state.allDevices[index].uuid!] ??
false == false) {
BlocProvider.of<ManageUnitBloc>(context).add(
AssignRoomEvent(
deviceId:
state.allDevices[index].uuid ??
'',
roomId: roomId));
}
},
child: SvgPicture.asset(
state.roomDevicesId[
state.allDevices[index].uuid!] ??
false
? Assets.blueCheckboxIcon
: Assets.emptyCheckboxIcon,
width: 22,
height: 22,
))
],
SvgPicture.asset(
state.allDevices[index].icon!,
fit: BoxFit.contain,
),
Text(state.allDevices[index].name ?? ''),
GestureDetector(
onTap: () {
if (state.roomDevicesId[
state.allDevices[index].uuid!] ??
false == false) {
BlocProvider.of<ManageUnitBloc>(context).add(
AssignRoomEvent(
deviceId:
state.allDevices[index].uuid ?? '',
roomId: roomId));
}
},
child: SvgPicture.asset(
state.roomDevicesId[
state.allDevices[index].uuid!] ??
false
? Assets.blueCheckboxIcon
: Assets.emptyCheckboxIcon,
width: 22,
height: 22,
))
],
),
);
}),
)
: Container());
}));
Text(state.allDevices[index].name ?? ''),
],
),
);
}),
)
: Container());
}));
}
}
@@ -30,7 +30,8 @@ class ManageHomeView extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(
children:
List.generate(
spaces.length,
(index) {
if (index == spaces.length - 1) {
@@ -54,7 +54,8 @@ class RoomsView extends StatelessWidget {
return GestureDetector(
onTap: () {
// BlocProvider.of<ManageUnitBloc>(context).add(
// FetchDevicesByRoomIdEvent(roomId: roomId));
// FetchDevicesByRoomIdEvent(
// roomId: state.roomsList[index].id ?? ''));
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AssignDeviceView(
@@ -16,19 +16,17 @@ class SceneRoomsTabBarDevicesView extends StatefulWidget {
const SceneRoomsTabBarDevicesView({super.key});
@override
State<SceneRoomsTabBarDevicesView> createState() =>
_SceneRoomsTabBarDevicesViewState();
State<SceneRoomsTabBarDevicesView> createState() => _SceneRoomsTabBarDevicesViewState();
}
class _SceneRoomsTabBarDevicesViewState
extends State<SceneRoomsTabBarDevicesView>
class _SceneRoomsTabBarDevicesViewState extends State<SceneRoomsTabBarDevicesView>
with SingleTickerProviderStateMixin {
late final TabController _tabController;
List<RoomModel>? rooms = [];
@override
void initState() {
rooms = HomeCubit.getInstance().selectedSpace?.rooms;
rooms = List.from(HomeCubit.getInstance().selectedSpace?.rooms ?? []);
if (rooms != null) {
if (rooms![0].id != '-1') {
rooms?.insert(
@@ -43,8 +41,7 @@ class _SceneRoomsTabBarDevicesViewState
}
}
_tabController =
TabController(length: rooms!.length, vsync: this, initialIndex: 0);
_tabController = TabController(length: rooms!.length, vsync: this, initialIndex: 0);
_tabController.addListener(_handleTabSwitched);
super.initState();
}
@@ -54,8 +51,9 @@ class _SceneRoomsTabBarDevicesViewState
final value = _tabController.index;
/// select tab
context.read<TabBarBloc>().add(
TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
context
.read<TabBarBloc>()
.add(TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
return;
}
}
@@ -1,79 +1,72 @@
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/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DevicesDefaultSwitch extends StatelessWidget {
const DevicesDefaultSwitch({
super.key,
required this.model,
});
const DevicesDefaultSwitch(
{super.key, required this.switchValue, required this.action, this.secondAction});
final DeviceModel model;
final bool switchValue;
final Function action;
final Function? secondAction;
@override
Widget build(BuildContext context) {
return BlocBuilder<DevicesCubit, DevicesState>(
builder: (context, state) {
return Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () {
DevicesCubit.getInstance().turnOnOffDevice(model);
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: model.isOnline ?? false
? ColorsManager.primaryColor
: Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
bottomLeft: Radius.circular(15),
),
),
child: Center(
child: BodyMedium(
text: "ON",
fontColor: model.isOnline ?? false ? Colors.white : null,
fontWeight: FontWeight.bold,
),
),
return Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () {
action();
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: switchValue ? ColorsManager.primaryColor : Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
bottomLeft: Radius.circular(15),
),
),
child: Center(
child: BodyMedium(
text: "ON",
fontColor: switchValue ? Colors.white : null,
fontWeight: FontWeight.bold,
),
),
),
Expanded(
child: InkWell(
onTap: () {
DevicesCubit.getInstance().turnOnOffDevice(model);
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: model.isOnline ?? false
? Colors.white
: ColorsManager.primaryColor,
borderRadius: const BorderRadius.only(
topRight: Radius.circular(15),
bottomRight: Radius.circular(15),
),
),
child: Center(
child: BodyMedium(
text: "OFF",
fontColor: model.isOnline ?? false ? null : Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
Expanded(
child: InkWell(
onTap: () {
if (secondAction != null) {
secondAction!();
} else {
action();
}
},
child: Container(
height: 60,
decoration: BoxDecoration(
color: switchValue ? Colors.white : ColorsManager.primaryColor,
borderRadius: const BorderRadius.only(
topRight: Radius.circular(15),
bottomRight: Radius.circular(15),
),
),
child: Center(
child: BodyMedium(
text: "OFF",
fontColor: switchValue ? null : Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
);
},
),
),
],
);
}
}
+100 -134
View File
@@ -3,8 +3,7 @@ class Assets {
/// Assets for assetsFontsAftikaRegular
/// assets/fonts/AftikaRegular.ttf
static const String assetsFontsAftikaRegular =
"assets/fonts/AftikaRegular.ttf";
static const String assetsFontsAftikaRegular = "assets/fonts/AftikaRegular.ttf";
/// Assets for assetsIcons3GangSwitch
/// assets/icons/3GangSwitch.svg
@@ -20,97 +19,82 @@ class Assets {
/// Assets for assetsIconsAutomatedClock
/// assets/icons/automated_clock.svg
static const String assetsIconsAutomatedClock =
"assets/icons/automated_clock.svg";
static const String assetsIconsAutomatedClock = "assets/icons/automated_clock.svg";
static const String acSwitchIcon = "assets/icons/ac_switch_ic.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
static const String assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg
static const String
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
static const String assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff
/// assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg
static const String
assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
static const String assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
"assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOnstlowpmdmOff
@@ -120,44 +104,37 @@ class Assets {
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
static const String assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn
/// assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg
static const String
assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
static const String assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
"assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOnstlowpmdmOn
@@ -167,44 +144,37 @@ class Assets {
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
static const String assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn
/// assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg
static const String
assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
static const String assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
"assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOnstlowpmdmOn
@@ -256,8 +226,7 @@ class Assets {
/// Assets for assetsIconsDashboardFill
/// assets/icons/dashboard-fill.svg
static const String assetsIconsDashboardFill =
"assets/icons/dashboard-fill.svg";
static const String assetsIconsDashboardFill = "assets/icons/dashboard-fill.svg";
/// Assets for assetsIconsDevices
/// assets/icons/Devices.svg
@@ -273,8 +242,7 @@ class Assets {
/// Assets for assetsIconsDoorLockLinkage
/// assets/icons/DoorLockLinkage.svg
static const String assetsIconsDoorLockLinkage =
"assets/icons/DoorLockLinkage.svg";
static const String assetsIconsDoorLockLinkage = "assets/icons/DoorLockLinkage.svg";
/// Assets for assetsIconsDoorLockLock
/// assets/icons/DoorLockLock.svg
@@ -282,18 +250,15 @@ class Assets {
/// Assets for assetsIconsDoorLockMembers
/// assets/icons/DoorLockMembers.svg
static const String assetsIconsDoorLockMembers =
"assets/icons/DoorLockMembers.svg";
static const String assetsIconsDoorLockMembers = "assets/icons/DoorLockMembers.svg";
/// Assets for assetsIconsDoorLockPassword
/// assets/icons/DoorLockPassword.svg
static const String assetsIconsDoorLockPassword =
"assets/icons/DoorLockPassword.svg";
static const String assetsIconsDoorLockPassword = "assets/icons/DoorLockPassword.svg";
/// Assets for assetsIconsDoorLockRecords
/// assets/icons/DoorLockRecords.svg
static const String assetsIconsDoorLockRecords =
"assets/icons/DoorLockRecords.svg";
static const String assetsIconsDoorLockRecords = "assets/icons/DoorLockRecords.svg";
/// Assets for assetsIconsDoorlockAssetsBatteryIndicator
/// assets/icons/doorlock-assets/BatteryIndicator.svg
@@ -314,8 +279,7 @@ class Assets {
/// assets/icons/doorlock-assets/lockIcon.svg
static const String assetsIconsDoorlockAssetsLockIcon =
"assets/icons/doorlock-assets/lockIcon.svg";
static const String doorUnlockIcon =
"assets/icons/doorlock-assets/door_un_look_ic.svg";
static const String doorUnlockIcon = "assets/icons/doorlock-assets/door_un_look_ic.svg";
/// Assets for assetsIconsDoorlockAssetsMembersManagement
/// assets/icons/doorlock-assets/members-management.svg
@@ -403,19 +367,33 @@ class Assets {
/// Assets for assetsIconsLightSwitchOff
/// assets/icons/lightSwitchOff.svg
static const String assetsIconsLightSwitchOff =
"assets/icons/lightSwitchOff.svg";
static const String assetsIconsLightSwitchOff = "assets/icons/lightSwitchOff.svg";
/// Assets for assetsIconsLightSwitchOn
/// assets/icons/lightSwitchOn.svg
static const String assetsIconsLightSwitchOn =
"assets/icons/lightSwitchOn.svg";
static const String assetsIconsLightSwitchOn = "assets/icons/lightSwitchOn.svg";
/// Assets for assetsIconsLinkageIconsDoorLockAlarm
/// assets/icons/linkageIcons/doorLockAlarm.svg
static const String assetsIconsLinkageIconsDoorLockAlarm =
"assets/icons/linkageIcons/doorLockAlarm.svg";
/// Assets for assetsIconsLinkTimeLimitedPasswordIcon
/// assets/icons/timeLimitedPasswordIcon.svg
static const String timeLimitedPasswordIcon = "assets/icons/timeLimitedPasswordIcon.svg";
/// Assets for assetsIconsoneTimePassword
/// assets/icons/oneTimePassword.svg
static const String oneTimePassword = "assets/icons/oneTimePassword.svg";
/// Assets for assetsIconsTimeLimitedPassword
/// assets/icons/timeLimitedPassword.svg
static const String timeLimitedPassword = "assets/icons/timeLimitedPassword.svg";
/// Assets for assetsIconsNoValidPasswords
/// assets/icons/noValidPasswords.svg
static const String noValidPasswords = "assets/icons/noValidPasswords.svg";
/// Assets for assetsIconsLinkageIconsFamilyHome
/// assets/icons/linkageIcons/familyHome.svg
static const String assetsIconsLinkageIconsFamilyHome =
@@ -577,6 +555,19 @@ class Assets {
static const String assetsIconsPresenceSensorAssetsParameterSettings =
"assets/icons/presence-sensor-assets/parameter-settings.svg";
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
/// assets/icons/presence-sensor-assets/space_type_icon.svg
static const String spaceTypeIcon = "assets/icons/presence-sensor-assets/space_type_icon.svg";
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
/// assets/icons/presence-sensor-assets/space_type_icon.svg
static const String sensitivityIcon = "assets/icons/presence-sensor-assets/Sensitivity.svg";
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
/// assets/icons/presence-sensor-assets/maximum_distance.svg
static const String maximumDistanceIcon =
"assets/icons/presence-sensor-assets/maximum_distance.svg";
/// Assets for assetsIconsPresenceSensorAssetsPresence
/// assets/icons/presence-sensor-assets/Presence.svg
static const String assetsIconsPresenceSensorAssetsPresence =
@@ -603,8 +594,7 @@ class Assets {
/// Assets for assetsIconsRoutinesFill
/// assets/icons/Routines-fill.svg
static const String assetsIconsRoutinesFill =
"assets/icons/Routines-fill.svg";
static const String assetsIconsRoutinesFill = "assets/icons/Routines-fill.svg";
/// Assets for assetsIconsScan
/// assets/icons/Scan.svg
@@ -636,8 +626,7 @@ class Assets {
/// Assets for assetsIconsSustainability
/// assets/icons/sustainability.svg
static const String assetsIconsSustainability =
"assets/icons/sustainability.svg";
static const String assetsIconsSustainability = "assets/icons/sustainability.svg";
/// Assets for assetsIconsUnlockingMethodsIconsFace
/// assets/icons/unlockingMethodsIcons/face.svg
@@ -695,6 +684,9 @@ class Assets {
static const String addIcon = "assets/icons/add.svg";
static const String player = "assets/icons/player.svg";
static const String delay = "assets/icons/delay.svg";
static const String pauseIcon = "assets/icons/pause_ic.svg";
static const String playIcon = "assets/icons/play_ic.svg";
static const String gatewayIcon = "assets/icons/gateway_icon.svg";
/// Assets for assetsImagesAutomation
/// assets/images/automation.jpg
@@ -726,8 +718,7 @@ class Assets {
/// Assets for assetsImagesHorizintalBlade
/// assets/images/HorizintalBlade.png
static const String assetsImagesHorizintalBlade =
"assets/images/HorizintalBlade.png";
static const String assetsImagesHorizintalBlade = "assets/images/HorizintalBlade.png";
/// Assets for assetsImagesLogo
/// assets/images/Logo.svg
@@ -735,8 +726,7 @@ class Assets {
/// Assets for assetsImagesLogoHorizontal
/// assets/images/logo_horizontal.png
static const String assetsImagesLogoHorizontal =
"assets/images/logo_horizontal.png";
static const String assetsImagesLogoHorizontal = "assets/images/logo_horizontal.png";
/// Assets for assetsImagesPause
/// assets/images/Pause.png
@@ -766,8 +756,7 @@ class Assets {
/// assets/images/Window.png
static const String assetsImagesWindow = "assets/images/Window.png";
static const String assetsSensitivityFunction =
"assets/icons/functions_icons/sensitivity.svg";
static const String assetsSensitivityFunction = "assets/icons/functions_icons/sensitivity.svg";
//assets/icons/functions_icons/sesitivity_operation_icon.svg
static const String assetsSensitivityOperationIcon =
@@ -775,73 +764,59 @@ class Assets {
//assets/icons/functions_icons/ac_power.svg
static const String assetsAcPower =
"assets/icons/functions_icons/ac_power.svg";
static const String assetsAcPower = "assets/icons/functions_icons/ac_power.svg";
//assets/icons/functions_icons/ac_power_off.svg
static const String assetsAcPowerOFF =
"assets/icons/functions_icons/ac_power_off.svg";
static const String assetsAcPowerOFF = "assets/icons/functions_icons/ac_power_off.svg";
//assets/icons/functions_icons/child_lock.svg
static const String assetsChildLock =
"assets/icons/functions_icons/child_lock.svg";
static const String assetsChildLock = "assets/icons/functions_icons/child_lock.svg";
//assets/icons/functions_icons/cooling.svg
static const String assetsFreezing =
"assets/icons/functions_icons/freezing.svg";
static const String assetsFreezing = "assets/icons/functions_icons/freezing.svg";
//assets/icons/functions_icons/fan_speed.svg
static const String assetsFanSpeed =
"assets/icons/functions_icons/fan_speed.svg";
static const String assetsFanSpeed = "assets/icons/functions_icons/fan_speed.svg";
//assets/icons/functions_icons/ac_cooling.svg
static const String assetsAcCooling =
"assets/icons/functions_icons/ac_cooling.svg";
static const String assetsAcCooling = "assets/icons/functions_icons/ac_cooling.svg";
//assets/icons/functions_icons/ac_heating.svg
static const String assetsAcHeating =
"assets/icons/functions_icons/ac_heating.svg";
static const String assetsAcHeating = "assets/icons/functions_icons/ac_heating.svg";
//assets/icons/functions_icons/celsius_degrees.svg
static const String assetsCelsiusDegrees =
"assets/icons/functions_icons/celsius_degrees.svg";
static const String assetsCelsiusDegrees = "assets/icons/functions_icons/celsius_degrees.svg";
//assets/icons/functions_icons/tempreture.svg
static const String assetsTempreture =
"assets/icons/functions_icons/tempreture.svg";
static const String assetsTempreture = "assets/icons/functions_icons/tempreture.svg";
//assets/icons/functions_icons/ac_fan_low.svg
static const String assetsAcFanLow =
"assets/icons/functions_icons/ac_fan_low.svg";
static const String assetsAcFanLow = "assets/icons/functions_icons/ac_fan_low.svg";
//assets/icons/functions_icons/ac_fan_middle.svg
static const String assetsAcFanMiddle =
"assets/icons/functions_icons/ac_fan_middle.svg";
static const String assetsAcFanMiddle = "assets/icons/functions_icons/ac_fan_middle.svg";
//assets/icons/functions_icons/ac_fan_high.svg
static const String assetsAcFanHigh =
"assets/icons/functions_icons/ac_fan_high.svg";
static const String assetsAcFanHigh = "assets/icons/functions_icons/ac_fan_high.svg";
//assets/icons/functions_icons/ac_fan_auto.svg
static const String assetsAcFanAuto =
"assets/icons/functions_icons/ac_fan_auto.svg";
static const String assetsAcFanAuto = "assets/icons/functions_icons/ac_fan_auto.svg";
//assets/icons/functions_icons/scene_child_lock.svg
static const String assetsSceneChildLock =
"assets/icons/functions_icons/scene_child_lock.svg";
static const String assetsSceneChildLock = "assets/icons/functions_icons/scene_child_lock.svg";
//assets/icons/functions_icons/scene_child_unlock.svg
@@ -850,18 +825,15 @@ class Assets {
//assets/icons/functions_icons/scene_refresh.svg
static const String assetsSceneRefresh =
"assets/icons/functions_icons/scene_refresh.svg";
static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg";
//assets/icons/functions_icons/light_countdown.svg
static const String assetsLightCountdown =
"assets/icons/functions_icons/light_countdown.svg";
static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg";
//assets/icons/functions_icons/far_detection.svg
static const String assetsFarDetection =
"assets/icons/functions_icons/far_detection.svg";
static const String assetsFarDetection = "assets/icons/functions_icons/far_detection.svg";
//assets/icons/functions_icons/far_detection_function.svg
@@ -870,13 +842,11 @@ class Assets {
//assets/icons/functions_icons/indicator.svg
static const String assetsIndicator =
"assets/icons/functions_icons/indicator.svg";
static const String assetsIndicator = "assets/icons/functions_icons/indicator.svg";
//assets/icons/functions_icons/motion_detection.svg
static const String assetsMotionDetection =
"assets/icons/functions_icons/motion_detection.svg";
static const String assetsMotionDetection = "assets/icons/functions_icons/motion_detection.svg";
//assets/icons/functions_icons/motionless_detection.svg
@@ -885,18 +855,15 @@ class Assets {
//assets/icons/functions_icons/nobody_time.svg
static const String assetsNobodyTime =
"assets/icons/functions_icons/nobody_time.svg";
static const String assetsNobodyTime = "assets/icons/functions_icons/nobody_time.svg";
//assets/icons/functions_icons/factory_reset.svg
static const String assetsFactoryReset =
"assets/icons/functions_icons/factory_reset.svg";
static const String assetsFactoryReset = "assets/icons/functions_icons/factory_reset.svg";
//assets/icons/functions_icons/master_state.svg
static const String assetsMasterState =
"assets/icons/functions_icons/master_state.svg";
static const String assetsMasterState = "assets/icons/functions_icons/master_state.svg";
//assets/icons/functions_icons/switch_alarm_sound.svg
@@ -905,6 +872,5 @@ class Assets {
//assets/icons/functions_icons/reset_off.svg
static const String assetsResetOff =
"assets/icons/functions_icons/reset_off.svg";
static const String assetsResetOff = "assets/icons/functions_icons/reset_off.svg";
}
+16 -29
View File
@@ -24,67 +24,54 @@ class Router {
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case Routes.splash:
return MaterialPageRoute(
builder: (_) => const SplashView(), settings: settings);
return MaterialPageRoute(builder: (_) => const SplashView(), settings: settings);
// case Routes.devicesRoute:
// return MaterialPageRoute(
// builder: (_) => const DevicesView(), settings: settings);
case Routes.profileRoute:
return MaterialPageRoute(
builder: (_) => const ProfileView(), settings: settings);
return MaterialPageRoute(builder: (_) => const ProfileView(), settings: settings);
case Routes.sceneRoute:
return MaterialPageRoute(
builder: (_) => const SceneView(), settings: settings);
return MaterialPageRoute(builder: (_) => const SceneView(), settings: settings);
case Routes.layoutRoute:
return MaterialPageRoute(
builder: (_) => const LayoutPage(), settings: settings);
return MaterialPageRoute(builder: (_) => const LayoutPage(), settings: settings);
case Routes.authLogin:
return MaterialPageRoute(
builder: (_) => const LoginView(), settings: settings);
return MaterialPageRoute(builder: (_) => const LoginView(), settings: settings);
case Routes.otpRoute:
return MaterialPageRoute(
builder: (_) => const OtpView(), settings: settings);
return MaterialPageRoute(builder: (_) => const OtpView(), settings: settings);
case Routes.authSignUp:
return MaterialPageRoute(
builder: (_) => const SignUpView(), settings: settings);
return MaterialPageRoute(builder: (_) => const SignUpView(), settings: settings);
case Routes.dashboardRoute:
return MaterialPageRoute(
builder: (_) => const DashboardView(), settings: settings);
return MaterialPageRoute(builder: (_) => const DashboardView(), settings: settings);
case Routes.homeRoute:
return MaterialPageRoute(
builder: (_) => const AppLayout(), settings: settings);
return MaterialPageRoute(builder: (_) => const AppLayout(), settings: settings);
case Routes.menuRoute:
return MaterialPageRoute(
builder: (_) => const MenuView(), settings: settings);
return MaterialPageRoute(builder: (_) => const MenuView(), settings: settings);
case Routes.createUnit:
return MaterialPageRoute(
builder: (_) => const CreateUnitView(), settings: settings);
return MaterialPageRoute(builder: (_) => const CreateUnitView(), settings: settings);
case Routes.sceneTasksRoute:
return MaterialPageRoute(
builder: (_) => const SceneTasksView(), settings: settings);
return MaterialPageRoute(builder: (_) => const SceneTasksView(), settings: settings);
case Routes.sceneControlDevicesRoute:
return MaterialPageRoute(
builder: (_) => MultiBlocProvider(
providers: [
BlocProvider(
create: (BuildContext context) =>
DeviceManagerBloc()..add(FetchAllDevices()),
create: (BuildContext context) => DeviceManagerBloc()..add(FetchAllDevices()),
),
BlocProvider(
create: (BuildContext context) => TabBarBloc(
context.read<DeviceManagerBloc>())
..add(const TabChanged(selectedIndex: 0, roomId: '-1')),
create: (BuildContext context) =>
TabBarBloc(context.read<DeviceManagerBloc>())
..add(const TabChanged(selectedIndex: 0, roomId: '-1')),
),
],
child: const SceneRoomsTabBarDevicesView(),
+39 -23
View File
@@ -9,8 +9,7 @@ abstract class ApiEndpoints {
static const String deleteUser = '$baseUrl/authentication/user/delete/{id}';
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
static const String forgetPassword =
'$baseUrl/authentication/user/forget-password';
static const String forgetPassword = '$baseUrl/authentication/user/forget-password';
////////////////////////////////////// Spaces ///////////////////////////////////////
@@ -20,12 +19,10 @@ abstract class ApiEndpoints {
static const String addCommunityToUser = '$baseUrl/community/user';
//GET
static const String communityByUuid = '$baseUrl/community/{communityUuid}';
static const String communityChild =
'$baseUrl/community/child/{communityUuid}';
static const String communityChild = '$baseUrl/community/child/{communityUuid}';
static const String communityUser = '$baseUrl/community/user/{userUuid}';
//PUT
static const String renameCommunity =
'$baseUrl/community/rename/{communityUuid}';
static const String renameCommunity = '$baseUrl/community/rename/{communityUuid}';
///Building Module
//POST
@@ -34,12 +31,10 @@ abstract class ApiEndpoints {
//GET
static const String buildingByUuid = '$baseUrl/building/{buildingUuid}';
static const String buildingChild = '$baseUrl/building/child/{buildingUuid}';
static const String buildingParent =
'$baseUrl/building/parent/{buildingUuid}';
static const String buildingParent = '$baseUrl/building/parent/{buildingUuid}';
static const String buildingUser = '$baseUrl/building/user/{userUuid}';
//PUT
static const String renameBuilding =
'$baseUrl/building/rename/{buildingUuid}';
static const String renameBuilding = '$baseUrl/building/rename/{buildingUuid}';
///Floor Module
//POST
@@ -62,8 +57,7 @@ abstract class ApiEndpoints {
static const String unitChild = '$baseUrl/unit/child/';
static const String unitParent = '$baseUrl/unit/parent/{unitUuid}';
static const String unitUser = '$baseUrl/unit/user/';
static const String invitationCode =
'$baseUrl/unit/{unitUuid}/invitation-code';
static const String invitationCode = '$baseUrl/unit/{unitUuid}/invitation-code';
static const String verifyInvitationCode = '$baseUrl/unit/user/verify-code';
//PUT
@@ -85,7 +79,9 @@ abstract class ApiEndpoints {
static const String addGroup = '$baseUrl/group';
static const String controlGroup = '$baseUrl/group/control';
//GET
static const String groupBySpace = '$baseUrl/group/space/{spaceUuid}';
static const String groupBySpace = '$baseUrl/group/{unitUuid}';
static const String devicesByGroupName = '$baseUrl/group/{unitUuid}/devices/{groupName}';
static const String groupByUuid = '$baseUrl/group/{groupUuid}';
//DELETE
static const String deleteGroup = '$baseUrl/group/{groupUuid}';
@@ -96,15 +92,15 @@ abstract class ApiEndpoints {
static const String addDeviceToRoom = '$baseUrl/device/room';
static const String addDeviceToGroup = '$baseUrl/device/group';
static const String controlDevice = '$baseUrl/device/{deviceUuid}/control';
static const String firmwareDevice = '$baseUrl/device/{deviceUuid}/firmware/{firmwareVersion}';
static const String getDevicesByUserId = '$baseUrl/device/user/{userId}';
//GET
static const String deviceByRoom = '$baseUrl/device/room';
static const String deviceByUuid = '$baseUrl/device/{deviceUuid}';
static const String deviceFunctions =
'$baseUrl/device/{deviceUuid}/functions';
static const String deviceFunctionsStatus =
'$baseUrl/device/{deviceUuid}/functions/status';
static const String deviceFunctions = '$baseUrl/device/{deviceUuid}/functions';
static const String gatewayApi = '$baseUrl/device/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus = '$baseUrl/device/{deviceUuid}/functions/status';
///Device Permission Module
//POST
@@ -112,16 +108,14 @@ abstract class ApiEndpoints {
//GET
static const String devicePermissionList = '$baseUrl/device-permission/list';
//PUT
static const String editDevicePermission =
'$baseUrl/device-permission/edit/{userId}';
static const String editDevicePermission = '$baseUrl/device-permission/edit/{userId}';
static const String assignDeviceToRoom = '$baseUrl/device/room';
/// Scene API ////////////////////
/// POST
static const String createScene = '$baseUrl/scene/tap-to-run';
static const String triggerScene =
'$baseUrl/scene/tap-to-run/trigger/{sceneId}';
static const String triggerScene = '$baseUrl/scene/tap-to-run/trigger/{sceneId}';
/// GET
static const String getUnitScenes = '$baseUrl/scene/tap-to-run/{unitUuid}';
@@ -132,6 +126,28 @@ abstract class ApiEndpoints {
static const String updateScene = '$baseUrl/scene/{sceneId}';
/// DELETE
static const String deleteScene =
'$baseUrl/scene/tap-to-run/{sceneUuid}/{sceneId}';
static const String deleteScene = '$baseUrl/scene/tap-to-run/{sceneUuid}/{sceneId}';
//////////////////////Door Lock //////////////////////
//online
static const String addTemporaryPassword =
'$baseUrl/door-lock/temporary-password/online/{doorLockUuid}';
static const String getTemporaryPassword =
'$baseUrl/door-lock/temporary-password/online/{doorLockUuid}';
//one-time offline
static const String addOneTimeTemporaryPassword =
'$baseUrl/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
static const String getOneTimeTemporaryPassword =
'$baseUrl/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
//multiple-time offline
static const String addMultipleTimeTemporaryPassword =
'$baseUrl/door-lock/temporary-password/offline/multiple-time/{doorLockUuid}';
static const String getMultipleTimeTemporaryPassword =
'$baseUrl/door-lock/temporary-password/offline/multiple-time/{doorLockUuid}';
//multiple-time offline
static const String deleteTemporaryPassword =
'$baseUrl/door-lock/temporary-password/{doorLockUuid}/{passwordId}';
}
+10
View File
@@ -40,4 +40,14 @@ class AuthenticationAPI {
expectedResponseModel: (json) => json['data']);
return response;
}
static Future<Map<String, dynamic>> forgetPassword({required String email,required String password ,}) async {
Map<String, dynamic> params = {"email": email, "password": password,};
final response = await HTTPService().post(
path: ApiEndpoints.forgetPassword,
body: params,
showServerMessage: false,
expectedResponseModel: (json) => json['data']);
return response;
}
}
+133 -16
View File
@@ -1,5 +1,4 @@
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';
@@ -7,9 +6,29 @@ 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';
import '../../features/devices/model/create_temporary_password_model.dart';
class DevicesAPI {
static final HTTPService _httpService = HTTPService();
static Future<Map<String, dynamic>> firmwareDevice(
{required String deviceId, required String firmwareVersion}) async {
try {
final response = await _httpService.post(
path: ApiEndpoints.firmwareDevice
.replaceAll('{deviceUuid}', deviceId)
.replaceAll('{firmwareVersion}', firmwareVersion),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
},
);
return response;
} catch (e) {
rethrow;
}
}
static Future<Map<String, dynamic>> controlDevice(
DeviceControlModel controlModel, String deviceId) async {
try {
@@ -28,26 +47,20 @@ class DevicesAPI {
}
static Future<List<DevicesCategoryModel>> fetchGroups(String spaceId) async {
Map<String, dynamic> params = {
"homeId": spaceId,
"pageSize": 100,
"pageNo": 1
};
// Map<String, dynamic> params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1};
final response = await _httpService.get(
path: ApiEndpoints.groupBySpace.replaceAll("{spaceUuid}", spaceId),
queryParameters: params,
path: ApiEndpoints.groupBySpace.replaceAll('{unitUuid}', spaceId),
// queryParameters: params,
showServerMessage: false,
expectedResponseModel: (json) =>
DevicesCategoryModel.fromJsonList(json['groups']),
expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json),
);
return response;
}
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
final response = await _httpService.get(
path: ApiEndpoints.deviceFunctionsStatus
.replaceAll('{deviceUuid}', deviceId),
path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
@@ -59,18 +72,36 @@ class DevicesAPI {
/// Get Device Functions
static Future<FunctionModel> deviceFunctions(String deviceId) async {
final response = await _httpService.get(
path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId),
path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
final functions = FunctionModel.fromJson(json);
return functions;
});
return response;
}
static Future<List<DeviceModel>> getDeviceByGroupName(String unitId, String groupName) async {
final response = await _httpService.get(
path: ApiEndpoints.devicesByGroupName
.replaceAll('{unitUuid}', unitId)
.replaceAll('{groupName}', groupName),
showServerMessage: false,
expectedResponseModel: (json) {
final functions = FunctionModel.fromJson(json);
return functions;
if (json == null || json.isEmpty || json == []) {
return <DeviceModel>[];
}
List<DeviceModel> devices = [];
for (var device in json) {
devices.add(DeviceModel.fromJson(device));
}
return devices;
},
);
return response;
}
static Future<List<DeviceModel>> getDevicesByRoomId(String roomId) async {
// print("Room ID: $roomId");
final response = await _httpService.get(
path: ApiEndpoints.deviceByRoom,
queryParameters: {"roomUuid": roomId},
@@ -88,4 +119,90 @@ class DevicesAPI {
);
return response;
}
static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
final response = await _httpService.get(
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
showServerMessage: false,
expectedResponseModel: (json) {
List<DeviceModel> devices = [];
if (json == null || json.isEmpty || json == []) {
return devices;
}
for (var device in json['devices']) {
devices.add(DeviceModel.fromJson(device));
}
return devices;
},
);
return response;
}
static Future getTemporaryPasswords(String deviceId, pageType) async {
final response = await _httpService.get(
path: pageType == 'One-Time'
? ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId)
: pageType == 'Online Password'
? ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId)
: ApiEndpoints.getMultipleTimeTemporaryPassword
.replaceAll('{doorLockUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
},
);
return response;
}
//create password
static Future createPassword({
required String name,
required String password,
required String effectiveTime,
required String invalidTime,
required String deviceId,
required String pageType,
List<Schedule>? scheduleList,
}) async {
String endpointPath;
if (pageType == 'Online Password') {
endpointPath = ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId);
} else if (pageType == 'One-Time') {
endpointPath =
ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId);
} else {
endpointPath =
ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId);
}
Map<String, dynamic> body = {
"name": name,
"password": password,
"effectiveTime": effectiveTime,
"invalidTime": invalidTime,
};
if (pageType == 'Online Password' && scheduleList != null) {
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
}
final response = await _httpService.post(
path: endpointPath,
body: body,
showServerMessage: false,
expectedResponseModel: (json) => json,
);
return response;
}
static Future<Map<String, dynamic>> deletePassword(
{required String passwordId, required String deviceId}) async {
final response = await _httpService.delete(
path: ApiEndpoints.deleteTemporaryPassword
.replaceAll('{doorLockUuid}', deviceId)
.replaceAll('{passwordId}', passwordId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
},
);
return response;
}
}
+11 -4
View File
@@ -63,9 +63,16 @@ class StringHelpers {
}
static String toTitleCase(String text) {
return text
.split(' ')
.map((word) => word[0].toUpperCase() + word.substring(1))
.join(' ');
if (text.contains(' ')) {
//remove empty elements
String title = text.split(' ').where((element) => element.isNotEmpty).join(' ');
String result = title
.split(' ')
.map((element) => element[0].toUpperCase() + element.substring(1))
.join(' ');
return result;
} else {
return text.toUpperCase();
}
}
}
@@ -4,9 +4,8 @@ abstract class ColorsManager {
static const Color textPrimaryColor = Color(0xFF5D5D5D);
static const Color switchOffColor = Color(0x7F8D99AE);
static const Color primaryColor = Color(0xFF0030CB);
static Color primaryColorWithOpacity =
const Color(0xFF023DFE).withOpacity(0.6);
static const Color secondaryTextColor = Color(0xFF848484);
static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
static const Color onPrimaryColor = Colors.white;
static const Color secondaryColor = Color(0xFF023DFE);
static const Color onSecondaryColor = Color(0xFF023DFE);
@@ -20,4 +19,9 @@ abstract class ColorsManager {
static const Color relaxColor = Color(0xFFFBD288);
static const Color readingColor = Color(0xFFF7D69C);
static const Color energizingColor = Color(0xFFEDEDED);
static const Color dividerColor = Color(0xFFEBEBEB);
static const Color slidingBlueColor = Color(0x99023DFE);
static const Color blackColor = Color(0xFF000000);
static const Color lightGreen = Color(0xFF00FF0A);
static const Color grayColor = Color(0xFF999999);
}
+35 -37
View File
@@ -1,43 +1,41 @@
// ignore_for_file: lines_longer_than_80_chars, constant_identifier_names
class StringsManager {
static const noRouteFound = 'No route found';
static const noInternetConnection = 'No internet connection';
static const dashboard = 'Dashboard';
static const devices = 'Devices';
static const routine = 'Routines';
static const tapToRunRoutine = 'Tap to run routine';
static const wizard = 'Wizard';
static const active = 'Active';
static const current = 'Current';
static const frequency = 'Frequency';
static const energyUsage = 'Energy Usage';
static const totalConsumption = 'Total Consumption';
static const ACConsumption = 'AC Consumption';
static const units = 'Units';
static const emissions = 'Emissions';
static const reductions = 'Reductions';
static const winter = 'Winter';
static const winterMode = 'Winter Mode';
static const summer = 'Summer';
static const summerMode = 'Summer Mode';
static const on = 'ON';
static const off = 'OFF';
static const timer = 'Timer';
static const dimmerAndColor = "Dimmer & color";
static const recentlyUsed = "Recently used colors";
static const lightingModes = "Lighting modes";
static const doze = "Doze";
static const relax = "Relax";
static const reading = "Reading";
static const energizing = "Energizing";
static const createScene = 'Create Scene';
static const tapToRun = 'Launch: Tap - To - Run';
static const turnOffAllLights =
'Example: turn off all lights in the with one tap.';
static const whenDeviceStatusChanges = 'When device status changes';
static const whenUnusualActivityIsDetected =
static const String dashboard = 'Dashboard';
static const String devices = 'Devices';
static const String routine = 'Routines';
static const String tapToRunRoutine = 'Tap to run routine';
static const String wizard = 'Wizard';
static const String active = 'Active';
static const String current = 'Current';
static const String frequency = 'Frequency';
static const String energyUsage = 'Energy Usage';
static const String totalConsumption = 'Total Consumption';
static const String ACConsumption = 'AC Consumption';
static const String units = 'Units';
static const String emissions = 'Emissions';
static const String reductions = 'Reductions';
static const String winter = 'Winter';
static const String winterMode = 'Winter Mode';
static const String summer = 'Summer';
static const String summerMode = 'Summer Mode';
static const String on = 'ON';
static const String off = 'OFF';
static const String timer = 'Timer';
static const String dimmerAndColor = "Dimmer & color";
static const String recentlyUsed = "Recently used colors";
static const String lightingModes = "Lighting modes";
static const String doze = "Doze";
static const String relax = "Relax";
static const String reading = "Reading";
static const String energizing = "Energizing";
static const String createScene = 'Create Scene';
static const String tapToRun = 'Launch: Tap - To - Run';
static const String turnOffAllLights = 'Example: turn off all lights in the with one tap.';
static const String whenDeviceStatusChanges = 'When device status changes';
static const String whenUnusualActivityIsDetected =
'Example: when an unusual activity is detected.';
static const functions = "Functions";
static const String functions = "Functions";
static const String firstLaunch = "firstLaunch";
}