diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 81543587..9dd449c6 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -22,7 +22,8 @@ android { namespace = "com.cloudsolutions.HMGPatientApp" compileSdk = 36 // Using NDK 26 for better compatibility with Zoom SDK native libraries - ndkVersion = "27.0.12077973" +// ndkVersion = "27.0.12077973" + ndkVersion = "28.2.13676358" // ndkVersion = "25.1.8937393" sourceSets { @@ -105,7 +106,8 @@ android { "lib/arm64-v8a/libc++_shared.so", "**/*.so" ) - useLegacyPackaging = true +// useLegacyPackaging = true + useLegacyPackaging = false // Keep Zoom SDK libraries unstripped to preserve symbols keepDebugSymbols += listOf( "*/libzoom_util.so", @@ -177,14 +179,15 @@ dependencies { // implementation("androidx.room:room-runtime:$room_version") // annotationProcessor("androidx.room:room-compiler:$room_version") - implementation("net.zetetic:android-database-sqlcipher:4.5.4") +// implementation("net.zetetic:android-database-sqlcipher:4.5.4") implementation("com.intuit.ssp:ssp-android:1.1.0") implementation("com.intuit.sdp:sdp-android:1.1.0") implementation("com.github.bumptech.glide:glide:4.16.0") annotationProcessor("com.github.bumptech.glide:compiler:4.16.0") - implementation("com.mapbox.maps:android:11.5.0") +// implementation("com.mapbox.maps:android:11.5.0") + implementation("com.mapbox.maps:android-ndk27:11.22.0") implementation("com.mapbox.mapboxsdk:mapbox-sdk-turf:7.3.1") // implementation("com.mapbox.maps:android:11.4.0") @@ -208,7 +211,7 @@ dependencies { implementation("androidx.appcompat:appcompat:1.7.1") implementation("com.google.android.material:material:1.12.0") - implementation("pl.droidsonroids.gif:android-gif-drawable:1.2.25") + implementation("pl.droidsonroids.gif:android-gif-drawable:1.2.29") implementation("com.mapbox.mapboxsdk:mapbox-sdk-turf:7.3.1") androidTestImplementation("androidx.test:core:1.6.1") diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dec59139..f5b408d8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -42,6 +42,7 @@ tools:node="remove" /> + diff --git a/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so b/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so index a80c8b38..ff5ae6e5 100755 Binary files a/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so and b/android/app/src/main/jniLibs/arm64-v8a/libc++_shared.so differ diff --git a/android/app/src/main/jniLibs/armeabi-v7a/libc++_shared.so b/android/app/src/main/jniLibs/armeabi-v7a/libc++_shared.so index cbff8a90..e642b798 100755 Binary files a/android/app/src/main/jniLibs/armeabi-v7a/libc++_shared.so and b/android/app/src/main/jniLibs/armeabi-v7a/libc++_shared.so differ diff --git a/android/gradle.properties b/android/gradle.properties index 647291d1..f47e3b3a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -2,7 +2,7 @@ android.enableR8=true android.enableJetifier=true android.useDeprecatedNdk=true -org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 org.gradle.daemon=true org.gradle.parallel=true org.gradle.configureondemand=true diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 1331dff6..c25d80ef 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1814,7 +1814,7 @@ "bloodDonationService": "التبرع \n بالدم", "bookAppointmentService": "حجز\nموعد", "pinchToZoom": "اضغط للتكبير", - "gotIt": "فهمت", + "gotIt": "حسنا", "zoomIntoDetails": "قم بالتكبير لرؤية التفاصيل", "pinchWithTwoFingersToZoom": "اضغط بإصبعين للتكبير", "dragToMoveAround": "اسحب للتحرك", diff --git a/check_elf_alignment.sh b/check_elf_alignment.sh new file mode 100755 index 00000000..debc0028 --- /dev/null +++ b/check_elf_alignment.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +# Check ELF .so alignment in APK for 16KB page size compatibility +# Files must have PT_LOAD segments aligned to 16384 bytes (0x4000) + +APK="${1:-/Users/mohamedmekawy/Documents/Work/HMG_Patient_App_New/android/app/release/app-release.apk}" +LLVM_READELF="/Users/mohamedmekawy/Library/Android/sdk/ndk/28.2.13676358/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf" +EXTRACT_DIR="/tmp/apk_alignment_check" +REQUIRED_ALIGNMENT=16384 # 16 KB + +echo "========================================" +echo " ELF Alignment Check for 16KB Page Size" +echo "========================================" +echo "APK: $APK" +echo "" + +if [ ! -f "$APK" ]; then + echo "ERROR: APK not found at $APK" + exit 1 +fi + +# Clean and extract APK +rm -rf "$EXTRACT_DIR" +mkdir -p "$EXTRACT_DIR" +unzip -q "$APK" -d "$EXTRACT_DIR" + +# Find all .so files +SO_FILES=$(find "$EXTRACT_DIR" -name "*.so") + +if [ -z "$SO_FILES" ]; then + echo "No .so files found in APK." + exit 0 +fi + +FAILED=() +PASSED=() + +for SO in $SO_FILES; do + RELATIVE="${SO#$EXTRACT_DIR/}" + + # Check if it's a valid ELF + MAGIC=$(xxd -l 4 "$SO" 2>/dev/null | head -1) + if [[ "$MAGIC" != *"7f45 4c46"* ]]; then + continue + fi + + # Use llvm-readelf from NDK + READELF_OUTPUT=$("$LLVM_READELF" -l "$SO" 2>/dev/null) + + if [ -z "$READELF_OUTPUT" ]; then + echo "⚠️ SKIP (readelf unavailable): $RELATIVE" + continue + fi + + # Extract LOAD segment alignments + MISALIGNED=false + while IFS= read -r line; do + if [[ "$line" == *"LOAD"* ]]; then + # Get the last field (Align column) + ALIGN=$(echo "$line" | awk '{print $NF}') + # Convert hex to decimal if needed + if [[ "$ALIGN" == 0x* ]]; then + ALIGN_DEC=$((ALIGN)) + else + ALIGN_DEC=$ALIGN + fi + + if [[ "$ALIGN_DEC" =~ ^[0-9]+$ ]]; then + if [ "$ALIGN_DEC" -lt "$REQUIRED_ALIGNMENT" ] && [ "$ALIGN_DEC" -gt 0 ]; then + MISALIGNED=true + ALIGN_KB=$((ALIGN_DEC / 1024)) + echo "❌ FAIL (${ALIGN_KB}KB aligned): $RELATIVE" + break + fi + fi + fi + done <<< "$READELF_OUTPUT" + + if [ "$MISALIGNED" = false ]; then + ALIGN_LINE=$(echo "$READELF_OUTPUT" | grep "LOAD" | head -1 | awk '{print $NF}') + echo "✅ PASS ($ALIGN_LINE aligned): $RELATIVE" + PASSED+=("$RELATIVE") + else + FAILED+=("$RELATIVE") + fi +done + +echo "" +echo "========================================" +echo "SUMMARY" +echo "========================================" +echo "✅ Passed (16KB+ aligned): ${#PASSED[@]}" +echo "❌ Failed (< 16KB aligned): ${#FAILED[@]}" + +if [ ${#FAILED[@]} -gt 0 ]; then + echo "" + echo "The following .so files are NOT 16KB page aligned:" + for f in "${FAILED[@]}"; do + echo " - $f" + done + echo "" + echo "These files will cause issues on Android 15+ devices with 16KB page size." +else + echo "" + echo "All .so files are 16KB page aligned. ✅" +fi + +# Cleanup +rm -rf "$EXTRACT_DIR" + diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart index a13dbcdd..01cee861 100644 --- a/lib/presentation/prescriptions/prescription_detail_page.dart +++ b/lib/presentation/prescriptions/prescription_detail_page.dart @@ -9,12 +9,14 @@ import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_item_view.dart'; +import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; @@ -237,7 +239,8 @@ class _PrescriptionDetailPageState extends State { ), ), ), - Container( + Column( + children: [ Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 24.h, @@ -268,8 +271,55 @@ class _PrescriptionDetailPageState extends State { icon: AppAssets.prescription_refill_icon, iconColor: widget.prescriptionsResponseModel.isHomeMedicineDeliverySupported! ? Colors.white : AppColors.textColor.withOpacity(0.35), iconSize: 20.h, - ).paddingSymmetrical(24.h, 24.h), + ).paddingSymmetrical(24.h, 0.h), ), + Utils.havePrivilege(119) ? Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: true, + ), + child: Container( + height: 56.h, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.r), + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + stops: [0.236, 1.0], // 53.6% and 100% + colors: [ + Color(0xFF8A38F5), // Transparent + Color(0xFFE20BBB), // Solid #F8F8F8 + ], + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(right: 4.w, left: 4.w), + child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white), + ), + LocaleKeys.generateAiAnalysisResult.tr(context: context).toText16(isBold: true, color: Colors.white) + ], + ), + ).paddingSymmetrical(24.h, 24.h).onPress(() async { + final _dialogService = getIt.get(); + await _dialogService.showCommonBottomSheetWithoutH( + message: LocaleKeys.aiDisclaimer.tr(), + label: LocaleKeys.consent.tr(), + okLabel: LocaleKeys.acceptLbl.tr(), + cancelLabel: LocaleKeys.rejectView.tr(), + onOkPressed: () { + + }, + onCancelPressed: () { + context.pop(); + }); + }), + ) : SizedBox(height: 24,) , + ]) ], ), ); diff --git a/lib/presentation/symptoms_checker/organ_selector_screen.dart b/lib/presentation/symptoms_checker/organ_selector_screen.dart index 93e826df..9d7f78e8 100644 --- a/lib/presentation/symptoms_checker/organ_selector_screen.dart +++ b/lib/presentation/symptoms_checker/organ_selector_screen.dart @@ -44,8 +44,8 @@ class _OrganSelectorPageState extends State { } Future _checkAndShowTutorial() async { - final hasSeenTutorial = cacheService.getBool(key: CacheConst.organSelectorTutorialShown) ?? false; - if (!hasSeenTutorial) { + // final hasSeenTutorial = cacheService.getBool(key: CacheConst.organSelectorTutorialShown) ?? false; + // if (!hasSeenTutorial) { // Show tutorial after a short delay to ensure the screen is fully built await Future.delayed(const Duration(milliseconds: 500)); if (mounted) { @@ -53,7 +53,7 @@ class _OrganSelectorPageState extends State { _showTutorial = true; }); } - } + // } } void _onTutorialComplete() async { diff --git a/pubspec.yaml b/pubspec.yaml index 34e04a02..14ad3913 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,8 +2,8 @@ name: hmg_patient_app_new description: "New HMG Patient App" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.19+18 -#version: 0.0.1+18 +#version: 0.0.22+21 +version: 0.0.1+20 environment: sdk: ">=3.6.0 <4.0.0"