This commit is contained in:
Hamza-Ayed
2024-07-16 13:39:47 +03:00
parent 8661bd7f3f
commit 54e92f4aa3
16 changed files with 256 additions and 33 deletions

View File

@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Existing permissions remain unchanged -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
@@ -32,7 +33,19 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<!-- Add this new intent filter for deep linking -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "sefer://" -->
<data android:scheme="sefer" />
<!-- Accepts URIs that begin with "https://sefer.live" -->
<data android:scheme="https" android:host="sefer.live" />
</intent-filter>
</activity> </activity>
<!-- Existing meta-data and other activities remain unchanged -->
<meta-data <meta-data
android:name="com.google.android.geo.API_KEY" android:name="com.google.android.geo.API_KEY"
android:value="@string/api_key" /> android:value="@string/api_key" />

View File

@@ -8,6 +8,7 @@ class BoxName {
static const String gender = "gender"; static const String gender = "gender";
static const String carType = "carType"; static const String carType = "carType";
static const String carPlate = "carPlate"; static const String carPlate = "carPlate";
static const String packagInfo = "packagInfo";
static const String isVerified = '0'; static const String isVerified = '0';
static const String statusDriverLocation = "statusDriverLocation"; static const String statusDriverLocation = "statusDriverLocation";
static const String password = "password"; static const String password = "password";

View File

@@ -134,12 +134,12 @@ class FirebaseMessagesController extends GetxController {
NotificationController() NotificationController()
.showNotification('Promo', 'Show latest promo'.tr, 'promo'); .showNotification('Promo', 'Show latest promo'.tr, 'promo');
Get.to(const PromosPassengerPage()); Get.to(const PromosPassengerPage());
} else if (message.notification!.title! == 'Trip Monitoring') { } else if (message.notification!.title! == 'Trip Monitoring'.tr) {
NotificationController().showNotification( NotificationController()
'Trip Monitoring'.tr, 'Show latest promo'.tr, 'iphone_ringtone'); .showNotification('Trip Monitoring'.tr, '', 'iphone_ringtone');
var myListString = message.data['passengerList']; var myListString = message.data['passengerList'];
var myList = jsonDecode(myListString) as List<dynamic>; var myList = jsonDecode(myListString) as List<dynamic>;
Get.to(const TripMonitor(), arguments: { Get.toNamed('/tripmonitor', arguments: {
'rideId': myList[0].toString(), 'rideId': myList[0].toString(),
'driverId': myList[1].toString(), 'driverId': myList[1].toString(),
}); });
@@ -214,9 +214,11 @@ class FirebaseMessagesController extends GetxController {
onPressed: () { onPressed: () {
Get.offAll(() => const MapPagePassenger()); Get.offAll(() => const MapPagePassenger());
})); }));
} else if (message.notification!.title! == "Trip Monitoring".tr) { }
Get.to(() => const TripMonitor()); // else if (message.notification!.title! == "Trip Monitoring".tr) {
} else if (message.notification!.title! == 'Call Income') { // Get.to(() => const TripMonitor());
// }
else if (message.notification!.title! == 'Call Income') {
try { try {
var myListString = message.data['passengerList']; var myListString = message.data['passengerList'];
var driverList = jsonDecode(myListString) as List<dynamic>; var driverList = jsonDecode(myListString) as List<dynamic>;

View File

@@ -7,14 +7,18 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../../constant/box_name.dart';
import '../../constant/info.dart'; import '../../constant/info.dart';
import '../../main.dart';
Future<void> checkForUpdate(BuildContext context) async { Future<void> checkForUpdate(BuildContext context) async {
final packageInfo = await PackageInfo.fromPlatform(); final packageInfo = await PackageInfo.fromPlatform();
final currentVersion = packageInfo.buildNumber; final currentVersion = packageInfo.buildNumber;
final version = packageInfo.version;
print('currentVersion is : $currentVersion'); print('currentVersion is : $currentVersion');
// Fetch the latest version from your server // Fetch the latest version from your server
String latestVersion = await getPackageInfo(); String latestVersion = await getPackageInfo();
box.write(BoxName.packagInfo, version);
if (latestVersion.isNotEmpty && latestVersion != currentVersion) { if (latestVersion.isNotEmpty && latestVersion != currentVersion) {
showUpdateDialog(context); showUpdateDialog(context);

View File

@@ -1431,7 +1431,7 @@ class MapPassengerController extends GetxController {
var res = await CRUD().getTokenParent( var res = await CRUD().getTokenParent(
link: AppLink.getTokenParent, link: AppLink.getTokenParent,
payload: {'phone': '+2' + box.read(BoxName.sosPhonePassenger)}); payload: {'phone': '+2${box.read(BoxName.sosPhonePassenger)}'});
// Check if `res` is already a map // Check if `res` is already a map
if (res is Map<String, dynamic>) { if (res is Map<String, dynamic>) {

View File

@@ -1,9 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:SEFER/views/auth/login_page.dart'; import 'package:SEFER/views/auth/login_page.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:uni_links/uni_links.dart';
import '../../constant/box_name.dart'; import '../../constant/box_name.dart';
import '../../main.dart'; import '../../main.dart';
@@ -29,10 +31,52 @@ class SplashScreenController extends GetxController
update(); update();
} }
StreamSubscription? _sub;
Future<void> initUniLinks() async {
// Handle initial URI if the app was launched from a link
try {
final initialUri = await getInitialUri();
if (initialUri != null) {
handleLink(initialUri);
}
} on PlatformException {
// Handle exception by warning the user their action did not succeed
print("Failed to get initial uri");
}
// Listen to new links while the app is running
_sub = uriLinkStream.listen((Uri? uri) {
if (uri != null) {
handleLink(uri);
}
}, onError: (Object err) {
print('Error occurred: $err');
});
}
void handleLink(Uri uri) {
if (uri.host == 'sefer.live' && uri.path == '/tripmonitor') {
final rideId = uri.queryParameters['rideId'];
final driverId = uri.queryParameters['driverId'];
if (rideId != null && driverId != null) {
Get.toNamed('/tripmonitor', parameters: {
'rideId': rideId,
'driverId': driverId,
});
} else {
// Handle the case where rideId or driverId is null
print('Invalid parameters in the deep link');
// You might want to show an error message to the user or handle this case differently
}
}
}
@override @override
void onInit() async { void onInit() async {
super.onInit(); super.onInit();
checkForUpdate(); checkForUpdate();
initUniLinks();
animationController = AnimationController( animationController = AnimationController(
vsync: this, vsync: this,
duration: const Duration(seconds: 4), duration: const Duration(seconds: 4),

View File

@@ -51,11 +51,18 @@ class TripMonitorController extends GetxController {
}); });
} }
init() async { // init() async {
final arguments = Get.arguments; // final arguments = Get.arguments;
driverId = arguments['driverId']; // driverId = arguments['driverId'];
rideId = arguments['rideId']; // rideId = arguments['rideId'];
// await getLocationParent();
// }
Future<void> init({String? rideId, String? driverId}) async {
this.driverId = driverId!;
this.rideId = rideId!;
await getLocationParent(); await getLocationParent();
update();
} }
void addCustomCarIcon() { void addCustomCarIcon() {

View File

@@ -58,8 +58,7 @@ class MyTranslation extends Translations {
"You can only use one device at a time. This device will now be set as your active device.": "You can only use one device at a time. This device will now be set as your active device.":
"يمكنك استخدام جهاز واحد في المرة الواحدة. سيتم الآن تعيين هذا الجهاز كجهازك النشط.", "يمكنك استخدام جهاز واحد في المرة الواحدة. سيتم الآن تعيين هذا الجهاز كجهازك النشط.",
"Click here point": "انقر هنا", // Click here (literal translation) "Click here point": "انقر هنا", // Click here (literal translation)
"Pick or Tap to confirm":
"اختر أو اضغط للتأكيد", // Choose or Tap to confirm
"Are you want to change": "هل تريد التغيير؟", "Are you want to change": "هل تريد التغيير؟",
'by': 'ب', 'by': 'ب',
"Enter your complaint here": "أدخل شكواك هنا", "Enter your complaint here": "أدخل شكواك هنا",
@@ -259,7 +258,7 @@ iOS [https://getapp.cc/app/6458734951]
"Enter your phone number": "أدخل رقم هاتفك", "Enter your phone number": "أدخل رقم هاتفك",
"Please enter your phone number.": "يرجى إدخال رقم هاتفك.", "Please enter your phone number.": "يرجى إدخال رقم هاتفك.",
"Please enter Your Password.": "يرجى إدخال كلمة المرور.", "Please enter Your Password.": "يرجى إدخال كلمة المرور.",
"Submit": "إرسال",
"if you dont have account": "إذا لم يكن لديك حساب", "if you dont have account": "إذا لم يكن لديك حساب",
"Register": "تسجيل", "Register": "تسجيل",
"Accept Ride's Terms & Review Privacy Notice": "Accept Ride's Terms & Review Privacy Notice":
@@ -321,7 +320,7 @@ iOS [https://getapp.cc/app/6458734951]
"Favorite Places": "الأَمَاكِن المُفَضَّلَة", "Favorite Places": "الأَمَاكِن المُفَضَّلَة",
"From : Current Location": "مِنْ: المَوْقِع الحَالِي", "From : Current Location": "مِنْ: المَوْقِع الحَالِي",
"Where to": "إِلَى أَيْن", "Where to": "إِلَى أَيْن",
"Notifications": "الإشْعَارَات", // "Notifications": "الإشْعَارَات",
"Profile": "الملف الشَّخْصِي", "Profile": "الملف الشَّخْصِي",
"Home": "الصَّفْحَة الرَّئِيسِيَّة", "Home": "الصَّفْحَة الرَّئِيسِيَّة",
"My Cared": "المُهْتَمَّ بِهِ", "My Cared": "المُهْتَمَّ بِهِ",
@@ -401,12 +400,12 @@ iOS [https://getapp.cc/app/6458734951]
"Delete My Account": "حَذْف حِسَابِي", "Delete My Account": "حَذْف حِسَابِي",
"Edit Profile": "تَعْدِيل الْمِلَف الشَّخْصِي", "Edit Profile": "تَعْدِيل الْمِلَف الشَّخْصِي",
"Name": "الاسْم", "Name": "الاسْم",
"Gender": "الْجِنْس", // "Gender": "الْجِنْس",
"Update Gender": "تَحْدِيث الْجِنْس", "Update Gender": "تَحْدِيث الْجِنْس",
"Education": "التَّعْلِيم", "Education": "التَّعْلِيم",
"Update Education": "تَحْدِيث التَّعْلِيم", "Update Education": "تَحْدِيث التَّعْلِيم",
"Employment Type": "نَوْع التَّوْظِيف", "Employment Type": "نَوْع التَّوْظِيف",
"Marital Status": "الْحَالَة الاجْتِمَاعِيَّة", // "Marital Status": "الْحَالَة الاجْتِمَاعِيَّة",
"SOS Phone": "هَاتِف الطَّوَارِئ", "SOS Phone": "هَاتِف الطَّوَارِئ",
"High School Diploma": "شَهَادَة الثَّانَوِيَّة الْعَامَّة", "High School Diploma": "شَهَادَة الثَّانَوِيَّة الْعَامَّة",
"Associate Degree": "دَرَجَة الزَّمَالَة", "Associate Degree": "دَرَجَة الزَّمَالَة",

View File

@@ -21,6 +21,7 @@ import 'controller/payment/paymob/paymob_wallet.dart';
import 'firebase_options.dart'; import 'firebase_options.dart';
import 'models/db_sql.dart'; import 'models/db_sql.dart';
import 'splash_screen_page.dart'; import 'splash_screen_page.dart';
import 'views/home/HomePage/trip_monitor/trip_monitor.dart';
final box = GetStorage(); final box = GetStorage();
const storage = FlutterSecureStorage(); const storage = FlutterSecureStorage();
@@ -112,6 +113,12 @@ class MyApp extends StatelessWidget {
key: UniqueKey(), key: UniqueKey(),
// routes: {'/':const HomePage()}, // routes: {'/':const HomePage()},
// home: LoginCaptin()); // home: LoginCaptin());
home: SplashScreen()); initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => SplashScreen()),
GetPage(name: '/tripmonitor', page: () => const TripMonitor()),
],
// home: SplashScreen()
);
} }
} }

View File

@@ -5,7 +5,9 @@ import 'package:SEFER/constant/colors.dart';
import 'package:SEFER/constant/info.dart'; import 'package:SEFER/constant/info.dart';
import 'package:SEFER/constant/style.dart'; import 'package:SEFER/constant/style.dart';
import 'constant/box_name.dart';
import 'controller/home/splash_screen_controlle.dart'; import 'controller/home/splash_screen_controlle.dart';
import 'main.dart';
class SplashScreen extends StatelessWidget { class SplashScreen extends StatelessWidget {
final SplashScreenController splashScreenController = final SplashScreenController splashScreenController =
@@ -63,13 +65,18 @@ class SplashScreen extends StatelessWidget {
const SizedBox( const SizedBox(
height: 100, height: 100,
), ),
Text(
splashScreenController.version.toString(),
style: AppStyle.title,
),
], ],
), ),
), ),
bottomNavigationBar: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
box.read(BoxName.packagInfo) ?? '1.4.54',
style: AppStyle.subtitle,
),
],
),
); );
} }
} }

View File

@@ -0,0 +1,105 @@
import 'dart:io';
import 'package:SEFER/controller/home/trip_monitor_controller.dart';
import 'package:SEFER/views/widgets/my_scafold.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:vibration/vibration.dart';
import '../../../../constant/colors.dart';
import '../../../../constant/style.dart';
import '../../../widgets/elevated_btn.dart';
class TripMonitor extends StatelessWidget {
const TripMonitor({super.key});
@override
Widget build(BuildContext context) {
final params = Get.parameters;
// Use params to initialize your controller or pass data
Get.put(TripMonitorController()).init();
return GetBuilder<TripMonitorController>(builder: (tripMonitorController) {
return MyScafolld(
title: 'Trip Monitor'.tr,
body: [
GoogleMap(
onMapCreated: tripMonitorController.onMapCreated,
initialCameraPosition: CameraPosition(
// bearing: 45,
target: tripMonitorController.parentLocation,
zoom: 16,
tilt: 40,
),
// onCameraMove: (position) {},
markers: {
Marker(
markerId: MarkerId('start'.tr),
position: tripMonitorController.parentLocation,
draggable: true,
icon: tripMonitorController.tripData['message'][0]['model']
.contains('دراجة')
? tripMonitorController.motoIcon
: tripMonitorController.tripData['message'][0]['model']
['gender'] ==
'Male'
? tripMonitorController.carIcon
: tripMonitorController.ladyIcon,
rotation: tripMonitorController.rotation,
),
},
),
speedCircle()
],
isleading: true,
);
});
}
}
GetBuilder<TripMonitorController> speedCircle() {
if (Get.find<TripMonitorController>().speed > 100) {
if (Platform.isIOS) {
HapticFeedback.selectionClick();
} else {
Vibration.vibrate(duration: 1000);
}
Get.defaultDialog(
barrierDismissible: false,
titleStyle: AppStyle.title,
title: 'Speed Over'.tr,
middleText: 'Please slow down'.tr,
middleTextStyle: AppStyle.title,
confirm: MyElevatedButton(
title: 'I will slow down'.tr,
onPressed: () => Get.back(),
),
);
}
return GetBuilder<TripMonitorController>(
builder: (tripMonitorController) {
return Positioned(
bottom: 25,
right: 100,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: tripMonitorController.speed > 100
? Colors.red
: AppColor.secondaryColor,
border: Border.all(width: 3, color: AppColor.redColor),
),
height: 60,
width: 60,
child: Center(
child: Text(
tripMonitorController.speed.toStringAsFixed(0),
style: AppStyle.number,
),
),
),
);
},
);
}

View File

@@ -17,7 +17,15 @@ class TripMonitor extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Get.put(TripMonitorController()).init(); final params = Get.parameters;
final arguments = Get.arguments as Map<String, dynamic>?;
// Use params or arguments to initialize your controller
final controller = Get.put(TripMonitorController());
controller.init(
rideId: params['rideId'] ?? arguments?['rideId'],
driverId: params['driverId'] ?? arguments?['driverId'],
);
return GetBuilder<TripMonitorController>(builder: (tripMonitorController) { return GetBuilder<TripMonitorController>(builder: (tripMonitorController) {
return MyScafolld( return MyScafolld(
title: 'Trip Monitor'.tr, title: 'Trip Monitor'.tr,

View File

@@ -34,6 +34,7 @@ class MapPagePassenger extends StatelessWidget {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
checkForUpdate(context); checkForUpdate(context);
}); });
return Scaffold( return Scaffold(
body: SafeArea( body: SafeArea(
child: Stack( child: Stack(

View File

@@ -297,7 +297,7 @@ class RideBeginPassenger extends StatelessWidget {
await controller.getTokenForParent(); await controller.getTokenForParent();
}, },
icon: const Icon( icon: const Icon(
Foundation.record, Foundation.video,
color: AppColor.blueColor, color: AppColor.blueColor,
), ),
), ),

View File

@@ -1717,6 +1717,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.2" version: "1.3.2"
uni_links:
dependency: "direct main"
description:
name: uni_links
sha256: "051098acfc9e26a9fde03b487bef5d3d228ca8f67693480c6f33fd4fbb8e2b6e"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
uni_links_platform_interface:
dependency: transitive
description:
name: uni_links_platform_interface
sha256: "929cf1a71b59e3b7c2d8a2605a9cf7e0b125b13bc858e55083d88c62722d4507"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
uni_links_web:
dependency: transitive
description:
name: uni_links_web
sha256: "7539db908e25f67de2438e33cc1020b30ab94e66720b5677ba6763b25f6394df"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
url_launcher: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -57,6 +57,7 @@ dependencies:
sign_in_with_apple: ^6.1.0 sign_in_with_apple: ^6.1.0
firebase_auth: ^4.19.6 firebase_auth: ^4.19.6
package_info_plus: ^8.0.0 package_info_plus: ^8.0.0
uni_links: ^0.5.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: