From a6be594b3b681fbcc9db3aa0c0fc9b8bd7a477c3 Mon Sep 17 00:00:00 2001 From: taha Date: Thu, 1 Oct 2026 14:30:54 +0300 Subject: [PATCH] Update dependencies and improve code structure --- analysis_options.yaml | 5 + android/app/build.gradle | 8 +- android/app/src/main/AndroidManifest.xml | 1 - android/build.gradle | 9 + android/gradle.properties | 6 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 6 +- check.sh | 699 ++++++++++++++++++ ios/Flutter/AppFrameworkInfo.plist | 2 - ios/Runner.xcodeproj/project.pbxproj | 68 +- .../xcshareddata/xcschemes/Runner.xcscheme | 18 + ios/Runner/AppDelegate.swift | 9 +- ios/Runner/Info.plist | 25 +- lib/api/dashboard_api_client.dart | 5 +- lib/classes/date_uitl.dart | 5 +- lib/classes/utils.dart | 37 +- lib/generated_plugin_registrant.dart | 2 - lib/main.dart | 51 +- lib/provider/chat_provider_model.dart | 14 +- lib/theme/app_theme.dart | 1 + lib/ui/login/verify_last_login_screen.dart | 10 +- lib/ui/login/verify_login_screen.dart | 4 +- lib/ui/marathon/widgets/question_card.dart | 11 +- lib/ui/my_team/subordinate_leave.dart | 8 +- .../announcements/announcement_details.dart | 7 +- .../mowadhafhi/mowadhafhi_hr_request.dart | 4 +- .../my_document_detail_screen.dart | 17 +- lib/ui/screens/my_requests/my_requests.dart | 6 +- .../offers_and_discounts_details.dart | 14 +- lib/ui/work_list/item_history_screen.dart | 6 +- lib/ui/work_list/work_list_screen.dart | 2 +- .../worklist_fragments/info_fragments.dart | 2 +- lib/widgets/image_picker.dart | 6 +- lib/widgets/nfc/nfc_reader_sheet.dart | 25 +- pubspec.yaml | 93 +-- 35 files changed, 1010 insertions(+), 178 deletions(-) create mode 100755 check.sh diff --git a/analysis_options.yaml b/analysis_options.yaml index 674be66..8716f74 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -19,6 +19,11 @@ analyzer: unnecessary_null_checks: error unnecessary_brace_in_string_interps: error unnecessary_final: error + exclude: + - build/** + - android/** + - ios/** + - web/** linter: diff --git a/android/app/build.gradle b/android/app/build.gradle index 1901f3a..20d77eb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -18,7 +18,7 @@ if (keystorePropertiesFile.exists()) { android { namespace 'hmg.cloudSolutions.mohem' - compileSdk 36 + compileSdk 37 ndkVersion '28.2.13676358' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "hmg.cloudSolutions.mohem" minSdkVersion 30 - targetSdk 35 + targetSdk 37 targetSdk = flutter.targetSdkVersion versionCode flutter.versionCode versionName flutter.versionName @@ -60,12 +60,14 @@ android { buildTypes { debug { signingConfig signingConfigs.debug + minifyEnabled false + shrinkResources false } release { signingConfig signingConfigs.release minifyEnabled true shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles 'proguard-rules.pro' } } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a8196e0..6477dfd 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -43,7 +43,6 @@ android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="MoheM" - android:extractNativeLibs="true" android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round"> + if (project.name == "huawei_push") { + project.android { + compileSdk 36 + } + } + } +} rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" diff --git a/android/gradle.properties b/android/gradle.properties index 8df3fe9..acecd2f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -4,4 +4,8 @@ android.useAndroidX=true android.enableJetifier=true apmsInstrumentationEnabled=false -#org.gradle.java.home=/Users/amirs/Library/Java/JavaVirtualMachines/jbr-17.0.12/Contents/Home/ \ No newline at end of file +#org.gradle.java.home=/Users/amirs/Library/Java/JavaVirtualMachines/jbr-17.0.12/Contents/Home/ +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 941ceb1..54ce42e 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jul 08 11:08:34 AST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/settings.gradle b/android/settings.gradle index 10a4a8d..1f8397e 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -30,8 +30,10 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.11.0' apply false - id("org.jetbrains.kotlin.android") version "2.2.0" apply false +// id "com.android.application" version '8.11.0' apply false +// id("org.jetbrains.kotlin.android") version "2.2.0" apply false + id "com.android.application" version '9.0.1' apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false id("com.google.gms.google-services") version "4.4.3" apply false id("com.google.firebase.crashlytics") version "3.0.4" apply false id('org.gradle.toolchains.foojay-resolver-convention') version '0.9.0' apply false diff --git a/check.sh b/check.sh new file mode 100755 index 0000000..d8db129 --- /dev/null +++ b/check.sh @@ -0,0 +1,699 @@ +#!/bin/bash + +# Enhanced ELF Alignment Checker for Android 16KB Page Size Compatibility +# This script checks if your app's native libraries are compatible with 16KB page size devices +# as required by Google Play starting November 1st, 2025 for apps targeting Android 15+ + +progname="${0##*/}" +progname="${progname%.sh}" + +# Color codes and formatting - detect if colors are supported +if [[ -t 1 ]] && command -v tput >/dev/null 2>&1 && tput colors >/dev/null 2>&1 && [[ $(tput colors) -ge 8 ]]; then + RED="\033[31m" + GREEN="\033[32m" + YELLOW="\033[33m" + BLUE="\033[34m" + CYAN="\033[36m" + PURPLE="\033[35m" + BOLD="\033[1m" + DIM="\033[2m" + ENDCOLOR="\033[0m" + USE_COLORS=true +else + # No color support - use plain text + RED="" + GREEN="" + YELLOW="" + BLUE="" + CYAN="" + PURPLE="" + BOLD="" + DIM="" + ENDCOLOR="" + USE_COLORS=false +fi + +# Unicode symbols with fallbacks +if [[ $USE_COLORS == true ]]; then + CHECK_MARK="āœ“" + CROSS_MARK="āœ—" + WARNING_MARK="⚠" + INFO_MARK="ℹ" + ROCKET="šŸš€" + GEAR="āš™" + PACKAGE="šŸ“¦" + DOCUMENT="šŸ“„" + ALERT="🚨" + PARTY="šŸŽ‰" + TOOLS="šŸ”§" + BOOKS="šŸ“š" + ARROW="ā–¶" +else + CHECK_MARK="[OK]" + CROSS_MARK="[X]" + WARNING_MARK="[!]" + INFO_MARK="[i]" + ROCKET="[>]" + GEAR="[*]" + PACKAGE="[P]" + DOCUMENT="[D]" + ALERT="[!]" + PARTY="[*]" + TOOLS="[T]" + BOOKS="[B]" + ARROW=">" +fi + +# Enhanced formatting functions +print_banner() { + local title="$1" + local subtitle="$2" + local width=88 + + echo + printf "%*s\n" $width | tr ' ' '═' + + # Main title + local title_len=${#title} + local title_padding=$(( (width - title_len - 4) / 2 )) + printf "ā•‘${BOLD}${BLUE}%*s %s %*s${ENDCOLOR}ā•‘\n" \ + $title_padding "" "$title" $title_padding "" + + # Subtitle if provided + if [[ -n "$subtitle" ]]; then + local subtitle_len=${#subtitle} + local subtitle_padding=$(( (width - subtitle_len - 4) / 2 )) + printf "ā•‘${DIM}%*s %s %*s${ENDCOLOR}ā•‘\n" \ + $subtitle_padding "" "$subtitle" $subtitle_padding "" + fi + + printf "%*s\n" $width | tr ' ' '═' + echo +} + +print_section() { + local icon="$1" + local title="$2" + local description="$3" + + echo + echo -e "${BOLD}${BLUE}$icon $title${ENDCOLOR}" + if [[ -n "$description" ]]; then + echo -e "${DIM}$description${ENDCOLOR}" + fi + printf "${BLUE}%*s${ENDCOLOR}\n" 80 | tr ' ' '─' +} + +print_status() { + local status="$1" + local message="$2" + local detail="$3" + + case $status in + "success") + printf " ${GREEN}${CHECK_MARK}${ENDCOLOR} %s" "$message" + ;; + "error") + printf " ${RED}${CROSS_MARK}${ENDCOLOR} %s" "$message" + ;; + "warning") + printf " ${YELLOW}${WARNING_MARK}${ENDCOLOR} %s" "$message" + ;; + "info") + printf " ${CYAN}${INFO_MARK}${ENDCOLOR} %s" "$message" + ;; + "processing") + printf " ${PURPLE}${GEAR}${ENDCOLOR} %s" "$message" + ;; + esac + + if [[ -n "$detail" ]]; then + printf "\n ${DIM}%s${ENDCOLOR}" "$detail" + fi + echo +} + +print_subsection() { + local title="$1" + echo + echo -e " ${BOLD}${PURPLE}${ARROW} $title${ENDCOLOR}" + printf " ${PURPLE}%*s${ENDCOLOR}\n" 50 | tr ' ' 'ā”ˆ' +} + +print_table_header() { + echo + local line1="ā”Œ$(printf '─%.0s' {1..29})┬$(printf '─%.0s' {1..18})┬$(printf '─%.0s' {1..15})┬$(printf '─%.0s' {1..13})┐" + local line2="│ $(printf '%-27s' 'Library') │ $(printf '%-16s' 'Architecture') │ $(printf '%-13s' 'Alignment') │ $(printf '%-11s' 'Status') │" + local line3="ā”œ$(printf '─%.0s' {1..29})┼$(printf '─%.0s' {1..18})┼$(printf '─%.0s' {1..15})┼$(printf '─%.0s' {1..13})┤" + + echo -e "${CYAN}$line1${ENDCOLOR}" + echo -e "${BOLD}${CYAN}$line2${ENDCOLOR}" + echo -e "${CYAN}$line3${ENDCOLOR}" +} + +print_table_row() { + local lib="$1" + local arch="$2" + local alignment="$3" + local status="$4" + local is_critical="$5" + + local status_symbol + local status_color + local status_text + + if [[ $status == "ALIGNED" ]]; then + status_symbol="$CHECK_MARK" + status_color="$GREEN" + status_text="PASS" + else + status_symbol="$CROSS_MARK" + if [[ $is_critical == "true" ]]; then + status_color="$RED" + status_text="FAIL" + else + status_color="$YELLOW" + status_text="WARN" + fi + fi + + # Truncate library name if too long + local display_lib="$lib" + if [[ ${#lib} -gt 27 ]]; then + display_lib="${lib:0:24}..." + fi + + printf "${CYAN}│${ENDCOLOR} %-27s ${CYAN}│${ENDCOLOR} %-16s ${CYAN}│${ENDCOLOR} %-13s ${CYAN}│${ENDCOLOR} ${status_color}%s %-7s${ENDCOLOR} ${CYAN}│${ENDCOLOR}\n" \ + "$display_lib" "$arch" "$alignment" "$status_symbol" "$status_text" + + if [[ $is_critical == "true" && $status == "UNALIGNED" ]]; then + printf "${CYAN}│${ENDCOLOR} ${RED}%-75s${ENDCOLOR} ${CYAN}│${ENDCOLOR}\n" " ${ALERT} CRITICAL: Required for Google Play compliance!" + fi +} + +print_table_footer() { + local line="ā””$(printf '─%.0s' {1..29})┓$(printf '─%.0s' {1..18})┓$(printf '─%.0s' {1..15})┓$(printf '─%.0s' {1..13})ā”˜" + echo -e "${CYAN}$line${ENDCOLOR}" + echo +} + +print_summary_box() { + local title="$1" + local status="$2" # success, warning, error + shift 2 + local lines=("$@") + + local box_color + local title_color + case $status in + "success") box_color="$GREEN"; title_color="$GREEN" ;; + "warning") box_color="$YELLOW"; title_color="$YELLOW" ;; + "error") box_color="$RED"; title_color="$RED" ;; + *) box_color="$BLUE"; title_color="$BLUE" ;; + esac + + local width=78 + echo + printf "${box_color}ā”Œ%*s┐${ENDCOLOR}\n" $((width-2)) | tr ' ' '─' + + # Title + local title_len=${#title} + local title_padding=$(( (width - title_len - 4) / 2 )) + printf "${box_color}│${ENDCOLOR}${BOLD}${title_color}%*s %s %*s${ENDCOLOR}${box_color}│${ENDCOLOR}\n" \ + $title_padding "" "$title" $title_padding "" + + printf "${box_color}ā”œ%*s┤${ENDCOLOR}\n" $((width-2)) | tr ' ' '─' + + # Content lines + for line in "${lines[@]}"; do + printf "${box_color}│${ENDCOLOR} %-*s ${box_color}│${ENDCOLOR}\n" $((width-4)) "$line" + done + + printf "${box_color}ā””%*sā”˜${ENDCOLOR}\n" $((width-2)) | tr ' ' '─' + echo +} + +cleanup_trap() { + if [ -n "${tmp}" -a -d "${tmp}" ]; then + print_status "processing" "Cleaning up temporary files..." + rm -rf "${tmp}" + fi + exit $1 +} + +usage() { + print_banner "Android 16KB Page Size Compatibility Checker" "Google Play Compliance Tool" + + echo -e "${BOLD}DESCRIPTION:${ENDCOLOR}" + echo " This tool verifies that your Android app's native libraries are compatible" + echo " with 16KB page size devices, as required by Google Play starting November 1st, 2025." + echo + + echo -e "${BOLD}USAGE:${ENDCOLOR}" + echo -e " ${GREEN}$progname${ENDCOLOR} ${CYAN}[input-path|input-APK|input-APEX]${ENDCOLOR}" + echo + + echo -e "${BOLD}EXAMPLES:${ENDCOLOR}" + echo -e " ${DIM}# Check an APK file${ENDCOLOR}" + echo -e " $progname ${CYAN}app/build/outputs/apk/release/app-release.apk${ENDCOLOR}" + echo + echo -e " ${DIM}# Check a directory of native libraries${ENDCOLOR}" + echo -e " $progname ${CYAN}/path/to/native/libs/${ENDCOLOR}" + echo + + echo -e "${BOLD}WHAT THIS TOOL CHECKS:${ENDCOLOR}" + echo -e " ${CHECK_MARK} APK zip-alignment for 16KB boundaries (requires build-tools 35.0.0+)" + echo -e " ${CHECK_MARK} ELF segment alignment in native libraries (arm64-v8a and x86_64)" + echo -e " ${CHECK_MARK} Compliance with Android 16KB page size requirements" + echo + + echo -e "${BOLD}RESULT MEANINGS:${ENDCOLOR}" + echo -e " ${GREEN}${CHECK_MARK} PASS${ENDCOLOR} - Library is compatible with 16KB page sizes (2**14 or higher)" + echo -e " ${RED}${CROSS_MARK} FAIL${ENDCOLOR} - Library needs recompilation with 16KB ELF alignment" + echo -e " ${YELLOW}${WARNING_MARK} WARN${ENDCOLOR} - Non-critical architecture but should be fixed" + echo +} + +# Enhanced dependency checking +check_dependencies() { + print_section "$GEAR" "Dependency Check" "Verifying required tools are available" + + local missing_tools=() + local available_tools=() + + # Check each tool + local tools=("objdump" "unzip" "file") + for tool in "${tools[@]}"; do + if command -v "$tool" >/dev/null 2>&1; then + available_tools+=("$tool") + print_status "success" "$tool" "$(which "$tool")" + else + missing_tools+=("$tool") + print_status "error" "$tool not found" + fi + done + + if [ ${#missing_tools[@]} -gt 0 ]; then + echo + print_subsection "Installation Instructions" + for tool in "${missing_tools[@]}"; do + case $tool in + objdump) + print_status "info" "Install objdump:" "macOS: Xcode Command Line Tools or Android NDK's llvm-objdump" + print_status "info" "" "Linux: sudo apt-get install binutils (Ubuntu/Debian)" + ;; + unzip) + print_status "info" "Install unzip:" "Usually pre-installed on most systems" + print_status "info" "" "Linux: sudo apt-get install unzip" + ;; + file) + print_status "info" "Install file:" "Usually pre-installed on most systems" + print_status "info" "" "Linux: sudo apt-get install file" + ;; + esac + echo + done + exit 1 + fi + + print_status "success" "All dependencies satisfied" "${#available_tools[@]} tools available" +} + +# Validate input arguments +if [ ${#} -ne 1 ]; then + usage + exit 1 +fi + +case ${1} in + --help | -h | -\?) + usage + exit 0 + ;; + *) + dir="${1}" + ;; +esac + +# Validate input file/directory +if ! [ -f "${dir}" -o -d "${dir}" ]; then + print_status "error" "Invalid input: ${dir}" + echo " Please provide a valid APK file, APEX file, or directory containing native libraries." + exit 1 +fi + +# Check dependencies before proceeding +check_dependencies + +print_banner "ANALYSIS IN PROGRESS" "Checking 16KB Page Size Compatibility" + +print_status "processing" "Target: $(basename "${dir}")" +print_status "info" "Compliance Deadline: November 1st, 2025" +print_status "info" "Requirement: Apps targeting Android 15+ must support 16KB pages" + +# APK Processing +if [[ "${dir}" == *.apk ]]; then + trap 'cleanup_trap' EXIT + + print_section "$PACKAGE" "APK Analysis" "Processing Android Package file" + + # Enhanced zipalign check + if command -v zipalign >/dev/null 2>&1; then + if { zipalign --help 2>&1 | grep -q "\-P "; }; then + print_status "processing" "Checking APK zip-alignment for 16KB boundaries..." + + zip_result=$(zipalign -v -c -P 16 4 "${dir}" 2>&1) + zip_exit_code=$? + + if [ $zip_exit_code -eq 0 ]; then + print_status "success" "APK zip-alignment verification passed" + else + print_status "error" "APK zip-alignment verification failed" + echo " ${DIM}Details:${ENDCOLOR}" + echo "$zip_result" | grep -E 'lib/arm64-v8a|lib/x86_64|Verification|would be' | sed 's/^/ /' || echo " $zip_result" + fi + else + print_status "warning" "zipalign version doesn't support 16KB alignment checks" + print_status "info" "Solution: Update to Android SDK build-tools 35.0.0+" + echo " ${DIM}Update via Android Studio → SDK Manager → SDK Tools${ENDCOLOR}" + echo " ${DIM}Or run: sdkmanager \"build-tools;35.0.0\"${ENDCOLOR}" + fi + else + print_status "warning" "zipalign not found in PATH" + print_status "info" "Ensure Android SDK build-tools are installed and in PATH" + fi + + # Extract APK + dir_filename=$(basename "${dir}") + tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX") + + if [ ! -d "${tmp}" ]; then + print_status "error" "Failed to create temporary directory" + exit 1 + fi + + print_status "processing" "Extracting native libraries from APK..." + if ! unzip -q "${dir}" "lib/*" -d "${tmp}" 2>/dev/null; then + print_summary_box "NO NATIVE LIBRARIES FOUND" "success" \ + "${PARTY} Your app contains only Java/Kotlin code!" \ + "" \ + "${CHECK_MARK} Apps without native libraries automatically support 16KB devices" \ + "${CHECK_MARK} No additional changes required for Google Play compliance" \ + "${CHECK_MARK} You're all set for the November 1st, 2025 deadline!" + cleanup_trap 0 + fi + + dir="${tmp}" +fi + +# APEX Processing +if [[ "${dir}" == *.apex ]]; then + trap 'cleanup_trap' EXIT + + print_section "$DOCUMENT" "APEX Analysis" "Processing Android Pony EXpress file" + + if ! command -v deapexer >/dev/null 2>&1; then + print_status "error" "deapexer tool not found" + echo " Please ensure Android SDK tools are properly installed and in your PATH." + exit 1 + fi + + dir_filename=$(basename "${dir}") + tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX") + + if [ ! -d "${tmp}" ]; then + print_status "error" "Failed to create temporary directory" + exit 1 + fi + + print_status "processing" "Extracting APEX contents..." + if ! deapexer extract "${dir}" "${tmp}"; then + print_status "error" "Failed to extract APEX file" + cleanup_trap 1 + fi + + dir="${tmp}" +fi + +# Track libraries for enhanced summary +unaligned_libs=() +aligned_libs=() +critical_unaligned_libs=() +non_critical_unaligned_libs=() +total_libs=0 +critical_libs=0 + +print_section "$GEAR" "ELF Segment Analysis" "Scanning native libraries for 16KB alignment compliance" + +# Find all native libraries +matches="$(find "${dir}" -type f -name '*.so' 2>/dev/null)" +if [ -z "$matches" ]; then + # Also check for ELF files without .so extension + matches="$(find "${dir}" -type f -exec file {} \; 2>/dev/null | grep 'ELF' | cut -d: -f1)" +fi + +if [ -z "$matches" ]; then + print_summary_box "NO NATIVE LIBRARIES DETECTED" "success" \ + "${PARTY} Your app uses only Java/Kotlin code!" \ + "" \ + "${CHECK_MARK} No native library alignment issues to worry about" \ + "${CHECK_MARK} Already compatible with 16KB page size devices" \ + "${CHECK_MARK} Ready for Google Play's November 1st, 2025 requirement!" + cleanup_trap 0 +fi + +print_status "info" "Found native libraries - analyzing ELF segment alignment..." + +print_table_header + +IFS=$'\n' +for match in $matches; do + # Skip non-ELF files and nested packages + if [[ "${match}" == *".apk" ]]; then + continue + fi + if [[ "${match}" == *".apex" ]]; then + continue + fi + + # Verify it's actually an ELF file + if ! [[ $(file "${match}" 2>/dev/null) == *"ELF"* ]]; then + continue + fi + + total_libs=$((total_libs + 1)) + + # Determine architecture and criticality + arch="unknown" + is_critical="false" + if [[ "${match}" == *"arm64-v8a"* ]]; then + arch="arm64-v8a" + is_critical="true" + critical_libs=$((critical_libs + 1)) + elif [[ "${match}" == *"x86_64"* ]]; then + arch="x86_64" + is_critical="true" + critical_libs=$((critical_libs + 1)) + elif [[ "${match}" == *"armeabi-v7a"* ]]; then + arch="armeabi-v7a" + elif [[ "${match}" == *"x86"* ]]; then + arch="x86" + fi + + # Check ELF segment alignment + res="$(objdump -p "${match}" 2>/dev/null | grep LOAD | awk '{ print $NF }' | head -1)" + + if [ -z "$res" ]; then + print_table_row "$(basename "${match}")" "$arch" "UNKNOWN" "FAILED" "$is_critical" + continue + fi + + # Check if alignment meets 16KB requirement (2**14 or higher) + if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then + print_table_row "$(basename "${match}")" "$arch" "$res" "ALIGNED" "$is_critical" + aligned_libs+=("${match}") + else + print_table_row "$(basename "${match}")" "$arch" "$res" "UNALIGNED" "$is_critical" + unaligned_libs+=("${match}") + + if [[ "$is_critical" == "true" ]]; then + critical_unaligned_libs+=("${match}") + else + non_critical_unaligned_libs+=("${match}") + fi + fi +done + +print_table_footer + +# Enhanced Summary Section +if [ ${#unaligned_libs[@]} -gt 0 ]; then + # Failure case - unaligned libraries found + summary_lines=( + "${ALERT} ACTION REQUIRED: Unaligned native libraries detected!" + "" + "Analysis Results:" + " • Total libraries scanned: $total_libs" + " • Critical architectures (64-bit): $critical_libs" + " • Libraries aligned: ${#aligned_libs[@]}" + " • Libraries UNALIGNED: ${#unaligned_libs[@]}" + ) + + if [ ${#critical_unaligned_libs[@]} -gt 0 ]; then + summary_lines+=(" • Critical failures: ${#critical_unaligned_libs[@]} (MUST FIX)") + fi + + if [ ${#non_critical_unaligned_libs[@]} -gt 0 ]; then + summary_lines+=(" • Non-critical warnings: ${#non_critical_unaligned_libs[@]} (SHOULD FIX)") + fi + + summary_lines+=("") + summary_lines+=("Google Play Compliance: FAILED") + summary_lines+=("Deadline: November 1st, 2025") + + print_summary_box "COMPATIBILITY CHECK FAILED" "error" "${summary_lines[@]}" + + # Detailed library breakdown + if [ ${#critical_unaligned_libs[@]} -gt 0 ]; then + print_subsection "Critical Libraries Requiring Immediate Attention" + for lib in "${critical_unaligned_libs[@]}"; do + arch_type="64-bit" + [[ "${lib}" == *"arm64-v8a"* ]] && arch_type="ARM64" + [[ "${lib}" == *"x86_64"* ]] && arch_type="x86_64" + print_status "error" "$(basename "$lib")" "$arch_type architecture - Required for Google Play" + done + fi + + if [ ${#non_critical_unaligned_libs[@]} -gt 0 ]; then + print_subsection "Non-Critical Libraries (Recommended to Fix)" + for lib in "${non_critical_unaligned_libs[@]}"; do + arch_type="32-bit" + [[ "${lib}" == *"armeabi-v7a"* ]] && arch_type="ARMv7" + [[ "${lib}" == *"x86"* ]] && arch_type="x86" + print_status "warning" "$(basename "$lib")" "$arch_type architecture" + done + fi + + # Comprehensive fix instructions + print_section "$TOOLS" "How to Fix Unaligned Libraries" "Step-by-step guide to achieve 16KB compatibility" + + print_subsection "Step 1: Update Your Build Environment" + print_status "info" "Android Gradle Plugin (AGP)" "Upgrade to version 8.5.1 or higher" + print_status "info" "Android NDK" "Update to NDK r27 or higher (r28+ recommended)" + print_status "info" "Build Tools" "Ensure Android SDK build-tools 35.0.0+ for zipalign" + + print_subsection "Step 2: Configure 16KB ELF Alignment" + echo + echo -e "${BOLD}For NDK r28 and newer:${ENDCOLOR}" + print_status "success" "Automatic Support" "16KB alignment enabled by default - no changes needed!" + + echo + echo -e "${BOLD}For NDK r27:${ENDCOLOR}" + print_status "info" "Gradle Configuration" "Add to your app/build.gradle:" + echo -e "${DIM} android {" + echo -e " defaultConfig {" + echo -e " externalNativeBuild {" + echo -e " cmake {" + echo -e " arguments '-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON'" + echo -e " }" + echo -e " }" + echo -e " }" + echo -e " }${ENDCOLOR}" + + print_status "info" "NDK-Build Configuration" "Add to Application.mk:" + echo -e "${DIM} APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true${ENDCOLOR}" + + echo + echo -e "${BOLD}For NDK r26 and older:${ENDCOLOR}" + print_status "info" "Manual Linker Flags" "Add to your native build configuration:" + echo -e "${DIM} # For Android.mk:" + echo -e " LOCAL_LDFLAGS += \"-Wl,-z,max-page-size=16384\"" + echo + echo -e " # For CMakeLists.txt:" + echo -e " target_link_options(\${CMAKE_PROJECT_NAME} PRIVATE \"-Wl,-z,max-page-size=16384\")${ENDCOLOR}" + + print_subsection "Step 3: Update Library Packaging" + print_status "info" "AGP 8.5.1+" "Uncompressed libraries used by default (no changes needed)" + print_status "info" "Older AGP versions" "Add to app/build.gradle:" + echo -e "${DIM} android {" + echo -e " packagingOptions {" + echo -e " jniLibs {" + echo -e " useLegacyPackaging = true" + echo -e " }" + echo -e " }" + echo -e " }${ENDCOLOR}" + + print_subsection "Step 4: Build and Verify" + print_status "processing" "Clean Build" "Run ./gradlew clean" + print_status "processing" "Rebuild Project" "Run ./gradlew assembleRelease" + print_status "processing" "Re-run This Script" "Verify all libraries are now aligned" + print_status "processing" "Test on Device" "Use Android 15 emulator with 16KB system image" + + print_section "$BOOKS" "Additional Resources" "Learn more about 16KB page size support" + print_status "info" "Official Guide" "https://developer.android.com/guide/practices/page-sizes" + print_status "info" "NDK Documentation" "https://developer.android.com/ndk/guides/" + print_status "info" "Testing Guide" "Use 'adb shell getconf PAGE_SIZE' (should return 16384)" + print_status "info" "Emulator Setup" "Android 15 system images with 16KB page size" + + final_message="" + if [ ${#critical_unaligned_libs[@]} -gt 0 ]; then + final_message="CRITICAL: Fix required for Google Play compliance by November 1st, 2025!" + else + final_message="Warning: Non-critical issues found - recommended to fix for complete compatibility" + fi + + print_summary_box "NEXT STEPS" "error" \ + "$final_message" \ + "" \ + "1. Update your build tools and NDK version" \ + "2. Apply the configuration changes above" \ + "3. Clean and rebuild your project" \ + "4. Run this script again to verify fixes" \ + "5. Test thoroughly on 16KB devices/emulator" + + cleanup_trap 1 +else + # Success case - all libraries aligned + summary_lines=( + "${PARTY} All native libraries are properly aligned!" + "" + "Analysis Results:" + " • Total libraries scanned: $total_libs" + " • Critical architectures: $critical_libs" + " • All libraries: ${#aligned_libs[@]}/${total_libs} ALIGNED" + "" + "Google Play Compliance: PASSED ${CHECK_MARK}" + "Ready for November 1st, 2025 deadline!" + ) + + print_summary_box "COMPATIBILITY CHECK PASSED" "success" "${summary_lines[@]}" + + print_section "$ROCKET" "Next Steps" "Ensure complete 16KB compatibility" + + print_status "success" "Library Alignment" "All ELF segments properly aligned for 16KB pages" + print_status "info" "Runtime Testing" "Test on Android 15 emulator with 16KB system image" + print_status "info" "Code Review" "Check for hardcoded PAGE_SIZE dependencies in your code" + print_status "info" "Third-party SDKs" "Verify all dependencies are 16KB compatible" + print_status "info" "Zipalign Verification" "Run: zipalign -c -P 16 -v 4 your-app.apk" + + print_subsection "Testing Commands" + echo -e "${DIM} # Verify page size on device/emulator${ENDCOLOR}" + echo -e "${DIM} adb shell getconf PAGE_SIZE # Should return: 16384${ENDCOLOR}" + echo + echo -e "${DIM} # Verify APK alignment${ENDCOLOR}" + echo -e "${DIM} zipalign -c -P 16 -v 4 app-release.apk${ENDCOLOR}" + + print_summary_box "CONGRATULATIONS!" "success" \ + "${PARTY} Your app is 16KB page size compatible!" \ + "" \ + "${CHECK_MARK} All native libraries meet Google Play requirements" \ + "${CHECK_MARK} Ready for devices with 16KB page sizes" \ + "${CHECK_MARK} Compliant with November 1st, 2025 deadline" \ + "" \ + "Recommendation: Test thoroughly on 16KB environment to ensure" \ + "no runtime issues exist in your application code." +fi + +echo +print_status "info" "Analysis completed at $(date)" +echo diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 7c56964..391a902 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 12.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 6aac74d..fe5b6ee 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ @@ -12,6 +12,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 76AE113C28E078EA00513112 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 76AE113B28E078EA00513112 /* GoogleService-Info.plist */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -39,6 +40,7 @@ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7627313328E45A2400F354F7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 76AE113B28E078EA00513112 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -57,6 +59,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, 1CCF895CFB3C95DEBB84A05F /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -75,6 +78,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -144,13 +148,16 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, C4CFBC4C5CAC00182015ACD5 /* [CP] Embed Pods Frameworks */, - EF29CE25BB57F5AA48CE1136 /* [CP] Copy Pods Resources */, + D9FFC0F21D4146458615A992 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -179,6 +186,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -242,23 +252,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 6C6E76E4FB19FAF11C24005D /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -291,6 +284,23 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + D9FFC0F21D4146458615A992 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -367,7 +377,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -454,7 +464,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -504,7 +514,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -600,6 +610,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 9c12df5..5db441f 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneDelegateClassName + FlutterSceneDelegate + UISceneConfigurationName + flutter + UISceneStoryboardFile + Main + + + + CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion @@ -57,10 +78,10 @@ This App requires access to your location to mark your attendance. NSMicrophoneUsageDescription This app requires microphone access for calls and speech-to-text input. - NSSpeechRecognitionUsageDescription - This app requires speech recognition to convert your voice to text. NSPhotoLibraryUsageDescription This app requires photo library access to select image as document & upload it. + NSSpeechRecognitionUsageDescription + This app requires speech recognition to convert your voice to text. UIApplicationSupportsIndirectInputEvents UIBackgroundModes diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart index fa4d00a..39be599 100644 --- a/lib/api/dashboard_api_client.dart +++ b/lib/api/dashboard_api_client.dart @@ -5,7 +5,6 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:http/http.dart' as http; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:mobile_device_identifier/mobile_device_identifier.dart'; import 'package:mohem_flutter_app/api/api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; @@ -254,7 +253,7 @@ class DashboardApiClient { String QRValue = "", String payrollCode = "", }) async { - var _mobileDeviceIdentifierPlugin = MobileDeviceIdentifier(); + Codec stringToBase64 = utf8.fuse(base64); String url = "${ApiConsts.swpRest}AuthenticateAndSwipeUserSupportNFC"; var uuid = Uuid(); @@ -262,7 +261,7 @@ class DashboardApiClient { // Generate a v4 (random) id if (Platform.isAndroid) { AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; - deviceId = await _mobileDeviceIdentifierPlugin.getDeviceId() ?? androidInfo.id; + deviceId = await androidInfo.id; deviceId = stringToBase64.encode(deviceId); deviceId = deviceId.length >= 50 ? deviceId.substring(0, 48) : deviceId; } else if (Platform.isIOS) { diff --git a/lib/classes/date_uitl.dart b/lib/classes/date_uitl.dart index 8714b40..55f371b 100644 --- a/lib/classes/date_uitl.dart +++ b/lib/classes/date_uitl.dart @@ -22,7 +22,7 @@ class DateUtil { return DateTime.now(); } - static DateTime convertStringToDate(String date) { + static DateTime convertStringToDate(String? date) { // /Date(1585774800000+0300)/ if (date != null) { const start = "/Date("; @@ -34,8 +34,9 @@ class DateUtil { date.substring(startIndex + start.length, endIndex), ), ); - } else + } else { return DateTime.now(); + } } static DateTime convertSimpleStringDateToDate(String date, {bool isITG = false}) { diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart index 6a9b16b..8843414 100644 --- a/lib/classes/utils.dart +++ b/lib/classes/utils.dart @@ -20,7 +20,9 @@ import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart'; import 'package:mohem_flutter_app/widgets/loading_dialog.dart'; import 'package:nfc_manager/nfc_manager.dart'; -import 'package:nfc_manager/platform_tags.dart'; +import 'package:nfc_manager/nfc_manager_android.dart'; +import 'package:nfc_manager/nfc_manager_ios.dart'; +// import 'package:nfc_manager/platform_tags.dart'; import 'package:shared_preferences/shared_preferences.dart'; // ignore_for_file: avoid_annotating_with_dynamic @@ -349,15 +351,34 @@ class Utils { NfcManager.instance .startSession( onDiscovered: (NfcTag tag) async { - MifareUltralight f; + // MifareUltralight f; + // if (Platform.isAndroid) { + // print(tag); + // f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + // } else { + // f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + // } + + Uint8List? id; + if (Platform.isAndroid) { - print(tag); - f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); - } else { - f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + id = NfcTagAndroid.from(tag)?.id; + } else if (Platform.isIOS) { + id = MiFareIos.from(tag)?.identifier; + } + + if (id == null) { + await NfcManager.instance.stopSession(); + return; } - String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); - NfcManager.instance.stopSession(); + + String identifier = + id.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + print(identifier); + + await NfcManager.instance.stopSession(); + // String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + // NfcManager.instance.stopSession(); onRead(identifier); }, pollingOptions: {NfcPollingOption.iso14443}, diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index 213926c..6a0ba5b 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -8,7 +8,6 @@ import 'package:audio_session/audio_session_web.dart'; import 'package:camera_web/camera_web.dart'; -import 'package:file_picker/_internal/file_picker_web.dart'; import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_messaging_web/firebase_messaging_web.dart'; import 'package:fluttertoast/fluttertoast_web.dart'; @@ -27,7 +26,6 @@ import 'package:flutter_web_plugins/flutter_web_plugins.dart'; void registerPlugins(Registrar registrar) { AudioSessionWeb.registerWith(registrar); CameraPlugin.registerWith(registrar); - FilePickerWeb.registerWith(registrar); FirebaseCoreWeb.registerWith(registrar); FirebaseMessagingWeb.registerWith(registrar); FluttertoastWebPlugin.registerWith(registrar); diff --git a/lib/main.dart b/lib/main.dart index 263ed8e..8cd7d66 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,6 +18,8 @@ import 'package:month_year_picker/month_year_picker.dart'; import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:sizer/sizer.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb; // test uat account // username 199067 @@ -75,32 +77,33 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return Sizer( - builder: (BuildContext context, Orientation orientation, DeviceType deviceType) { + builder: (BuildContext context, Orientation orientation, ScreenType deviceType){ PostParamsModel? obj = AppState().postParamsObject; - obj?.languageID = EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2; - AppState().setPostParamsModel(obj!); - List> delegates = context.localizationDelegates; - // delegates.add(GlobalMaterialLocalizations.delegate); - delegates.add(MonthYearPickerLocalizations.delegate); - return SafeArea( - top: false, // Set to true if you want to avoid the notch area as well - bottom: Platform.isIOS ? false : true, - child: MaterialApp( - navigatorKey: AppRoutes.navigatorKey, - builder: (BuildContext context, Widget? child) { - return MediaQuery(data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: child!); - }, - theme: AppTheme.getTheme(EasyLocalization.of(context)?.locale.languageCode == "ar"), - debugShowCheckedModeBanner: false, - localizationsDelegates: delegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - initialRoute: AppRoutes.initialRoute, - routes: AppRoutes.routes, - ), - ); - }, + obj?.languageID = EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2; + AppState().setPostParamsModel(obj!); + List> delegates = context.localizationDelegates; + // delegates.add(GlobalMaterialLocalizations.delegate); + delegates.add(MonthYearPickerLocalizations.delegate); + return SafeArea( + top: false, // Set to true if you want to avoid the notch area as well + bottom: Platform.isIOS ? false : true, + child: MaterialApp( + navigatorKey: AppRoutes.navigatorKey, + builder: (BuildContext context, Widget? child) { + return MediaQuery(data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: child!); + }, + theme: AppTheme.getTheme(EasyLocalization.of(context)?.locale.languageCode == "ar"), + debugShowCheckedModeBanner: false, + localizationsDelegates: delegates, + supportedLocales: context.supportedLocales, + locale: context.locale, + initialRoute: AppRoutes.initialRoute, + routes: AppRoutes.routes, + ), + ); + } ); + } } diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 4c19817..232df22 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1609,13 +1609,13 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { await File('$dirPath/.nomedia').create(); } path = "$dirPath/${AppState().chatDetails!.response!.id}-$receiverID-${DateTime.now().microsecondsSinceEpoch}.aac"; - recorderController = RecorderController() - ..androidEncoder = AndroidEncoder.aac - ..androidOutputFormat = AndroidOutputFormat.mpeg4 - ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC - ..sampleRate = 6000 - ..updateFrequency = const Duration(milliseconds: 100) - ..bitRate = 18000; + recorderController = RecorderController(); + // ..androidEncoder = AndroidEncoder.aac + // ..androidOutputFormat = AndroidOutputFormat.mpeg4 + // ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC + // ..sampleRate = 6000 + // ..updateFrequency = const Duration(milliseconds: 100) + // ..bitRate = 18000; playerController = PlayerController(); } diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart index f228600..d2d9fab 100644 --- a/lib/theme/app_theme.dart +++ b/lib/theme/app_theme.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; diff --git a/lib/ui/login/verify_last_login_screen.dart b/lib/ui/login/verify_last_login_screen.dart index 5c76092..36425aa 100644 --- a/lib/ui/login/verify_last_login_screen.dart +++ b/lib/ui/login/verify_last_login_screen.dart @@ -112,7 +112,7 @@ class _VerifyLastLoginScreenState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, - children: [LocaleKeys.lastLoginDetails.tr().toText16(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn ?? DateTime.now().toString()), false).toText12()], + children: [LocaleKeys.lastLoginDetails.tr().toText16(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(mobileLoginInfoListModel?.editedOn ?? null), false).toText12()], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -121,7 +121,7 @@ class _VerifyLastLoginScreenState extends State { LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), getVerificationType(mobileLoginInfoListModel!.loginType!).toText12(), const Expanded(child: SizedBox()), - DateUtil.formatDateToTime(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn!)).toText12(), + DateUtil.formatDateToTime(DateUtil.convertStringToDate(mobileLoginInfoListModel?.editedOn)).toText12(), ], ), ], @@ -208,7 +208,7 @@ class _VerifyLastLoginScreenState extends State { Future loginWithFaceIDAndBiometrics() async { - IOSAuthMessages iosStrings = const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + IOSAuthMessages iosStrings = const IOSAuthMessages(cancelButton: 'cancel'); // IOSAuthMessages iosStrings = const IOSAuthMessages( // cancelButton: 'cancel', @@ -219,9 +219,7 @@ class _VerifyLastLoginScreenState extends State { bool authenticated = false; try { - authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', options: const AuthenticationOptions( - useErrorDialogs: true, stickyAuth: true, biometricOnly: true, - ), + authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', authMessages: [ iosStrings, const AndroidAuthMessages(), diff --git a/lib/ui/login/verify_login_screen.dart b/lib/ui/login/verify_login_screen.dart index e0015e0..625db60 100644 --- a/lib/ui/login/verify_login_screen.dart +++ b/lib/ui/login/verify_login_screen.dart @@ -515,11 +515,11 @@ class _VerifyLoginScreenState extends State { Future loginWithFaceIDAndBiometrics() async { IOSAuthMessages iosStrings = - const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); + const IOSAuthMessages(cancelButton: 'cancel',); bool authenticated = false; try { authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', - options: const AuthenticationOptions(useErrorDialogs: true, stickyAuth: true, biometricOnly: true,), authMessages: [ + authMessages: [ iosStrings, const AndroidAuthMessages(), ],); diff --git a/lib/ui/marathon/widgets/question_card.dart b/lib/ui/marathon/widgets/question_card.dart index 0965c9d..28395d1 100644 --- a/lib/ui/marathon/widgets/question_card.dart +++ b/lib/ui/marathon/widgets/question_card.dart @@ -30,18 +30,21 @@ class QuestionCard extends StatelessWidget { width: double.infinity, child: AppinioSwiper( duration: const Duration(milliseconds: 400), - padding: EdgeInsets.zero, + swipeOptions: const SwipeOptions.all(), isDisabled: true, controller: provider.swiperController, - unswipe: (int index, AppinioSwiperDirection direction) {}, - onSwipe: (int index, AppinioSwiperDirection direction) {}, - cards: provider.cardContentList, + cardCount: provider.cardContentList.length, + cardBuilder: (BuildContext context, int index) { + return provider.cardContentList[index]; + }, ), ), ); } } + + class CardContent extends StatelessWidget { const CardContent({Key? key}) : super(key: key); diff --git a/lib/ui/my_team/subordinate_leave.dart b/lib/ui/my_team/subordinate_leave.dart index e2fb999..85e85c0 100644 --- a/lib/ui/my_team/subordinate_leave.dart +++ b/lib/ui/my_team/subordinate_leave.dart @@ -97,8 +97,8 @@ class _SubordinateLeaveState extends State { separatorBuilder: (BuildContext cxt, int index) => 12.height, itemCount: getSubordinatesLeavesTotalList.length, itemBuilder: (BuildContext context, int index) { - var diffDays = DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATEEND!) - .difference(DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATESTART!)) + var diffDays = DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATEEND) + .difference(DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATESTART)) .inDays + 1; return Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -109,8 +109,8 @@ class _SubordinateLeaveState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ getSubordinatesLeavesTotalList[index].eMPLOYEENAME!.toText16(), - ItemDetailView(LocaleKeys.from.tr(), DateUtil.getFormattedDate(DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATESTART!), "MMM dd yyyy")), - ItemDetailView(LocaleKeys.to.tr(), DateUtil.getFormattedDate(DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATEEND!), "MMM dd yyyy")), + ItemDetailView(LocaleKeys.from.tr(), DateUtil.getFormattedDate(DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATESTART), "MMM dd yyyy")), + ItemDetailView(LocaleKeys.to.tr(), DateUtil.getFormattedDate(DateUtil.convertStringToDate(getSubordinatesLeavesTotalList[index].dATEEND), "MMM dd yyyy")), ItemDetailView(LocaleKeys.numberDays.tr(), diffDays.toString()), ], ).expanded diff --git a/lib/ui/screens/announcements/announcement_details.dart b/lib/ui/screens/announcements/announcement_details.dart index 210a8f7..a8cbcac 100644 --- a/lib/ui/screens/announcements/announcement_details.dart +++ b/lib/ui/screens/announcements/announcement_details.dart @@ -2,7 +2,8 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; +// import 'package:flutter_html/flutter_html.dart'; import 'package:mohem_flutter_app/api/pending_transactions_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; @@ -59,8 +60,8 @@ class _AnnouncementDetailsState extends State { ), ), ), - Html( - data: AppState().isArabic(context) ? getAnnouncementDetailsObj?.bodyAR : getAnnouncementDetailsObj?.bodyEN, + HtmlWidget( + AppState().isArabic(context) ? getAnnouncementDetailsObj?.bodyAR??"" : getAnnouncementDetailsObj?.bodyEN ??"", ).paddingOnly(top: 12), ], ).objectContainerView().paddingAll(21), diff --git a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart index 44b3833..f1f8cda 100644 --- a/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart +++ b/lib/ui/screens/mowadhafhi/mowadhafhi_hr_request.dart @@ -190,9 +190,9 @@ class _MowadhafhiHRRequestState extends State { title.toText16().expanded, 6.width, SimpleButton(LocaleKeys.add.tr(), () async { - FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true); + List? result = await FilePicker.pickFiles(); if (result != null) { - attachmentFiles = attachmentFiles + result.paths.map((path) => File(path!)).toList(); + attachmentFiles = attachmentFiles + result.map((path) => File(path.uri.toFilePath())).toList(); attachmentFiles = attachmentFiles.toSet().toList(); setState(() {}); } diff --git a/lib/ui/screens/my_documents/my_document_detail_screen.dart b/lib/ui/screens/my_documents/my_document_detail_screen.dart index ec97586..86ebd1c 100644 --- a/lib/ui/screens/my_documents/my_document_detail_screen.dart +++ b/lib/ui/screens/my_documents/my_document_detail_screen.dart @@ -92,17 +92,22 @@ class _MyDocumentDetailScreenState extends State { ), 12.height, DottedBorder( - borderType: BorderType.RRect, - radius: const Radius.circular(10), - padding: const EdgeInsets.all(12), - dashPattern: const [2, 1], - color: MyColors.selectedBorderColor, + options: RoundedRectDottedBorderOptions( + radius: const Radius.circular(10), + padding: const EdgeInsets.all(12), + dashPattern: const [2, 1], + color: MyColors.selectedBorderColor, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Transform.rotate( angle: 45, - child: const Icon(Icons.attach_file_rounded, size: 16, color: MyColors.selectedBorderColor), + child: const Icon( + Icons.attach_file_rounded, + size: 16, + color: MyColors.selectedBorderColor, + ), ), 4.width, "Attach Image".toText14(color: MyColors.selectedBorderColor), diff --git a/lib/ui/screens/my_requests/my_requests.dart b/lib/ui/screens/my_requests/my_requests.dart index 4d16219..12410ae 100644 --- a/lib/ui/screens/my_requests/my_requests.dart +++ b/lib/ui/screens/my_requests/my_requests.dart @@ -67,10 +67,10 @@ class _MyRequestsState extends State { isReadOnly: false, ).paddingOnly(bottom: 12), itemBuilder: (_) => >[ - for (int i = 0; i < getConcurrentProgramsList!.length; i++) PopupMenuItem(child: Text(getConcurrentProgramsList![i].uSERCONCURRENTPROGRAMNAME!), value: i), + for (int i = 0; i < getConcurrentProgramsList.length; i++) PopupMenuItem(child: Text(getConcurrentProgramsList[i].uSERCONCURRENTPROGRAMNAME!), value: i), ], onSelected: (int popupIndex) { - selectedConcurrentProgramList = getConcurrentProgramsList![popupIndex]; + selectedConcurrentProgramList = getConcurrentProgramsList[popupIndex]; getCCPTransactions(selectedConcurrentProgramList?.cONCURRENTPROGRAMNAME); setState(() {}); }), @@ -105,7 +105,7 @@ class _MyRequestsState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ("Request ID: " + getCCPTransactionsList[index].rEQUESTID.toString()).toText12(color: MyColors.grey57Color), - DateUtil.formatDateToDate(DateUtil.convertStringToDate(getCCPTransactionsList[index].rEQUESTDATE!), false).toText12(color: MyColors.grey70Color), + DateUtil.formatDateToDate(DateUtil.convertStringToDate(getCCPTransactionsList[index].rEQUESTDATE), false).toText12(color: MyColors.grey70Color), ], ), Container( diff --git a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart index be0582c..890d1a4 100644 --- a/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart +++ b/lib/ui/screens/offers_and_discounts/offers_and_discounts_details.dart @@ -6,8 +6,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -16,7 +16,7 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/models/offers_and_discounts/get_offers_list.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:share_plus/share_plus.dart'; +// import 'package:share_plus/share_plus.dart'; import 'package:url_launcher/url_launcher.dart'; class OffersAndDiscountsDetails extends StatefulWidget { @@ -68,10 +68,12 @@ class _OffersAndDiscountsDetailsState extends State { AppState().isArabic(context) ? getOffersList[0].titleAr!.toText22(isBold: true, color: const Color(0xff2B353E)).center : getOffersList[0].titleEn!.toText22(isBold: true, color: const Color(0xff2B353E)).center, - Html( - data: AppState().isArabic(context) ? getOffersList[0].descriptionAr! : getOffersList[0].descriptionEn ?? "", - onLinkTap: (String? url, Map attributes, _) { + HtmlWidget( + AppState().isArabic(context) ? getOffersList[0].descriptionAr! : getOffersList[0].descriptionEn ?? "", + onTapUrl: (String? url) { launchUrl(Uri.parse(url!)); + + return true; }, ), checkDate(getOffersList[0].endDate!).paddingOnly(left: 8), @@ -122,7 +124,7 @@ class _OffersAndDiscountsDetailsState extends State { Directory tempDir = await getTemporaryDirectory(); File file = await File('${tempDir.path}/${DateTime.now().toString()}.png').create(); await file.writeAsBytes(pngBytes); - await SharePlus.instance.share(ShareParams(files: [(XFile(file.path))], text: AppState().isArabic(context) ? getOffersList[0].titleAr : getOffersList[0].titleEn)); + // await SharePlus.instance.share(ShareParams(files: [(XFile(file.path))], text: AppState().isArabic(context) ? getOffersList[0].titleAr : getOffersList[0].titleEn)); } catch (ex) { debugPrint(ex.toString()); } diff --git a/lib/ui/work_list/item_history_screen.dart b/lib/ui/work_list/item_history_screen.dart index 4bc6579..a8c3a75 100644 --- a/lib/ui/work_list/item_history_screen.dart +++ b/lib/ui/work_list/item_history_screen.dart @@ -211,7 +211,7 @@ class _ItemHistoryScreenState extends State { interval: 1, getTitlesWidget: (double value, TitleMeta meta) { return SideTitleWidget( - axisSide: meta.axisSide, + meta: meta, child: Text(reversedList[int.parse(meta.formattedValue)].cREATIONDATE!, style: TextStyle(fontSize: 10)), ); })), @@ -222,7 +222,7 @@ class _ItemHistoryScreenState extends State { interval: 1, getTitlesWidget: (double value, TitleMeta meta) { return SideTitleWidget( - axisSide: meta.axisSide, + meta: meta, child: Text(meta.formattedValue, style: TextStyle(fontSize: 10)), ); })), @@ -233,7 +233,7 @@ class _ItemHistoryScreenState extends State { reservedSize: 15, getTitlesWidget: (double value, TitleMeta meta) { return SideTitleWidget( - axisSide: meta.axisSide, + meta: meta, child: Text("", style: TextStyle(fontSize: 10)), ); })), diff --git a/lib/ui/work_list/work_list_screen.dart b/lib/ui/work_list/work_list_screen.dart index d659ea6..4f75edc 100644 --- a/lib/ui/work_list/work_list_screen.dart +++ b/lib/ui/work_list/work_list_screen.dart @@ -472,7 +472,7 @@ class _WorkListScreenState extends State { 10.height, Row( children: [ - DateUtil.formatDateToDate(DateUtil.convertStringToDate(requestDetails.modifiedDate!), false).toText10(color: MyColors.lightTextColor).expanded, + DateUtil.formatDateToDate(DateUtil.convertStringToDate(requestDetails.modifiedDate), false).toText10(color: MyColors.lightTextColor).expanded, RotatedBox(quarterTurns: AppState().isArabic(context) ? 2 : 4, child: SvgPicture.asset("assets/images/arrow_next.svg", color: MyColors.darkIconColor)), ], ), diff --git a/lib/ui/work_list/worklist_fragments/info_fragments.dart b/lib/ui/work_list/worklist_fragments/info_fragments.dart index 541d347..d6016d8 100644 --- a/lib/ui/work_list/worklist_fragments/info_fragments.dart +++ b/lib/ui/work_list/worklist_fragments/info_fragments.dart @@ -750,7 +750,7 @@ class InfoFragment extends StatelessWidget { ItemDetailGrid( ItemDetailViewCol( LocaleKeys.requestDate.tr(), DateUtil.formatDateToDate( - DateUtil.convertStringToDate(data.paymentDetailsList![0].requestDate!), false) ?? ""), + DateUtil.convertStringToDate(data.paymentDetailsList![0].requestDate), false) ?? ""), ItemDetailViewCol( LocaleKeys.requesterEmpName.tr(), data.paymentDetailsList![0].requesterEmployeeName ?? ""), ), diff --git a/lib/widgets/image_picker.dart b/lib/widgets/image_picker.dart index a5d346f..b85e80a 100644 --- a/lib/widgets/image_picker.dart +++ b/lib/widgets/image_picker.dart @@ -47,7 +47,7 @@ class ImageOptions { } }, onFilesTap: () async { - FilePickerResult? result = await FilePicker.platform.pickFiles( + List? result = await FilePicker.pickFiles( type: FileType.custom, allowedExtensions: [ 'jpg', @@ -63,8 +63,8 @@ class ImageOptions { 'zip', ], ); - List files = result!.paths.map((path) => File(path!)).toList(); - image(result.files.first.path.toString(), files.first); + List files = result!.map((path) => File(path.uri.toFilePath())).toList(); + image(result.first.path.toString(), files.first); }, ), ); diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart index 5e0b62d..136c504 100644 --- a/lib/widgets/nfc/nfc_reader_sheet.dart +++ b/lib/widgets/nfc/nfc_reader_sheet.dart @@ -3,7 +3,9 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:nfc_manager/nfc_manager.dart'; -import 'package:nfc_manager/platform_tags.dart'; +import 'package:nfc_manager/nfc_manager_android.dart'; +import 'package:nfc_manager/nfc_manager_ios.dart'; +import 'dart:typed_data'; void showNfcReader(BuildContext context, {required Function(String? nfcId) onNcfScan}) { showModalBottomSheet( @@ -40,14 +42,23 @@ class _NfcLayoutState extends State { void initState() { super.initState(); - NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async { - var f; + NfcManager.instance.startSession( pollingOptions: {NfcPollingOption.iso14443},onDiscovered: (NfcTag tag) async { + Uint8List? id; + if (Platform.isAndroid) { - f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); - } else { - f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22); + id = NfcTagAndroid.from(tag)?.id; + } else if (Platform.isIOS) { + id = MiFareIos.from(tag)?.identifier; + } + + if (id == null) { + await NfcManager.instance.stopSession(); + return; } - String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + + String identifier = + id.map((e) => e.toRadixString(16).padLeft(2, '0')).join(''); + print(identifier); nfcId = identifier; setState(() { diff --git a/pubspec.yaml b/pubspec.yaml index 1234352..88f1f6e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,93 +38,98 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.4 path_provider: ^2.0.8 - injector: ^2.0.0 + injector: ^4.0.0 provider: ^6.0.1 easy_localization: ^3.0.0 http: ^1.4.0 - permission_handler: ^12.0.1 + permission_handler: ^13.0.2 flutter_svg: any - sizer: ^2.0.15 - local_auth: ^2.3.0 - fluttertoast: ^8.0.8 - syncfusion_flutter_calendar: ^29.1.38 + sizer: ^3.1.3 + local_auth: ^3.0.2 + fluttertoast: ^10.0.0 + syncfusion_flutter_calendar: ^35.1.37 # flutter_calendar_carousel: ^2.1.0 pie_chart: ^5.1.0 shared_preferences: ^2.0.12 - firebase_messaging: ^15.2.9 - shimmer: ^2.0.0 - logger: ^1.1.0 + firebase_messaging: ^16.7.0 + shimmer: ^4.0.0 + logger: ^2.8.0 flutter_countdown_timer: ^4.1.0 # platform_device_id_plus: ^1.0.7 - mobile_device_identifier: ^0.0.3 - device_info_plus: ^11.5.0 +# mobile_device_identifier: ^0.0.3 + device_info_plus: ^13.2.0 image_picker: ^1.1.2 - file_picker: ^8.3.1 - geolocator: ^9.0.2 + file_picker: ^13.1.0 + geolocator: ^14.1.1 month_year_picker: ^0.5.0+1 month_picker_dialog: ^6.0.3 # open_file: ^3.2.1 open_filex: ^4.6.0 - wifi_iot: ^0.3.19+1 - flutter_html: ^3.0.0-alpha.6 - mobile_scanner: ^6.0.10 + wifi_iot: ^0.4.0 +# flutter_html: ^3.0.0-alpha.6 + flutter_widget_from_html: ^0.17.4 + just_audio: ^0.10.6 + + +# mobile@1234 + mobile_scanner: ^7.4.2 # flutter_barcode_scanner: ^2.0.0 # qr_code_scanner: ^1.0.1 # qr_flutter: ^4.0.0 url_launcher: ^6.0.15 - share_plus: ^11.0.0 +# share_plus: ^13.3.0 flutter_rating_bar: ^4.0.1 auto_size_text: ^3.0.0 pull_to_refresh: ^2.0.0 - fl_chart: ^0.66.0 + fl_chart: ^1.2.0 # lottie json animations lottie: any # Marathon Card Swipe - appinio_swiper: ^1.1.1 + appinio_swiper: ^2.1.1 expandable: ^5.0.1 safe_device: ^1.1.9 # networkImage - cached_network_image: ^3.2.2 + cached_network_image: ^4.0.3 #Chat signalr_netcore: ^1.3.3 logging: ^1.0.1 swipe_to: ^1.0.2 - flutter_webrtc: ^0.12.11 + flutter_webrtc: ^1.6.2+hotfix.3 # camera: ^0.10.3 - camera: ^0.11.2 - flutter_local_notifications: ^18.0.1 + camera: ^0.12.1 + flutter_local_notifications: ^22.3.1 #firebase_analytics: any #Chat Voice Message Recoding & Play - audio_waveforms: ^1.3.0 - rxdart: ^0.27.7 + audio_waveforms: ^2.0.2 + rxdart: ^0.28.0 #Encryption - flutter_des: ^2.1.0 + flutter_des: ^3.0.0 - video_player: 2.7.0 - just_audio: ^0.9.30 + video_player: ^2.14.0 +# just_audio: ^0.9.30 # safe_device: ^1.1.2 flutter_layout_grid: ^2.0.1 #Huawei Dependencies # huawei_hmsavailability: ^6.6.0+300 # huawei_location: 6.0.0+302 - huawei_location: ^6.14.2+301 + huawei_location: ^6.17.0+300 # huawei_push: ^6.7.0+300 - huawei_map: - git: - url: https://github.com/fleoparra/hms-flutter-plugin.git - path: flutter-hms-map - huawei_push: - git: - url: https://github.com/crasowas/hms-flutter-plugin.git - path: flutter-hms-push - firebase_crashlytics: ^4.3.9 +# huawei_map: +# git: +# url: https://github.com/fleoparra/hms-flutter-plugin.git +# path: flutter-hms-map + huawei_push: ^6.15.0+300 + # git: +# url: https://github.com/crasowas/hms-flutter-plugin.git +# path: flutter-hms-push + firebase_crashlytics: ^5.4.0 #Items for sale Image Carousel Slider carousel_slider: ^5.1.1 @@ -132,15 +137,15 @@ dependencies: #Huawei Specified # store_checker: ^1.1.0 google_api_availability: ^5.0.1 - google_maps_flutter_web: ^0.5.4 - in_app_update: 4.1.0 + google_maps_flutter_web: ^0.6.4+1 + in_app_update: 5.0.0 flutter_inappwebview: ^6.1.5 - flutter_blurhash: ^0.8.0 + flutter_blurhash: ^0.9.1 #todo its for temporary purpose, later will remove this. - dotted_border: ^2.0.0+3 + dotted_border: ^3.1.0 webview_flutter: ^4.13.0 - nfc_manager: ^3.2.0 + nfc_manager: ^4.2.1 speech_to_text: ^7.3.0 @@ -161,7 +166,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^1.0.4 + flutter_lints: ^6.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec