diff --git a/android/app/key.properties b/android/app/key.properties new file mode 100644 index 00000000..5f99fd60 --- /dev/null +++ b/android/app/key.properties @@ -0,0 +1,4 @@ +storePassword=HmGsa123 +keyPassword=HmGsa123 +keyAlias=hmg +storeFile=key \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 70a68707..fc13a9f2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -31,6 +31,9 @@ + @@ -64,6 +67,7 @@ + @@ -128,7 +132,6 @@ ) { + Log.d("updateRemoteViews", "current ticket is ${data["queueNo"] as? String ?: ""}") + Log.d("updateRemoteViews", "remoteViews is $remoteViews") + val progress = when (data["callType"] as? Int) { + 0 -> 33 + 1 -> 66 + 2 ->99 + else -> 99} + + val (nextStepButtonBackground, textColor, containerBackground) = when (data["callType"] as? Int) { + 0 -> Triple(R.drawable.grey_rounded_corner_widget, R.color.text_color, R.drawable.whitebg_yellow_border_rounded_corner_widget) + 1 -> Triple(R.drawable.dark_red_rounded_corner_widget, R.color.colorWhite, R.drawable.whitebg_red_border_rounded_corner_widget) + 2 -> Triple(R.drawable.green_rounded_corner_widget, R. color.colorWhite, R. drawable.whitebg_green_border_rounded_corner_widget) + else -> Triple(R. drawable.grey_rounded_corner_widget, R.color.text_color, R.drawable.whitebg_yellow_border_rounded_corner_widget) + } + + + + remoteViews.setInt(R.id.status_container, "setBackgroundResource", nextStepButtonBackground) + remoteViews.setInt(R.id.role_badge, "setBackgroundResource", nextStepButtonBackground) +// remoteViews.setInt(R.id.container, "setBackgroundResource", containerBackground) + remoteViews.setTextColor(R.id.status_text, ContextCompat.getColor(context, textColor)) + remoteViews.setTextColor(R.id.currentServingStatus, ContextCompat.getColor(context, textColor)) + remoteViews.setProgressBar(R.id.progress_bar,1, progress, true) + + remoteViews.setProgressTintList( + R.id.progress_bar, + "setProgressTintList", + ColorStateList.valueOf(nextStepButtonBackground) // your desired color + ); + + remoteViews.setTextViewText(R.id.queue_number, data["queueNo"] as? String ?: "") + remoteViews.setTextViewText(R.id.currentServingStatus, data["currentlyServingStatus"] as? String ?: "") + remoteViews.setTextViewText(R. id.serving_number, data["currentlyServingToken"] as? String ?: "") + remoteViews.setTextViewText(R.id.status_text, data["nextTicketStatus"] as? String ?: "") + remoteViews.setTextViewText(R.id.queue_label, data["yourTicketHeader"] as? String ?: "") + remoteViews.setTextViewText(R.id.serving_label, data["currentlyServingTitle"] as? String ?: "") + + // Hide serving_layout if currentlyServingToken is empty + val currentlyServingToken = data["currentlyServingToken"] as? String ?: "" + if (currentlyServingToken.isEmpty()) { + remoteViews.setViewVisibility(R.id.serving_layout, android.view.View.GONE) + } else { + remoteViews.setViewVisibility(R.id.serving_layout, android.view.View.VISIBLE) + } + + + } + + private suspend fun updateCollapsedView(data: Map) { + Log.d("updateCollapsedView", "current ticket is ${data["queueNo"] as? String ?: ""}") + Log.d("updateCollapsedView", "remoteViews is $collapesView") + + collapesView.setTextViewText(R.id.queue_number, data["queueNo"] as? String ?: "") + remoteViews.setTextViewText(R.id.queue_label, data["yourTicketHeader"] as? String ?: "") + } + + override suspend fun buildNotification( + notification: Notification.Builder, + event: String, + data: Map + ): Notification { +// val notificationManager = +// context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager +// if (notificationManager != null) { +// notificationManager.cancelAll(); +// } + + collapesView.apply { + updateCollapsedView(data) + } + remoteViews.apply { + updateRemoteViews(data) + } + Log.d("buildNotification", "Building notification for event: $event with data: $data") + Log.d("buildNotification", "Building notification for collapesView: $collapesView with remoteViews: $remoteViews") + + return notification + .setSmallIcon(R.drawable.hmg) + .setContentTitle(data["title"] as? String ?: "Patient Queue") + .setContentIntent(pendingIntent) + .setContentText(data["content"] as? String ?: "Patient Queues") + .setStyle(Notification.DecoratedCustomViewStyle()) + .setCustomContentView(collapesView) + .setCustomBigContentView(remoteViews) + .setPriority(Notification.PRIORITY_HIGH) + .setCategory(Notification.CATEGORY_EVENT) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setOngoing(true) + + .build() + } +} diff --git a/android/app/src/main/res/drawable/dark_red_rounded_corner_widget.xml b/android/app/src/main/res/drawable/dark_red_rounded_corner_widget.xml new file mode 100644 index 00000000..7f6098a6 --- /dev/null +++ b/android/app/src/main/res/drawable/dark_red_rounded_corner_widget.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/green_rounded_corner_widget.xml b/android/app/src/main/res/drawable/green_rounded_corner_widget.xml new file mode 100644 index 00000000..79e7f569 --- /dev/null +++ b/android/app/src/main/res/drawable/green_rounded_corner_widget.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/grey_rounded_corner_widget.xml b/android/app/src/main/res/drawable/grey_rounded_corner_widget.xml new file mode 100644 index 00000000..eda87791 --- /dev/null +++ b/android/app/src/main/res/drawable/grey_rounded_corner_widget.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/hmc.xml b/android/app/src/main/res/drawable/hmc.xml new file mode 100644 index 00000000..5dffd390 --- /dev/null +++ b/android/app/src/main/res/drawable/hmc.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/drawable/hmg.xml b/android/app/src/main/res/drawable/hmg.xml new file mode 100644 index 00000000..ba3a4b2f --- /dev/null +++ b/android/app/src/main/res/drawable/hmg.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/drawable/ic_notification.png b/android/app/src/main/res/drawable/ic_notification.png new file mode 100644 index 00000000..e4a08151 Binary files /dev/null and b/android/app/src/main/res/drawable/ic_notification.png differ diff --git a/android/app/src/main/res/drawable/icon.xml b/android/app/src/main/res/drawable/icon.xml new file mode 100644 index 00000000..68ce3c25 --- /dev/null +++ b/android/app/src/main/res/drawable/icon.xml @@ -0,0 +1,15 @@ + + + + diff --git a/android/app/src/main/res/drawable/profession.xml b/android/app/src/main/res/drawable/profession.xml new file mode 100644 index 00000000..7282bc0f --- /dev/null +++ b/android/app/src/main/res/drawable/profession.xml @@ -0,0 +1,13 @@ + + + + diff --git a/android/app/src/main/res/drawable/progress_bar_drawable.xml b/android/app/src/main/res/drawable/progress_bar_drawable.xml new file mode 100644 index 00000000..9d08e71d --- /dev/null +++ b/android/app/src/main/res/drawable/progress_bar_drawable.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/progress_thumb.xml b/android/app/src/main/res/drawable/progress_thumb.xml new file mode 100644 index 00000000..4c5e39fc --- /dev/null +++ b/android/app/src/main/res/drawable/progress_thumb.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/queue_card_background.xml b/android/app/src/main/res/drawable/queue_card_background.xml new file mode 100644 index 00000000..da4d7207 --- /dev/null +++ b/android/app/src/main/res/drawable/queue_card_background.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/queue_card_background_low_radius.xml b/android/app/src/main/res/drawable/queue_card_background_low_radius.xml new file mode 100644 index 00000000..0d59d1b6 --- /dev/null +++ b/android/app/src/main/res/drawable/queue_card_background_low_radius.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/red_rounded_corner_widget.xml b/android/app/src/main/res/drawable/red_rounded_corner_widget.xml new file mode 100644 index 00000000..5e1395a0 --- /dev/null +++ b/android/app/src/main/res/drawable/red_rounded_corner_widget.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/seekbar_thumb_image.xml b/android/app/src/main/res/drawable/seekbar_thumb_image.xml new file mode 100644 index 00000000..ba9b8c72 --- /dev/null +++ b/android/app/src/main/res/drawable/seekbar_thumb_image.xml @@ -0,0 +1,11 @@ + + + diff --git a/android/app/src/main/res/drawable/status_box_background.xml b/android/app/src/main/res/drawable/status_box_background.xml new file mode 100644 index 00000000..148bcef6 --- /dev/null +++ b/android/app/src/main/res/drawable/status_box_background.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/whitebg_green_border_rounded_corner_widget.xml b/android/app/src/main/res/drawable/whitebg_green_border_rounded_corner_widget.xml new file mode 100644 index 00000000..d75af999 --- /dev/null +++ b/android/app/src/main/res/drawable/whitebg_green_border_rounded_corner_widget.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/whitebg_red_border_rounded_corner_widget.xml b/android/app/src/main/res/drawable/whitebg_red_border_rounded_corner_widget.xml new file mode 100644 index 00000000..246c9613 --- /dev/null +++ b/android/app/src/main/res/drawable/whitebg_red_border_rounded_corner_widget.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/whitebg_yellow_border_rounded_corner_widget.xml b/android/app/src/main/res/drawable/whitebg_yellow_border_rounded_corner_widget.xml new file mode 100644 index 00000000..92e81441 --- /dev/null +++ b/android/app/src/main/res/drawable/whitebg_yellow_border_rounded_corner_widget.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/font/poppins_medium.ttf b/android/app/src/main/res/font/poppins_medium.ttf new file mode 100644 index 00000000..e90e87ed Binary files /dev/null and b/android/app/src/main/res/font/poppins_medium.ttf differ diff --git a/android/app/src/main/res/layout/live_activity.xml b/android/app/src/main/res/layout/live_activity.xml new file mode 100644 index 00000000..06b51931 --- /dev/null +++ b/android/app/src/main/res/layout/live_activity.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/live_activity_collapsed.xml b/android/app/src/main/res/layout/live_activity_collapsed.xml new file mode 100644 index 00000000..096f542c --- /dev/null +++ b/android/app/src/main/res/layout/live_activity_collapsed.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..44004699 --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,13 @@ + + + #ED1C2B + #FFAF15 + #18C273 + #332E3039 + #A2A2A2 + #FFFF + #8F9AA3 + #2E3039 + #18C273 + + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 2d103337..4a6602a0 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -20,4 +20,5 @@ Geofence requests happened too frequently. pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ + diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..13372aef Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 00000000..9d82f789 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/key.properties b/android/key.properties new file mode 100644 index 00000000..5f99fd60 --- /dev/null +++ b/android/key.properties @@ -0,0 +1,4 @@ +storePassword=HmGsa123 +keyPassword=HmGsa123 +keyAlias=hmg +storeFile=key \ No newline at end of file diff --git a/android/local.properties b/android/local.properties new file mode 100644 index 00000000..6316c058 --- /dev/null +++ b/android/local.properties @@ -0,0 +1,5 @@ +flutter.buildMode=debug +flutter.sdk=/Users/cloud/sdk/flutter +flutter.versionCode=38 +flutter.versionName=0.0.39 +sdk.dir=/Users/cloud/Library/Android/sdk \ No newline at end of file diff --git a/assets/files/rule.txt b/assets/files/rule.txt new file mode 100644 index 00000000..49c1cb46 --- /dev/null +++ b/assets/files/rule.txt @@ -0,0 +1 @@ +this is a match \ No newline at end of file diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index d0321ace..d5c45e3c 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1966,5 +1966,12 @@ "weeklyShift": "الفترات الأسبوعية", "dayOff": "إجازة", "notAvailable": "غير متاح", - "hide": "إخفاء" + "hide": "إخفاء", + "yesPleaseINeedHelp": "نعم، من فضلك أريد المساعدة", + "noThanksIKnowTheClinic": "لا شكراً، أعرف العيادة", + "unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة", + "callForVitalSign": "استدعاء لأخذ العلامات الحيوية", + "callForDoctor": "استدعاء الطبيب", + "yourQueueNumber": "رقمك في الدور", + "currentServing": "الدور الحالي" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index ae344b01..e3916d21 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1956,7 +1956,14 @@ "weeklyShift": "Weekly Shift", "dayOff": "Off", "notAvailable": "Not Available", - "hide": "Hide" + "hide": "Hide", + "yesPleaseINeedHelp": "Yes, Please I need help", + "noThanksIKnowTheClinic": "No, Thanks. I Know the clinic", + "unableToSendOTP": "Unable to send Verification OTP", + "callForVitalSign": "Call for vital signs", + "callForDoctor": "Call for Doctor", + "yourQueueNumber": "Your Queue Number", + "currentServing" : "Current Serving" } diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 1dc6cf76..391a902b 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 13.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 00000000..b858ea36 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,677 @@ +PODS: + - amazon_payfort (1.1.4): + - Flutter + - PayFortSDK + - audio_session (0.0.1): + - Flutter + - barcode_scan2 (0.0.1): + - Flutter + - SwiftProtobuf (~> 1.33) + - clarity_flutter (1.0.0): + - Flutter + - 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_amazonpaymentservices (0.0.1): + - Flutter + - PayFortSDK + - flutter_app_group_directory (0.0.1): + - Flutter + - 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_paytabs_bridge (2.7.12): + - Flutter + - PayTabsSDK (= 6.6.54) + - flutter_screenshot_blocker (0.0.1): + - Flutter + - flutter_zoom_videosdk (0.0.1): + - Flutter + - ZoomVideoSDK/CptShare (= 2.4.0) + - ZoomVideoSDK/Whiteboard (= 2.4.0) + - ZoomVideoSDK/zm_annoter_dynamic (= 2.4.0) + - ZoomVideoSDK/zoomcml (= 2.4.0) + - ZoomVideoSDK/ZoomTask (= 2.4.0) + - ZoomVideoSDK/ZoomVideoSDK (= 2.4.0) + - 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 + - live_activities (0.0.1): + - Flutter + - 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.2): + - 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) + - PayTabsSDK (6.6.54) + - permission_handler_apple (9.3.0): + - Flutter + - Polyline (5.1.0) + - PromisesObjC (2.4.0) + - PromisesSwift (2.4.0): + - PromisesObjC (= 2.4.0) + - screen_brightness_ios (0.1.0): + - Flutter + - SDWebImage (5.21.2): + - SDWebImage/Core (= 5.21.2) + - SDWebImage/Core (5.21.2) + - 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.38.1) + - 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.4.0) + - ZoomVideoSDK/Whiteboard (2.4.0) + - ZoomVideoSDK/zm_annoter_dynamic (2.4.0) + - ZoomVideoSDK/zoomcml (2.4.0) + - ZoomVideoSDK/ZoomTask (2.4.0) + - ZoomVideoSDK/ZoomVideoSDK (2.4.0) + +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`) + - clarity_flutter (from `.symlinks/plugins/clarity_flutter/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_amazonpaymentservices (from `.symlinks/plugins/flutter_amazonpaymentservices/ios`) + - flutter_app_group_directory (from `.symlinks/plugins/flutter_app_group_directory/ios`) + - 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_paytabs_bridge (from `.symlinks/plugins/flutter_paytabs_bridge/ios`) + - flutter_screenshot_blocker (from `.symlinks/plugins/flutter_screenshot_blocker/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`) + - live_activities (from `.symlinks/plugins/live_activities/ios`) + - 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`) + - screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/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 + - PayTabsSDK + - 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" + clarity_flutter: + :path: ".symlinks/plugins/clarity_flutter/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_amazonpaymentservices: + :path: ".symlinks/plugins/flutter_amazonpaymentservices/ios" + flutter_app_group_directory: + :path: ".symlinks/plugins/flutter_app_group_directory/ios" + 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_paytabs_bridge: + :path: ".symlinks/plugins/flutter_paytabs_bridge/ios" + flutter_screenshot_blocker: + :path: ".symlinks/plugins/flutter_screenshot_blocker/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" + live_activities: + :path: ".symlinks/plugins/live_activities/ios" + 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" + screen_brightness_ios: + :path: ".symlinks/plugins/screen_brightness_ios/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: 4ad7a3413acc1c4c4022117a80d18fee23c572d3 + audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0 + barcode_scan2: 4e4b850b112f4e29017833e4715f36161f987966 + clarity_flutter: d665e4a61c0000a28e7829668a4e287cc1b657bd + connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd + CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90 + device_calendar: b55b2c5406cfba45c95a59f9059156daee1f74ed + device_calendar_plus_ios: 2c04ad7643c6e697438216e33693b84e8ca45ded + device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be + Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e + firebase_analytics: 0e25ca1d4001ccedd40b4e5b74c0ec34e18f6425 + firebase_core: 995454a784ff288be5689b796deb9e9fa3601818 + firebase_crashlytics: 30dcd6dfd2fe895c0848af46722a4227346c19aa + firebase_messaging: f4a41dd102ac18b840eba3f39d67e77922d3f707 + FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae + FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e + FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435 + FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 + FirebaseCrashlytics: e09d0bc19aa54a51e45b8039c836ef73f32c039a + FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 + FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 + FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa + FirebaseSessions: b9a92c1c51bbb81e78fc3142cda6d925d700f8e7 + FLAnimatedImage: bbf914596368867157cc71b38a8ec834b3eeb32b + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + flutter_amazonpaymentservices: 30d57c19319b81de776345023e4f0697c7d94866 + flutter_app_group_directory: 55b5362007d1c0cb45dc1dd1e94f67d615f45a6b + flutter_callkit_incoming: cb8138af67cda6dd981f7101a5d709003af21502 + flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1 + flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 + flutter_ios_voip_kit_karmm: 371663476722afb631d5a13a39dee74c56c1abd0 + flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb + flutter_nfc_kit: e1b71583eafd2c9650bc86844a7f2d185fb414f6 + flutter_paytabs_bridge: 193d7ae44a86bf5a9b618fc839433e721e04012d + flutter_screenshot_blocker: 87493b3202126286ddce134a2703fdfc1f9267ea + flutter_zoom_videosdk: d0c2be11c6e3bfdae9ace300f878943036cf909c + fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 + geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e + Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321 + google_maps_flutter_ios: 3213e1e5f5588b6134935cb8fc59acb4e6d88377 + GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64 + GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 + GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 + GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d + GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 + health: 32d2fbc7f26f9a2388d1a514ce168adbfa5bda65 + image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 + in_app_review: 7dd1ea365263f834b8464673f9df72c80c17c937 + just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed + libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 + live_activities: 4dfa736d0736e1c77866a2f9c056a76513cc9e7b + local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb + location: 155caecf9da4f280ab5fe4a55f94ceccfab838f8 + manage_calendar_events: fe1541069431af035ced925ebd9def8b4b271254 + Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d + map_launcher: 8051ad5783913cafce93f2414c6858f2904fd8df + MapboxCommon: 119f3759f7dc9457f0695848108ab323eb643cb4 + MapboxCoreMaps: ca17f67baced23f8c952166ac6314c35bad3f66c + MapboxCoreNavigation: 3be9990fae3ed732a101001746d0e3b4234ec023 + MapboxDirections: d4fe7d43cff82aa0c15955d1b4563a5a01e2d4de + MapboxMaps: b7f29ec7c33f7dc6d2947c1148edce6db81db9a7 + MapboxMobileEvents: d044b9edbe0ec7df60f6c2c9634fe9a7f449266b + MapboxNavigation: da9cf3d773ed5b0fa0fb388fccdaa117ee681f31 + MapboxNavigationNative: 629e359f3d2590acd1ebbacaaf99e1a80ee57e42 + MapboxSpeech: cd25ef99c3a3d2e0da72620ff558276ea5991a77 + nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 + network_info_plus: cf61925ab5205dce05a4f0895989afdb6aade5fc + open_filex: 432f3cd11432da3e39f47fcc0df2b1603854eff1 + OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 + PayFortSDK: 233eabe9a45601fdbeac67fa6e5aae46ed8faf82 + PayTabsSDK: 51d21d0174679d08ee816583266aa5f557ebf5ed + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + Polyline: 2a1f29f87f8d9b7de868940f4f76deb8c678a5b1 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 + screen_brightness_ios: 28c5fbdb40634de44f86025d84470158ad4df48c + SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a + SDWebImageWebPCoder: 0e06e365080397465cc73a7a9b472d8a3bd0f377 + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + Solar-dev: 4612dc9878b9fed2667d23b327f1d4e54e16e8d0 + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 + SwiftProtobuf: 409d3aaec90e51b1705b1dd8065b56893450e77c + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 + Turf: aa2ede4298009639d10db36aba1a7ebaad072a5e + url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b + video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a + wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 + webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d + ZoomVideoSDK: c3ac797074847382d9b539044d77f5971d6b62cd + +PODFILE CHECKSUM: b2fdde559476ac2931f2a7ceec6cf5a78743c72b + +COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index fdc3bdfa..d4f26a7e 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -8,24 +8,16 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 1587365701FF0D2AAAFED0D8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A83C76CFF9D3F92EDE3B22B4 /* Pods_Runner.framework */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */; }; - 61243B492EC5FA3700D46FA0 /* PenguinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */; }; - 61243B4C2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */; }; - 61243B502EC5FA3700D46FA0 /* PenguinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B452EC5FA3700D46FA0 /* PenguinView.swift */; }; - 61243B542EC5FA3700D46FA0 /* PenguinPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B442EC5FA3700D46FA0 /* PenguinPlugin.swift */; }; - 61243B562EC5FA3700D46FA0 /* PenguinNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */; }; - 61243B572EC5FA3700D46FA0 /* PenguinViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */; }; + 58A16A1D1E63FA0AF61318A5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE7076AA781403E32077FCBF /* Pods_Runner.framework */; }; + 61AE8DCB3010AA4700DB059A /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61D6D9F1300F522E002E5487 /* WidgetKit.framework */; }; + 61AE8DCC3010AA4700DB059A /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61D6D9F3300F522E002E5487 /* SwiftUI.framework */; }; + 61AE8DD93010AA4A00DB059A /* live_notificationExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 61AE8DCA3010AA4700DB059A /* live_notificationExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 61D6DAB9300F718A002E5487 /* LiveActivityHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D6DAB8300F718A002E5487 /* LiveActivityHelper.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 76AA18AE2F3B2A4D00DC8DFC /* ring_30Sec.caf in Resources */ = {isa = PBXBuildFile; fileRef = 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */; }; - 76B1D2512F91BF8000DBBD1B /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */; }; - 76B1D2522F91BF8000DBBD1B /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 76B1D2532F91BF8000DBBD1B /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */; }; - 76B1D2542F91BF8000DBBD1B /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 76B1D2552F91BF8000DBBD1B /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */; }; - 76B1D2562F91BF8000DBBD1B /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 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,18 +31,33 @@ remoteGlobalIDString = 97C146ED1CF9000F007C117D; remoteInfo = Runner; }; + 61AE8DD73010AA4A00DB059A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 61AE8DC93010AA4700DB059A; + remoteInfo = live_notificationExtension; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 61D6DA07300F5240002E5487 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 61AE8DD93010AA4A00DB059A /* live_notificationExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 765A5A922F35CD8B0003FF7D /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 76B1D2542F91BF8000DBBD1B /* PenguinINRenderer.xcframework in Embed Frameworks */, - 76B1D2522F91BF8000DBBD1B /* Penguin.xcframework in Embed Frameworks */, - 76B1D2562F91BF8000DBBD1B /* PenNavUI.xcframework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -58,30 +65,26 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 05E1B2A0E6844572ADA81174 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 237D1205ED89EAB6C90BC64D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3EAE1F31D8D0AA94CA6C11EB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPenguinInPlatformBridge.swift; sourceTree = ""; }; - 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinModel.swift; sourceTree = ""; }; - 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = ""; }; - 61243B442EC5FA3700D46FA0 /* PenguinPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinPlugin.swift; sourceTree = ""; }; - 61243B452EC5FA3700D46FA0 /* PenguinView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinView.swift; sourceTree = ""; }; - 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinViewFactory.swift; sourceTree = ""; }; + 612BC91D3011009600FF6F5B /* live_notificationExtensionDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = live_notificationExtensionDebug.entitlements; sourceTree = ""; }; + 61AE8DCA3010AA4700DB059A /* live_notificationExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = live_notificationExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 61D6D9F1300F522E002E5487 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 61D6D9F3300F522E002E5487 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; + 61D6DAB8300F718A002E5487 /* LiveActivityHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveActivityHelper.swift; path = Helper/LiveActivityHelper.swift; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = ring_30Sec.caf; sourceTree = ""; }; - 76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = ""; }; - 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = ""; }; - 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7BEF44ABFEF585D64D3F266C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 80AB360F7825C2FB720CB86E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 93CFB47A4DD7AA77469CFEC2 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.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 = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -89,18 +92,49 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A83C76CFF9D3F92EDE3B22B4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CE7076AA781403E32077FCBF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 61AE8DDA3010AA4A00DB059A /* Exceptions for "live_notification" folder in "live_notificationExtension" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 61AE8DC93010AA4700DB059A /* live_notificationExtension */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 61AE8DCD3010AA4700DB059A /* live_notification */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 61AE8DDA3010AA4A00DB059A /* Exceptions for "live_notification" folder in "live_notificationExtension" target */, + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = live_notification; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ + 61AE8DC73010AA4700DB059A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 61AE8DCC3010AA4700DB059A /* SwiftUI.framework in Frameworks */, + 61AE8DCB3010AA4700DB059A /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 76B1D2512F91BF8000DBBD1B /* Penguin.xcframework in Frameworks */, - 76B1D2552F91BF8000DBBD1B /* PenNavUI.xcframework in Frameworks */, - 76B1D2532F91BF8000DBBD1B /* PenguinINRenderer.xcframework in Frameworks */, - DE1EF78253E64BE86845D2CC /* Pods_Runner.framework in Frameworks */, + 58A16A1D1E63FA0AF61318A5 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -115,33 +149,12 @@ path = RunnerTests; sourceTree = ""; }; - 61243B412EC5FA3700D46FA0 /* Helper */ = { - isa = PBXGroup; - children = ( - 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */, - ); - path = Helper; - sourceTree = ""; - }; - 61243B472EC5FA3700D46FA0 /* Penguin */ = { - isa = PBXGroup; - children = ( - 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */, - 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */, - 61243B442EC5FA3700D46FA0 /* PenguinPlugin.swift */, - 61243B452EC5FA3700D46FA0 /* PenguinView.swift */, - 61243B462EC5FA3700D46FA0 /* PenguinViewFactory.swift */, - ); - path = Penguin; - sourceTree = ""; - }; 766D8CB22EC60BE600D05E07 /* Frameworks */ = { isa = PBXGroup; children = ( - 76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */, - 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */, - 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */, - A83C76CFF9D3F92EDE3B22B4 /* Pods_Runner.framework */, + 61D6D9F1300F522E002E5487 /* WidgetKit.framework */, + 61D6D9F3300F522E002E5487 /* SwiftUI.framework */, + CE7076AA781403E32077FCBF /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -149,9 +162,9 @@ 79DD2093A1D9674C94359FC8 /* Pods */ = { isa = PBXGroup; children = ( - 3EAE1F31D8D0AA94CA6C11EB /* Pods-Runner.debug.xcconfig */, - 05E1B2A0E6844572ADA81174 /* Pods-Runner.release.xcconfig */, - 7BEF44ABFEF585D64D3F266C /* Pods-Runner.profile.xcconfig */, + 237D1205ED89EAB6C90BC64D /* Pods-Runner.debug.xcconfig */, + 93CFB47A4DD7AA77469CFEC2 /* Pods-Runner.release.xcconfig */, + 80AB360F7825C2FB720CB86E /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -170,8 +183,10 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + 612BC91D3011009600FF6F5B /* live_notificationExtensionDebug.entitlements */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, + 61AE8DCD3010AA4700DB059A /* live_notification */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, 79DD2093A1D9674C94359FC8 /* Pods */, @@ -184,6 +199,7 @@ children = ( 97C146EE1CF9000F007C117D /* Runner.app */, 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + 61AE8DCA3010AA4700DB059A /* live_notificationExtension.appex */, ); name = Products; sourceTree = ""; @@ -191,9 +207,8 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 61D6DAB8300F718A002E5487 /* LiveActivityHelper.swift */, 76AA18AC2F3B2A4D00DC8DFC /* ring_30Sec.caf */, - 61243B412EC5FA3700D46FA0 /* Helper */, - 61243B472EC5FA3700D46FA0 /* Penguin */, 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */, 478CFA952E6E20A60064F3D7 /* Runner.entitlements */, 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */, @@ -229,23 +244,45 @@ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 61AE8DC93010AA4700DB059A /* live_notificationExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 61AE8DDB3010AA4A00DB059A /* Build configuration list for PBXNativeTarget "live_notificationExtension" */; + buildPhases = ( + 61AE8DC63010AA4700DB059A /* Sources */, + 61AE8DC73010AA4700DB059A /* Frameworks */, + 61AE8DC83010AA4700DB059A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 61AE8DCD3010AA4700DB059A /* live_notification */, + ); + name = live_notificationExtension; + productName = live_notificationExtension; + productReference = 61AE8DCA3010AA4700DB059A /* live_notificationExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - EA10FC42B68E41E75A052FAA /* [CP] Check Pods Manifest.lock */, + 8DED67C11B08C38D4CA4B516 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, + 61D6DA07300F5240002E5487 /* Embed Foundation Extensions */, 97C146EC1CF9000F007C117D /* Resources */, 765A5A922F35CD8B0003FF7D /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 5D78F615DF2D966539B34DE2 /* [CP] Embed Pods Frameworks */, - 4AA9AE39AD56A64A1F16E548 /* [CP] Copy Pods Resources */, + 64913143522DD2E7A5709D09 /* [CP] Embed Pods Frameworks */, + 57400ED2A0499CE460F108E2 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( + 61AE8DD83010AA4A00DB059A /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -259,6 +296,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 2640; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { @@ -266,6 +304,9 @@ CreatedOnToolsVersion = 14.0; TestTargetID = 97C146ED1CF9000F007C117D; }; + 61AE8DC93010AA4700DB059A = { + CreatedOnToolsVersion = 26.4.1; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -287,6 +328,7 @@ targets = ( 97C146ED1CF9000F007C117D /* Runner */, 331C8080294A63A400263BE5 /* RunnerTests */, + 61AE8DC93010AA4700DB059A /* live_notificationExtension */, ); }; /* End PBXProject section */ @@ -299,6 +341,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 61AE8DC83010AA4700DB059A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -329,9 +378,9 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; }; - 4AA9AE39AD56A64A1F16E548 /* [CP] Copy Pods Resources */ = { + 57400ED2A0499CE460F108E2 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -348,7 +397,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 5D78F615DF2D966539B34DE2 /* [CP] Embed Pods Frameworks */ = { + 64913143522DD2E7A5709D09 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -365,42 +414,42 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 8DED67C11B08C38D4CA4B516 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - EA10FC42B68E41E75A052FAA /* [CP] Check Pods Manifest.lock */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ @@ -413,18 +462,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 61AE8DC63010AA4700DB059A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 61243B492EC5FA3700D46FA0 /* PenguinModel.swift in Sources */, - 61243B4C2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift in Sources */, - 61243B502EC5FA3700D46FA0 /* PenguinView.swift in Sources */, - 61243B542EC5FA3700D46FA0 /* PenguinPlugin.swift in Sources */, - 61243B562EC5FA3700D46FA0 /* PenguinNavigator.swift in Sources */, - 61243B572EC5FA3700D46FA0 /* PenguinViewFactory.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + 61D6DAB9300F718A002E5487 /* LiveActivityHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -436,6 +487,11 @@ target = 97C146ED1CF9000F007C117D /* Runner */; targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; }; + 61AE8DD83010AA4A00DB059A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 61AE8DC93010AA4700DB059A /* live_notificationExtension */; + targetProxy = 61AE8DD73010AA4A00DB059A /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -586,6 +642,136 @@ }; name = Profile; }; + 61AE8DDC3010AA4A00DB059A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = live_notificationExtensionDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 3A359E86ZF; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = live_notification/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = live_notification; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.cloudsolutions.HMGPatientApp.live-notification"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 61AE8DDD3010AA4A00DB059A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 3A359E86ZF; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = live_notification/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = live_notification; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.cloudsolutions.HMGPatientApp.live-notification"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 61AE8DDE3010AA4A00DB059A /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 3A359E86ZF; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = live_notification/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = live_notification; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.cloudsolutions.HMGPatientApp.live-notification"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -703,7 +889,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 2; @@ -769,6 +955,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + 61AE8DDB3010AA4A00DB059A /* Build configuration list for PBXNativeTarget "live_notificationExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 61AE8DDC3010AA4A00DB059A /* Debug */, + 61AE8DDD3010AA4A00DB059A /* Release */, + 61AE8DDE3010AA4A00DB059A /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index dc11bbed..a1a793d9 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -13,11 +13,14 @@ import GoogleMaps FirebaseApp.configure() initializePlatformChannels() GeneratedPluginRegistrant.register(with: self) + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } func initializePlatformChannels(){ if let mainViewController = window?.rootViewController as? FlutterViewController{ // platform initialization suppose to be in foreground HMGPenguinInPlatformBridge.initialize(flutterViewController: mainViewController) + LiveActivityHelper().initialize(mainViewController) } } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data){ diff --git a/ios/Runner/Helper/LiveActivityHelper.swift b/ios/Runner/Helper/LiveActivityHelper.swift new file mode 100644 index 00000000..4ebde7fd --- /dev/null +++ b/ios/Runner/Helper/LiveActivityHelper.swift @@ -0,0 +1,37 @@ +// +// LiveActivityHelper.swift +// Runner +// +// Created by Cloud Solutions on 28/01/2026. +// + +import Foundation + + +class LiveActivityHelper{ + + private let channelName = "clear_data" + + var flutterMethodChannelPenguinIn:FlutterMethodChannel? = nil + func initialize(_ controller :FlutterViewController){ + openChannel(controller: controller) + } + + private func openChannel(controller :FlutterViewController){ + flutterMethodChannelPenguinIn = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger) + + flutterMethodChannelPenguinIn?.setMethodCallHandler { (methodCall, result) in + print("Called function \(methodCall.method)") + + + if methodCall.method == "clearUserDefaultData"{ + let sharedDefaults: UserDefaults = UserDefaults(suiteName: "group.alhabib.patientApp")! + sharedDefaults.removePersistentDomain(forName: "group.alhabib.patientApp") + sharedDefaults.synchronize() + result(nil) + } + + } + } + +} diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 5b3b2681..7cb5fbec 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -95,8 +95,14 @@ This app requires calendar access to set reminders for Virtual & Normal Appointments. NSSpeechRecognitionUsageDescription This app requires speech recognition access to access voice command features. + NSSupportsLiveActivities + NSUserActivityTypes + UIAppFonts + + Poppins-Medium.ttf + UIApplicationSupportsIndirectInputEvents UIBackgroundModes @@ -105,6 +111,7 @@ fetch remote-notification voip + processing UILaunchStoryboardName LaunchScreen diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements index 2c37e774..2b950d14 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner/Runner.entitlements @@ -21,5 +21,9 @@ TAG + com.apple.security.application-groups + + group.alhabib.patientApp + diff --git a/ios/Runner/RunnerDebug.entitlements b/ios/Runner/RunnerDebug.entitlements index 319178a4..2b950d14 100644 --- a/ios/Runner/RunnerDebug.entitlements +++ b/ios/Runner/RunnerDebug.entitlements @@ -4,6 +4,14 @@ aps-environment development + com.apple.developer.healthkit + + com.apple.developer.healthkit.access + + health-records + + com.apple.developer.healthkit.background-delivery + com.apple.developer.in-app-payments merchant.com.hmgwebservices @@ -13,5 +21,9 @@ TAG + com.apple.security.application-groups + + group.alhabib.patientApp + diff --git a/ios/live_notification/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/live_notification/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notification/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/live_notification/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..23058801 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notification/Assets.xcassets/Contents.json b/ios/live_notification/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notification/Assets.xcassets/WidgetBackground.colorset/Contents.json b/ios/live_notification/Assets.xcassets/WidgetBackground.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/WidgetBackground.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notification/Assets.xcassets/hmg.imageset/Contents.json b/ios/live_notification/Assets.xcassets/hmg.imageset/Contents.json new file mode 100644 index 00000000..ed588f89 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/hmg.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "hmg.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hmg 1.svg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hmg 2.svg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notification/Assets.xcassets/hmg.imageset/hmg 1.svg b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg 1.svg new file mode 100644 index 00000000..ccaed0c3 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg 1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/live_notification/Assets.xcassets/hmg.imageset/hmg 2.svg b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg 2.svg new file mode 100644 index 00000000..ccaed0c3 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg 2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/live_notification/Assets.xcassets/hmg.imageset/hmg.svg b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg.svg new file mode 100644 index 00000000..ccaed0c3 --- /dev/null +++ b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/live_notification/Info.plist b/ios/live_notification/Info.plist new file mode 100644 index 00000000..0f118fb7 --- /dev/null +++ b/ios/live_notification/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + diff --git a/ios/live_notification/live_notificationBundle.swift b/ios/live_notification/live_notificationBundle.swift new file mode 100644 index 00000000..51dfc678 --- /dev/null +++ b/ios/live_notification/live_notificationBundle.swift @@ -0,0 +1,16 @@ +// +// live_notificationBundle.swift +// live_notification +// +// Created by Cloud Solutions on 22/07/2026. +// + +import WidgetKit +import SwiftUI + +@main +struct live_notificationBundle: WidgetBundle { + var body: some Widget { + live_notificationLiveActivity() + } +} diff --git a/ios/live_notification/live_notificationLiveActivity.swift b/ios/live_notification/live_notificationLiveActivity.swift new file mode 100644 index 00000000..37f8cf07 --- /dev/null +++ b/ios/live_notification/live_notificationLiveActivity.swift @@ -0,0 +1,583 @@ +import ActivityKit +import WidgetKit +import SwiftUI + + +struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable { + public typealias LiveDeliveryData = ContentState // don't forget to add this line, otherwise, live activity will not display it. + + public struct ContentState: Codable, Hashable { } + + var id = UUID() +} + + +let sharedDefault = UserDefaults(suiteName: "group.alhabib.patientApp")! +struct AppWidgetAttributes: ActivityAttributes { + public struct ContentState: Codable, Hashable { + // Dynamic stateful properties about your activity go here! + var emoji: String + } + + // Fixed non-changing properties about your activity go here! + var name: String +} + +extension Color { + static let redColorText = Color(hex: "#ED1C2B") + static let yellowColor = Color(hex: "#FFAF15") + static let successColor = Color(hex: "#18C273") + static let inactiveColor = Color(hex: "#FFA2A2A2") + static let textColor = Color(hex: "#A2A2A2") + static let colorWhite = Color(hex: "#FFFFFF") + + // Helper initializer for hex colors + init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: // RGB (12-bit) + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (255, 0, 0, 0) + } + self.init( + .sRGB, + red: Double(r) / 255, + green: Double(g) / 255, + blue: Double(b) / 255, + opacity: Double(a) / 255 + ) + } +} + +// MARK: - Widget Configuration based on nextStepBackground +struct WidgetColorConfig { + let nextStepBackground: Color + let nextStepTextColor: Color + let containerBorderColor: Color + + static func config(for value: Int) -> WidgetColorConfig { + switch value { + case 0: + return WidgetColorConfig( + nextStepBackground: .inactiveColor, + nextStepTextColor: .colorWhite, + containerBorderColor: .yellowColor + ) + case 1: + return WidgetColorConfig( + nextStepBackground: .redColorText, + nextStepTextColor: .colorWhite, + containerBorderColor: .redColorText + ) + case 2: + return WidgetColorConfig( + nextStepBackground: .successColor, + nextStepTextColor: .colorWhite, + containerBorderColor: .successColor + ) + default: + return WidgetColorConfig( + nextStepBackground: .inactiveColor, + nextStepTextColor: .textColor, + containerBorderColor: .yellowColor + ) + } + } +} + +// MARK: - Widget Data Model +struct NotificationWidgetData { + let currentTicket: String + let currentlyServingHeader: String + let currentlyServing: String + let currentlyServingStatus: String + let nextStep: String + let imageName: String + let colorConfig: WidgetColorConfig + let progress: Double + let yourTicketHeaderText : String +} +struct NotificationWidgetView: View { + private let data: NotificationWidgetData + private let backgroundColor: Color + let animateProgress = false + init(data: NotificationWidgetData, backgroundColor: Color = .white) { + print("it is being loaded") + self.data = data + self.backgroundColor = backgroundColor + } + + + var body : some View{ + ZStack { + // Dark background + Color(red: 0.15, green: 0.15, blue: 0.15) + .ignoresSafeArea() + + // Main card + VStack(alignment: .leading, spacing: 0) { + // Header section + HStack(alignment: .top) { + HStack( alignment: .center,spacing: 4) { + Text(data.currentTicket) + .font(.system(size: 32, weight: .bold, design: .default)) + .foregroundColor(Color(red: 0, green: 0.2, blue: 0.4)) + + Text(data.yourTicketHeaderText) + .font(.system(size: 14, weight: .regular)) + .foregroundColor(Color(hex: "#8F9AA3")) + } + + Spacer() + + // Hourglass icon + Image("hmg") + .frame(width: 24, height:24 ) + .foregroundColor(Color(hex: "#2E3039")) + .padding(.top, 4) + } + .padding(.top,4) + + .padding(.bottom, 4) + + // Alert banner + HStack(spacing: 4) { + Image("profession") + + Text(data.nextStep) + .font(.system(size: 10, weight: .semibold)) + .foregroundColor(data.colorConfig.nextStepTextColor) + + } + .padding(8) + .background(data.colorConfig.nextStepBackground) + .cornerRadius(8) + .padding(.bottom, 10) + +// // Progress bar +// VStack(alignment: .leading) { +// ZStack(alignment: .leading) { +// // Background track +// Capsule() +// .fill(Color(red: 0.9, green: 0.9, blue: 0.9)) +// .frame(height: 4) +// +// // Progress fill +// Capsule() +// .fill(Color.green) +// .frame(width: data.progress, height: 4) +// .animation( +// Animation.easeInOut(duration: 1.5) +// .delay(0.3), +// value: animateProgress +// ) +// +// ZStack{ +// Circle() +// .fill(Color.white) +// .frame(width: 12, height: 12) +// +// Circle() +// .fill(data.colorConfig.nextStepBackground) +// .frame(width: 10, height: 10) +// +// .animation( +// Animation.easeInOut(duration: 1.5) +// .delay(0.3), +// value: animateProgress +// ) +// } +// .offset(x:data.progress) +// +// } +// } +// .padding(.bottom, 10) + + // Footer section + if !data.currentlyServing.isEmpty { + HStack { + VStack(alignment: .leading, spacing: 0) { + HStack(spacing: 4) { + Text(data.currentlyServingHeader) + .font(.system(size: 14, weight: .regular)) + .foregroundColor(Color(hex:"#8F9AA3")) + + Text(data.currentlyServing) + .font(.system(size: 18, weight: .bold)) + .foregroundColor(Color(hex:"#2E3039")) + } + } + + Spacer() + + // Visiting Nurse badge + HStack(spacing: 8) { + Image("profession") + .font(.system(size: 10, weight: .semibold)) + .foregroundColor(Color(hex: "#18C273")) + + Text(data.currentlyServingStatus) + .font(.system(size: 10, weight: .semibold)) + .foregroundColor(data.colorConfig.nextStepTextColor) + } + .padding(8) + .background(data.colorConfig.nextStepBackground) + .cornerRadius(8) + } + .padding(.horizontal, 8) + .padding(.bottom, 8) + } + } + .padding(24) + .background(backgroundColor) + .cornerRadius(24) + + } + + + } + // var body2 : some View { + // Text(data.currentTicket) + // .font(.custom("Poppins-Medium", size: 28)) + // .fontWeight(.bold) + // .foregroundColor(.black) + // .padding(.trailing, 10) + // .frame(maxWidth: .infinity, alignment: .leading) + // } +//current one that todo will be handled +// var body2: some View { +// VStack(alignment: .leading, spacing: 0) { +// // Top section with current ticket and image +// HStack(alignment: .top, spacing: 0) { +// // Current ticket value +// Text(data.currentTicket) +// .font(.custom("Poppins-Medium", size: 28)) +// .fontWeight(.bold) +// .foregroundColor(.black) +// .padding(.trailing, 10) +// .frame(maxWidth: .infinity, alignment: .leading) +// +// Image(data.imageName) +// .resizable() +// .scaledToFit() +// .frame(width: 34, height: 34) +// } +// .padding(.top, 16) +// .padding(.horizontal, 16) +// +// // Currently Serving Header +// Text(data.currentlyServingHeader) +// .font(.custom("Poppins-Medium", size: 14)) +// .fontWeight(.bold) +// .foregroundColor(.black) +// .padding(.trailing, 12) +// .padding(.bottom, 10) +// .padding(.horizontal, 16) +// +// // Currently Serving section with currentlyServingStatus +// HStack(alignment: .center, spacing: 0) { +// // Currently serving text +// Text(data.currentlyServing) +// .font(.custom("Poppins-Medium", size: 16)) +// .fontWeight(.bold) +// .foregroundColor(.black) +// .frame(maxWidth: .infinity, alignment: .leading) +// +// // currentlyServingStatus badge +// Text(data.currentlyServingStatus) +// .font(.custom("Poppins-Medium", size: 12)) +// .foregroundColor(data.colorConfig.nextStepTextColor) +// .padding(.horizontal, 12) +// .padding(.vertical, 8) +// .background( +// RoundedRectangle(cornerRadius: 8) +// .fill(Color.inactiveColor.opacity(0.2)) +// ) +// } +// .padding(.horizontal, 16) +// Spacer() +// // Next Step badge +// Text(data.nextStep) +// .font(.custom("Poppins-Medium", size: 12)) +// .foregroundColor(data.colorConfig.nextStepTextColor) +// .padding(.horizontal, 12) +// .padding(.vertical, 8) +// .background( +// RoundedRectangle(cornerRadius: 8) +// .fill(data.colorConfig.nextStepBackground) +// ) +// .padding(.horizontal, 16) +// .padding(.bottom, 16) +// } +// .background(Color.black.opacity(0.01)) +// .cornerRadius(20) + +// .border(width: 10, edges: [.top, .bottom], color: data.colorConfig.containerBorderColor) +// .border(width: 2, edges: [.leading, .trailing], color: data.colorConfig.containerBorderColor) +// .overlay( +// RoundedRectangle(cornerRadius: 20) +// .stroke(data.colorConfig.containerBorderColor, lineWidth: 20) +// ) +// } +} + + +// MARK: - Live Activity Widget +struct live_notificationLiveActivity: Widget { + + var body: some WidgetConfiguration { + ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in + + // Extract parameters from Flutter + +// print("the queno is \(context.attributes.prefixedKey("title")) ===== \(sharedDefault.string(forKey: context.attributes.prefixedKey("queueNo")) )") +// let title = sharedDefault.string(forKey: context.attributes.prefixedKey("title")) ?? "testes" +// let contentText = sharedDefault.string(forKey: context.attributes.prefixedKey("contentText")) ?? "tested" +// let currentTicket = sharedDefault.string(forKey: context.attributes.prefixedKey("queueNo")) ?? "test1234" +// let currentlyServingStatus = sharedDefault.string(forKey: context.attributes.prefixedKey("callType")) ?? "test3345" +// let currentlyServing = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingTitle")) ?? "tes" +// let nextStep = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingcurrentlyServingStatus")) ?? +// "test111" +// let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) + + // let title = sharedDefault.string(forKey: context.attributes.prefixedKey("title")) ?? "testes" +// let contentText = sharedDefault.string(forKey: context.attributes.prefixedKey("contentText")) ?? "tested" + let currentTicket = getValueFromSharedDefaults("queueNo") + let currentlyServingStatus = getValueFromSharedDefaults("currentlyServingStatus") ?? "test3345" + let currentlyServing = getValueFromSharedDefaults("currentlyServingToken") + let currentlyServingHeader = getValueFromSharedDefaults("currentlyServingTitle") + let yourTicketHeader = getValueFromSharedDefaults("yourTicketHeader") + let nextStep = getValueFromSharedDefaults("nextTicketStatus") + let nextStepBackground = Int(sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingCallType")) ?? "0") ?? 0 + let callType = sharedDefault.integer(forKey: context.attributes.prefixedKey("callType")) ?? 0 + + + + + // Get color configuration based on nextStepBackground + let colorConfig = WidgetColorConfig.config(for: callType) + + // Create widget data + let widgetData = NotificationWidgetData( + currentTicket: currentTicket, + currentlyServingHeader: currentlyServingHeader, + currentlyServing: currentlyServing, + currentlyServingStatus: currentlyServingStatus, + nextStep: nextStep, + imageName:"hmg", + colorConfig: colorConfig, + progress: 33 * Double(callType), + yourTicketHeaderText : yourTicketHeader, + ) +// + // Lock screen/banner UI + NotificationWidgetView(data: widgetData) + + + // Text(widgetData.currentTicket) + // .font(.custom("Poppins-Medium", size: 28)) + // .fontWeight(.bold) + // .foregroundColor(.black) + // .padding(.trailing, 10) + // .frame(maxWidth: .infinity, alignment: .leading) + + } dynamicIsland: { context in + + let currentTicket = getValueFromSharedDefaults("queueNo") + let currentlyServingStatus = getValueFromSharedDefaults("currentlyServingStatus") ?? "test3345" + let currentlyServing = getValueFromSharedDefaults("currentlyServingToken") + let nextStep = getValueFromSharedDefaults("nextTicketStatus") + let nextStepBackground = Int(sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingCallType")) ?? "0") ?? 0 + let currentlyServingHeader = getValueFromSharedDefaults("currentlyServingTitle") + let yourTicketHeader = getValueFromSharedDefaults("yourTicketHeader") + let callType = sharedDefault.integer(forKey: context.attributes.prefixedKey("callType")) ?? 0 + + + + let colorConfig = WidgetColorConfig.config(for: callType) + let widgetData = NotificationWidgetData( + currentTicket: currentTicket, + currentlyServingHeader: currentlyServingHeader, + currentlyServing: currentlyServing, + currentlyServingStatus: currentlyServingStatus, + nextStep: nextStep, + imageName:"hmg", + colorConfig: colorConfig, + progress: 33 * Double(callType), + yourTicketHeaderText: yourTicketHeader + ) + return DynamicIsland { + + // + // Lock screen/banner UI + + +// // Expanded UI + DynamicIslandExpandedRegion(.center) { + NotificationWidgetView(data: widgetData, backgroundColor: .black.opacity(0.4)).padding(-24) + } + +// DynamicIslandExpandedRegion(.trailing) { +// Image("hmg") +// .resizable() +// .scaledToFit() +// .frame(width: 34, height: 34) +// .foregroundColor(.gray) +// } +// +// DynamicIslandExpandedRegion(.center) { +// VStack(spacing: 4) { +// Text("Currently Servings:") +// .font(.caption2) +// .foregroundColor(.secondary) +// +// Text(currentlyServing) +// .font(.caption) +// .fontWeight(.semibold) +// } +// } +// +// DynamicIslandExpandedRegion(.bottom) { +// HStack { +// Text(currentlyServingStatus) +// .font(.caption2) +// .padding(.horizontal, 8) +// .padding(.vertical, 4) +// .background( +// RoundedRectangle(cornerRadius: 6) +// .fill(colorConfig.nextStepBackground.opacity(0.2)) +// ) +// +// Spacer() +// +// Text(nextStep) +// .font(.caption2) +// .foregroundColor(colorConfig.nextStepTextColor) +// .padding(.horizontal, 8) +// .padding(.vertical, 4) +// .background( +// RoundedRectangle(cornerRadius: 6) +// .fill(colorConfig.nextStepBackground) +// ) +// } +// .padding(.horizontal) +// } + + } compactLeading: { + // Compact leading view + Text(currentTicket) + .font(.caption2) + .fontWeight(.bold) + } compactTrailing: { + // Compact trailing view + Image("hmg") + .resizable() + .scaledToFit() + .frame(width: 12, height: 12) + .foregroundColor(colorConfig.containerBorderColor).padding(4) + } minimal: { + // Minimal view + HStack{ + Text(currentTicket) + .font(.caption2) + .fontWeight(.bold) + Spacer() + Image("hmg") + .resizable() + .scaledToFit() + .frame(width: 4, height: 4) + .foregroundColor(colorConfig.containerBorderColor) + }.padding(2) + + } + + } + } +} + + +extension LiveActivitiesAppAttributes { + func prefixedKey(_ key: String) -> String { + print("the id is \(id)") + return "\(id)_\(key)" + } +} + +//struct NotificationWidgetView_Previews: PreviewProvider { +// static var previews: some View { +// Group { +// // Preview with nextStepBackground = 0 (Yellow border) +// NotificationWidgetView( +// data: NotificationWidgetData( +// currentTicket: "42", +// currentlyServingHeader: "Currently Serving3:", +// currentlyServing: "Customer #15", +// currentlyServingStatus: "Pending", +// nextStep: "Next: Prepare Order", +// imageName: "bell.fill", +// colorConfig: .config(for: 0) +// ) +// ) +// .previewDisplayName("Yellow Border (0)") +// +// // Preview with nextStepBackground = 1 (Red border) +// NotificationWidgetView( +// data: NotificationWidgetData( +// currentTicket: "89", +// currentlyServingHeader: "Currently Serving2:", +// currentlyServing: "Customer #67", +// currentlyServingStatus: "Active", +// nextStep: "Next: Quality Check", +// imageName: "bell.fill", +// colorConfig: .config(for: 1) +// ) +// ) +// .previewDisplayName("Red Border (1)") +// +// // Preview with nextStepBackground = 2 (Green border) +// NotificationWidgetView( +// data: NotificationWidgetData( +// currentTicket: "125", +// currentlyServingHeader: "Currently Serving1:", +// currentlyServing: "Customer #98", +// currentlyServingStatus: "Completed", +// nextStep: "Next: Ready for Pickup", +// imageName: "bell.fill", +// colorConfig: .config(for: 2) +// ) +// ) +// .previewDisplayName("Green Border (2)") +// } +// .padding() +// .previewLayout(.sizeThatFits) +// } +//} + + +func getValueFromSharedDefaults(_ containingString: String) -> String { + print("Function `getValueFromSharedDefaults` is being called") + let dictionary = sharedDefault.dictionaryRepresentation() + print("Contents of sharedDefault: \(dictionary)") + + for (key, value) in dictionary { + print("Inspecting key: \(key), value: \(value)") + + if key.contains(containingString) { + let components = key.split(separator: "_") + if let stringValue = value as? String { + return stringValue + } else { + return "" + } + } + } + return "" +} diff --git a/ios/live_notificationExtensionDebug.entitlements b/ios/live_notificationExtensionDebug.entitlements new file mode 100644 index 00000000..a1ca053c --- /dev/null +++ b/ios/live_notificationExtensionDebug.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.alhabib.patientApp + + + diff --git a/ios/live_notifications/AppIntent.swift b/ios/live_notifications/AppIntent.swift new file mode 100644 index 00000000..cca69d59 --- /dev/null +++ b/ios/live_notifications/AppIntent.swift @@ -0,0 +1,18 @@ +// +// AppIntent.swift +// live_notifications +// +// Created by Haroon Amjad on 20/07/2026. +// + +import WidgetKit +import AppIntents + +struct ConfigurationAppIntent: WidgetConfigurationIntent { + static var title: LocalizedStringResource { "Configuration" } + static var description: IntentDescription { "This is an example widget." } + + // An example configurable parameter. + @Parameter(title: "Favorite Emoji", default: "😃") + var favoriteEmoji: String +} diff --git a/ios/live_notifications/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/live_notifications/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notifications/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/live_notifications/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..23058801 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notifications/Assets.xcassets/Contents.json b/ios/live_notifications/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notifications/Assets.xcassets/WidgetBackground.colorset/Contents.json b/ios/live_notifications/Assets.xcassets/WidgetBackground.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/WidgetBackground.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notifications/Assets.xcassets/hmg.imageset/Contents.json b/ios/live_notifications/Assets.xcassets/hmg.imageset/Contents.json new file mode 100644 index 00000000..ed588f89 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/hmg.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "hmg.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hmg 1.svg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hmg 2.svg", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg 1.svg b/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg 1.svg new file mode 100644 index 00000000..ccaed0c3 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg 1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg 2.svg b/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg 2.svg new file mode 100644 index 00000000..ccaed0c3 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg 2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg.svg b/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg.svg new file mode 100644 index 00000000..ccaed0c3 --- /dev/null +++ b/ios/live_notifications/Assets.xcassets/hmg.imageset/hmg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/live_notifications/Info.plist b/ios/live_notifications/Info.plist new file mode 100644 index 00000000..0f118fb7 --- /dev/null +++ b/ios/live_notifications/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + diff --git a/ios/live_notifications/live_notification.swift b/ios/live_notifications/live_notification.swift new file mode 100644 index 00000000..9eec9203 --- /dev/null +++ b/ios/live_notifications/live_notification.swift @@ -0,0 +1,84 @@ +// +// live_notifications.swift +// live_notifications +// +// Created by Cloud Solutions on 21/07/2026. +// + +import WidgetKit +import SwiftUI + +struct Provider: TimelineProvider { + func placeholder(in context: Context) -> SimpleEntry { + SimpleEntry(date: Date(), emoji: "😀") + } + + func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { + let entry = SimpleEntry(date: Date(), emoji: "😀") + completion(entry) + } + + func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { + var entries: [SimpleEntry] = [] + + // Generate a timeline consisting of five entries an hour apart, starting from the current date. + let currentDate = Date() + for hourOffset in 0 ..< 5 { + let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)! + let entry = SimpleEntry(date: entryDate, emoji: "😀") + entries.append(entry) + } + + let timeline = Timeline(entries: entries, policy: .atEnd) + completion(timeline) + } + +// func relevances() async -> WidgetRelevances { +// // Generate a list containing the contexts this widget is relevant in. +// } +} + +struct SimpleEntry: TimelineEntry { + let date: Date + let emoji: String +} + +struct live_notificationEntryView : View { + var entry: Provider.Entry + + var body: some View { + VStack { + Text("Time:") + Text(entry.date, style: .time) + + Text("Emoji:") + Text(entry.emoji) + } + } +} + +struct live_notification: Widget { + let kind: String = "live_notifications" + + var body: some WidgetConfiguration { + StaticConfiguration(kind: kind, provider: Provider()) { entry in + if #available(iOS 17.0, *) { + live_notificationEntryView(entry: entry) + .containerBackground(.fill.tertiary, for: .widget) + } else { + live_notificationEntryView(entry: entry) + .padding() + .background() + } + } + .configurationDisplayName("My Widget") + .description("This is an example widget.") + } +} + +#Preview(as: .systemSmall) { + live_notification() +} timeline: { + SimpleEntry(date: .now, emoji: "😀") + SimpleEntry(date: .now, emoji: "🤩") +} diff --git a/ios/live_notifications/live_notificationBundle.swift b/ios/live_notifications/live_notificationBundle.swift new file mode 100644 index 00000000..2a55111c --- /dev/null +++ b/ios/live_notifications/live_notificationBundle.swift @@ -0,0 +1,16 @@ +// +// live_notificationBundle.swift +// live_notifications +// +// Created by Haroon Amjad on 20/07/2026. +// + +import WidgetKit +import SwiftUI + +@main +struct live_notificationBundle: WidgetBundle { + var body: some Widget { + live_notificationLiveActivity() + } +} diff --git a/ios/live_notifications/live_notificationLiveActivity.swift b/ios/live_notifications/live_notificationLiveActivity.swift new file mode 100644 index 00000000..ec976f41 --- /dev/null +++ b/ios/live_notifications/live_notificationLiveActivity.swift @@ -0,0 +1,420 @@ +import ActivityKit +import WidgetKit +import SwiftUI + +struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable { + public typealias LiveDeliveryData = ContentState // don't forget to add this line, otherwise, live activity will not display it. + + public struct ContentState: Codable, Hashable { } + + var id = UUID() +} + + +let sharedDefault = UserDefaults(suiteName: "group.alhabib.patientApp")! +struct AppWidgetAttributes: ActivityAttributes { + public struct ContentState: Codable, Hashable { + // Dynamic stateful properties about your activity go here! + var emoji: String + } + + // Fixed non-changing properties about your activity go here! + var name: String +} + +extension Color { + static let redColorText = Color(hex: "#ED1C2B") + static let yellowColor = Color(hex: "#FFAF15") + static let successColor = Color(hex: "#18C273") + static let inactiveColor = Color(hex: "#ED1C2B") + static let textColor = Color(hex: "#A2A2A2") + static let colorWhite = Color(hex: "#FFFFFF") + + // Helper initializer for hex colors + init(hex: String) { + let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int: UInt64 = 0 + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: // RGB (12-bit) + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (255, 0, 0, 0) + } + self.init( + .sRGB, + red: Double(r) / 255, + green: Double(g) / 255, + blue: Double(b) / 255, + opacity: Double(a) / 255 + ) + } +} + +// MARK: - Widget Configuration based on currentServingStatusBackground +struct WidgetColorConfig { + let currentServingStatusBackground: Color + let currentServingStatusTextColor: Color + let containerBorderColor: Color + + static func config(for value: Int) -> WidgetColorConfig { + switch value { + case 0: + return WidgetColorConfig( + currentServingStatusBackground: .inactiveColor, + currentServingStatusTextColor: .textColor, + containerBorderColor: .yellowColor + ) + case 1: + return WidgetColorConfig( + currentServingStatusBackground: .redColorText, + currentServingStatusTextColor: .colorWhite, + containerBorderColor: .redColorText + ) + case 2: + return WidgetColorConfig( + currentServingStatusBackground: .successColor, + currentServingStatusTextColor: .colorWhite, + containerBorderColor: .successColor + ) + default: + return WidgetColorConfig( + currentServingStatusBackground: .inactiveColor, + currentServingStatusTextColor: .textColor, + containerBorderColor: .yellowColor + ) + } + } +} + +// MARK: - Widget Data Model +struct NotificationWidgetData { + let queueNo: String + let yourTicketHeader: String + let currentlyServing: String + let status: Int + let currentServingStatus: String + let imageName: String + let nextTicketStatus: String + let colorConfig: WidgetColorConfig +} +struct NotificationWidgetView: View { + private let data: NotificationWidgetData + + init(data: NotificationWidgetData) { + print("it is being loaded") + self.data = data + } + + + var body : some View{ +// ZStack(){ + body2 +// .frame(width: .infinity, height: 400 ) +// .padding(.top, 340) +// .cornerRadius(20) +// }.background(data.colorConfig.containerBorderColor) +// .cornerRadius(20) + + } + // var body2 : some View { + // Text(data.queueNo) + // .font(.custom("Poppins-Medium", size: 28)) + // .fontWeight(.bold) + // .foregroundColor(.black) + // .padding(.trailing, 10) + // .frame(maxWidth: .infinity, alignment: .leading) + // } +//current one that todo will be handled + var body2: some View { + VStack(alignment: .leading, spacing: 0) { + // Top section with current ticket and image + HStack(alignment: .top, spacing: 0) { + // Current ticket value + Text(data.yourTicketHeader) + .font(.custom("Poppins-Medium", size: 28)) + .fontWeight(.bold) + .foregroundColor(.black) + .padding(.trailing, 10) + .frame(maxWidth: .infinity, alignment: .leading) + + Image(data.imageName) + .resizable() + .scaledToFit() + .frame(width: 34, height: 34) + } + .padding(.top, 16) + .padding(.horizontal, 16) + + // Currently Serving Header + Text(data.queueNo) + .font(.custom("Poppins-Medium", size: 14)) + .fontWeight(.bold) + .foregroundColor(.black) + .padding(.trailing, 12) + .padding(.bottom, 10) + .padding(.horizontal, 16) + + // Currently Serving section with status + HStack(alignment: .center, spacing: 0) { + // Currently serving text + Text(data.currentlyServing) + .font(.custom("Poppins-Medium", size: 16)) + .fontWeight(.bold) + .foregroundColor(.black) + .frame(maxWidth: .infinity, alignment: .leading) + + // Status badge + Text(data.currentServingStatus) + .font(.custom("Poppins-Medium", size: 12)) + .foregroundColor(data.colorConfig.currentServingStatusTextColor) + .padding(.horizontal, 12) + .padding(.vertical, 8) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color.inactiveColor.opacity(0.2)) + ) + } + .padding(.horizontal, 16) + Spacer() + // Next Step badge + Text(data.currentServingStatus) + .font(.custom("Poppins-Medium", size: 12)) + .foregroundColor(data.colorConfig.currentServingStatusTextColor) + .padding(.horizontal, 12) + .padding(.vertical, 8) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(data.colorConfig.currentServingStatusBackground) + ) + .padding(.horizontal, 16) + .padding(.bottom, 16) + } + .background(Color.black.opacity(0.01)) + .cornerRadius(20) + +// .border(width: 10, edges: [.top, .bottom], color: data.colorConfig.containerBorderColor) +// .border(width: 2, edges: [.leading, .trailing], color: data.colorConfig.containerBorderColor) +// .overlay( +// RoundedRectangle(cornerRadius: 20) +// .stroke(data.colorConfig.containerBorderColor, lineWidth: 20) +// ) + } +} + + +// MARK: - Live Activity Widget +struct live_notificationLiveActivity: Widget { + + var body: some WidgetConfiguration { + ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in + // Extract parameters from Flut +// print("the queno is \(context.attributes.prefixedKey("title")) ===== \(sharedDefault.string(forKey: context.attributes.prefixedKey("queueNo")) )") + let title = sharedDefault.string(forKey: context.attributes.prefixedKey("title")) ?? "" + let yourTicketHeader = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingHeader")) ?? "" + let nextTicketStatus = sharedDefault.string(forKey: context.attributes.prefixedKey("nextTicketStatus")) ?? "" + + let queueNo = sharedDefault.string(forKey: context.attributes.prefixedKey("queueNo")) ?? "" + let currentlyServingToken = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingToken")) ?? "" + let currentlyServing = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingTitle")) ?? "" + let currentServingStatus = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingStatus")) ?? + "" + let currentServingStatusBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) + + let status = sharedDefault.integer(forKey: context.attributes.prefixedKey("callType")) ?? 0 + + + // Get color configuration based on currentServingStatusBackground + let colorConfig = WidgetColorConfig.config(for: status) + + // Create widget data + let widgetData = NotificationWidgetData( + queueNo: queueNo, + yourTicketHeader: yourTicketHeader, + currentlyServing: currentlyServing, + status: status, + currentServingStatus: currentServingStatus, + imageName:"hmg", + nextTicketStatus:nextTicketStatus, + colorConfig: colorConfig + ) +// + // Lock screen/banner UI + NotificationWidgetView(data: widgetData) + .activityBackgroundTint(Color.clear) + .activitySystemActionForegroundColor(Color.black) + + // Text(widgetData.queueNo) + // .font(.custom("Poppins-Medium", size: 28)) + // .fontWeight(.bold) + // .foregroundColor(.black) + // .padding(.trailing, 10) + // .frame(maxWidth: .infinity, alignment: .leading) + + } dynamicIsland: { context in + + let title = sharedDefault.string(forKey: context.attributes.prefixedKey("title")) ?? "testes" + let contentText = sharedDefault.string(forKey: context.attributes.prefixedKey("contentText")) ?? "tested" + let queueNo = sharedDefault.string(forKey: context.attributes.prefixedKey("queueNo")) ?? "test1234" + let status = sharedDefault.string(forKey: context.attributes.prefixedKey("callType")) ?? "test3345" + let currentlyServing = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingTitle")) ?? "tes" + let currentServingStatus = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingStatus")) ?? + "test111" + let currentServingStatusBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) + + + let colorConfig = WidgetColorConfig.config(for: currentServingStatusBackground) + + return DynamicIsland { + // Expanded UI + DynamicIslandExpandedRegion(.leading) { + VStack(alignment: .leading) { + Text(queueNo) + .font(.system(size: 24, weight: .bold)) + .foregroundColor(.primary) + } + } + + DynamicIslandExpandedRegion(.trailing) { + Image("hmg") + .resizable() + .scaledToFit() + .frame(width: 34, height: 34) + .foregroundColor(.gray) + } + + DynamicIslandExpandedRegion(.center) { + VStack(spacing: 4) { + Text("Currently Servings:") + .font(.caption2) + .foregroundColor(.secondary) + + Text(currentlyServing) + .font(.caption) + .fontWeight(.semibold) + } + } + + DynamicIslandExpandedRegion(.bottom) { + HStack { + Text(status) + .font(.caption2) + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background( + RoundedRectangle(cornerRadius: 6) + .fill(colorConfig.currentServingStatusBackground.opacity(0.2)) + ) + + Spacer() + + Text(currentServingStatus) + .font(.caption2) + .foregroundColor(colorConfig.currentServingStatusTextColor) + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background( + RoundedRectangle(cornerRadius: 6) + .fill(colorConfig.currentServingStatusBackground) + ) + } + .padding(.horizontal) + } + + } compactLeading: { + // Compact leading view + Text(queueNo) + .font(.caption2) + .fontWeight(.bold) + } compactTrailing: { + // Compact trailing view + Image("hmg") + .resizable() + .scaledToFit() + .frame(width: 12, height: 12) + .foregroundColor(colorConfig.containerBorderColor).padding(4) + } minimal: { + // Minimal view + HStack{ + Text(queueNo) + .font(.caption2) + .fontWeight(.bold) + Spacer() + Image("hmg") + .resizable() + .scaledToFit() + .frame(width: 4, height: 4) + .foregroundColor(colorConfig.containerBorderColor) + }.padding(2) + + } + .contentMargins(.all, 20,for: .expanded) + } + } + } + + +extension LiveActivitiesAppAttributes { + func prefixedKey(_ key: String) -> String { + print("the id to get the element is \(id)") + return "\(id)_\(key)" + } +} +// MARK: - Preview for Testing +struct NotificationWidgetView_Previews: PreviewProvider { + static var previews: some View { + Group { + // Preview with currentServingStatusBackground = 0 (Yellow border) + NotificationWidgetView( + data: NotificationWidgetData( + queueNo: "42", + yourTicketHeader: "Currently Serving3:", + currentlyServing: "Customer #15", + status: 0, + currentServingStatus: "Next: Prepare Order", + imageName: "bell.fill", + nextTicketStatus: "bell.fill", + colorConfig: .config(for: 0) + ) + ) + .previewDisplayName("Yellow Border (0)") + + // Preview with currentServingStatusBackground = 1 (Red border) + NotificationWidgetView( + data: NotificationWidgetData( + queueNo: "89", + yourTicketHeader: "Currently Serving2:", + currentlyServing: "Customer #67", + status: 1, + currentServingStatus: "Next: Quality Check", + imageName: "bell.fill", + nextTicketStatus: "bell.fill", + colorConfig: .config(for: 1) + ) + ) + .previewDisplayName("Red Border (1)") + + // Preview with currentServingStatusBackground = 2 (Green border) + NotificationWidgetView( + data: NotificationWidgetData( + queueNo: "125", + yourTicketHeader: "Currently Serving1:", + currentlyServing: "Customer #98", + status: 1, + currentServingStatus: "Next: Ready for Pickup", + imageName: "bell.fill", + nextTicketStatus: "bell.fill", + colorConfig: .config(for: 2) + ) + ) + .previewDisplayName("Green Border (2)") + } + .padding() + .previewLayout(.sizeThatFits) + } +} diff --git a/ios/liveappExtension.entitlements b/ios/liveappExtension.entitlements new file mode 100644 index 00000000..a1ca053c --- /dev/null +++ b/ios/liveappExtension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.alhabib.patientApp + + + diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index a27b727e..4b3d2e0c 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -47,6 +47,7 @@ class AppState { AuthenticatedUser? _authenticatedChildUser; bool isPaytabsEnabled = false; + bool isLiveActivityEnabled = true; bool isPayfortHostedPageEnabled = true; void setIsPaytabsEnabled(bool value) { diff --git a/lib/core/cache_consts.dart b/lib/core/cache_consts.dart index 758676b2..e10f0679 100644 --- a/lib/core/cache_consts.dart +++ b/lib/core/cache_consts.dart @@ -81,5 +81,7 @@ class CacheConst { static const String zoomRoomID = 'zoom-room-id'; static const String callTypeID = 'call-type-id'; static String isAppOpenedFromCall = "is_app_opened_from_call"; + + static const String patientQueueNoForLiveActivity = "QUEUENO_FOR_ACTIVITYID"; static const String organSelectorTutorialShown = 'organ_selector_tutorial_shown'; } diff --git a/lib/core/common_models/patient_queue.dart b/lib/core/common_models/patient_queue.dart new file mode 100644 index 00000000..82b3d3dd --- /dev/null +++ b/lib/core/common_models/patient_queue.dart @@ -0,0 +1,30 @@ +class PatientQueue { + + final String? queueNo; + final String? currentlyServingStatus; + final String? currentlyServingToken; + final String? yourTicketHeader; + final String? currentlyServingTitle; + final String? nextTicketStatus; + final int? currentlyServingCallType; + final int? callType;// background will be same as of the [Utils.getCardButtonColor] + + const PatientQueue({this.yourTicketHeader,this.currentlyServingTitle, this.queueNo, this.currentlyServingStatus, this.nextTicketStatus, this.callType, this.currentlyServingToken,this + .currentlyServingCallType, +}); + + /// Converts this PatientQueue object to a map. + /// This is used for passing data to the native side for Live Activities. + Map toMap() { + return { + 'queueNo': queueNo, + 'currentlyServingStatus': currentlyServingStatus, + 'nextTicketStatus': nextTicketStatus, + 'callType': callType, + 'currentlyServingToken': currentlyServingToken, + 'currentlyServingCallType': currentlyServingCallType, + 'yourTicketHeader':yourTicketHeader, + 'currentlyServingTitle':currentlyServingTitle, + }; + } +} \ No newline at end of file diff --git a/lib/core/firebase_message.dart b/lib/core/firebase_message.dart new file mode 100644 index 00000000..0a236613 --- /dev/null +++ b/lib/core/firebase_message.dart @@ -0,0 +1,38 @@ + + +// Background message handler (must be top-level function) +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; + +@pragma('vm:entry-point') +Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { + await Firebase.initializeApp(); + print('Handling background message: ${message.messageId}'); +} + +class NotificationService { + final FirebaseMessaging _fcm = FirebaseMessaging.instance; + + + Future initialize() async { + + String? token = await _fcm. getToken(); + print('FCM Token: $token'); + + // Set up background handler + FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); + + // Foreground message handler + FirebaseMessaging.onMessage.listen(_handleForegroundMessage); + + } + + // Foreground message handler + void _handleForegroundMessage(RemoteMessage message) { + print('Foreground notification: ${message.notification?.title}'); + + + } + + +} \ No newline at end of file diff --git a/lib/core/utils/calender_utils_new.dart b/lib/core/utils/calender_utils_new.dart index f733f82e..702f23ce 100644 --- a/lib/core/utils/calender_utils_new.dart +++ b/lib/core/utils/calender_utils_new.dart @@ -93,13 +93,13 @@ class CalenderUtilsNew { // String eventId = await getEventIdIfEventExist(title!.split("#").last); // if (eventId.isEmpty) { eventResult = await DeviceCalendar.instance.createEvent( - calendarId: writableCalendars!.id, - title: title, - description: description, - startDate: scheduleDateTime!, - endDate: scheduleDateTime!.add(Duration(minutes: 30)), - - reminderMinutes: reminderMinutes, // TODO : NEED TO CONFIRM THIS FROM TAHA + calendarId: writableCalendars!.id, + title: title, + description: description, + startDate: scheduleDateTime!, + endDate: scheduleDateTime!.add(Duration(minutes: 30)), + reminderMinutes: reminderMinutes + // TODO : NEED TO CONFIRM THIS FROM TAHA ); return eventResult.isNotEmpty; // } diff --git a/lib/core/utils/live_activty_helper_channel.dart b/lib/core/utils/live_activty_helper_channel.dart new file mode 100644 index 00000000..e59f30e2 --- /dev/null +++ b/lib/core/utils/live_activty_helper_channel.dart @@ -0,0 +1,14 @@ +import 'package:flutter/services.dart'; + +class LiveActivityHelperChannel { + static const MethodChannel _channel = MethodChannel('clear_data'); + + static Future removeData() async { + try { + await _channel.invokeMethod('clearUserDefaultData'); + } on PlatformException catch (e) { + print("Failed to removeData: '${e.message}'."); + } + } + +} diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart index 89f6969a..3b09b1cb 100644 --- a/lib/core/utils/push_notification_handler.dart +++ b/lib/core/utils/push_notification_handler.dart @@ -1,13 +1,16 @@ import 'dart:async'; import 'dart:developer'; import 'dart:io'; +import 'dart:ui'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart' as fir; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_callkit_incoming/entities/android_params.dart'; import 'package:flutter_callkit_incoming/entities/call_kit_params.dart'; import 'package:flutter_callkit_incoming/entities/ios_params.dart'; @@ -15,12 +18,21 @@ import 'package:flutter_callkit_incoming/entities/notification_params.dart'; import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart'; import 'package:flutter_ios_voip_kit_karmm/call_state_type.dart'; import 'package:flutter_ios_voip_kit_karmm/flutter_ios_voip_kit.dart'; +import 'package:hmg_patient_app_new/core/common_models/patient_queue.dart'; import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/live_activty_helper_channel.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/services/cache_service.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; +import 'package:live_activities/live_activities.dart' show LiveActivities; import 'package:hmg_patient_app_new/features/notifications/models/resp_models/notification_response_model.dart'; import 'package:hmg_patient_app_new/presentation/notifications/notification_details_page.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -40,14 +52,118 @@ Future backgroundMessageHandler(dynamic message) async { log("Firebase backgroundMessageHandler!!!"); await Firebase.initializeApp(); fir.RemoteMessage message_; + if(message.data == null ){ + return; + } - if (message.data != null && (message.data['is_call'] == 'true' || message.data['is_call'] == true)) { + if (message.data['is_call'] == 'true' || message.data['is_call'] == true) { // showCallkitIncoming(message); _incomingCall(message.data); return; } + if (message.data['isLiveActivity'] == true || message.data['isLiveActivity'] == "true") { + try { + // Initialize Firebase + await Firebase.initializeApp(); + WidgetsFlutterBinding.ensureInitialized(); + DartPluginRegistrant.ensureInitialized(); + await Future.delayed(Duration(seconds: 2)); + Utils.addLiveNotification(message, isBackgroundMessage: true); + } catch (e, stackTrace) { + } + } } +// addLiveNotification(dynamic message, {bool isBackgroundMessage = false}) async{ +// print("live activity called"); +// var liveActivity = LiveActivities(); +// +// +// var activityId = await Utils.getStringFromPrefs( message.data['queueNo'] ??""); +// +// var buttonText = Utils.getCardButtonText(int.parse(message.data['callType']??"1"), message.data['roomNo']); +// PatientQueue _patientQueue = PatientQueue( +// queueNo: message.data['queueNo'] ?? "IME-1", +// currentlyServingStatus: (message.data['servingCallType'] ?? 0) == "1" ? "Call for vital signs".needTranslation : "Call for Doctor".needTranslation, +// currentlyServingTitle: message.data['servingQueueNo'] ?? "IME-3", +// nextTicketStatus: buttonText, +// callType: int.parse(message.data['callType']??"1"), +// currentlyServingCallType: int.parse(message.data['servingCallType']??"1")); +// if((activityId??"") != (message.data['queueNo']??"")){ +// liveActivity.endActivity(activityId); +// activityId = ""; +// } +// print("the activity id is $activityId"); +// +// if( activityId == ""){ +// String? id = await liveActivity.createActivity( +// DateTime.now().millisecondsSinceEpoch.toString(), +// _patientQueue.toMap(), +// ); +// print("the activity id created is $id"); +// await Utils.saveStringFromPrefs(message.data['queueNo'] ??"", message.data['queueNo']??""); +// print("the activity id saved is ${await Utils.getStringFromPrefs(message.data['queueNo'] ??"")}"); +// print("the activity is created"); +// return; +// } +// +// await liveActivity.updateActivity( +// activityId, +// _patientQueue.toMap(), +// ); +// +// print("the activity is is created or updated"); +// +// } +// addLiveNotification(dynamic data, {bool isBackgroundMessage = false}) async{ +// +// var liveActivity = LiveActivities(); +// +// liveActivity.init(appGroupId: "group.alhabib.patientApp"); +// // if(Platform.isIOS){ +// // LiveActivityHelperChannel.removeData(); +// // } +// var queueNoForWhichActivityIdCreated = await Utils.getStringFromPrefs( CacheConst.patientQueueNoForLiveActivity); +// var activityId = await Utils.getStringFromPrefs( data.data['queueNo'] ??""); +// +// var buttonText = Utils.getCardButtonText(int.parse(data.data['callType']??"1"), data.data['roomNo']); +// PatientQueue _patientQueue = PatientQueue( +// queueNo: data.data['queueNo'] ?? "IME-1", +// currentlyServingStatus: (data.data['servingCallType'] ?? 0) == "1" ?LocaleKeys.callForVitalSign.tr() : LocaleKeys.callForDoctor.tr() , +// currentlyServingToken: data.data['servingQueueNo'] ?? "IME-3", +// nextTicketStatus: buttonText, +// callType: int.parse(data.data['callType']??"1"), +// currentlyServingCallType: int.parse(data.data['servingCallType']??"1"), +// yourTicketHeader: LocaleKeys.yourQueueNumber.tr(), +// currentlyServingTitle: LocaleKeys.currentServing.tr() +// ); +// if((queueNoForWhichActivityIdCreated??"") != (_patientQueue.queueNo??"")){ +// liveActivity.endActivity(activityId); +// activityId = ""; +// } +// +// if( activityId == ""){ +// String? id = await liveActivity.createActivity( +// DateTime.now().millisecondsSinceEpoch.toString(), +// _patientQueue.toMap(), +// ); +// await Utils.saveStringFromPrefs(_patientQueue.queueNo ??"", id??""); +// await Utils.saveStringFromPrefs(CacheConst.patientQueueNoForLiveActivity ??"", _patientQueue.queueNo??""); +// return; +// } +// if(Platform.isIOS) { +// await liveActivity.createOrUpdateActivity( +// activityId, +// _patientQueue.toMap(), +// ); +// }else{ +// await liveActivity.updateActivity( +// activityId, +// _patientQueue.toMap(), +// ); +// } +// } + callPage(String sessionID, String token) async {} _incomingCall(Map data) async { @@ -309,7 +425,6 @@ class PushNotificationHandler { // late HmsApiAvailability hmsApiAvailability; final voIPKit = FlutterIOSVoIPKit.instance; - late Timer timeOutTimer; bool isTalking = false; @@ -355,166 +470,172 @@ class PushNotificationHandler { init(BuildContext context) async { this.context = context; + final PermissionStatus status = await Permission.notification.request(); + if (status.isGranted) { + // Notification permissions granted + } else if (status.isDenied) { + // Notification permissions denied - await requestPermissions(); + await requestPermissions(); - if (Platform.isIOS) { - voIPKit.getVoIPToken().then((value) { - log("🎈 APNS VOIP KIT TOKEN: $value"); - Utils.saveStringFromPrefs(CacheConst.voipToken, value ?? ""); - // AppSharedPreferences().setString(APNS_TOKEN, value!); - }); - - voIPKit.onDidUpdatePushToken = (String token) { - log('🎈 example: onDidUpdatePushToken: $token'); - }; - - voIPKit.onDidReceiveIncomingPush = ( - Map payload, - ) async { - log('🎈 example: onDidReceiveIncomingPush $payload'); - // _timeOut(); - }; - - voIPKit.onDidRejectIncomingCall = ( - String uuid, - String callerId, - ) async { - try { - log('🎈 example: onDidRejectIncomingCall $uuid - $callerId'); - timeOutTimer.cancel(); - // Cleanup on reject with API call - if (_currentCallId != null) { - await _endCallAndCleanup(_currentCallId!, isDeclined: true); - } - } catch (err) { - log(err.toString()); - } - }; - - voIPKit.onDidAcceptIncomingCall = ( - String uuid, - String callerId, - ) async { - log('🎈 example: onDidAcceptIncomingCall $uuid - $callerId'); - await voIPKit.acceptIncomingCall(callerState: CallStateType.calling); - await voIPKit.callConnected(); - - // Cleanup on accept - cancel timer and reset flags - _callTimeoutTimer?.cancel(); - _callTimeoutTimer = null; - _isCallInProgress = false; - _currentCallId = null; - await Future.delayed(Duration(seconds: 2)).then((val) async { - await voIPKit.endCall(); + if (Platform.isIOS) { + voIPKit.getVoIPToken().then((value) { + log("🎈 APNS VOIP KIT TOKEN: $value"); + Utils.saveStringFromPrefs(CacheConst.voipToken, value ?? ""); + // AppSharedPreferences().setString(APNS_TOKEN, value!); }); - // Navigator.pushNamed( - // locator().navigatorKey.currentContext!, - // "zoom_call_page", - // arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false), - // ); - - // Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN, - // arguments: VideoArgus( - // reservationId: int.parse(callerId), token: null, isVideo: true)); + voIPKit.onDidUpdatePushToken = (String token) { + log('🎈 example: onDidUpdatePushToken: $token'); + }; + + voIPKit.onDidReceiveIncomingPush = ( + Map payload, + ) async { + log('🎈 example: onDidReceiveIncomingPush $payload'); + // _timeOut(); + }; + + voIPKit.onDidRejectIncomingCall = ( + String uuid, + String callerId, + ) async { + try { + log('🎈 example: onDidRejectIncomingCall $uuid - $callerId'); + timeOutTimer.cancel(); + // Cleanup on reject with API call + if (_currentCallId != null) { + await _endCallAndCleanup(_currentCallId!, isDeclined: true); + } + } catch (err) { + log(err.toString()); + } + }; + + voIPKit.onDidAcceptIncomingCall = ( + String uuid, + String callerId, + ) async { + log('🎈 example: onDidAcceptIncomingCall $uuid - $callerId'); + await voIPKit.acceptIncomingCall(callerState: CallStateType.calling); + await voIPKit.callConnected(); + + // Cleanup on accept - cancel timer and reset flags + _callTimeoutTimer?.cancel(); + _callTimeoutTimer = null; + _isCallInProgress = false; + _currentCallId = null; + await Future.delayed(Duration(seconds: 2)).then((val) async { + await voIPKit.endCall(); + }); + + // Navigator.pushNamed( + // locator().navigatorKey.currentContext!, + // "zoom_call_page", + // arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false), + // ); + + // Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN, + // arguments: VideoArgus( + // reservationId: int.parse(callerId), token: null, isVideo: true)); + + // timeOutTimer.cancel(); + }; + } - // timeOutTimer.cancel(); - }; - } + if (Platform.isAndroid) { + try { + final fcmToken = await FirebaseMessaging.instance.getToken().catchError((err) { + log(err); + }); + if (fcmToken != null) onToken(fcmToken); + // } + } catch (ex) { + log("Notification Exception: $ex"); + } + FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); + } - if (Platform.isAndroid) { - try { - final fcmToken = await FirebaseMessaging.instance.getToken().catchError((err) { - log(err); + if (Platform.isIOS) { + final permission = await FirebaseMessaging.instance.requestPermission(); + await FirebaseMessaging.instance.getAPNSToken().then((value) async { + log("APNS token: $value"); + await Utils.saveStringFromPrefs(CacheConst.apnsToken, value.toString()); }); - if (fcmToken != null) onToken(fcmToken); - // } - } catch (ex) { - log("Notification Exception: $ex"); + await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( + alert: true, // Required to display a heads up notification + badge: true, + sound: true, + ); + // if (permission.authorizationStatus == AuthorizationStatus.denied) return; + } else { + final permission = await FirebaseMessaging.instance.requestPermission(); } - FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); - } - if (Platform.isIOS) { - final permission = await FirebaseMessaging.instance.requestPermission(); - await FirebaseMessaging.instance.getAPNSToken().then((value) async { - log("APNS token: $value"); - await Utils.saveStringFromPrefs(CacheConst.apnsToken, value.toString()); - }); - await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( - alert: true, // Required to display a heads up notification - badge: true, - sound: true, - ); - // if (permission.authorizationStatus == AuthorizationStatus.denied) return; - } else { - final permission = await FirebaseMessaging.instance.requestPermission(); - } - - try { - FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) async { - if (message != null) { - if (Platform.isIOS) { - await Future.delayed(Duration(milliseconds: 3000)).then((value) { - if (message != null) newMessage(message); - }); - } else if (message != null) newMessage(message); + try { + FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) async { + if (message != null) { + if (Platform.isIOS) { + await Future.delayed(Duration(milliseconds: 3000)).then((value) { + if (message != null) newMessage(message); + }); + } else if (message != null) newMessage(message); + } + }); + } catch (ex) {} + + FirebaseMessaging.onMessage.listen((RemoteMessage message) async { + log("Firebase onMessage!!!"); + // showCallkitIncoming(); + if (Platform.isIOS) { + await Future.delayed(Duration(milliseconds: 3000)).then((value) { + newMessage(message); + }); + } else { + newMessage(message); } }); - } catch (ex) {} - FirebaseMessaging.onMessage.listen((RemoteMessage message) async { - log("Firebase onMessage!!!"); - // showCallkitIncoming(); - if (Platform.isIOS) { - await Future.delayed(Duration(milliseconds: 3000)).then((value) { + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async { + log("Firebase onMessageOpenedApp!!!"); + if (Platform.isIOS) { + await Future.delayed(Duration(milliseconds: 3000)).then((value) { + newMessage(message); + }); + } else { newMessage(message); - }); - } else { - newMessage(message); - } - }); + } + }); - FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async { - log("Firebase onMessageOpenedApp!!!"); if (Platform.isIOS) { - await Future.delayed(Duration(milliseconds: 3000)).then((value) { - newMessage(message); + FirebaseMessaging.instance.getAPNSToken().then((String? token) { + log("Push Notification getAPNSToken: ${token!}"); + }).catchError((err) { + log("Push Notification getAPNSToken ERR: ${err.toString()}"); }); - } else { - newMessage(message); } - }); - if (Platform.isIOS) { - FirebaseMessaging.instance.getAPNSToken().then((String? token) { - log("Push Notification getAPNSToken: ${token!}"); + FirebaseMessaging.instance.getToken().then((String? token) { + log("Push Notification getToken: ${token!}"); + onToken(token!); }).catchError((err) { - log("Push Notification getAPNSToken ERR: ${err.toString()}"); + log(err.toString()); }); - } - FirebaseMessaging.instance.getToken().then((String? token) { - log("Push Notification getToken: ${token!}"); - onToken(token!); - }).catchError((err) { - log(err.toString()); - }); - - FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) { - log("Push Notification onTokenRefresh: $fcm_token"); - onToken(fcm_token); - }); - - if (Platform.isAndroid) { - final deviceInfo = DeviceInfoPlugin(); - final androidInfo = await deviceInfo.androidInfo; - - // int sdkInt = androidInfo.version.sdkInt ?? 0; - // if (sdkInt >= 33) { - // await FlutterCallkitIncoming.requestFullIntentPermission(); - // } + FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) { + log("Push Notification onTokenRefresh: $fcm_token"); + onToken(fcm_token); + }); + + if (Platform.isAndroid) { + final deviceInfo = DeviceInfoPlugin(); + final androidInfo = await deviceInfo.androidInfo; + + // int sdkInt = androidInfo.version.sdkInt ?? 0; + // if (sdkInt >= 33) { + // await FlutterCallkitIncoming.requestFullIntentPermission(); + // } + } } } @@ -523,30 +644,58 @@ class PushNotificationHandler { if (remoteMessage.data.isEmpty) { return; } - log('the value of the remote message is ${remoteMessage.data}'); + log('the value of the remote message is 1 ${remoteMessage.data}'); if (remoteMessage.data['is_call'] == 'true' || remoteMessage.data['is_call'] == true) { _incomingCall(remoteMessage.data); // showCallkitIncoming(); } else { - NotificationResponseModel notification = NotificationResponseModel(); - - notification.createdOn = DateUtil.convertDateToString(DateTime.now()); - notification.isSentOn = DateUtil.convertDateToString(DateTime.now()); - notification.messageTypeData = remoteMessage.data['picture']; - notification.messageType = notification.messageTypeData != null && notification.messageTypeData!.isNotEmpty ? "image" : ""; - notification.message = remoteMessage.data['message']; - notification.notificationType = remoteMessage.data["NotificationType"].toString(); - if (remoteMessage.data["NotificationType"] == "2") { - notification.videoURL = remoteMessage.data["VideoUrl"]; + + if(remoteMessage.data['isLiveActivity'] == true || remoteMessage.data['isLiveActivity'] == 'true'){ + // print("live activity called"); + // LiveActivities().init(appGroupId: "group.alhabib.patientApp"); + // await LiveActivities().endAllActivities(); + // // await Permission.notification.request(); + // var buttonText = Utils.getCardButtonText(int.parse(remoteMessage.data['callType']??"1"), remoteMessage.data['roomNo']); + // PatientQueue _patientQueue = + // PatientQueue( + // queueNo: remoteMessage.data['queueNo'] ?? "IME-1", + // currentlyServingStatus: (remoteMessage.data['servingCallType'] ?? 0) == 1 ? "Call for vital signs".needTranslation : "Call for Doctor".needTranslation, + // currentlyServingTitle: remoteMessage.data['servingQueueNo'] ?? "IME-3", + // nextTicketStatus: buttonText, + // callType: int.parse(remoteMessage.data['callType']??"1"),currentlyServingCallType: int.parse(remoteMessage.data['servingCallType']??"1")); + // var activity = await LiveActivities().createActivity( + // DateTime.now().millisecondsSinceEpoch.toString(), + // _patientQueue.toMap(), + // ); + // print("the activity is $activity"); + + Utils.addLiveNotification(remoteMessage, isBackgroundMessage: false); + } + else { + NotificationResponseModel notification = NotificationResponseModel(); + + notification.createdOn = DateUtil.convertDateToString(DateTime.now()); + notification.isSentOn = DateUtil.convertDateToString(DateTime.now()); + notification.messageTypeData = remoteMessage.data['picture']; + notification.messageType = notification.messageTypeData != null && notification.messageTypeData!.isNotEmpty ? "image" : ""; + notification.message = remoteMessage.data['message']; + notification.notificationType = remoteMessage.data["NotificationType"].toString(); + if (remoteMessage.data["NotificationType"] == "2") { + notification.videoURL = remoteMessage.data["VideoUrl"]; + } - Navigator.of(getIt.get().navigatorKey.currentContext!).push( - CustomPageRoute( - page: NotificationDetailsPage( - notification: notification, + Navigator.of(getIt + .get() + .navigatorKey + .currentContext!).push( + CustomPageRoute( + page: NotificationDetailsPage( + notification: notification, + ), ), - ), - ); + ); + } // GetNotificationsResponseModel notification = new GetNotificationsResponseModel(); // diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index 320bd1cf..9818d592 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -15,8 +15,11 @@ import 'package:get_it/get_it.dart'; import 'package:google_api_availability/google_api_availability.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/cache_consts.dart'; +import 'package:hmg_patient_app_new/core/common_models/patient_queue.dart'; import 'package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailListModel.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/live_activty_helper_channel.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; @@ -30,6 +33,7 @@ import 'package:hmg_patient_app_new/widgets/dialogs/confirm_dialog.dart'; import 'package:hmg_patient_app_new/widgets/loading_dialog.dart'; import 'package:hmg_patient_app_new/widgets/accessibility/preserve_image_colors.dart'; import 'package:hmg_patient_app_new/widgets/accessibility/preserve_svg_colors.dart'; +import 'package:live_activities/live_activities.dart'; import 'package:lottie/lottie.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -1172,4 +1176,61 @@ class Utils { return normalized; } + + static addLiveNotification(dynamic data, {bool isBackgroundMessage = false}) async { + debugPrint("live activity is enabled or not ${getIt().isLiveActivityEnabled}"); + if(!getIt().isLiveActivityEnabled) return; + + var liveActivity = LiveActivities(); + + liveActivity.init(appGroupId: "group.alhabib.patientApp"); + if (Platform.isIOS) { + LiveActivityHelperChannel.removeData(); + } + var queueNoForWhichActivityIdCreated = await Utils.getStringFromPrefs(CacheConst.patientQueueNoForLiveActivity); + var activityId = await Utils.getStringFromPrefs(data.data['queueNo'] ?? ""); + + var buttonText = Utils.getCardButtonText(int.parse(data.data['callType'] ?? "0"), data.data['roomNo']); + PatientQueue _patientQueue = PatientQueue( + queueNo: data.data['queueNo'] ?? "", + currentlyServingStatus: (data.data['servingCallType'] ?? 0) == "1" ? LocaleKeys.callForVitalSign.tr() : LocaleKeys.callForDoctor.tr(), + currentlyServingToken: data.data['servingQueueNo'] ?? "", + nextTicketStatus: buttonText, + callType: int.parse(data.data['callType'] ?? "0"), + currentlyServingCallType: data.data['servingCallType'].isEmpty?0:int.parse(data.data['servingCallType'] ?? "0"), + yourTicketHeader: LocaleKeys.yourQueueNumber.tr(), + currentlyServingTitle: LocaleKeys.currentServing.tr()); + if ((queueNoForWhichActivityIdCreated ?? "") != (_patientQueue.queueNo ?? "")) { + liveActivity.endAllActivities(); + activityId = ""; + } + + if (activityId == "") { + String? id = await liveActivity.createActivity( + DateTime.now().millisecondsSinceEpoch.toString(), + _patientQueue.toMap(), + ); + await Utils.saveStringFromPrefs(_patientQueue.queueNo ?? "", id ?? ""); + await Utils.saveStringFromPrefs(CacheConst.patientQueueNoForLiveActivity ?? "", _patientQueue.queueNo ?? ""); + return; + } + // if (Platform.isIOS) { + // await liveActivity.createOrUpdateActivity( + // activityId, + // _patientQueue.toMap(), + // ); + // } else { + try{ + await liveActivity.updateActivity( + activityId, + _patientQueue.toMap(), + );} + catch(e){ + await liveActivity.createOrUpdateActivity( + activityId, + _patientQueue.toMap(), + ); + } + // } + } } diff --git a/lib/features/my_appointments/models/patient_queue_live_notification_model.dart b/lib/features/my_appointments/models/patient_queue_live_notification_model.dart new file mode 100644 index 00000000..d151e6db --- /dev/null +++ b/lib/features/my_appointments/models/patient_queue_live_notification_model.dart @@ -0,0 +1,3 @@ +class QueueLiveNotificationModel { + Map data = {}; +} diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index b480a354..1fe3dccb 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -12,6 +12,7 @@ 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/features/book_appointments/models/resp_models/get_favorite_doctors_list.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/appointemnet_filters.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/patient_queue_live_notification_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/reminder_type.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/appointment_parking_QR_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/appointment_rated_response_model.dart'; @@ -1026,6 +1027,19 @@ class MyAppointmentsViewModel extends ChangeNotifier { // if (patientQueueDetailsList.length > 1) { patientQueueDetailsList.removeWhere((element) => element.patientID == patientArrivedAppointmentsHistoryList.first.patientID); // } + + QueueLiveNotificationModel queueLiveNotificationModel = QueueLiveNotificationModel(); + + queueLiveNotificationModel.data = { + "queueNo": currentPatientQueueDetails.queueNo, + "callType": currentPatientQueueDetails.callType.toString(), + "servingQueueNo": patientQueueDetailsList.isEmpty ? null : patientQueueDetailsList.first.queueNo, + "servingCallType": patientQueueDetailsList.isEmpty ? null : patientQueueDetailsList.first.callType.toString(), + "roomNo": patientQueueDetailsList.isEmpty ? "" : patientQueueDetailsList.first.roomNo, + "servingNow": "true" + }; + + Utils.addLiveNotification(queueLiveNotificationModel, isBackgroundMessage: false); } else { patientQueueDetailsList.clear(); isPatientHasQueueAppointment = false; diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 80cea8b4..e9f6d9c5 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -932,6 +932,10 @@ abstract class LocaleKeys { static const laserClinic = 'laserClinic'; static const continueString = 'continueString'; static const covid_info = 'covid_info'; + static const callForVitalSign = 'callForVitalSign'; + static const callForDoctor = 'callForDoctor'; + static const yourQueueNumber = 'yourQueueNumber'; + static const currentServing = 'currentServing'; static const appointmentDetails = 'appointmentDetails'; static const checkingDoctorAvailability = 'checkingDoctorAvailability'; static const cancellingAppointmentPleaseWait = 'cancellingAppointmentPleaseWait'; @@ -1043,7 +1047,6 @@ abstract class LocaleKeys { static const thankYouForPatience = 'thankYouForPatience'; static const servingNow = 'servingNow'; static const callForVitalSigns = 'callForVitalSigns'; - static const callForDoctor = 'callForDoctor'; static const thingsToAskDoctor = 'thingsToAskDoctor'; static const improveOverallHealth = 'improveOverallHealth'; static const routineScreenings = 'routineScreenings'; diff --git a/lib/main.dart b/lib/main.dart index aa266871..8d0e041b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -56,6 +56,7 @@ import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/app_theme.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_calendar_model.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart' show DateRangeSelectorRangeViewModel; +import 'package:live_activities/live_activities.dart'; import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; @@ -121,6 +122,7 @@ Future callInitializations() async { } await AppDependencies.addDependencies(); + LiveActivities().init(appGroupId: "group.alhabib.patientApp"); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); HttpOverrides.global = MyHttpOverrides(); await callAppStateInitializations(); diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 85f1e972..b292347d 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -27,6 +27,7 @@ import 'package:hmg_patient_app_new/features/hospital/hospital_selection_view_mo import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/appointment_rating_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/patient_queue_live_notification_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_queue_details_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; @@ -316,6 +317,28 @@ class _LandingPageState extends State { padding: EdgeInsets.fromLTRB(12.h, 0, 12.h, 0), height: 40.h, ), + ElevatedButton(onPressed: (){ + QueueLiveNotificationModel queueLiveNotificationModel = QueueLiveNotificationModel(); + + queueLiveNotificationModel.data = { + "msgID": "123", + "notfID": "123", + "isLiveActivity":"true", + "notification_foreground": "true", + "patientID": "12345", + "patientName": "John Doe", + "queueNo": "A-104", + "callType": "1", + "servingQueueNo": "", + "servingCallType": "", + "roomNo": "204", + "calledOn": "2024-05-21T14:30:00Z", + "servingNow": "true" + }; + + Utils.addLiveNotification(queueLiveNotificationModel, isBackgroundMessage: false); + + }, child: Text("press")).paddingOnly(top: 56.h), Consumer(builder: (context, todoSectionVM, child) { return Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/presentation/onboarding/onboarding_screen.dart b/lib/presentation/onboarding/onboarding_screen.dart index 0af63b40..3cc1747e 100644 --- a/lib/presentation/onboarding/onboarding_screen.dart +++ b/lib/presentation/onboarding/onboarding_screen.dart @@ -7,6 +7,7 @@ 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/my_appointments/models/patient_queue_live_notification_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; @@ -64,6 +65,28 @@ class _OnboardingScreenState extends State { child: Column( spacing: 24.h, children: [ + ElevatedButton(onPressed: (){ + QueueLiveNotificationModel queueLiveNotificationModel = QueueLiveNotificationModel(); + + queueLiveNotificationModel.data = { + "msgID": "123", + "notfID": "123", + "isLiveActivity":"true", + "notification_foreground": "true", + "patientID": "12345", + "patientName": "John Doe", + "queueNo": "A-109", + "callType": "0", + "servingQueueNo": "", + "servingCallType": "", + "roomNo": "204", + "calledOn": "2024-05-21T14:30:00Z", + "servingNow": "true" + }; + + Utils.addLiveNotification(queueLiveNotificationModel, isBackgroundMessage: false); + + }, child: Text("press")).paddingOnly(top: 56.h), PageView( controller: pageController, children: [ diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart index fd154c61..e978f29f 100644 --- a/lib/services/notification_service.dart +++ b/lib/services/notification_service.dart @@ -5,6 +5,10 @@ import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:timezone/data/latest_all.dart' as tz; import 'package:timezone/timezone.dart' as tz show TZDateTime, local, setLocalLocation, getLocation; +///it will be used to not call init every time it has the live activity notification channel created +///will stop the calling reduntant code again and again +bool isNotificationChannelCreatedForLiveActivity = false; + /// Abstract class defining the notification service interface abstract class NotificationService { /// Initialize the notification service diff --git a/lib/splashPage.dart b/lib/splashPage.dart index dc49428a..881f9895 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -16,6 +16,7 @@ import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/patient_queue_live_notification_model.dart'; import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart'; import 'package:hmg_patient_app_new/presentation/onboarding/onboarding_screen.dart'; import 'package:hmg_patient_app_new/presentation/onboarding/splash_animation_screen.dart'; diff --git a/pubspec.lock b/pubspec.lock index 4f2c35ac..e4df9f82 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" chewie: dependency: transitive description: @@ -145,6 +145,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + cloudflare_turnstile: + dependency: "direct main" + description: + name: cloudflare_turnstile + sha256: f04191fd1f9c658e98c11175356f34aaeca42b4ed91ee66d42fb250b3346160d + url: "https://pub.dev" + source: hosted + version: "3.8.0" collection: dependency: transitive description: @@ -499,6 +507,22 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_amazonpaymentservices: + dependency: "direct main" + description: + name: flutter_amazonpaymentservices + sha256: "23f45fd3b1e12a0933da3704d66cebd19c4c41e28a50d4fd458d3e3e6311f332" + url: "https://pub.dev" + source: hosted + version: "0.0.13" + flutter_app_group_directory: + dependency: transitive + description: + name: flutter_app_group_directory + sha256: "680ef9b2dee84c237cd7bb7fc78bc45867b32556a8a5f0de61278078b9fefd05" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter_cache_manager: dependency: transitive description: @@ -720,6 +744,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.1" + flutter_screenshot_blocker: + dependency: "direct main" + description: + name: flutter_screenshot_blocker + sha256: "20e36b4aaca20259008dbb1403b77af6207d48cd8382a772b9c27619bc116849" + url: "https://pub.dev" + source: hosted + version: "1.0.4" flutter_staggered_animations: dependency: "direct main" description: @@ -773,10 +805,10 @@ packages: dependency: "direct main" description: name: flutter_zoom_videosdk - sha256: "46a4dea664b1c969099328a499c198a1755adf9ac333dea28bea5187910b3bf9" + sha256: "8f6dba6b5c910097aca7f3c582a11b10a6fb5def49fead745d837283b5f5ef52" url: "https://pub.dev" source: hosted - version: "2.1.10" + version: "2.4.0" fluttertoast: dependency: "direct main" description: @@ -1233,6 +1265,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + live_activities: + dependency: "direct main" + description: + name: live_activities + sha256: "060f4d8f57b399e5c8beb255fa8426b9b4789320414ae68c8510aec113269dbd" + url: "https://pub.dev" + source: hosted + version: "2.4.9" local_auth: dependency: "direct main" description: @@ -1341,18 +1381,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: @@ -1641,6 +1681,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + screen_brightness: + dependency: "direct main" + description: + name: screen_brightness + sha256: "7d4ac84ae26b37c01d6f5db7123a72db7933e1f2a2a8c369a51e08f81b3178d8" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + screen_brightness_android: + dependency: transitive + description: + name: screen_brightness_android + sha256: "8c69d3ac475e4d625e7fa682a3a51a69ff59abe5b4a9e57f6ec7d830a6c69bd6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + screen_brightness_ios: + dependency: transitive + description: + name: screen_brightness_ios + sha256: f08f70ca1ac3e30719764b5cfb8b3fe1e28163065018a41b3e6f243ab146c2f1 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + screen_brightness_macos: + dependency: transitive + description: + name: screen_brightness_macos + sha256: "70c2efa4534e22b927e82693488f127dd4a0f008469fccf4f0eefe9061bbdd6a" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + screen_brightness_platform_interface: + dependency: transitive + description: + name: screen_brightness_platform_interface + sha256: "9f3ebf7f22d5487e7676fe9ddaf3fc55b6ff8057707cf6dc0121c7dfda346a16" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + screen_brightness_windows: + dependency: transitive + description: + name: screen_brightness_windows + sha256: c8e12a91cf6dd912a48bd41fcf749282a51afa17f536c3460d8d05702fb89ffa + url: "https://pub.dev" + source: hosted + version: "1.0.1" scrollable_positioned_list: dependency: "direct main" description: @@ -1890,10 +1978,10 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.10" time: dependency: transitive description: @@ -2175,5 +2263,5 @@ packages: source: hosted version: "1.2.0" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.11.0 <4.0.0" + flutter: ">=3.41.0" diff --git a/pubspec.yaml b/pubspec.yaml index bdce8130..17e59274 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: geolocator: ^14.0.2 dropdown_search: ^6.0.2 google_maps_flutter: ^2.13.1 - flutter_zoom_videosdk: 2.1.10 + flutter_zoom_videosdk: 2.4.0 dart_jsonwebtoken: ^3.2.0 dartz: ^0.10.1 equatable: ^2.0.7 @@ -110,6 +110,7 @@ dependencies: screen_brightness: ^1.0.1 flutter_screenshot_blocker: ^1.0.4 cloudflare_turnstile: ^3.7.2 + live_activities: ^2.4.2 dev_dependencies: flutter_test: