local auth fail handling and improvements.

design_3.0_demo_module
Sikander Saleem 8 months ago
parent 633c2da82a
commit 262b3aa42f

@ -157,7 +157,6 @@ class ApiManager {
headers.addAll(_headers); headers.addAll(_headers);
Uri url0 = Uri.parse(url); Uri url0 = Uri.parse(url);
print(url0);
// print(headers); // print(headers);
// log(json.encode(body)); // log(json.encode(body));
var request = http.Request('PUT', url0); var request = http.Request('PUT', url0);

@ -204,7 +204,6 @@ class FirebaseNotificationManger {
}); });
FirebaseMessaging.onMessage.listen((RemoteMessage message) { FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('notification i got is ${message.toMap()}');
if (Platform.isAndroid) { if (Platform.isAndroid) {
if (message.data["notificationType"] != 'NurseConfirmArrive') { if (message.data["notificationType"] != 'NurseConfirmArrive') {
NotificationManger.showNotification( NotificationManger.showNotification(

@ -31,7 +31,6 @@ class NotificationManger {
} else if (Platform.isAndroid) { } else if (Platform.isAndroid) {
final AndroidFlutterLocalNotificationsPlugin? androidImplementation = localNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>(); final AndroidFlutterLocalNotificationsPlugin? androidImplementation = localNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
final bool granted = await androidImplementation?.requestNotificationsPermission() ?? false; final bool granted = await androidImplementation?.requestNotificationsPermission() ?? false;
print('permission value is $granted');
if (!granted) { if (!granted) {
if (kDebugMode) { if (kDebugMode) {
print("-------------------- Permission Granted ------------------------"); print("-------------------- Permission Granted ------------------------");
@ -43,7 +42,8 @@ class NotificationManger {
await localNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: onNotificationPressed); await localNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: onNotificationPressed);
} // push new notification } // push new notification
static const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails(
static const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails(
'com.hmg.atoms', 'com.hmg.atoms',
'ATOMS', 'ATOMS',
channelDescription: 'Push notification service for ATOMS', channelDescription: 'Push notification service for ATOMS',
@ -76,7 +76,6 @@ class NotificationManger {
// groupKey: 'com.hmg.atoms', // groupKey: 'com.hmg.atoms',
// ); // );
// const DarwinNotificationDetails iosNotificationDetails = DarwinNotificationDetails( // const DarwinNotificationDetails iosNotificationDetails = DarwinNotificationDetails(
// categoryIdentifier: "atoms", // categoryIdentifier: "atoms",
// ); // );
@ -86,16 +85,9 @@ class NotificationManger {
await localNotificationsPlugin.show(hashcode, title, subtext, platformChannel, payload: payload); await localNotificationsPlugin.show(hashcode, title, subtext, platformChannel, payload: payload);
} }
static Future scheduleNotification( static Future scheduleNotification({int? id, String? title, String? body, String? payLoad, required DateTime scheduledNotificationDateTime}) async {
{int?id,
String? title,
String? body,
String? payLoad,
required DateTime scheduledNotificationDateTime}) async {
print('time i got is ${scheduledNotificationDateTime}');
return localNotificationsPlugin.zonedSchedule( return localNotificationsPlugin.zonedSchedule(
id??0, id ?? 0,
title, title,
body, body,
// tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)), // tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
@ -103,13 +95,12 @@ class NotificationManger {
scheduledNotificationDateTime, scheduledNotificationDateTime,
tz.local, tz.local,
), ),
const NotificationDetails(android: androidNotificationDetails, iOS: iosNotificationDetails, macOS: iosNotificationDetails), const NotificationDetails(android: androidNotificationDetails, iOS: iosNotificationDetails, macOS: iosNotificationDetails),
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
uiLocalNotificationDateInterpretation: uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime);
UILocalNotificationDateInterpretation.absoluteTime);
} }
static Future<void> cancelNotificationById(int notificationId) async { static Future<void> cancelNotificationById(int notificationId) async {
await localNotificationsPlugin.cancel(notificationId); await localNotificationsPlugin.cancel(notificationId);
print("Notification with ID $notificationId has been canceled.");
} }
} }

@ -52,7 +52,6 @@ class NotificationsProvider extends ChangeNotifier {
response = await ApiManager.instance.post(URLs.getSystemNotifications, body: body); response = await ApiManager.instance.post(URLs.getSystemNotifications, body: body);
stateCode = response.statusCode; stateCode = response.statusCode;
print('notifaction response is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List requestsListJson = json.decode(response.body)["data"]; List requestsListJson = json.decode(response.body)["data"];

@ -7,7 +7,6 @@ import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart'; import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/service_request/service_report.dart'; import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/service_request/service_request.dart';
@ -268,7 +267,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
Future<PendingAssetServiceRequest?> checkAssetPendingRequest(int assetId) async { Future<PendingAssetServiceRequest?> checkAssetPendingRequest(int assetId) async {
Response response; Response response;
try { try {
response = await ApiManager.instance.post(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId",body: {}); response = await ApiManager.instance.post(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId", body: {});
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {} if (response.statusCode >= 200 && response.statusCode < 300) {}
return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]); return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]);
@ -423,7 +422,6 @@ class ServiceRequestsProvider extends ChangeNotifier {
Future<CallRequest?> getCallRequestForWorkOrder({required String callId}) async { Future<CallRequest?> getCallRequestForWorkOrder({required String callId}) async {
Response response; Response response;
print('call id i got is ${callId}');
try { try {
response = await ApiManager.instance.get(URLs.getCallRequestForWorkOrder + "?callId=$callId"); response = await ApiManager.instance.get(URLs.getCallRequestForWorkOrder + "?callId=$callId");
stateCode = response.statusCode; stateCode = response.statusCode;

@ -102,7 +102,6 @@ class ServiceRequest {
List list = parsedJson["attachmentsCallRequest"]; List list = parsedJson["attachmentsCallRequest"];
images = list.map((e) => URLs.getFileUrl(e["name"]!) as String).toList(); images = list.map((e) => URLs.getFileUrl(e["name"]!) as String).toList();
} }
// print(parsedJson["requestedDate"]??"");
return ServiceRequest( return ServiceRequest(
id: parsedJson["id"].toString(), id: parsedJson["id"].toString(),
@ -180,7 +179,6 @@ class ServiceRequest {
} }
return true; return true;
} }
} }
class CallCreatedBy { class CallCreatedBy {

@ -812,7 +812,6 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
body: {}, body: {},
); );
print('response i got is ${response.body}');
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {

@ -1,4 +1,3 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart';
@ -119,9 +118,7 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
onPick: (time) { onPick: (time) {
requestDetailProvider.activityMaintenanceHelperModel?.activityTimePicker = time; requestDetailProvider.activityMaintenanceHelperModel?.activityTimePicker = time;
}, },
timerProgress: (isRunning) { timerProgress: (isRunning) {},
print("timerProgress:$isRunning");
},
onChange: (timer) async { onChange: (timer) async {
requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer;
if (timer.startAt != null && timer.endAt != null) { if (timer.startAt != null && timer.endAt != null) {

@ -77,9 +77,8 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
@override @override
void didUpdateWidget(covariant SingleItemDropDownMenu<T, X> oldWidget) { void didUpdateWidget(covariant SingleItemDropDownMenu<T, X> oldWidget) {
if (widget.initialValue != null) { if (widget.initialValue != null) {
// print("$provider:start3:${DateTime.now()}");
final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier); final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
// print("$provider:start4:${DateTime.now()}");
if (result?.isNotEmpty ?? false) { if (result?.isNotEmpty ?? false) {
_selectedItem = result?.first as T?; _selectedItem = result?.first as T?;
} else { } else {

@ -1,6 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pinput/pinput.dart'; import 'package:pinput/pinput.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -10,14 +9,14 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/new_models/general_response_model.dart'; import 'package:test_sa/models/new_models/general_response_model.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/forget_password_module/reset_password_view.dart'; import 'package:test_sa/new_views/forget_password_module/reset_password_view.dart';
class ForgetPasswordVerifyOtpView extends StatefulWidget { class ForgetPasswordVerifyOtpView extends StatefulWidget {
Map<String,dynamic> data={}; Map<String, dynamic> data = {};
ForgetPasswordVerifyOtpView({Key ?key,required this.data}) : super(key: key); ForgetPasswordVerifyOtpView({Key? key, required this.data}) : super(key: key);
@override @override
State<ForgetPasswordVerifyOtpView> createState() => _ForgetPasswordVerifyOtpViewState(); State<ForgetPasswordVerifyOtpView> createState() => _ForgetPasswordVerifyOtpViewState();
@ -25,7 +24,7 @@ class ForgetPasswordVerifyOtpView extends StatefulWidget {
class _ForgetPasswordVerifyOtpViewState extends State<ForgetPasswordVerifyOtpView> { class _ForgetPasswordVerifyOtpViewState extends State<ForgetPasswordVerifyOtpView> {
String otp = ''; String otp = '';
Timer? _timer; Timer? _timer;
int _remainingSeconds = 180; // 3 minutes in seconds int _remainingSeconds = 180; // 3 minutes in seconds
@override @override
@ -111,17 +110,16 @@ class _ForgetPasswordVerifyOtpViewState extends State<ForgetPasswordVerifyOtpVie
InkWell( InkWell(
onTap: _remainingSeconds == 0 onTap: _remainingSeconds == 0
? () async { ? () async {
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false); UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
String employeeId = widget.data['employeeId']; String employeeId = widget.data['employeeId'];
GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp( GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp(
context: context, context: context,
employeeId: employeeId, employeeId: employeeId,
); );
print('Response of send OTP: ${response.toJson()}');
// Restart the timer // Restart the timer
_startTimer(); _startTimer();
} }
: null, : null,
child: Text( child: Text(
'Resend', 'Resend',
@ -150,15 +148,16 @@ class _ForgetPasswordVerifyOtpViewState extends State<ForgetPasswordVerifyOtpVie
).paddingOnly(start: 20, end: 20, bottom: 16), ).paddingOnly(start: 20, end: 20, bottom: 16),
); );
} }
void verifyOtp() async{
void verifyOtp() async {
if (otp.isNotEmpty) { if (otp.isNotEmpty) {
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false); UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
GeneralResponseModel generalResponseModel = await _userProvider.forgetPasswordValidateOtp( GeneralResponseModel generalResponseModel = await _userProvider.forgetPasswordValidateOtp(
context: context, context: context,
employeeId:widget.data['employeeId'], employeeId: widget.data['employeeId'],
otp: otp, otp: otp,
); );
if (generalResponseModel.isSuccess==true) { if (generalResponseModel.isSuccess == true) {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ResetPasswordView())); Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ResetPasswordView()));
} }
} }

@ -15,6 +15,7 @@ import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart';
import 'package:test_sa/new_views/pages/login_page.dart'; import 'package:test_sa/new_views/pages/login_page.dart';
import 'package:test_sa/new_views/pages/unsafe_device_view.dart'; import 'package:test_sa/new_views/pages/unsafe_device_view.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/local_auth_failed_dialog.dart';
import 'package:test_sa/new_views/swipe_module/swipe_view.dart'; import 'package:test_sa/new_views/swipe_module/swipe_view.dart';
import 'package:test_sa/views/update_available_screen.dart'; import 'package:test_sa/views/update_available_screen.dart';
@ -84,24 +85,38 @@ class _SplashPageState extends State<SplashPage> {
loading = false; loading = false;
}); });
if (isValid && _settingProvider.isLocalAuthEnable) { if (isValid && _settingProvider.isLocalAuthEnable) {
bool isSuccess = await checkDualAuthentication(); handleLocalAuth();
if (isSuccess) {
_userProvider.setUser(_settingProvider.user!);
if (_userProvider.user!.onlySwipe!) {
Navigator.of(context).pushNamedAndRemoveUntil(SwipeView.routeName, (routes) => true);
} else {
Navigator.of(context).pushNamedAndRemoveUntil(LandPage.routeName, (routes) => true);
}
} else {
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
}
} else { } else {
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
} }
} }
} }
void handleLocalAuth() async {
bool isSuccess = await checkDualAuthentication();
if (isSuccess) {
_userProvider.setUser(_settingProvider.user!);
if (_userProvider.user!.onlySwipe!) {
Navigator.of(context).pushNamedAndRemoveUntil(SwipeView.routeName, (routes) => true);
} else {
Navigator.of(context).pushNamedAndRemoveUntil(LandPage.routeName, (routes) => true);
}
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => LocalAuthFailedDialog(
onRetry: () {
handleLocalAuth();
},
onLogin: () {
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
},
),
);
}
}
Future<bool> checkDualAuthentication() async { Future<bool> checkDualAuthentication() async {
return await _settingProvider.auth.authenticate( return await _settingProvider.auth.authenticate(
localizedReason: Platform.isAndroid ? "Scan your fingerprint to authenticate" : "Scan with face id to authenticate", localizedReason: Platform.isAndroid ? "Scan your fingerprint to authenticate" : "Scan with face id to authenticate",
@ -139,7 +154,7 @@ class _SplashPageState extends State<SplashPage> {
animation: "splash", animation: "splash",
callback: (animation) async { callback: (animation) async {
bool isSafe = await checkDeviceSafety(); bool isSafe = await checkDeviceSafety();
print('is safe is ${isSafe}');
if (!isSafe) { if (!isSafe) {
Navigator.pushNamedAndRemoveUntil(context, UnsafeDeviceScreen.routeName, (_) => false); Navigator.pushNamedAndRemoveUntil(context, UnsafeDeviceScreen.routeName, (_) => false);
} else { } else {

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
class LocalAuthFailedDialog extends StatelessWidget {
final String? title;
final String? message;
final String? okTitle;
final String? retryBtnText;
final String? loginBtnText;
final VoidCallback onRetry;
final VoidCallback onLogin;
const LocalAuthFailedDialog(
{Key? key, this.title, this.message = "Authentication Failed, Please try again or login", this.okTitle, required this.onRetry, required this.onLogin, this.retryBtnText, this.loginBtnText})
: super(key: key);
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(),
insetPadding: const EdgeInsets.only(left: 21, right: 21),
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
const Text(
"Confirm",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96),
).paddingOnly(top: 16, bottom: 8),
message != null ? message!.heading5(context).custom(color: AppColor.neutral50) : const SizedBox(),
28.height,
Column(
children: [
AppFilledButton(
label: retryBtnText ?? "Retry",
onPressed: () {
Navigator.of(context).pop();
onRetry();
},
buttonColor: AppColor.primary90,
),
16.height,
AppFilledButton(
label: loginBtnText ?? "Login",
buttonColor: Colors.white54,
textColor: AppColor.black10,
height: 48,
showBorder: true,
onPressed: () {
Navigator.of(context).pop();
onLogin();
},
),
],
),
],
),
),
);
}
}

@ -127,8 +127,7 @@ class _AddSupplierEngineerBottomSheetState extends State<AddSupplierEngineerBott
} }
engineer.personRoleId = suppEngRole?.id; engineer.personRoleId = suppEngRole?.id;
// print(engineer.toJson());
// return;
SuppEngineerWorkOrders? suppEngineer = await snapshot.addSupplierEngineer(engineer); SuppEngineerWorkOrders? suppEngineer = await snapshot.addSupplierEngineer(engineer);
if (suppEngineer == null) { if (suppEngineer == null) {
Fluttertoast.showToast(msg: context.translation.failedToCompleteRequest); Fluttertoast.showToast(msg: context.translation.failedToCompleteRequest);

@ -378,11 +378,6 @@ class CreateServiceRequestPageState extends State<CreateServiceRequestPage> {
_serviceRequest.requestedThrough = Provider.of<RequestedThroughProvider>(context, listen: false).items.firstWhere((element) => element.value == 3, orElse: null); _serviceRequest.requestedThrough = Provider.of<RequestedThroughProvider>(context, listen: false).items.firstWhere((element) => element.value == 3, orElse: null);
_serviceRequest.type = Provider.of<TypeOfRequestProvider>(context, listen: false).items.firstWhere((element) => element.value == 1, orElse: null); _serviceRequest.type = Provider.of<TypeOfRequestProvider>(context, listen: false).items.firstWhere((element) => element.value == 1, orElse: null);
// print("_serviceRequest?.requestedThrough:${_serviceRequest?.requestedThrough.toJson()}");
// print("_serviceRequest?.type:${_serviceRequest?.type.toJson()}");
// print("_serviceRequest?.priority:${_serviceRequest?.priority.toJson()}");
// return;
if (_formKey.currentState!.validate() && await _serviceRequest.validateNewRequest(context)) { if (_formKey.currentState!.validate() && await _serviceRequest.validateNewRequest(context)) {
_formKey.currentState!.save(); _formKey.currentState!.save();

@ -32,7 +32,6 @@ class _AutoCompletePartsFieldState extends State<AutoCompletePartsField> {
@override @override
void initState() { void initState() {
print('initial value i got is ${widget.initialValue}');
_controller = TextEditingController(text: widget.initialValue); _controller = TextEditingController(text: widget.initialValue);
super.initState(); super.initState();
} }
@ -75,7 +74,7 @@ class _AutoCompletePartsFieldState extends State<AutoCompletePartsField> {
displayStringForOption: (SparePartsWorkOrders option) => widget.byName ? option.sparePart?.partName ?? "" : option.sparePart?.partNo ?? "", displayStringForOption: (SparePartsWorkOrders option) => widget.byName ? option.sparePart?.partName ?? "" : option.sparePart?.partNo ?? "",
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
return TextField( return TextField(
controller: _controller, controller: _controller,
focusNode: fieldFocusNode, focusNode: fieldFocusNode,
style: AppTextStyles.bodyText.copyWith(color: AppColor.black10), style: AppTextStyles.bodyText.copyWith(color: AppColor.black10),
textAlign: TextAlign.start, textAlign: TextAlign.start,
@ -96,8 +95,8 @@ class _AutoCompletePartsFieldState extends State<AutoCompletePartsField> {
labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120), labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120),
), ),
textInputAction: TextInputAction.search, textInputAction: TextInputAction.search,
onChanged: (text){ onChanged: (text) {
fieldTextEditingController.text =text; fieldTextEditingController.text = text;
}, },
onSubmitted: (String value) { onSubmitted: (String value) {
onFieldSubmitted(); onFieldSubmitted();

@ -158,7 +158,6 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
if (_audio != widget.audio) { if (_audio != widget.audio) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
_audio = widget.audio; _audio = widget.audio;
print('audio position i got is $_audioPosition');
if (_isLocalFile) { if (_isLocalFile) {
await _audioPlayer.setSourceDeviceFile(_audio); await _audioPlayer.setSourceDeviceFile(_audio);
} else { } else {
@ -199,7 +198,8 @@ class _ASoundPlayerState extends State<ASoundPlayer> {
).paddingOnly(start: 8, end: 8).expanded, ).paddingOnly(start: 8, end: 8).expanded,
_failedToLoad _failedToLoad
? Text("Failed to load", style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60)) ? Text("Failed to load", style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60))
: Text("${format(_audioPosition??Duration.zero)}/${format(_audioTime??Duration.zero)}", style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), : Text("${format(_audioPosition ?? Duration.zero)}/${format(_audioTime ?? Duration.zero)}",
style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
], ],
), ),
], ],

@ -1,12 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/lookup.dart';
import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/app_style/app_color.dart';
class SingleStatusMenu extends StatefulWidget { class SingleStatusMenu extends StatefulWidget {
final List<Lookup>? statuses;// Nullable list final List<Lookup>? statuses; // Nullable list
final Lookup? initialStatus; // Nullable final Lookup? initialStatus; // Nullable
final Function(Lookup?)? onSelect; // Nullable function, accepts nullable Lookup final Function(Lookup?)? onSelect; // Nullable function, accepts nullable Lookup
final bool enabled; final bool enabled;
@ -35,9 +35,7 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
@override @override
void didUpdateWidget(covariant SingleStatusMenu oldWidget) { void didUpdateWidget(covariant SingleStatusMenu oldWidget) {
_selectedStatus = widget.statuses?.firstWhere( _selectedStatus = widget.statuses?.firstWhere((element) => element == widget.initialStatus, orElse: null);
(element) => element == widget.initialStatus,
orElse: null);
if (widget.initialStatus != _selectedStatus) { if (widget.initialStatus != _selectedStatus) {
widget.onSelect?.call(_selectedStatus); // Use null-aware operator widget.onSelect?.call(_selectedStatus); // Use null-aware operator
@ -48,10 +46,7 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
@override @override
void initState() { void initState() {
print('status lenght is ${widget.statuses?.length}'); _selectedStatus = widget.statuses?.firstWhere((element) => element == widget.initialStatus, orElse: () => Lookup());
_selectedStatus = widget.statuses?.firstWhere(
(element) => element == widget.initialStatus,
orElse: () => Lookup());
if (widget.initialStatus != _selectedStatus) { if (widget.initialStatus != _selectedStatus) {
widget.onSelect?.call(_selectedStatus); // Use null-aware operator widget.onSelect?.call(_selectedStatus); // Use null-aware operator
@ -62,25 +57,22 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container(height: 60.toScreenHeight, return Container(
height: 60.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
decoration: BoxDecoration( decoration: BoxDecoration(
color: context.isDark && (!widget.enabled || widget.statuses!.isEmpty) color: context.isDark && (!widget.enabled || widget.statuses!.isEmpty)
? AppColor.neutral50 ? AppColor.neutral50
: (!widget.enabled || widget.statuses!.isEmpty) : (!widget.enabled || widget.statuses!.isEmpty)
? AppColor.neutral40 ? AppColor.neutral40
: AppColor.background(context), : AppColor.background(context),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
boxShadow: [ boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)
],
), ),
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
if (widget.enabled) if (widget.enabled) const PositionedDirectional(end: 0, child: Icon(Icons.keyboard_arrow_down_rounded)),
const PositionedDirectional(
end: 0, child: Icon(Icons.keyboard_arrow_down_rounded)),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -88,9 +80,7 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
if (widget.title != null) if (widget.title != null)
Text( Text(
widget.title!, // Use null assertion operator widget.title!, // Use null assertion operator
style: Theme.of(context).textTheme.bodySmall?.copyWith( style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
color: context.isDark ? null : AppColor.neutral20,
fontWeight: FontWeight.w500),
), ),
DropdownButton<Lookup>( DropdownButton<Lookup>(
value: _selectedStatus, value: _selectedStatus,
@ -107,22 +97,22 @@ class _SingleStatusMenuState extends State<SingleStatusMenu> {
underline: const SizedBox.shrink(), underline: const SizedBox.shrink(),
onChanged: !widget.enabled onChanged: !widget.enabled
? null ? null
: (Lookup? newValue) { // Nullable Lookup : (Lookup? newValue) {
setState(() { // Nullable Lookup
_selectedStatus = newValue; setState(() {
}); _selectedStatus = newValue;
widget.onSelect?.call(newValue); // Use null-aware operator });
}, widget.onSelect?.call(newValue); // Use null-aware operator
items: widget.statuses },
?.map<DropdownMenuItem<Lookup>>((value) { items: widget.statuses?.map<DropdownMenuItem<Lookup>>((value) {
return DropdownMenuItem<Lookup>( return DropdownMenuItem<Lookup>(
value: value, value: value,
child: Text(value.name ?? "", // Use null-aware operator child: Text(
value.name ?? "", // Use null-aware operator
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
), ),
); );
}) }).toList(),
.toList(),
), ),
], ],
), ),

Loading…
Cancel
Save