Merge remote-tracking branch 'origin/master' into changes
# Conflicts: # assets/langs/ar-SA.json # lib/generated/codegen_loader.g.dart # lib/generated/locale_kesy.g.dartchanges
commit
a31c4c99df
@ -1,626 +0,0 @@
|
||||
PODS:
|
||||
- amazon_payfort (1.1.4):
|
||||
- Flutter
|
||||
- PayFortSDK
|
||||
- audio_session (0.0.1):
|
||||
- Flutter
|
||||
- barcode_scan2 (0.0.1):
|
||||
- Flutter
|
||||
- SwiftProtobuf (~> 1.33)
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- CryptoSwift (1.8.4)
|
||||
- device_calendar (0.0.1):
|
||||
- Flutter
|
||||
- device_calendar_plus_ios (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- DKImagePickerController/Core (4.3.9):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.9)
|
||||
- DKPhotoGallery (0.0.19):
|
||||
- DKPhotoGallery/Core (= 0.0.19)
|
||||
- DKPhotoGallery/Model (= 0.0.19)
|
||||
- DKPhotoGallery/Preview (= 0.0.19)
|
||||
- DKPhotoGallery/Resource (= 0.0.19)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Firebase/Analytics (11.15.0):
|
||||
- Firebase/Core
|
||||
- Firebase/Core (11.15.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (~> 11.15.0)
|
||||
- Firebase/CoreOnly (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- Firebase/Crashlytics (11.15.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 11.15.0)
|
||||
- Firebase/Messaging (11.15.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 11.15.0)
|
||||
- firebase_analytics (11.6.0):
|
||||
- Firebase/Analytics (= 11.15.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_core (3.15.2):
|
||||
- Firebase/CoreOnly (= 11.15.0)
|
||||
- Flutter
|
||||
- firebase_crashlytics (4.3.10):
|
||||
- Firebase/Crashlytics (= 11.15.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_messaging (15.2.10):
|
||||
- Firebase/Messaging (= 11.15.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseAnalytics (11.15.0):
|
||||
- FirebaseAnalytics/Default (= 11.15.0)
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseInstallations (~> 11.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseAnalytics/Default (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseInstallations (~> 11.0)
|
||||
- GoogleAppMeasurement/Default (= 11.15.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseCore (11.15.0):
|
||||
- FirebaseCoreInternal (~> 11.15.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreExtension (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseCoreInternal (11.15.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseCrashlytics (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseInstallations (~> 11.0)
|
||||
- FirebaseRemoteConfigInterop (~> 11.0)
|
||||
- FirebaseSessions (~> 11.0)
|
||||
- GoogleDataTransport (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseInstallations (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseInstallations (~> 11.0)
|
||||
- GoogleDataTransport (~> 10.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Reachability (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseRemoteConfigInterop (11.15.0)
|
||||
- FirebaseSessions (11.15.0):
|
||||
- FirebaseCore (~> 11.15.0)
|
||||
- FirebaseCoreExtension (~> 11.15.0)
|
||||
- FirebaseInstallations (~> 11.0)
|
||||
- GoogleDataTransport (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesSwift (~> 2.1)
|
||||
- FLAnimatedImage (1.0.17)
|
||||
- Flutter (1.0.0)
|
||||
- flutter_callkit_incoming (0.0.1):
|
||||
- CryptoSwift
|
||||
- Flutter
|
||||
- flutter_image_compress_common (1.0.0):
|
||||
- Flutter
|
||||
- Mantle
|
||||
- SDWebImage
|
||||
- SDWebImageWebPCoder
|
||||
- flutter_inappwebview_ios (0.0.1):
|
||||
- Flutter
|
||||
- flutter_inappwebview_ios/Core (= 0.0.1)
|
||||
- OrderedSet (~> 6.0.3)
|
||||
- flutter_inappwebview_ios/Core (0.0.1):
|
||||
- Flutter
|
||||
- OrderedSet (~> 6.0.3)
|
||||
- flutter_ios_voip_kit_karmm (0.8.0):
|
||||
- Flutter
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- Flutter
|
||||
- flutter_nfc_kit (3.6.0):
|
||||
- Flutter
|
||||
- flutter_zoom_videosdk (0.0.1):
|
||||
- Flutter
|
||||
- ZoomVideoSDK/CptShare (= 2.1.10)
|
||||
- ZoomVideoSDK/zm_annoter_dynamic (= 2.1.10)
|
||||
- ZoomVideoSDK/zoomcml (= 2.1.10)
|
||||
- ZoomVideoSDK/ZoomVideoSDK (= 2.1.10)
|
||||
- fluttertoast (0.0.2):
|
||||
- Flutter
|
||||
- geolocator_apple (1.2.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Google-Maps-iOS-Utils (5.0.0):
|
||||
- GoogleMaps (~> 8.0)
|
||||
- google_maps_flutter_ios (0.0.1):
|
||||
- Flutter
|
||||
- Google-Maps-iOS-Utils (< 7.0, >= 5.0)
|
||||
- GoogleMaps (< 11.0, >= 8.4)
|
||||
- GoogleAdsOnDeviceConversion (2.1.0):
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Core (11.15.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Default (11.15.0):
|
||||
- GoogleAdsOnDeviceConversion (= 2.1.0)
|
||||
- GoogleAppMeasurement/Core (= 11.15.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (= 11.15.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (11.15.0):
|
||||
- GoogleAppMeasurement/Core (= 11.15.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleDataTransport (10.1.0):
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- GoogleMaps (8.4.0):
|
||||
- GoogleMaps/Maps (= 8.4.0)
|
||||
- GoogleMaps/Base (8.4.0)
|
||||
- GoogleMaps/Maps (8.4.0):
|
||||
- GoogleMaps/Base
|
||||
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Environment (8.1.0):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Logger (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/MethodSwizzler (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Network (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (8.1.0)":
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (8.1.0)
|
||||
- GoogleUtilities/Reachability (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/UserDefaults (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- health (13.1.4):
|
||||
- Flutter
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- in_app_review (2.0.0):
|
||||
- Flutter
|
||||
- just_audio (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- libwebp (1.5.0):
|
||||
- libwebp/demux (= 1.5.0)
|
||||
- libwebp/mux (= 1.5.0)
|
||||
- libwebp/sharpyuv (= 1.5.0)
|
||||
- libwebp/webp (= 1.5.0)
|
||||
- libwebp/demux (1.5.0):
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.5.0):
|
||||
- libwebp/demux
|
||||
- libwebp/sharpyuv (1.5.0)
|
||||
- libwebp/webp (1.5.0):
|
||||
- libwebp/sharpyuv
|
||||
- local_auth_darwin (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- location (0.0.1):
|
||||
- Flutter
|
||||
- manage_calendar_events (0.0.1):
|
||||
- Flutter
|
||||
- Mantle (2.2.0):
|
||||
- Mantle/extobjc (= 2.2.0)
|
||||
- Mantle/extobjc (2.2.0)
|
||||
- map_launcher (0.0.1):
|
||||
- Flutter
|
||||
- MapboxCommon (23.11.0)
|
||||
- MapboxCoreMaps (10.19.1):
|
||||
- MapboxCommon (~> 23.11)
|
||||
- MapboxCoreNavigation (2.19.0):
|
||||
- MapboxDirections (~> 2.14)
|
||||
- MapboxNavigationNative (< 207.0.0, >= 206.0.1)
|
||||
- MapboxDirections (2.14.3):
|
||||
- Polyline (~> 5.0)
|
||||
- Turf (~> 2.8.0)
|
||||
- MapboxMaps (10.19.0):
|
||||
- MapboxCommon (= 23.11.0)
|
||||
- MapboxCoreMaps (= 10.19.1)
|
||||
- MapboxMobileEvents (= 2.0.0)
|
||||
- Turf (= 2.8.0)
|
||||
- MapboxMobileEvents (2.0.0)
|
||||
- MapboxNavigation (2.19.0):
|
||||
- MapboxCoreNavigation (= 2.19.0)
|
||||
- MapboxMaps (~> 10.18)
|
||||
- MapboxSpeech (~> 2.0)
|
||||
- Solar-dev (~> 3.0)
|
||||
- MapboxNavigationNative (206.2.2):
|
||||
- MapboxCommon (~> 23.10)
|
||||
- MapboxSpeech (2.1.1)
|
||||
- nanopb (3.30910.0):
|
||||
- nanopb/decode (= 3.30910.0)
|
||||
- nanopb/encode (= 3.30910.0)
|
||||
- nanopb/decode (3.30910.0)
|
||||
- nanopb/encode (3.30910.0)
|
||||
- network_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- open_filex (0.0.2):
|
||||
- Flutter
|
||||
- OrderedSet (6.0.3)
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- PayFortSDK (3.2.1)
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- Polyline (5.1.0)
|
||||
- PromisesObjC (2.4.0)
|
||||
- PromisesSwift (2.4.0):
|
||||
- PromisesObjC (= 2.4.0)
|
||||
- SDWebImage (5.21.5):
|
||||
- SDWebImage/Core (= 5.21.5)
|
||||
- SDWebImage/Core (5.21.5)
|
||||
- SDWebImageWebPCoder (0.15.0):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.17)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Solar-dev (3.0.1)
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SwiftProtobuf (1.33.3)
|
||||
- SwiftyGif (5.4.5)
|
||||
- Turf (2.8.0)
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- video_player_avfoundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- webview_flutter_wkwebview (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- ZoomVideoSDK/CptShare (2.1.10)
|
||||
- ZoomVideoSDK/zm_annoter_dynamic (2.1.10)
|
||||
- ZoomVideoSDK/zoomcml (2.1.10)
|
||||
- ZoomVideoSDK/ZoomVideoSDK (2.1.10)
|
||||
|
||||
DEPENDENCIES:
|
||||
- amazon_payfort (from `.symlinks/plugins/amazon_payfort/ios`)
|
||||
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
||||
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- device_calendar (from `.symlinks/plugins/device_calendar/ios`)
|
||||
- device_calendar_plus_ios (from `.symlinks/plugins/device_calendar_plus_ios/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||
- FLAnimatedImage
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_callkit_incoming (from `.symlinks/plugins/flutter_callkit_incoming/ios`)
|
||||
- flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`)
|
||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||
- flutter_ios_voip_kit_karmm (from `.symlinks/plugins/flutter_ios_voip_kit_karmm/ios`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- flutter_nfc_kit (from `.symlinks/plugins/flutter_nfc_kit/ios`)
|
||||
- flutter_zoom_videosdk (from `.symlinks/plugins/flutter_zoom_videosdk/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
|
||||
- google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`)
|
||||
- health (from `.symlinks/plugins/health/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
- just_audio (from `.symlinks/plugins/just_audio/darwin`)
|
||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||
- location (from `.symlinks/plugins/location/ios`)
|
||||
- manage_calendar_events (from `.symlinks/plugins/manage_calendar_events/ios`)
|
||||
- map_launcher (from `.symlinks/plugins/map_launcher/ios`)
|
||||
- MapboxMaps (= 10.19.0)
|
||||
- MapboxNavigation (= 2.19.0)
|
||||
- network_info_plus (from `.symlinks/plugins/network_info_plus/ios`)
|
||||
- open_filex (from `.symlinks/plugins/open_filex/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- CryptoSwift
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- Firebase
|
||||
- FirebaseAnalytics
|
||||
- FirebaseCore
|
||||
- FirebaseCoreExtension
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseCrashlytics
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- FirebaseRemoteConfigInterop
|
||||
- FirebaseSessions
|
||||
- FLAnimatedImage
|
||||
- Google-Maps-iOS-Utils
|
||||
- GoogleAdsOnDeviceConversion
|
||||
- GoogleAppMeasurement
|
||||
- GoogleDataTransport
|
||||
- GoogleMaps
|
||||
- GoogleUtilities
|
||||
- libwebp
|
||||
- Mantle
|
||||
- MapboxCommon
|
||||
- MapboxCoreMaps
|
||||
- MapboxCoreNavigation
|
||||
- MapboxDirections
|
||||
- MapboxMaps
|
||||
- MapboxMobileEvents
|
||||
- MapboxNavigation
|
||||
- MapboxNavigationNative
|
||||
- MapboxSpeech
|
||||
- nanopb
|
||||
- OrderedSet
|
||||
- PayFortSDK
|
||||
- Polyline
|
||||
- PromisesObjC
|
||||
- PromisesSwift
|
||||
- SDWebImage
|
||||
- SDWebImageWebPCoder
|
||||
- Solar-dev
|
||||
- SwiftProtobuf
|
||||
- SwiftyGif
|
||||
- Turf
|
||||
- ZoomVideoSDK
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
amazon_payfort:
|
||||
:path: ".symlinks/plugins/amazon_payfort/ios"
|
||||
audio_session:
|
||||
:path: ".symlinks/plugins/audio_session/ios"
|
||||
barcode_scan2:
|
||||
:path: ".symlinks/plugins/barcode_scan2/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
device_calendar:
|
||||
:path: ".symlinks/plugins/device_calendar/ios"
|
||||
device_calendar_plus_ios:
|
||||
:path: ".symlinks/plugins/device_calendar_plus_ios/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
firebase_analytics:
|
||||
:path: ".symlinks/plugins/firebase_analytics/ios"
|
||||
firebase_core:
|
||||
:path: ".symlinks/plugins/firebase_core/ios"
|
||||
firebase_crashlytics:
|
||||
:path: ".symlinks/plugins/firebase_crashlytics/ios"
|
||||
firebase_messaging:
|
||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_callkit_incoming:
|
||||
:path: ".symlinks/plugins/flutter_callkit_incoming/ios"
|
||||
flutter_image_compress_common:
|
||||
:path: ".symlinks/plugins/flutter_image_compress_common/ios"
|
||||
flutter_inappwebview_ios:
|
||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||
flutter_ios_voip_kit_karmm:
|
||||
:path: ".symlinks/plugins/flutter_ios_voip_kit_karmm/ios"
|
||||
flutter_local_notifications:
|
||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||
flutter_nfc_kit:
|
||||
:path: ".symlinks/plugins/flutter_nfc_kit/ios"
|
||||
flutter_zoom_videosdk:
|
||||
:path: ".symlinks/plugins/flutter_zoom_videosdk/ios"
|
||||
fluttertoast:
|
||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||
geolocator_apple:
|
||||
:path: ".symlinks/plugins/geolocator_apple/darwin"
|
||||
google_maps_flutter_ios:
|
||||
:path: ".symlinks/plugins/google_maps_flutter_ios/ios"
|
||||
health:
|
||||
:path: ".symlinks/plugins/health/ios"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
in_app_review:
|
||||
:path: ".symlinks/plugins/in_app_review/ios"
|
||||
just_audio:
|
||||
:path: ".symlinks/plugins/just_audio/darwin"
|
||||
local_auth_darwin:
|
||||
:path: ".symlinks/plugins/local_auth_darwin/darwin"
|
||||
location:
|
||||
:path: ".symlinks/plugins/location/ios"
|
||||
manage_calendar_events:
|
||||
:path: ".symlinks/plugins/manage_calendar_events/ios"
|
||||
map_launcher:
|
||||
:path: ".symlinks/plugins/map_launcher/ios"
|
||||
network_info_plus:
|
||||
:path: ".symlinks/plugins/network_info_plus/ios"
|
||||
open_filex:
|
||||
:path: ".symlinks/plugins/open_filex/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sqflite_darwin:
|
||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
video_player_avfoundation:
|
||||
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
||||
wakelock_plus:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
webview_flutter_wkwebview:
|
||||
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
amazon_payfort: 782d287860ac8962baf4e0a2a0fb2f81fdf27204
|
||||
audio_session: 19e9480dbdd4e5f6c4543826b2e8b0e4ab6145fe
|
||||
barcode_scan2: 050b7b327e85954c8918715d42e83c5a35c3ed89
|
||||
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
|
||||
CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90
|
||||
device_calendar: 9cb33f88a02e19652ec7b8b122ca778f751b1f7b
|
||||
device_calendar_plus_ios: 34dca387f44fad29b840096a840f94edc55af858
|
||||
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
|
||||
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
|
||||
firebase_analytics: bf93e20703c95030404d6ddbb1adf05bf5c3885b
|
||||
firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c
|
||||
firebase_crashlytics: 986773c0c7ea4c3f5a4ead141b58522fcd9dfdb1
|
||||
firebase_messaging: bf6697c61f31c7cc0f654131212ff04c0115c2c7
|
||||
FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae
|
||||
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
|
||||
FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435
|
||||
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
|
||||
FirebaseCrashlytics: e09d0bc19aa54a51e45b8039c836ef73f32c039a
|
||||
FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843
|
||||
FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09
|
||||
FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa
|
||||
FirebaseSessions: b9a92c1c51bbb81e78fc3142cda6d925d700f8e7
|
||||
FLAnimatedImage: bbf914596368867157cc71b38a8ec834b3eeb32b
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_callkit_incoming: 417dd1b46541cdd5d855ad795ccbe97d1c18155e
|
||||
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
|
||||
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
|
||||
flutter_ios_voip_kit_karmm: 7ea37381a8841c92d186edf1f4604df5cc437579
|
||||
flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f
|
||||
flutter_nfc_kit: 3985c93f749b9cb4747479205c2f10bd2f877a11
|
||||
flutter_zoom_videosdk: 7ddc97d617b85aeace252165d2b5fc5638678c38
|
||||
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
|
||||
geolocator_apple: 66b711889fd333205763b83c9dcf0a57a28c7afd
|
||||
Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321
|
||||
google_maps_flutter_ios: ffdd933832966673a1f57f5effd014dc8d4d43a2
|
||||
GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64
|
||||
GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
health: 9cd70a5c9d9ec559a12d639a1471091c0cbb6b48
|
||||
image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b
|
||||
in_app_review: 436034b18594851a7328d7f1c2ed5ec235b79cfc
|
||||
just_audio: a42c63806f16995daf5b219ae1d679deb76e6a79
|
||||
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||
local_auth_darwin: 63c73d6d28cc3e239be2b6aa460ea6e317cd5100
|
||||
location: d5cf8598915965547c3f36761ae9cc4f4e87d22e
|
||||
manage_calendar_events: 9b2889799340398027b3e3f5c4891d41599ec257
|
||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
||||
map_launcher: 8a4e484aaddff55680a7da9bc9e25f512067fb87
|
||||
MapboxCommon: 119f3759f7dc9457f0695848108ab323eb643cb4
|
||||
MapboxCoreMaps: ca17f67baced23f8c952166ac6314c35bad3f66c
|
||||
MapboxCoreNavigation: 3be9990fae3ed732a101001746d0e3b4234ec023
|
||||
MapboxDirections: d9ad8452e8927d95ed21e35f733834dbca7e0eb1
|
||||
MapboxMaps: b7f29ec7c33f7dc6d2947c1148edce6db81db9a7
|
||||
MapboxMobileEvents: d044b9edbe0ec7df60f6c2c9634fe9a7f449266b
|
||||
MapboxNavigation: da9cf3d773ed5b0fa0fb388fccdaa117ee681f31
|
||||
MapboxNavigationNative: 629e359f3d2590acd1ebbacaaf99e1a80ee57e42
|
||||
MapboxSpeech: cd25ef99c3a3d2e0da72620ff558276ea5991a77
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
network_info_plus: 6613d9d7cdeb0e6f366ed4dbe4b3c51c52d567a9
|
||||
open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
||||
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
|
||||
PayFortSDK: 233eabe9a45601fdbeac67fa6e5aae46ed8faf82
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
Polyline: 2a1f29f87f8d9b7de868940f4f76deb8c678a5b1
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||
SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838
|
||||
SDWebImageWebPCoder: 0e06e365080397465cc73a7a9b472d8a3bd0f377
|
||||
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||
Solar-dev: 4612dc9878b9fed2667d23b327f1d4e54e16e8d0
|
||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
||||
SwiftProtobuf: e1b437c8e31a4c5577b643249a0bb62ed4f02153
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
Turf: aa2ede4298009639d10db36aba1a7ebaad072a5e
|
||||
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa
|
||||
video_player_avfoundation: 7993f492ae0bd77edaea24d9dc051d8bb2cd7c86
|
||||
wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e
|
||||
webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4
|
||||
ZoomVideoSDK: 94e939820e57a075c5e712559f927017da0de06a
|
||||
|
||||
PODFILE CHECKSUM: 8235407385ddd5904afc2563d65406117a51993e
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
@ -0,0 +1,255 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.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/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.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/expandable_list_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class RadiologyAiAnalysisDetailedPage extends StatefulWidget {
|
||||
const RadiologyAiAnalysisDetailedPage({super.key});
|
||||
|
||||
@override
|
||||
State<RadiologyAiAnalysisDetailedPage> createState() => _RadiologyAiAnalysisDetailedPageState();
|
||||
}
|
||||
|
||||
class _RadiologyAiAnalysisDetailedPageState extends State<RadiologyAiAnalysisDetailedPage> {
|
||||
late RadiologyViewModel radiologyProvider;
|
||||
|
||||
List<String> _parseStringToList(String? text) {
|
||||
if (text == null || text.isEmpty) return [];
|
||||
// Split by newlines and filter out empty lines
|
||||
return text.split('\n').where((line) => line.trim().isNotEmpty).map((line) => line.trim()).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
radiologyProvider = Provider.of<RadiologyViewModel>(context, listen: false);
|
||||
return CollapsingListView(
|
||||
isClose: true,
|
||||
title: LocaleKeys.aiAnalysis.tr(context: context),
|
||||
child: Consumer<RadiologyViewModel>(
|
||||
builder: (context, model, child) {
|
||||
if (model.radiologyAiAnalysisResponse == null) {
|
||||
return Utils.getNoDataWidget(context);
|
||||
}
|
||||
|
||||
final analysis = model.radiologyAiAnalysisResponse!;
|
||||
List<ExpandableListItem> expandableItems = [];
|
||||
|
||||
// Parse string fields into lists
|
||||
final predictions = _parseStringToList(analysis.aiPredictions);
|
||||
final preventions = _parseStringToList(analysis.prevention);
|
||||
final riskFactorsText = _parseStringToList(analysis.riskFactors);
|
||||
|
||||
// Summary Section
|
||||
if (analysis.summary != null && analysis.summary!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.summary.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
initiallyExpanded: true,
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFF0B85F7)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: (analysis.summary ?? "").toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Lab Results Section (Radiology Results)
|
||||
if (analysis.labResults != null && analysis.labResults!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.labResults.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFF0B85F7)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: (analysis.labResults ?? "").toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// AI Predictions Section
|
||||
if (predictions.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.prediction.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFFFFAF15)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: predictions.map((prediction) => _buildBulletItem(prediction)).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Risk Factors Section
|
||||
if (riskFactorsText.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.riskFactors.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
...riskFactorsText.asMap().entries.map((entry) {
|
||||
final riskText = entry.value;
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: Color(0xFFFBCB6E).withOpacity(0.10),
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFFFBCB6E).withOpacity(0.10)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(icon: AppAssets.guradIcon),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: LocaleKeys.riskFactors.tr(context: context).toText16(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
riskText.toText14(
|
||||
color: AppColors.textColorLight,
|
||||
height: 1.5,
|
||||
weight: FontWeight.w400,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Prevention Section
|
||||
if (preventions.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.prevention.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFF18C273)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: preventions.map((prevention) => _buildBulletItem(prevention)).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
if (expandableItems.isEmpty)
|
||||
Utils.getNoDataWidget(context)
|
||||
else
|
||||
CustomExpandableList(
|
||||
expansionMode: ExpansionMode.exactlyOne,
|
||||
dividerColor: AppColors.dividerColor,
|
||||
itemPadding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.h),
|
||||
items: expandableItems,
|
||||
theme: ExpandableListTheme.custom(
|
||||
defaultTrailingIcon: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.arrow_down,
|
||||
height: 22.h,
|
||||
width: 22.w,
|
||||
iconColor: AppColors.textColor,
|
||||
),
|
||||
),
|
||||
).paddingSymmetrical(16.w, 0.0),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.info_outline, color: AppColors.greyTextColor, size: 20.r),
|
||||
SizedBox(width: 8.w),
|
||||
Expanded(
|
||||
child: ("${LocaleKeys.disclaimer.tr()}:${LocaleKeys.thisAboveInfo.tr()}")
|
||||
.toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.w, 16.h)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBulletItem(String text) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12.h),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: text.toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
enum CalendarDesignType {
|
||||
defaultUI,
|
||||
designV2,
|
||||
}
|
||||
|
||||
@ -0,0 +1,555 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||
import 'package:hmg_patient_app_new/services/dialog_service.dart';
|
||||
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
|
||||
|
||||
// ==================== Hijri Date Classes ====================
|
||||
|
||||
/// Represents a Hijri date with day, month, and year components.
|
||||
class HijriGregDate {
|
||||
final int day;
|
||||
final int month;
|
||||
final int year;
|
||||
|
||||
HijriGregDate({required this.day, required this.month, required this.year})
|
||||
: assert(day >= 1 && day <= 30, 'Day must be between 1 and 30'),
|
||||
assert(month >= 1 && month <= 12, 'Month must be between 1 and 12'),
|
||||
assert(year > 0, 'Year must be positive');
|
||||
|
||||
@override
|
||||
String toString() => '$day/$month/$year H';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is HijriGregDate && other.day == day && other.month == month && other.year == year;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => day.hashCode ^ month.hashCode ^ year.hashCode;
|
||||
}
|
||||
|
||||
/// Utility class for converting between Hijri and Gregorian calendars.
|
||||
class HijriGregConverter {
|
||||
static const int _hijriEpoch = 1948439;
|
||||
|
||||
static HijriGregDate gregorianToHijri(DateTime gregorianDate) {
|
||||
int julianDay = _gregorianToJulian(gregorianDate);
|
||||
return _julianToHijri(julianDay);
|
||||
}
|
||||
|
||||
static DateTime hijriToGregorian(HijriGregDate hijriDate) {
|
||||
int julianDay = _hijriToJulian(hijriDate);
|
||||
return _julianToGregorian(julianDay);
|
||||
}
|
||||
|
||||
static int _gregorianToJulian(DateTime date) {
|
||||
int year = date.year;
|
||||
int month = date.month;
|
||||
int day = date.day;
|
||||
|
||||
if (month <= 2) {
|
||||
year--;
|
||||
month += 12;
|
||||
}
|
||||
|
||||
int a = year ~/ 100;
|
||||
int b = 2 - a + (a ~/ 4);
|
||||
|
||||
return (365.25 * (year + 4716)).floor() + (30.6001 * (month + 1)).floor() + day + b - 1524;
|
||||
}
|
||||
|
||||
static DateTime _julianToGregorian(int julianDay) {
|
||||
int a = julianDay + 32044;
|
||||
int b = (4 * a + 3) ~/ 146097;
|
||||
int c = a - (146097 * b) ~/ 4;
|
||||
int d = (4 * c + 3) ~/ 1461;
|
||||
int e = c - (1461 * d) ~/ 4;
|
||||
int m = (5 * e + 2) ~/ 153;
|
||||
|
||||
int day = e - (153 * m + 2) ~/ 5 + 1;
|
||||
int month = m + 3 - 12 * (m ~/ 10);
|
||||
int year = 100 * b + d - 4800 + m ~/ 10;
|
||||
|
||||
return DateTime(year, month, day);
|
||||
}
|
||||
|
||||
static HijriGregDate _julianToHijri(int julianDay) {
|
||||
int daysSinceEpoch = julianDay - _hijriEpoch;
|
||||
int hijriYear = (daysSinceEpoch * 33 ~/ 10631) + 1;
|
||||
|
||||
int yearStartJulian = _hijriYearStartJulian(hijriYear);
|
||||
while (yearStartJulian > julianDay) {
|
||||
hijriYear--;
|
||||
yearStartJulian = _hijriYearStartJulian(hijriYear);
|
||||
}
|
||||
while (yearStartJulian + _hijriYearLength(hijriYear) <= julianDay) {
|
||||
hijriYear++;
|
||||
yearStartJulian = _hijriYearStartJulian(hijriYear);
|
||||
}
|
||||
|
||||
int dayOfYear = julianDay - yearStartJulian + 1;
|
||||
int month = 1;
|
||||
int dayInMonth = dayOfYear;
|
||||
|
||||
while (month <= 12) {
|
||||
int monthLength = _hijriMonthLength(hijriYear, month);
|
||||
if (dayInMonth <= monthLength) {
|
||||
break;
|
||||
}
|
||||
dayInMonth -= monthLength;
|
||||
month++;
|
||||
}
|
||||
|
||||
if (dayInMonth < 1) dayInMonth = 1;
|
||||
if (dayInMonth > 30) dayInMonth = 30;
|
||||
|
||||
return HijriGregDate(day: dayInMonth, month: month, year: hijriYear);
|
||||
}
|
||||
|
||||
static int _hijriToJulian(HijriGregDate hijriDate) {
|
||||
int yearStart = _hijriYearStartJulian(hijriDate.year);
|
||||
int dayOfYear = 0;
|
||||
|
||||
for (int i = 1; i < hijriDate.month; i++) {
|
||||
dayOfYear += _hijriMonthLength(hijriDate.year, i);
|
||||
}
|
||||
|
||||
dayOfYear += hijriDate.day - 1;
|
||||
return yearStart + dayOfYear;
|
||||
}
|
||||
|
||||
static int _hijriYearStartJulian(int hijriYear) {
|
||||
if (hijriYear <= 1) return _hijriEpoch;
|
||||
|
||||
int totalDays = 0;
|
||||
for (int year = 1; year < hijriYear; year++) {
|
||||
totalDays += _hijriYearLength(year);
|
||||
}
|
||||
|
||||
return _hijriEpoch + totalDays;
|
||||
}
|
||||
|
||||
static int _hijriYearLength(int year) {
|
||||
return _isHijriLeapYear(year) ? 355 : 354;
|
||||
}
|
||||
|
||||
static int _hijriMonthLength(int year, int month) {
|
||||
if (month <= 0 || month > 12) return 30;
|
||||
|
||||
const List<int> monthLengths = [30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29];
|
||||
int length = monthLengths[month - 1];
|
||||
|
||||
if (month == 12 && _isHijriLeapYear(year)) {
|
||||
length = 30;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static bool _isHijriLeapYear(int year) {
|
||||
if (year <= 0) return false;
|
||||
const leapYears = [2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29];
|
||||
int yearInCycle = ((year - 1) % 30) + 1;
|
||||
return leapYears.contains(yearInCycle);
|
||||
}
|
||||
|
||||
static int getHijriMonthLength(int year, int month) {
|
||||
return _hijriMonthLength(year, month);
|
||||
}
|
||||
|
||||
static bool isHijriLeapYear(int year) {
|
||||
return _isHijriLeapYear(year);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Main Model ====================
|
||||
|
||||
enum CalendarType {
|
||||
gregorian,
|
||||
hijri,
|
||||
}
|
||||
|
||||
class DateRangCalenderModel extends ChangeNotifier {
|
||||
final AppState appState;
|
||||
final ErrorHandlerService navigationService;
|
||||
final DialogService dialogService;
|
||||
|
||||
// Static variable to persist calendar type preference across instances
|
||||
static CalendarType _persistedCalendarType = CalendarType.gregorian;
|
||||
static int _persistedTabIndex = 0;
|
||||
|
||||
DateRangCalenderModel({required this.appState, required this.navigationService, required this.dialogService}) {
|
||||
// Initialize from persisted state
|
||||
_initializeFromPersistedState();
|
||||
}
|
||||
|
||||
int _selectedTabIndex = 0;
|
||||
CalendarType _calendarType = CalendarType.gregorian;
|
||||
|
||||
void _initializeFromPersistedState() {
|
||||
// Load from static persisted values
|
||||
_selectedTabIndex = _persistedTabIndex;
|
||||
_calendarType = _persistedCalendarType;
|
||||
}
|
||||
|
||||
// Umm al-Qura calendar adjustment (in days)
|
||||
// This offset corrects the astronomical calculation to match the official Saudi calendar
|
||||
static const int _ummAlQuraOffset = -1;
|
||||
|
||||
// Hijri month names in English (short form)
|
||||
static const List<String> _hijriMonthNamesShort = [
|
||||
'Muh',
|
||||
'Saf',
|
||||
'Rab I',
|
||||
'Rab II',
|
||||
'Jum I',
|
||||
'Jum II',
|
||||
'Raj',
|
||||
'Sha',
|
||||
'Ram',
|
||||
'Shaw',
|
||||
'Dhu Q',
|
||||
'Dhu H',
|
||||
];
|
||||
|
||||
// Hijri month names in English (full form) - public for month picker
|
||||
static const List<String> hijriMonthNamesEnglish = [
|
||||
'Muharram',
|
||||
'Safar',
|
||||
'Rabi\' I',
|
||||
'Rabi\' II',
|
||||
'Jumada I',
|
||||
'Jumada II',
|
||||
'Rajab',
|
||||
'Sha\'ban',
|
||||
'Ramadan',
|
||||
'Shawwal',
|
||||
'Dhu al-Qi\'dah',
|
||||
'Dhu al-Hijjah',
|
||||
];
|
||||
|
||||
// Hijri month names in Arabic (short form)
|
||||
static const List<String> _hijriMonthNamesShortArabic = [
|
||||
'محرم',
|
||||
'صفر',
|
||||
'ربيع الأول',
|
||||
'ربيع الثاني',
|
||||
'جمادى الأولى',
|
||||
'جمادى الثانية',
|
||||
'رجب',
|
||||
'شعبان',
|
||||
'رمضان',
|
||||
'شوال',
|
||||
'ذو القعدة',
|
||||
'ذو الحجة',
|
||||
];
|
||||
|
||||
// Hijri month names in Arabic (full form) - public for month picker
|
||||
static const List<String> hijriMonthNamesArabic = [
|
||||
'محرم',
|
||||
'صفر',
|
||||
'ربيع الأول',
|
||||
'ربيع الثاني',
|
||||
'جمادى الأولى',
|
||||
'جمادى الثانية',
|
||||
'رجب',
|
||||
'شعبان',
|
||||
'رمضان',
|
||||
'شوال',
|
||||
'ذو القعدة',
|
||||
'ذو الحجة',
|
||||
];
|
||||
|
||||
// Gregorian month names (short form)
|
||||
static const List<String> _gregorianMonthNames = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
];
|
||||
|
||||
// Gregorian month names in English (full form) - public for month picker
|
||||
static const List<String> gregorianMonthNamesEnglish = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
];
|
||||
|
||||
// Gregorian month names in Arabic
|
||||
static const List<String> _gregorianMonthNamesArabic = [
|
||||
'يناير',
|
||||
'فبراير',
|
||||
'مارس',
|
||||
'أبريل',
|
||||
'مايو',
|
||||
'يونيو',
|
||||
'يوليو',
|
||||
'أغسطس',
|
||||
'سبتمبر',
|
||||
'أكتوبر',
|
||||
'نوفمبر',
|
||||
'ديسمبر',
|
||||
];
|
||||
|
||||
// Gregorian month names in Arabic (full form) - public for month picker
|
||||
static const List<String> gregorianMonthNamesArabic = [
|
||||
'يناير',
|
||||
'فبراير',
|
||||
'مارس',
|
||||
'أبريل',
|
||||
'مايو',
|
||||
'يونيو',
|
||||
'يوليو',
|
||||
'أغسطس',
|
||||
'سبتمبر',
|
||||
'أكتوبر',
|
||||
'نوفمبر',
|
||||
'ديسمبر',
|
||||
];
|
||||
|
||||
// Weekday names in English (short form)
|
||||
static const List<String> _weekdayNamesEnglish = [
|
||||
'Sun',
|
||||
'Mon',
|
||||
'Tue',
|
||||
'Wed',
|
||||
'Thu',
|
||||
'Fri',
|
||||
'Sat',
|
||||
];
|
||||
|
||||
// Weekday names in Arabic (short form)
|
||||
static const List<String> _weekdayNamesArabic = [
|
||||
'أحد',
|
||||
'اثنين',
|
||||
'ثلاثاء',
|
||||
'أربعاء',
|
||||
'خميس',
|
||||
'جمعة',
|
||||
'سبت',
|
||||
];
|
||||
|
||||
int get getSelectedTabIndex => _selectedTabIndex;
|
||||
|
||||
CalendarType get calendarType => _calendarType;
|
||||
|
||||
set selectedTabIndex(int value) {
|
||||
_selectedTabIndex = value;
|
||||
_calendarType = value == 0 ? CalendarType.gregorian : CalendarType.hijri;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setTabIndex(int index) {
|
||||
_selectedTabIndex = index;
|
||||
_calendarType = index == 0 ? CalendarType.gregorian : CalendarType.hijri;
|
||||
// Persist the selection for next time the widget opens
|
||||
_persistCalendarTypePreference();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _persistCalendarTypePreference() {
|
||||
// Store the preference in static variables so it persists when widget reopens
|
||||
_persistedTabIndex = _selectedTabIndex;
|
||||
_persistedCalendarType = _calendarType;
|
||||
}
|
||||
|
||||
bool get isGregorian => _calendarType == CalendarType.gregorian;
|
||||
|
||||
bool get isHijri => _calendarType == CalendarType.hijri;
|
||||
|
||||
/// Reset to Gregorian and clear persisted preference
|
||||
/// Call this only when explicitly needed (e.g., logout)
|
||||
void reset({bool force = false}) {
|
||||
if (force) {
|
||||
// Force reset - clear both instance and persisted state
|
||||
_selectedTabIndex = 0;
|
||||
_calendarType = CalendarType.gregorian;
|
||||
_persistedTabIndex = 0;
|
||||
_persistedCalendarType = CalendarType.gregorian;
|
||||
notifyListeners();
|
||||
}
|
||||
// If not forcing, keep the user's preference (persisted state remains)
|
||||
}
|
||||
|
||||
/// Clear persisted calendar type preference (reset to Gregorian on next open)
|
||||
static void clearPersistedPreference() {
|
||||
_persistedTabIndex = 0;
|
||||
_persistedCalendarType = CalendarType.gregorian;
|
||||
}
|
||||
|
||||
// ==================== Conversion Methods ====================
|
||||
|
||||
/// Converts Gregorian DateTime to Hijri date with Umm al-Qura correction
|
||||
HijriGregDate gregorianToHijri(DateTime gregorianDate) {
|
||||
// Apply Umm al-Qura offset for accurate Saudi calendar
|
||||
final adjustedDate = gregorianDate.add(Duration(days: _ummAlQuraOffset));
|
||||
return HijriGregConverter.gregorianToHijri(adjustedDate);
|
||||
}
|
||||
|
||||
/// Converts Hijri date to Gregorian DateTime with Umm al-Qura correction
|
||||
DateTime hijriToGregorian(HijriGregDate hijriDate) {
|
||||
final gregorianDate = HijriGregConverter.hijriToGregorian(hijriDate);
|
||||
// Reverse the Umm al-Qura offset
|
||||
return gregorianDate.subtract(Duration(days: _ummAlQuraOffset));
|
||||
}
|
||||
|
||||
// ==================== Date Formatting Methods ====================
|
||||
|
||||
/// Formats a date based on the current calendar type
|
||||
/// Returns formatted string like "14 Apr,26" for Gregorian or "14 Muh,1447" for Hijri
|
||||
String formatDate(DateTime? date) {
|
||||
if (date == null) return "-";
|
||||
|
||||
if (isGregorian) {
|
||||
return formatGregorianDate(date);
|
||||
} else {
|
||||
return formatHijriDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats a Gregorian date
|
||||
/// Format: "dd MMM,yy" (e.g., "14 Apr,26")
|
||||
String formatGregorianDate(DateTime date) {
|
||||
String year = date.year.toString().substring(2);
|
||||
String month = _gregorianMonthNames[date.month - 1];
|
||||
String day = date.day.toString();
|
||||
return '$day $month,$year';
|
||||
}
|
||||
|
||||
/// Formats a date as Hijri
|
||||
/// Format: "dd MMM,yyyy" (e.g., "14 Muh,1447")
|
||||
String formatHijriDate(DateTime gregorianDate) {
|
||||
HijriGregDate hijriDate = gregorianToHijri(gregorianDate);
|
||||
String month = _hijriMonthNamesShort[hijriDate.month - 1];
|
||||
return '${hijriDate.day} $month,${hijriDate.year}';
|
||||
}
|
||||
|
||||
/// Gets month name based on current calendar type
|
||||
String getMonthName(int month) {
|
||||
if (isGregorian) {
|
||||
return _gregorianMonthNames[month - 1];
|
||||
} else {
|
||||
return _hijriMonthNamesShort[month - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets month name in Arabic based on current calendar type
|
||||
String getMonthNameArabic(int month) {
|
||||
if (isGregorian) {
|
||||
return _gregorianMonthNamesArabic[month - 1];
|
||||
} else {
|
||||
return _hijriMonthNamesShortArabic[month - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets month name with language support
|
||||
String getMonthNameLocalized(int month, bool isArabic) {
|
||||
return isArabic ? getMonthNameArabic(month) : getMonthName(month);
|
||||
}
|
||||
|
||||
/// Gets weekday name in English
|
||||
String getWeekdayName(int weekday) {
|
||||
// weekday: 1 = Monday, 7 = Sunday in DateTime
|
||||
// Convert to Sunday = 0 index
|
||||
int index = weekday % 7;
|
||||
return _weekdayNamesEnglish[index];
|
||||
}
|
||||
|
||||
/// Gets weekday name in Arabic
|
||||
String getWeekdayNameArabic(int weekday) {
|
||||
// weekday: 1 = Monday, 7 = Sunday in DateTime
|
||||
// Convert to Sunday = 0 index
|
||||
int index = weekday % 7;
|
||||
return _weekdayNamesArabic[index];
|
||||
}
|
||||
|
||||
/// Gets weekday name with language support
|
||||
String getWeekdayNameLocalized(int weekday, bool isArabic) {
|
||||
return isArabic ? getWeekdayNameArabic(weekday) : getWeekdayName(weekday);
|
||||
}
|
||||
|
||||
/// Converts a date string to display format based on calendar type
|
||||
String formatDateString(String? dateString) {
|
||||
if (dateString == null || dateString.isEmpty) return "-";
|
||||
|
||||
try {
|
||||
DateTime date = DateTime.parse(dateString);
|
||||
return formatDate(date);
|
||||
} catch (e) {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Date Range Methods ====================
|
||||
|
||||
/// Formats a date range based on current calendar type
|
||||
/// Returns formatted string like "14 Apr,26 - 20 Apr,26" for Gregorian
|
||||
String formatDateRange(DateTime? startDate, DateTime? endDate) {
|
||||
if (startDate == null || endDate == null) return "-";
|
||||
|
||||
String start = formatDate(startDate);
|
||||
String end = formatDate(endDate);
|
||||
return '$start - $end';
|
||||
}
|
||||
|
||||
/// Gets the current date in the selected calendar format
|
||||
String getCurrentDateFormatted() {
|
||||
return formatDate(DateTime.now());
|
||||
}
|
||||
|
||||
// ==================== Calendar Type Specific Helpers ====================
|
||||
|
||||
/// Gets the year based on calendar type
|
||||
int getCurrentYear() {
|
||||
if (isGregorian) {
|
||||
return DateTime.now().year;
|
||||
} else {
|
||||
return gregorianToHijri(DateTime.now()).year;
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets formatted year string based on calendar type
|
||||
String getFormattedYear(DateTime date) {
|
||||
if (isGregorian) {
|
||||
return date.year.toString();
|
||||
} else {
|
||||
return gregorianToHijri(date).year.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a year is leap year based on calendar type
|
||||
bool isLeapYear(int year) {
|
||||
if (isGregorian) {
|
||||
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
|
||||
} else {
|
||||
return HijriGregConverter.isHijriLeapYear(year);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the number of days in a month based on calendar type
|
||||
int getDaysInMonth(int year, int month) {
|
||||
if (isGregorian) {
|
||||
return DateTime(year, month + 1, 0).day;
|
||||
} else {
|
||||
return HijriGregConverter.getHijriMonthLength(year, month);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue