You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
13 KiB
Dart
314 lines
13 KiB
Dart
import 'dart:developer';
|
|
import 'dart:io';
|
|
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flare_flutter/flare_actor.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_callkit_incoming/entities/call_kit_params.dart';
|
|
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
|
|
import 'package:local_auth/local_auth.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:safe_device/safe_device.dart';
|
|
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
|
import 'package:test_sa/controllers/notification/firebase_notification_manger.dart';
|
|
import 'package:test_sa/controllers/providers/api/user_provider.dart';
|
|
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
|
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
|
import 'package:test_sa/modules/cx_module/chat/calling/audio_call_page.dart';
|
|
import 'package:test_sa/modules/cx_module/chat/calling/video_call_page.dart';
|
|
import 'package:test_sa/modules/cx_module/chat/model/chat_participant_model.dart';
|
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
|
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.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/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/dialoge/single_btn_dialog.dart';
|
|
import 'package:test_sa/new_views/swipe_module/swipe_view.dart';
|
|
import 'package:test_sa/views/update_available_screen.dart';
|
|
import 'package:app_badge_control_flutter/app_badge_control_flutter.dart';
|
|
import '../../models/size_config.dart';
|
|
|
|
class SplashPage extends StatefulWidget {
|
|
static const String routeName = '/splash_page';
|
|
|
|
const SplashPage({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<SplashPage> createState() => _SplashPageState();
|
|
}
|
|
|
|
class _SplashPageState extends State<SplashPage> {
|
|
late SettingProvider _settingProvider;
|
|
late UserProvider _userProvider;
|
|
|
|
bool loading = false;
|
|
|
|
@override
|
|
void initState() {
|
|
Firebase.initializeApp();
|
|
AppBadgeControlFlutter.isAppBadgeSupported().then((isSupported) {
|
|
if (isSupported) {
|
|
AppBadgeControlFlutter.removeBadge();
|
|
} else {
|
|
log("AppBadgeControlFlutter: Badge not supported");
|
|
}
|
|
});
|
|
|
|
// NotificationManger.initialisation((notificationDetails) {
|
|
// // todo @sikander, check notifications payload, because notification model is different to need to check from backend
|
|
// // SystemNotificationModel notification = SystemNotificationModel.fromJson(json.decode(notificationDetails.payload));
|
|
// // if (notification.path == null || notification.path.isEmpty) return;
|
|
// // Navigator.pushNamed(context, notification.path, arguments: notification.requestId);
|
|
//
|
|
// isnotificationCame = true;
|
|
// "initialisation:${notificationDetails?.toString()}".showToast;
|
|
//
|
|
// // Navigator.of(context).push(MaterialPageRoute(
|
|
// // builder: (_) => ServiceRequestDetailsPage(
|
|
// // serviceRequest: ServiceRequest(id: "72348"),
|
|
// // )));
|
|
//
|
|
// }, (id, title, body, payload) async {});
|
|
super.initState();
|
|
}
|
|
|
|
void checkTokenValidity(String token) async {
|
|
setState(() {
|
|
loading = true;
|
|
});
|
|
|
|
String osType;
|
|
if (Platform.isIOS) {
|
|
osType = "IOS";
|
|
} else {
|
|
if (await FirebaseNotificationManger.isGoogleServicesAvailable()) {
|
|
osType = "GOOGLE";
|
|
} else {
|
|
osType = "HUAWEI";
|
|
}
|
|
}
|
|
|
|
bool isAppUpdateAvailable = await _settingProvider.checkAppUpdate(URLs.appReleaseBuildNumber, osType);
|
|
if (isAppUpdateAvailable) {
|
|
setState(() {
|
|
loading = false;
|
|
});
|
|
Navigator.of(context).pushNamedAndRemoveUntil(UpdateAvailableScreen.routeName, (routes) => true);
|
|
} else {
|
|
bool isValid = await _settingProvider.checkUserTokenValidation(token);
|
|
setState(() {
|
|
loading = false;
|
|
});
|
|
|
|
if (isValid == false) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext cxt) => SingleBtnDialog(
|
|
title: "Session Expired",
|
|
message: "Login session is expired, Please login.",
|
|
okTitle: "Login",
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
|
|
}),
|
|
);
|
|
} else {
|
|
ApiManager.instance.user = _settingProvider.user!;
|
|
|
|
if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken();
|
|
setState(() {
|
|
loading = true;
|
|
});
|
|
await _userProvider.getUserInfo(fireBaseToken: FirebaseNotificationManger.token).then((status) async {
|
|
setState(() {
|
|
loading = false;
|
|
});
|
|
if (status && _userProvider.refreshedUser != null) {
|
|
_userProvider.refreshedUser!.token = _settingProvider.user?.token;
|
|
await _userProvider.getMobilePermissionByUser();
|
|
await _settingProvider.setUser(_userProvider.refreshedUser!);
|
|
_userProvider.setUser(_userProvider.refreshedUser!);
|
|
await _settingProvider.setAuth(_settingProvider.user?.isEnabledFaceId ?? false);
|
|
}
|
|
if (_settingProvider.isLocalAuthEnable) {
|
|
handleLocalAuth();
|
|
return;
|
|
}
|
|
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleLocalAuth() async {
|
|
bool isSuccess = false;
|
|
try {
|
|
isSuccess = await checkDualAuthentication();
|
|
} catch (ex) {
|
|
// ios exception when scan failed.
|
|
}
|
|
|
|
if (isSuccess) {
|
|
// _userProvider.setUser(_settingProvider.user!);
|
|
// if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken();
|
|
// await _userProvider.getUserInfo(fireBaseToken: FirebaseNotificationManger.token).then((status) async {
|
|
// if (status && _userProvider.refreshedUser != null) {
|
|
// _userProvider.refreshedUser!.token = _settingProvider.user?.token;
|
|
// await _settingProvider.setUser(_userProvider.refreshedUser!);
|
|
// _userProvider.setUser(_settingProvider.user!);
|
|
// await _settingProvider.setAuth(_settingProvider.user?.isEnabledFaceId ?? false);
|
|
// }
|
|
// });
|
|
|
|
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 {
|
|
return await _settingProvider.auth.authenticate(
|
|
localizedReason: Platform.isAndroid ? "Scan your fingerprint to authenticate" : "Scan with face id to authenticate",
|
|
options: const AuthenticationOptions(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
SizeConfig.init(context);
|
|
_settingProvider = Provider.of<SettingProvider>(context, listen: false);
|
|
_userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
return Scaffold(
|
|
body: Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
if (loading)
|
|
Positioned(
|
|
bottom: 100,
|
|
child: SizedBox(
|
|
width: 36,
|
|
height: 36,
|
|
child: CircularProgressIndicator(color: AppColor.loadingColor(context), strokeWidth: 3),
|
|
)),
|
|
SizedBox(
|
|
width: MediaQuery.of(context).size.width / 1.1,
|
|
child: Hero(
|
|
tag: "logo",
|
|
child: FlareActor(
|
|
"assets/rives/atoms_splash.flr",
|
|
fit: BoxFit.contain,
|
|
animation: "splash",
|
|
callback: (animation) async {
|
|
bool isSafe = await checkDeviceSafety();
|
|
await checkVoipCalling();
|
|
if (!isSafe) {
|
|
Navigator.pushNamedAndRemoveUntil(context, UnsafeDeviceScreen.routeName, (_) => false);
|
|
} else {
|
|
if (_settingProvider.isLoaded && (_settingProvider.user != null)) {
|
|
checkTokenValidity(_settingProvider.user!.token!);
|
|
} else {
|
|
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
|
|
}
|
|
}
|
|
|
|
// if (_settingProvider.isLoaded && (_settingProvider.user?.isLiveToken ?? false)) {
|
|
// _userProvider.user = _settingProvider.user;
|
|
// Navigator.of(context).pushNamedAndRemoveUntil(LandPage.routeName, (routes) => true);
|
|
// // if(isnotificationCame)
|
|
// // Navigator.of(context).push(MaterialPageRoute(
|
|
// // builder: (_) => ServiceRequestDetailsPage(
|
|
// // serviceRequest: ServiceRequest(id: "72348"),
|
|
// // )));
|
|
// /// The below line for the new design
|
|
// // Navigator.of(context).pushNamedAndRemoveUntil(LandPage.routeName, (routes) => true);
|
|
// }
|
|
},
|
|
),
|
|
),
|
|
).center,
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Future checkVoipCalling() async {
|
|
var activeCalls = await FlutterCallkitIncoming.activeCalls();
|
|
|
|
if (activeCalls is List && activeCalls.isNotEmpty) {
|
|
CallKitParams lastCall = activeCalls.last;
|
|
if (lastCall.isAccepted) {
|
|
final String? callUuid = lastCall.id;
|
|
final extra = lastCall.extra ?? {};
|
|
final isVideoCall = extra["isVideoCall"] == true || extra["isVideoCall"]?.toString().toLowerCase() == 'true';
|
|
|
|
// The same accepted call may also arrive via land_page's callkit listener - open it once.
|
|
if (!FirebaseNotificationManger.beginAcceptedCall(extra["callId"]?.toString() ?? callUuid ?? '')) return;
|
|
try {
|
|
// Asks for mic (+camera) on Accept; offers Settings if permanently denied.
|
|
if (!await ensureCallPermissionsOnAccept(context, isVideoCall: isVideoCall)) {
|
|
await FlutterCallkitIncoming.endAllCalls();
|
|
await notifyCallerDeclined(extra, reason: 'PERMISSION_DENIED');
|
|
return;
|
|
}
|
|
|
|
// iOS: never call setCallConnected on an already-answered call - it issues another
|
|
// CXAnswerCallAction, which re-emits ACTION_CALL_ACCEPT and re-opens the call page.
|
|
if (!Platform.isIOS) await FlutterCallkitIncoming.setCallConnected(callUuid!);
|
|
final sender = Participants(employeeNumber: extra["calleeEmployeeNumber"]?.toString());
|
|
final recipient = Participants(employeeNumber: extra["callerEmployeeNumber"]?.toString());
|
|
final moduleId = int.tryParse(extra["moduleId"]?.toString() ?? '') ?? 0;
|
|
final referenceID = int.tryParse(extra["referenceId"]?.toString() ?? '');
|
|
if (!mounted) return;
|
|
await Navigator.of(context).push(MaterialPageRoute(
|
|
builder: (_) => isVideoCall
|
|
? VideoCallPage(sender: sender, recipient: recipient, moduleId: moduleId, referenceID: referenceID, isAccept: true)
|
|
: AudioCallPage(sender: sender, recipient: recipient, moduleId: moduleId, referenceID: referenceID, isAccept: true)));
|
|
FlutterCallkitIncoming.endCall(lastCall.extra?["callId"]);
|
|
FlutterCallkitIncoming.endAllCalls();
|
|
} finally {
|
|
FirebaseNotificationManger.endAcceptedCall();
|
|
}
|
|
}
|
|
} else {
|
|
await FlutterCallkitIncoming.endAllCalls();
|
|
}
|
|
}
|
|
|
|
Future<bool> checkDeviceSafety() async {
|
|
if (!kReleaseMode) return true;
|
|
bool isJailBroken = false;
|
|
bool isRealDevice = false;
|
|
|
|
try {
|
|
isJailBroken = await SafeDevice.isJailBroken;
|
|
isRealDevice = await SafeDevice.isRealDevice;
|
|
if (isJailBroken || !isRealDevice) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
} catch (error) {
|
|
print(error);
|
|
return false;
|
|
}
|
|
}
|
|
}
|