diff --git a/android/.gradle/8.12/checksums/checksums.lock b/android/.gradle/8.12/checksums/checksums.lock index 6f80b2c..6fea520 100644 Binary files a/android/.gradle/8.12/checksums/checksums.lock and b/android/.gradle/8.12/checksums/checksums.lock differ diff --git a/android/.gradle/8.12/checksums/md5-checksums.bin b/android/.gradle/8.12/checksums/md5-checksums.bin index 4434d78..0f2e0f2 100644 Binary files a/android/.gradle/8.12/checksums/md5-checksums.bin and b/android/.gradle/8.12/checksums/md5-checksums.bin differ diff --git a/android/.gradle/8.12/checksums/sha1-checksums.bin b/android/.gradle/8.12/checksums/sha1-checksums.bin index fe0cae0..f59c76b 100644 Binary files a/android/.gradle/8.12/checksums/sha1-checksums.bin and b/android/.gradle/8.12/checksums/sha1-checksums.bin differ diff --git a/android/.gradle/8.12/executionHistory/executionHistory.bin b/android/.gradle/8.12/executionHistory/executionHistory.bin index 5181326..2cd6e02 100644 Binary files a/android/.gradle/8.12/executionHistory/executionHistory.bin and b/android/.gradle/8.12/executionHistory/executionHistory.bin differ diff --git a/android/.gradle/8.12/executionHistory/executionHistory.lock b/android/.gradle/8.12/executionHistory/executionHistory.lock index d7c6480..21f349b 100644 Binary files a/android/.gradle/8.12/executionHistory/executionHistory.lock and b/android/.gradle/8.12/executionHistory/executionHistory.lock differ diff --git a/android/.gradle/8.12/fileHashes/fileHashes.bin b/android/.gradle/8.12/fileHashes/fileHashes.bin index 9321039..5f11cd9 100644 Binary files a/android/.gradle/8.12/fileHashes/fileHashes.bin and b/android/.gradle/8.12/fileHashes/fileHashes.bin differ diff --git a/android/.gradle/8.12/fileHashes/fileHashes.lock b/android/.gradle/8.12/fileHashes/fileHashes.lock index 3a5900c..4e54282 100644 Binary files a/android/.gradle/8.12/fileHashes/fileHashes.lock and b/android/.gradle/8.12/fileHashes/fileHashes.lock differ diff --git a/android/.gradle/8.12/fileHashes/resourceHashesCache.bin b/android/.gradle/8.12/fileHashes/resourceHashesCache.bin index 5f190fd..ff89fb1 100644 Binary files a/android/.gradle/8.12/fileHashes/resourceHashesCache.bin and b/android/.gradle/8.12/fileHashes/resourceHashesCache.bin differ diff --git a/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 54eeae6..9d7a8c7 100644 Binary files a/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/android/.gradle/file-system.probe b/android/.gradle/file-system.probe index 038f9ec..296968a 100644 Binary files a/android/.gradle/file-system.probe and b/android/.gradle/file-system.probe differ diff --git a/android/app/src/main/kotlin/com/ejada/hmg/live_activity/CustomActiviy.kt b/android/app/src/main/kotlin/com/ejada/hmg/live_activity/CustomActiviy.kt index ed61a50..0ecdcfe 100644 --- a/android/app/src/main/kotlin/com/ejada/hmg/live_activity/CustomActiviy.kt +++ b/android/app/src/main/kotlin/com/ejada/hmg/live_activity/CustomActiviy.kt @@ -42,41 +42,30 @@ class CustomLiveActivityManager(context: Context) : Log.d("updateRemoteViews", "current ticket is ${data["queueNo"] as? String ?: ""}") Log.d("updateRemoteViews", "remoteViews is $remoteViews") - 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) + val progress = when (data["callType"] as? Int) { + 0 -> 33 + 1 -> 66 + 2 ->99 + else -> 99 } - var (currentServingBackground, currentServingFontColor) = when (data["currentlyServingCallType"] as? Int) { - 1->Pair(R.drawable.red_rounded_corner_widget, R.color.colorWhite) - else ->Pair(R.drawable.green_rounded_corner_widget, R.color.colorWhite) - } - remoteViews.setInt(R.id.nextStep, "setBackgroundResource", nextStepButtonBackground) - remoteViews.setInt(R.id.status, "setBackgroundResource", currentServingBackground) - remoteViews.setInt(R.id.container, "setBackgroundResource", containerBackground) - remoteViews.setTextColor(R.id.nextStep, ContextCompat.getColor(context, textColor)) - remoteViews.setTextColor(R.id.status, ContextCompat.getColor(context, currentServingFontColor)) - remoteViews.setTextViewText(R.id.countvalue, data["queueNo"] as? String ?: "") - remoteViews.setTextViewText(R.id.status, data["currentlyServingStatus"] as? String ?: "") - remoteViews.setTextViewText(R. id.currentlyserving, data["currentlyServingTitle"] as? String ?: "") - remoteViews.setTextViewText(R.id.nextStep, data["nextTicketStatus"] as? String ?: "") + + + 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 ?: "") } private suspend fun updateCollapsedView(data: Map) { Log.d("updateCollapsedView", "current ticket is ${data["queueNo"] as? String ?: ""}") Log.d("updateCollapsedView", "remoteViews is $collapesView") - val containerBackground = when (data["callType"] as? Int) { - 0 -> R.drawable.whitebg_yellow_border_rounded_corner_widget - 1 -> R. drawable.whitebg_red_border_rounded_corner_widget - 2 -> R.drawable. whitebg_green_border_rounded_corner_widget - else -> R.drawable.whitebg_yellow_border_rounded_corner_widget - } - collapesView.setInt(R.id.container, "setBackgroundResource", containerBackground) - collapesView.setTextViewText(R.id.countvalue_collapsed, data["queueNo"] as? String ?: "") + collapesView.setTextViewText(R.id.queue_number, data["queueNo"] as? String ?: "") + remoteViews.setTextViewText(R.id.queue_label, data["yourTicketHeader"] as? String ?: "") } override suspend fun buildNotification( 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 0000000..68ce3c2 --- /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 0000000..7282bc0 --- /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 0000000..9d08e71 --- /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 0000000..4c5e39f --- /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 0000000..da4d720 --- /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 0000000..0d59d1b --- /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/seekbar_thumb_image.xml b/android/app/src/main/res/drawable/seekbar_thumb_image.xml new file mode 100644 index 0000000..ba9b8c7 --- /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 0000000..148bcef --- /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/layout/live_activity.xml b/android/app/src/main/res/layout/live_activity.xml index fb92989..12a378e 100644 --- a/android/app/src/main/res/layout/live_activity.xml +++ b/android/app/src/main/res/layout/live_activity.xml @@ -1,116 +1,176 @@ - - + + android:layout_height="wrap_content"> + - - + android:layout_height="match_parent" + android:background="@drawable/queue_card_background" + android:orientation="vertical" + android:padding="24dp"> - + - - + + + + - + + + + + + + + + + + + - android:layout_below="@id/nextStep_ll" - android:layout_alignParentStart="true" - /> + + + - + + + - + + android:gravity="start|center_vertical" + android:orientation="horizontal"> + + + + + + + + + + + + + + + + - - - - + diff --git a/android/app/src/main/res/layout/live_activity_collapsed.xml b/android/app/src/main/res/layout/live_activity_collapsed.xml index 188b63f..096f542 100644 --- a/android/app/src/main/res/layout/live_activity_collapsed.xml +++ b/android/app/src/main/res/layout/live_activity_collapsed.xml @@ -1,32 +1,63 @@ - - - - - - - - + + android:background="@drawable/queue_card_background_low_radius"> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 474cff4..4400469 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -6,4 +6,8 @@ #332E3039 #A2A2A2 #FFFF + #8F9AA3 + #2E3039 + #18C273 + \ No newline at end of file diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index b8fc7eb..cde290e 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -877,5 +877,9 @@ "walkin": "زيارة بدون موعد", "laserClinic": "عيادة الليزر", "continueString": "يكمل", - "covid_info": "تجري مستشفيات د. سليمان الحبيب فحص فيروس كورونا المستجد وتصدر شهادات السفر على مدار الساعة، طوال أيام الأسبوع، وبسرعة ودقة عالية. يمكن للراغبين في الاستفادة من هذه الخدمة زيارة أحد فروع مستشفيات د. سليمان الحبيب وإجراء فحص كورونا خلال بضع دقائق والحصول على النتائج خلال عدة ساعات خدمة فحص فيروس كورونا Covid 19 بتقنية PCR للكشف عن الفيروس وفقاً لأعلى المعايير العالمية وبأحدث أجهزة RT-PCR عالية الدقة (GeneXpert الأمريكي وغيره)، وهي طرق معتمدة من قبل هيئة الغذاء والدواء وكذلك من قبل المركز السعودي للوقاية من الأمراض المُعدية" + "covid_info": "تجري مستشفيات د. سليمان الحبيب فحص فيروس كورونا المستجد وتصدر شهادات السفر على مدار الساعة، طوال أيام الأسبوع، وبسرعة ودقة عالية. يمكن للراغبين في الاستفادة من هذه الخدمة زيارة أحد فروع مستشفيات د. سليمان الحبيب وإجراء فحص كورونا خلال بضع دقائق والحصول على النتائج خلال عدة ساعات خدمة فحص فيروس كورونا Covid 19 بتقنية PCR للكشف عن الفيروس وفقاً لأعلى المعايير العالمية وبأحدث أجهزة RT-PCR عالية الدقة (GeneXpert الأمريكي وغيره)، وهي طرق معتمدة من قبل هيئة الغذاء والدواء وكذلك من قبل المركز السعودي للوقاية من الأمراض المُعدية", + "callForVitalSign": "استدعاء لأخذ العلامات الحيوية", + "callForDoctor": "استدعاء الطبيب", + "yourQueueNumber": "رقمك في الدور", + "currentServing": "الدور الحالي" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 7839083..c3ec0ad 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -873,5 +873,9 @@ "walkin": "Walk In", "continueString": "Continue", "laserClinic": "Laser Clinic", - "covid_info" :"Dr. Sulaiman Al Habib hospitals are conducting a test for the emerging corona virus and issuing travel certificates 24/7 in a short time and with high accuracy. Those wishing to benefit from this service can visit one of Dr. Sulaiman Al Habib branches to conduct a corona test within few minutes, and obtain the result within several hours. Corona Virus Covid 19 testing service with PCR technology to detect the virus according to the highest international standards and with the latest high-precision RT-PCR devices (American GeneXpert and others), That is approved by the Food and Drug Authority as well as by the Saudi Center for Infectious Diseases Prevention." + "covid_info" :"Dr. Sulaiman Al Habib hospitals are conducting a test for the emerging corona virus and issuing travel certificates 24/7 in a short time and with high accuracy. Those wishing to benefit from this service can visit one of Dr. Sulaiman Al Habib branches to conduct a corona test within few minutes, and obtain the result within several hours. Corona Virus Covid 19 testing service with PCR technology to detect the virus according to the highest international standards and with the latest high-precision RT-PCR devices (American GeneXpert and others), That is approved by the Food and Drug Authority as well as by the Saudi Center for Infectious Diseases Prevention.", + "callForVitalSign": "Call for vital signs", + "callForDoctor": "Call for Doctor", + "yourQueueNumber": "Your Queue Number", + "currentServing" : "Current Serving" } \ No newline at end of file diff --git a/ios/AppWidget/AppWidgetLiveActivity.swift b/ios/AppWidget/AppWidgetLiveActivity.swift index 8702b3b..51a4122 100644 --- a/ios/AppWidget/AppWidgetLiveActivity.swift +++ b/ios/AppWidget/AppWidgetLiveActivity.swift @@ -1,13 +1,7 @@ -// -// AppWidgetLiveActivity.swift -// AppWidget -// -// Created by Cloud Solutions on 15/12/2025. -// - 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. @@ -112,304 +106,86 @@ 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 { - 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) + var body: some View { + ZStack { + data.colorConfig.containerBorderColor // Background color + .edgesIgnoringSafeArea(.all) // Ensure it covers the entire screen + + 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) + Image(data.imageName) + .resizable() + .scaledToFit() + .frame(width: 34, height: 34) + } + .padding(.top, 16) .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)) + // Currently Serving Header + Text(data.currentlyServingHeader) + .font(.custom("Poppins-Medium", size: 14)) .fontWeight(.bold) .foregroundColor(.black) - .frame(maxWidth: .infinity, alignment: .leading) + .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.status) + .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) - // Status badge - Text(data.status) + 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(Color.inactiveColor.opacity(0.2)) + .fill(data.colorConfig.nextStepBackground) ) + .padding(.horizontal, 16) + .padding(.bottom, 16) } - .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) -// ) - } -} - -extension View { - func border(width: CGFloat, edges: [Edge], color: Color) -> some View { - overlay(EdgeBorder(width: width, edges: edges).foregroundColor(color)) + .background(Color.white) // Ensure content has a white background .cornerRadius(20) - - } -} - -struct EdgeBorder: Shape { - var width: CGFloat - var edges: [Edge] - - func path(in rect: CGRect) -> Path { - edges.map { edge -> Path in - switch edge { - case .top: return Path(.init(x: rect.minX, y: rect.minY, width: rect.width, height: width)) - case .bottom: return Path(.init(x: rect.minX, y: rect.maxY - width, width: rect.width, height: width)) - case .leading: return Path(.init(x: rect.minX, y: rect.minY, width: width, height: rect.height)) - case .trailing: return Path(.init(x: rect.maxX - width, y: rect.minY, width: width, height: rect.height)) - } - }.reduce(into: Path()) { $0.addPath($1) } + .padding() // Add padding to ensure it doesn't touch the edges + } } } -// MARK: - Main Widget View -//working widget but the border is not appearing -// struct NotificationWidgetView: View { -// private let data: NotificationWidgetData -// -// init(data: NotificationWidgetData) { -// self.data = data -// } -// -// var body: some View { -// VStack(alignment: .leading, spacing: 0) { -// -// 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) -// } -// -// // Currently Serving Header -// Text(data.currentlyServingHeader) -// .font(.custom("Poppins-Medium", size: 14)) -// .fontWeight(.bold) -// .foregroundColor(.black) -// .padding(.trailing, 12) -// .padding(.bottom, 10) -// -// // 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.status) -// .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)) -// ) -// } -// -// // 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() -// .background( RoundedRectangle(cornerRadius: 20) -// -// .fill(Color.white) -// ) -// // .border(data.colorConfig.containerBorderColor, width: 2) -// -// .overlay( -// RoundedRectangle(cornerRadius: 20) -// .stroke(data.colorConfig.containerBorderColor, lineWidth: 1) -// // RoundedRectangle(cornerRadius: 12, style: .continuous) -// // .stroke(data.colorConfig.containerBorderColor, lineWidth: 5) -// ) -// -// // .padding(12) -// } -// } - - -// MARK: - Main Widget View -// struct NotificationWidgetView: View { -// private let data: NotificationWidgetData -// -// init(data: NotificationWidgetData) { -// self.data = data -// } -// -// var body: some View { -// // Use a ZStack as the base to layer the background and content -// ZStack { -// // Layer 1: Glass effect background with border on all sides -// RoundedRectangle(cornerRadius: 12, style: .continuous) -// .strokeBorder(data.colorConfig.containerBorderColor, lineWidth: 3) -// .background( -// RoundedRectangle(cornerRadius: 12, style: .continuous) -// -// .background( -// RoundedRectangle(cornerRadius: 12, style: .continuous) -// .fill(Color.white) -// ) -// ) -// .shadow(color: Color.black.opacity(0.1), radius: 8, x: 0, y: 4) -// -// -// // Layer 2: Your content, padded from the edges -// VStack(alignment: .leading, spacing: 0) { -// // Top section with current ticket and image -// HStack(alignment: .top, spacing: 0) { -// Text(data.currentTicket) -// .font(.custom("Poppins-Medium", size: 28)) -// .fontWeight(.bold) -// .foregroundColor(.black) -// .padding(.trailing, 10) -// -// Spacer() // Pushes the image to the trailing edge -// -// Image(systemName: data.imageName) -// .resizable() -// .scaledToFit() -// .frame(width: 24, height: 24) -// .foregroundColor(.gray) -// } -// -// // Currently Serving Header -// Text(data.currentlyServingHeader) -// .font(.custom("Poppins-Medium", size: 14)) -// .fontWeight(.bold) -// .foregroundColor(.black) -// .padding(.top, 4) // Adjusted padding -// .padding(.bottom, 10) -// -// // Currently Serving section with status -// HStack(alignment: .center, spacing: 0) { -// Text(data.currentlyServing) -// .font(.custom("Poppins-Medium", size: 16)) -// .fontWeight(.bold) -// .foregroundColor(.black) -// -// Spacer() // Pushes status to the trailing edge -// -// Text(data.status) -// .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)) -// ) -// } -// -// // 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(.top, 10) -// -// // **CRITICAL FIX**: Pushes all content to the top -// // and makes the VStack fill the available height. -// Spacer(minLength: 0) -// } -// .padding(15) // Apply padding to the content VStack instead -// } -// } -// } // MARK: - Live Activity Widget @@ -418,13 +194,16 @@ struct AppWidgetLiveActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in // Extract parameters from Flutter - let title = sharedDefault.string(forKey: context.attributes.prefixedKey("title")) ?? "test" - let contentText = sharedDefault.string(forKey: context.attributes.prefixedKey("contentText")) ?? "test" - let currentTicket = sharedDefault.string(forKey: context.attributes.prefixedKey("currentTicket")) ?? "test" - let status = sharedDefault.string(forKey: context.attributes.prefixedKey("status")) ?? "test" - let currentlyServing = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServing")) ?? "test" - let nextStep = sharedDefault.string(forKey: context.attributes.prefixedKey("nextStep")) ?? "test" - let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("nextStepBackground")) + print("it is being loaded") +// 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 status = 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("currentlyServingStatus")) ?? + "test111" + let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) // Get color configuration based on nextStepBackground let colorConfig = WidgetColorConfig.config(for: nextStepBackground) @@ -432,26 +211,27 @@ struct AppWidgetLiveActivity: Widget { // Create widget data let widgetData = NotificationWidgetData( currentTicket: currentTicket, - currentlyServingHeader: "Currently Serving:", + currentlyServingHeader: "Currently Servingsssssssss:", currentlyServing: currentlyServing, status: status, nextStep: nextStep, imageName:"hmg", colorConfig: colorConfig ) - - // Lock screen/banner UI - NotificationWidgetView(data: widgetData) - .activityBackgroundTint(Color.clear) - .activitySystemActionForegroundColor(Color.black) - + NotificationWidgetView(data: widgetData) + .activityBackgroundTint(Color.clear) + .activitySystemActionForegroundColor(Color.black) } dynamicIsland: { context in - let currentTicket = sharedDefault.string(forKey: context.attributes.prefixedKey("currentTicket")) ?? "" - let status = sharedDefault.string(forKey: context.attributes.prefixedKey("status")) ?? "" - let currentlyServing = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServing")) ?? "" - let nextStep = sharedDefault.string(forKey: context.attributes.prefixedKey("nextStep")) ?? "" - let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("nextStepBackground")) + 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 status = 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("currentlyServingStatus")) ?? + "test111" + let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) + let colorConfig = WidgetColorConfig.config(for: nextStepBackground) @@ -536,7 +316,7 @@ struct AppWidgetLiveActivity: Widget { .frame(width: 4, height: 4) .foregroundColor(colorConfig.containerBorderColor) }.padding(2) - + } .contentMargins(.all, 20,for: .expanded) } @@ -557,7 +337,7 @@ struct NotificationWidgetView_Previews: PreviewProvider { NotificationWidgetView( data: NotificationWidgetData( currentTicket: "42", - currentlyServingHeader: "Currently Serving:", + currentlyServingHeader: "Currently Serving3:", currentlyServing: "Customer #15", status: "Pending", nextStep: "Next: Prepare Order", @@ -566,12 +346,12 @@ struct NotificationWidgetView_Previews: PreviewProvider { ) ) .previewDisplayName("Yellow Border (0)") - + // Preview with nextStepBackground = 1 (Red border) NotificationWidgetView( data: NotificationWidgetData( currentTicket: "89", - currentlyServingHeader: "Currently Serving:", + currentlyServingHeader: "Currently Serving2:", currentlyServing: "Customer #67", status: "Active", nextStep: "Next: Quality Check", @@ -580,12 +360,12 @@ struct NotificationWidgetView_Previews: PreviewProvider { ) ) .previewDisplayName("Red Border (1)") - + // Preview with nextStepBackground = 2 (Green border) NotificationWidgetView( data: NotificationWidgetData( currentTicket: "125", - currentlyServingHeader: "Currently Serving:", + currentlyServingHeader: "Currently Serving1:", currentlyServing: "Customer #98", status: "Completed", nextStep: "Next: Ready for Pickup", @@ -599,3 +379,4 @@ struct NotificationWidgetView_Previews: PreviewProvider { .previewLayout(.sizeThatFits) } } + diff --git a/ios/AppWidgetLiveActivity/AppWidgetLiveActivityBundle.swift b/ios/AppWidgetLiveActivity/AppWidgetLiveActivityBundle.swift new file mode 100644 index 0000000..f1e9842 --- /dev/null +++ b/ios/AppWidgetLiveActivity/AppWidgetLiveActivityBundle.swift @@ -0,0 +1,17 @@ +// +// AppWidgetLiveActivityBundle.swift +// AppWidgetLiveActivity +// +// Created by Cloud Solutions on 27/01/2026. +// + +import WidgetKit +import SwiftUI + +@main +struct AppWidgetLiveActivityBundle: WidgetBundle { + var body: some Widget { + + AppWidgetLiveActivity() + } +} diff --git a/ios/AppWidgetLiveActivity/AppWidgetLiveActivityLiveActivity.swift b/ios/AppWidgetLiveActivity/AppWidgetLiveActivityLiveActivity.swift new file mode 100644 index 0000000..18e1abe --- /dev/null +++ b/ios/AppWidgetLiveActivity/AppWidgetLiveActivityLiveActivity.swift @@ -0,0 +1,575 @@ +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 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: .textColor, + 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 status: 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("clock") + .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(Color(hex:"#18C273")) + + } + .padding(8) + .background(Color(hex:"#1A18C273")) + .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(Color.green) + .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 + 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.status) + .font(.system(size: 10, weight: .semibold)) + .foregroundColor(Color(hex: "#18C273")) + } + + .padding(8) + .background(Color(hex:"#1A18C273")) + .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 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.status) +// .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 AppWidgetLiveActivity: 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 status = 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("currentlyServingStatus")) ?? +// "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 status = 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 + + + // Get color configuration based on nextStepBackground + let colorConfig = WidgetColorConfig.config(for: nextStepBackground) + + // Create widget data + let widgetData = NotificationWidgetData( + currentTicket: currentTicket, + currentlyServingHeader: currentlyServingHeader, + currentlyServing: currentlyServing, + status: status, + nextStep: nextStep, + imageName:"hmg", + colorConfig: colorConfig, + progress: 33 * Double(nextStepBackground), + 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 status = 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 colorConfig = WidgetColorConfig.config(for: nextStepBackground) + let widgetData = NotificationWidgetData( + currentTicket: currentTicket, + currentlyServingHeader: currentlyServingHeader, + currentlyServing: currentlyServing, + status: status, + nextStep: nextStep, + imageName:"hmg", + colorConfig: colorConfig, + progress: 33 * Double(nextStepBackground), + 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(status) +// .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", +// status: "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", +// status: "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", +// status: "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 "no value" + } + } + } + return "no value" +} diff --git a/ios/liveapp/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from ios/liveapp/Assets.xcassets/AccentColor.colorset/Contents.json rename to ios/AppWidgetLiveActivity/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/ios/liveapp/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from ios/liveapp/Assets.xcassets/AppIcon.appiconset/Contents.json rename to ios/AppWidgetLiveActivity/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/ios/liveapp/Assets.xcassets/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/Contents.json similarity index 100% rename from ios/liveapp/Assets.xcassets/Contents.json rename to ios/AppWidgetLiveActivity/Assets.xcassets/Contents.json diff --git a/ios/liveapp/Assets.xcassets/WidgetBackground.colorset/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/WidgetBackground.colorset/Contents.json similarity index 100% rename from ios/liveapp/Assets.xcassets/WidgetBackground.colorset/Contents.json rename to ios/AppWidgetLiveActivity/Assets.xcassets/WidgetBackground.colorset/Contents.json diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/clock.imageset/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/clock.imageset/Contents.json new file mode 100644 index 0000000..f2e282f --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/clock.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/clock.imageset/icon.svg b/ios/AppWidgetLiveActivity/Assets.xcassets/clock.imageset/icon.svg new file mode 100644 index 0000000..d2e84a3 --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/clock.imageset/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/Contents.json new file mode 100644 index 0000000..ed588f8 --- /dev/null +++ b/ios/AppWidgetLiveActivity/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/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg 1.svg b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg 1.svg new file mode 100644 index 0000000..ccaed0c --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg 1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg 2.svg b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg 2.svg new file mode 100644 index 0000000..ccaed0c --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg 2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg.svg b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg.svg new file mode 100644 index 0000000..ccaed0c --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/hmg.imageset/hmg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/profession.imageset/Contents.json b/ios/AppWidgetLiveActivity/Assets.xcassets/profession.imageset/Contents.json new file mode 100644 index 0000000..f36884c --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/profession.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "doctor-02.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/AppWidgetLiveActivity/Assets.xcassets/profession.imageset/doctor-02.svg b/ios/AppWidgetLiveActivity/Assets.xcassets/profession.imageset/doctor-02.svg new file mode 100644 index 0000000..9c44db8 --- /dev/null +++ b/ios/AppWidgetLiveActivity/Assets.xcassets/profession.imageset/doctor-02.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ios/AppWidgetLiveActivity/Info.plist b/ios/AppWidgetLiveActivity/Info.plist new file mode 100644 index 0000000..0f118fb --- /dev/null +++ b/ios/AppWidgetLiveActivity/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + diff --git a/ios/AppWidgetLiveActivityExtension.entitlements b/ios/AppWidgetLiveActivityExtension.entitlements new file mode 100644 index 0000000..a1ca053 --- /dev/null +++ b/ios/AppWidgetLiveActivityExtension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.alhabib.patientApp + + + diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 1299de1..a03e5f6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -17,11 +17,15 @@ 61243B542EC5FA3700D46FA0 /* BuildFile in Sources */ = {isa = PBXBuildFile; }; 61243B562EC5FA3700D46FA0 /* BuildFile in Sources */ = {isa = PBXBuildFile; }; 61243B572EC5FA3700D46FA0 /* BuildFile in Sources */ = {isa = PBXBuildFile; }; + 614897042F28D996004105B3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61E1DA312F28A72E00CBF473 /* WidgetKit.framework */; }; + 614897052F28D996004105B3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61E1DA332F28A72E00CBF473 /* SwiftUI.framework */; }; + 614897122F28D99A004105B3 /* AppWidgetLiveActivityExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 614897032F28D996004105B3 /* AppWidgetLiveActivityExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 614897D22F29F952004105B3 /* LiveActivityHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 614897D12F29F94A004105B3 /* LiveActivityHelper.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 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 */; }; - C5586BA7BD57391D3F91EF2B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8076571670911AB920E1FF99 /* Pods_Runner.framework */; }; + FA9E781ABC7EBAA9AC2A559A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28E87B9D131B9D85858F792A /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -32,9 +36,27 @@ remoteGlobalIDString = 97C146ED1CF9000F007C117D; remoteInfo = Runner; }; + 614897102F28D99A004105B3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 614897022F28D996004105B3; + remoteInfo = AppWidgetLiveActivityExtension; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 61E1DA462F28A73100CBF473 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 614897122F28D99A004105B3 /* AppWidgetLiveActivityExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -48,20 +70,25 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 049415E7A479589C7A439E26 /* 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 = ""; }; + 28E87B9D131B9D85858F792A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 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; }; + 34F2654CE6CEE8475402FCE4 /* 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 = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; 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 = ""; }; + 614897032F28D996004105B3 /* AppWidgetLiveActivityExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AppWidgetLiveActivityExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 614897902F29E233004105B3 /* AppWidgetLiveActivityExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppWidgetLiveActivityExtension.entitlements; sourceTree = ""; }; + 614897D12F29F94A004105B3 /* LiveActivityHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityHelper.swift; sourceTree = ""; }; + 61E1DA312F28A72E00CBF473 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 61E1DA332F28A72E00CBF473 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; 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 = ""; }; - 7595037DD52211B91157B0F3 /* 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 = ""; }; 769C9BF82E6F106D009F68A9 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8076571670911AB920E1FF99 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8E12CEEB8E334EE22D5259D7 /* 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 = ""; }; 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; }; @@ -69,40 +96,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 = ""; }; - D6BB17A036DF7FCE75271203 /* 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 = ""; }; + B50C2F2EABBC2DFA70F931F1 /* 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - 6147DFA32EF2D46300A0F0AA /* Exceptions for "AppWidget" folder in "Runner" target */ = { + 614897132F28D99B004105B3 /* Exceptions for "AppWidgetLiveActivity" folder in "AppWidgetLiveActivityExtension" target */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( - "Poppins-Medium.ttf", + Info.plist, ); - target = 97C146ED1CF9000F007C117D /* Runner */; + target = 614897022F28D996004105B3 /* AppWidgetLiveActivityExtension */; }; /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - 61769DEA2EEFDD0F000EC14A /* AppWidget */ = { + 614897062F28D996004105B3 /* AppWidgetLiveActivity */ = { isa = PBXFileSystemSynchronizedRootGroup; exceptions = ( - 6147DFA32EF2D46300A0F0AA /* Exceptions for "AppWidget" folder in "Runner" target */, + 614897132F28D99B004105B3 /* Exceptions for "AppWidgetLiveActivity" folder in "AppWidgetLiveActivityExtension" target */, ); explicitFileTypes = { }; explicitFolders = ( ); - path = AppWidget; + path = AppWidgetLiveActivity; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ + 614897002F28D996004105B3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 614897052F28D996004105B3 /* SwiftUI.framework in Frameworks */, + 614897042F28D996004105B3 /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C5586BA7BD57391D3F91EF2B /* Pods_Runner.framework in Frameworks */, + FA9E781ABC7EBAA9AC2A559A /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -120,6 +156,7 @@ 61243B412EC5FA3700D46FA0 /* Helper */ = { isa = PBXGroup; children = ( + 614897D12F29F94A004105B3 /* LiveActivityHelper.swift */, ); path = Helper; sourceTree = ""; @@ -131,12 +168,22 @@ path = Penguin; sourceTree = ""; }; + 71E5EACB6652FDA92D3045F5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 28E87B9D131B9D85858F792A /* Pods_Runner.framework */, + 61E1DA312F28A72E00CBF473 /* WidgetKit.framework */, + 61E1DA332F28A72E00CBF473 /* SwiftUI.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 79DD2093A1D9674C94359FC8 /* Pods */ = { isa = PBXGroup; children = ( - 8E12CEEB8E334EE22D5259D7 /* Pods-Runner.debug.xcconfig */, - 7595037DD52211B91157B0F3 /* Pods-Runner.release.xcconfig */, - D6BB17A036DF7FCE75271203 /* Pods-Runner.profile.xcconfig */, + 34F2654CE6CEE8475402FCE4 /* Pods-Runner.debug.xcconfig */, + 049415E7A479589C7A439E26 /* Pods-Runner.release.xcconfig */, + B50C2F2EABBC2DFA70F931F1 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -155,13 +202,14 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + 614897902F29E233004105B3 /* AppWidgetLiveActivityExtension.entitlements */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, - 61769DEA2EEFDD0F000EC14A /* AppWidget */, + 614897062F28D996004105B3 /* AppWidgetLiveActivity */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, 79DD2093A1D9674C94359FC8 /* Pods */, - DBBFD4F9B92DEEED70E55CB8 /* Frameworks */, + 71E5EACB6652FDA92D3045F5 /* Frameworks */, ); sourceTree = ""; }; @@ -170,6 +218,7 @@ children = ( 97C146EE1CF9000F007C117D /* Runner.app */, 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + 614897032F28D996004105B3 /* AppWidgetLiveActivityExtension.appex */, ); name = Products; sourceTree = ""; @@ -194,14 +243,6 @@ path = Runner; sourceTree = ""; }; - DBBFD4F9B92DEEED70E55CB8 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 8076571670911AB920E1FF99 /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -222,23 +263,45 @@ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 614897022F28D996004105B3 /* AppWidgetLiveActivityExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 614897142F28D99B004105B3 /* Build configuration list for PBXNativeTarget "AppWidgetLiveActivityExtension" */; + buildPhases = ( + 614896FF2F28D996004105B3 /* Sources */, + 614897002F28D996004105B3 /* Frameworks */, + 614897012F28D996004105B3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 614897062F28D996004105B3 /* AppWidgetLiveActivity */, + ); + name = AppWidgetLiveActivityExtension; + productName = AppWidgetLiveActivityExtension; + productReference = 614897032F28D996004105B3 /* AppWidgetLiveActivityExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - BFED6CCFE59BB148875A533B /* [CP] Check Pods Manifest.lock */, + A6C952634C4302C01CA5C5E8 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, + E6CDE64936F529AE76962FE8 /* [CP] Copy Pods Resources */, + 61E1DA462F28A73100CBF473 /* Embed Foundation Extensions */, + D75CDA8F31A418BC8F9C299F /* [CP] Embed Pods Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 8372B02399CDF54531650AD4 /* [CP] Embed Pods Frameworks */, - 81DE7C26F41956799E954FCE /* [CP] Copy Pods Resources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 614897112F28D99A004105B3 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -252,6 +315,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1640; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { @@ -259,6 +323,9 @@ CreatedOnToolsVersion = 14.0; TestTargetID = 97C146ED1CF9000F007C117D; }; + 614897022F28D996004105B3 = { + CreatedOnToolsVersion = 16.4; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -280,6 +347,7 @@ targets = ( 97C146ED1CF9000F007C117D /* Runner */, 331C8080294A63A400263BE5 /* RunnerTests */, + 614897022F28D996004105B3 /* AppWidgetLiveActivityExtension */, ); }; /* End PBXProject section */ @@ -292,6 +360,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 614897012F28D996004105B3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -323,75 +398,75 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 81DE7C26F41956799E954FCE /* [CP] Copy Pods Resources */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + name = "Run Script"; + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 8372B02399CDF54531650AD4 /* [CP] Embed Pods Frameworks */ = { + A6C952634C4302C01CA5C5E8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + 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; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + D75CDA8F31A418BC8F9C299F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputPaths = ( + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "Run Script"; - outputPaths = ( + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; }; - BFED6CCFE59BB148875A533B /* [CP] Check Pods Manifest.lock */ = { + E6CDE64936F529AE76962FE8 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", ); 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"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -405,6 +480,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 614896FF2F28D996004105B3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -414,6 +496,7 @@ 61243B4C2EC5FA3700D46FA0 /* BuildFile in Sources */, 61243B502EC5FA3700D46FA0 /* BuildFile in Sources */, 61243B542EC5FA3700D46FA0 /* BuildFile in Sources */, + 614897D22F29F952004105B3 /* LiveActivityHelper.swift in Sources */, 61243B562EC5FA3700D46FA0 /* BuildFile in Sources */, 61243B572EC5FA3700D46FA0 /* BuildFile in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, @@ -428,6 +511,11 @@ target = 97C146ED1CF9000F007C117D /* Runner */; targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; }; + 614897112F28D99A004105B3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 614897022F28D996004105B3 /* AppWidgetLiveActivityExtension */; + targetProxy = 614897102F28D99A004105B3 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -577,6 +665,132 @@ }; name = Profile; }; + 614897152F28D99B004105B3 /* 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 = AppWidgetLiveActivityExtension.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 = AppWidgetLiveActivity/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = AppWidgetLiveActivity; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSSupportsLiveActivities = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + 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.HMG.HMG-Smartphone.AppWidgetLiveActivity"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 614897162F28D99B004105B3 /* 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_ENTITLEMENTS = AppWidgetLiveActivityExtension.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 = AppWidgetLiveActivity/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = AppWidgetLiveActivity; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSSupportsLiveActivities = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + 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.HMG.HMG-Smartphone.AppWidgetLiveActivity"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 614897172F28D99B004105B3 /* 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_ENTITLEMENTS = AppWidgetLiveActivityExtension.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 = AppWidgetLiveActivity/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = AppWidgetLiveActivity; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSSupportsLiveActivities = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + 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.HMG.HMG-Smartphone.AppWidgetLiveActivity"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -758,6 +972,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + 614897142F28D99B004105B3 /* Build configuration list for PBXNativeTarget "AppWidgetLiveActivityExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 614897152F28D99B004105B3 /* Debug */, + 614897162F28D99B004105B3 /* Release */, + 614897172F28D99B004105B3 /* 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 4172e0e..67ad532 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -13,11 +13,13 @@ 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 - + LiveActivityHelper().initialize(mainViewController) // HMGPenguinInPlatformBridge.initialize(flutterViewController: mainViewController) } diff --git a/ios/Runner/Helper/LiveActivityHelper.swift b/ios/Runner/Helper/LiveActivityHelper.swift new file mode 100644 index 0000000..ffab96d --- /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 +import FLAnimatedImage + +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 6dd8778..f8d3d87 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -110,6 +110,7 @@ location remote-notification voip + processing UILaunchStoryboardName LaunchScreen diff --git a/ios/liveapp/AppIntent.swift b/ios/live_notification/AppIntent.swift similarity index 85% rename from ios/liveapp/AppIntent.swift rename to ios/live_notification/AppIntent.swift index 55508c8..5771089 100644 --- a/ios/liveapp/AppIntent.swift +++ b/ios/live_notification/AppIntent.swift @@ -1,8 +1,8 @@ // // AppIntent.swift -// liveapp +// live_notification // -// Created by Cloud Solutions on 14/12/2025. +// Created by Cloud Solutions on 27/01/2026. // import WidgetKit 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 0000000..eb87897 --- /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 0000000..2305880 --- /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 0000000..73c0059 --- /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 0000000..eb87897 --- /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 0000000..ed588f8 --- /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 0000000..ccaed0c --- /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 0000000..ccaed0c --- /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 0000000..ccaed0c --- /dev/null +++ b/ios/live_notification/Assets.xcassets/hmg.imageset/hmg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/liveapp/Info.plist b/ios/live_notification/Info.plist similarity index 100% rename from ios/liveapp/Info.plist rename to ios/live_notification/Info.plist index 464a4f8..04f07b5 100644 --- a/ios/liveapp/Info.plist +++ b/ios/live_notification/Info.plist @@ -2,12 +2,12 @@ + NSSupportsLiveActivities + NSExtension NSExtensionPointIdentifier com.apple.widgetkit-extension - NSSupportsLiveActivities - diff --git a/ios/live_notification/live_notificationBundle.swift b/ios/live_notification/live_notificationBundle.swift new file mode 100644 index 0000000..0cf3114 --- /dev/null +++ b/ios/live_notification/live_notificationBundle.swift @@ -0,0 +1,16 @@ +// +// live_notificationBundle.swift +// live_notification +// +// Created by Cloud Solutions on 27/01/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 0000000..2652153 --- /dev/null +++ b/ios/live_notification/live_notificationLiveActivity.swift @@ -0,0 +1,410 @@ +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 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: .textColor, + 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 status: String + let nextStep: String + let imageName: 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.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 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.status) + .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 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")) ?? "testes" + let contentText = sharedDefault.string(forKey: context.attributes.prefixedKey("contentText")) ?? "tested" + let currentTicket = 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 nextStep = sharedDefault.string(forKey: context.attributes.prefixedKey("currentlyServingStatus")) ?? + "test111" + let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) + + // Get color configuration based on nextStepBackground + let colorConfig = WidgetColorConfig.config(for: nextStepBackground) + + // Create widget data + let widgetData = NotificationWidgetData( + currentTicket: currentTicket, + currentlyServingHeader: "Currently Servingsssssssss:", + currentlyServing: currentlyServing, + status: status, + nextStep: nextStep, + imageName:"hmg", + colorConfig: colorConfig + ) +// + // Lock screen/banner UI + NotificationWidgetView(data: widgetData) + .activityBackgroundTint(Color.clear) + .activitySystemActionForegroundColor(Color.black) + + // 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 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 status = 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("currentlyServingStatus")) ?? + "test111" + let nextStepBackground = sharedDefault.integer(forKey: context.attributes.prefixedKey("currentlyServingCallType")) + + + let colorConfig = WidgetColorConfig.config(for: nextStepBackground) + + return DynamicIsland { + // Expanded UI + DynamicIslandExpandedRegion(.leading) { + VStack(alignment: .leading) { + Text(currentTicket) + .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.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) + + } + .contentMargins(.all, 20,for: .expanded) + } + } + } + + +extension LiveActivitiesAppAttributes { + func prefixedKey(_ key: String) -> String { + return "\(id)_\(key)" + } +} +// MARK: - Preview for Testing +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", + status: "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", + status: "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", + status: "Completed", + nextStep: "Next: Ready for Pickup", + imageName: "bell.fill", + colorConfig: .config(for: 2) + ) + ) + .previewDisplayName("Green Border (2)") + } + .padding() + .previewLayout(.sizeThatFits) + } +} + diff --git a/ios/liveapp/liveapp.swift b/ios/liveapp/liveapp.swift deleted file mode 100644 index 6b58b65..0000000 --- a/ios/liveapp/liveapp.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// liveapp.swift -// liveapp -// -// Created by Cloud Solutions on 14/12/2025. -// - -import WidgetKit -import SwiftUI - -struct Provider: AppIntentTimelineProvider { - func placeholder(in context: Context) -> SimpleEntry { - SimpleEntry(date: Date(), configuration: ConfigurationAppIntent()) - } - - func snapshot(for configuration: ConfigurationAppIntent, in context: Context) async -> SimpleEntry { - SimpleEntry(date: Date(), configuration: configuration) - } - - func timeline(for configuration: ConfigurationAppIntent, in context: Context) async -> 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, configuration: configuration) - entries.append(entry) - } - - return Timeline(entries: entries, policy: .atEnd) - } - -// func relevances() async -> WidgetRelevances { -// // Generate a list containing the contexts this widget is relevant in. -// } -} - -struct SimpleEntry: TimelineEntry { - let date: Date - let configuration: ConfigurationAppIntent -} - -struct liveappEntryView : View { - var entry: Provider.Entry - - var body: some View { - VStack { - Text("Time:") - Text(entry.date, style: .time) - - Text("Favorite Emoji:") - Text(entry.configuration.favoriteEmoji) - } - } -} - -struct liveapp: Widget { - let kind: String = "liveapp" - - var body: some WidgetConfiguration { - AppIntentConfiguration(kind: kind, intent: ConfigurationAppIntent.self, provider: Provider()) { entry in - liveappEntryView(entry: entry) - .containerBackground(.fill.tertiary, for: .widget) - } - } -} - -extension ConfigurationAppIntent { - fileprivate static var smiley: ConfigurationAppIntent { - let intent = ConfigurationAppIntent() - intent.favoriteEmoji = "😀" - return intent - } - - fileprivate static var starEyes: ConfigurationAppIntent { - let intent = ConfigurationAppIntent() - intent.favoriteEmoji = "🤩" - return intent - } -} - -#Preview(as: .systemSmall) { - liveapp() -} timeline: { - SimpleEntry(date: .now, configuration: .smiley) - SimpleEntry(date: .now, configuration: .starEyes) -} diff --git a/ios/liveapp/liveappBundle.swift b/ios/liveapp/liveappBundle.swift deleted file mode 100644 index ea3cf45..0000000 --- a/ios/liveapp/liveappBundle.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// liveappBundle.swift -// liveapp -// -// Created by Cloud Solutions on 14/12/2025. -// - -import WidgetKit -import SwiftUI - -@main -struct liveappBundle: WidgetBundle { - var body: some Widget { - FootballMatchApp() - } -} diff --git a/ios/liveapp/liveappControl.swift b/ios/liveapp/liveappControl.swift deleted file mode 100644 index 955dbea..0000000 --- a/ios/liveapp/liveappControl.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// liveappControl.swift -// liveapp -// -// Created by Cloud Solutions on 14/12/2025. -// - -import AppIntents -import SwiftUI -import WidgetKit - -struct liveappControl: ControlWidget { - static let kind: String = "com.HMG.HMG-Smartphone.liveapp" - - var body: some ControlWidgetConfiguration { - AppIntentControlConfiguration( - kind: Self.kind, - provider: Provider() - ) { value in - ControlWidgetToggle( - "Start Timer", - isOn: value.isRunning, - action: StartTimerIntent(value.name) - ) { isRunning in - Label(isRunning ? "On" : "Off", systemImage: "timer") - } - } - .displayName("Timer") - .description("A an example control that runs a timer.") - } -} - -extension liveappControl { - struct Value { - var isRunning: Bool - var name: String - } - - struct Provider: AppIntentControlValueProvider { - func previewValue(configuration: TimerConfiguration) -> Value { - liveappControl.Value(isRunning: false, name: configuration.timerName) - } - - func currentValue(configuration: TimerConfiguration) async throws -> Value { - let isRunning = true // Check if the timer is running - return liveappControl.Value(isRunning: isRunning, name: configuration.timerName) - } - } -} - -struct TimerConfiguration: ControlConfigurationIntent { - static let title: LocalizedStringResource = "Timer Name Configuration" - - @Parameter(title: "Timer Name", default: "Timer") - var timerName: String -} - -struct StartTimerIntent: SetValueIntent { - static let title: LocalizedStringResource = "Start a timer" - - @Parameter(title: "Timer Name") - var name: String - - @Parameter(title: "Timer is running") - var value: Bool - - init() {} - - init(_ name: String) { - self.name = name - } - - func perform() async throws -> some IntentResult { - // Start the timer… - return .result() - } -} diff --git a/ios/liveapp/liveappLiveActivity.swift b/ios/liveapp/liveappLiveActivity.swift deleted file mode 100644 index ebc9b63..0000000 --- a/ios/liveapp/liveappLiveActivity.swift +++ /dev/null @@ -1,332 +0,0 @@ -// -// liveappLiveActivity.swift -// liveapp -// -// Created by Cloud Solutions on 14/12/2025. -// - -import ActivityKit -import WidgetKit -import SwiftUI - -struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable { - public typealias LiveDeliveryData = ContentState - - public struct ContentState: Codable, Hashable { } - - var id = UUID() -} - -// Create shared default with custom group -let sharedDefault = UserDefaults(suiteName: "group.alhabib.patientApp")! - -@available(iOSApplicationExtension 16.1, *) -struct FootballMatchApp: Widget { - var body: some WidgetConfiguration { - ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in - let matchName = sharedDefault.string(forKey: context.attributes.prefixedKey("matchName"))! - let ruleFile = sharedDefault.string(forKey: context.attributes.prefixedKey("ruleFile"))! - - let teamAName = sharedDefault.string(forKey: context.attributes.prefixedKey("teamAName"))! - let teamAState = sharedDefault.string(forKey: context.attributes.prefixedKey("teamAState"))! - let teamAScore = sharedDefault.integer(forKey: context.attributes.prefixedKey("teamAScore")) - let teamALogo = sharedDefault.string(forKey: context.attributes.prefixedKey("teamALogo"))! - - let teamBName = sharedDefault.string(forKey: context.attributes.prefixedKey("teamBName"))! - let teamBState = sharedDefault.string(forKey: context.attributes.prefixedKey("teamBState"))! - let teamBScore = sharedDefault.integer(forKey: context.attributes.prefixedKey("teamBScore")) - let teamBLogo = sharedDefault.string(forKey: context.attributes.prefixedKey("teamBLogo"))! - - let rule = (try? String(contentsOfFile: ruleFile, encoding: .utf8)) ?? "" - let matchStartDate = Date(timeIntervalSince1970: sharedDefault.double(forKey: context.attributes.prefixedKey("matchStartDate")) / 1000) - let matchEndDate = Date(timeIntervalSince1970: sharedDefault.double(forKey: context.attributes.prefixedKey("matchEndDate")) / 1000) - let matchRemainingTime = matchStartDate...matchEndDate - - ZStack { - LinearGradient(colors: [Color.black.opacity(0.5),Color.black.opacity(0.3)], startPoint: .topLeading, endPoint: .bottom) - - HStack { - ZStack { - VStack(alignment: .center, spacing: 2.0) { - - Spacer() - - Text(teamAName) - .lineLimit(1) - .font(.subheadline) - .fontWeight(.bold) - .multilineTextAlignment(.center) - - Text(teamAState) - .lineLimit(1) - .font(.footnote) - .fontWeight(.bold) - .multilineTextAlignment(.center) - } - .frame(width: 70, height: 120) - .padding(.bottom, 8) - .padding(.top, 8) - .background(.white.opacity(0.4), in: RoundedRectangle(cornerRadius: 16, style: .continuous)) - - ZStack { - if let uiImageTeamA = UIImage(contentsOfFile: teamALogo) - { - Image(uiImage: uiImageTeamA) - .resizable() - .frame(width: 80, height: 80) - .offset(y:-20) - } - } - } - - VStack(alignment: .center, spacing: 6.0) { - HStack { - Text("\(teamAScore)") - .font(.title) - .fontWeight(.bold) - - Text(":") - .font(.title) - .fontWeight(.bold) - .foregroundStyle(.primary) - - Text("\(teamBScore)") - .font(.title) - .fontWeight(.bold) - } - .padding(.horizontal, 5.0) - .background(.white.opacity(0.4), in: RoundedRectangle(cornerRadius: 8, style: .continuous)) - - HStack(alignment: .center, spacing: 2.0) { - Text(timerInterval: matchRemainingTime, countsDown: true) - .multilineTextAlignment(.center) - .frame(width: 50) - .monospacedDigit() - .font(.footnote) - .foregroundStyle(.white) - } - - VStack(alignment: .center, spacing: 1.0) { - Link(destination: URL(string: "la://my.app/stats")!) { - Text("See stats 📊") - }.padding(.vertical, 5).padding(.horizontal, 5) - Text(matchName) - .font(.footnote) - .foregroundStyle(.white) - .padding(.bottom, 5) - Text(rule) - .font(.footnote) - .foregroundStyle(.white.opacity(0.5)) - } - } - .padding(.vertical, 6.0) - - ZStack { - VStack(alignment: .center, spacing: 2.0) { - - Spacer() - - Text(teamBName) - .lineLimit(1) - .font(.subheadline) - .fontWeight(.bold) - .multilineTextAlignment(.center) - - Text(teamBState) - .lineLimit(1) - .font(.footnote) - .fontWeight(.bold) - .multilineTextAlignment(.center) - } - .frame(width: 70, height: 120) - .padding(.bottom, 8) - .padding(.top, 8) - .background(.white.opacity(0.4), in: RoundedRectangle(cornerRadius: 16, style: .continuous)) - - ZStack { - if let uiImageTeamB = UIImage(contentsOfFile: teamBLogo) - { - Image(uiImage: uiImageTeamB) - .resizable() - .frame(width: 80, height: 80) - .offset(y:-20) - } - } - } - } - .padding(.horizontal, 2.0) - }.frame(height: 160) - } dynamicIsland: { context in - let matchName = sharedDefault.string(forKey: context.attributes.prefixedKey("matchName"))! - - let teamAName = sharedDefault.string(forKey: context.attributes.prefixedKey("teamAName"))! - let teamAState = sharedDefault.string(forKey: context.attributes.prefixedKey("teamAState"))! - let teamAScore = sharedDefault.integer(forKey: context.attributes.prefixedKey("teamAScore")) - let teamALogo = sharedDefault.string(forKey: context.attributes.prefixedKey("teamALogo"))! - - let teamBName = sharedDefault.string(forKey: context.attributes.prefixedKey("teamBName"))! - let teamBState = sharedDefault.string(forKey: context.attributes.prefixedKey("teamBState"))! - let teamBScore = sharedDefault.integer(forKey: context.attributes.prefixedKey("teamBScore")) - let teamBLogo = sharedDefault.string(forKey: context.attributes.prefixedKey("teamBLogo"))! - - let matchStartDate = Date(timeIntervalSince1970: sharedDefault.double(forKey: context.attributes.prefixedKey("matchStartDate")) / 1000) - let matchEndDate = Date(timeIntervalSince1970: sharedDefault.double(forKey: context.attributes.prefixedKey("matchEndDate")) / 1000) - let matchRemainingTime = matchStartDate...matchEndDate - - return DynamicIsland { - DynamicIslandExpandedRegion(.leading) { - VStack(alignment: .center, spacing: 2.0) { - - if let uiImageTeamA = UIImage(contentsOfFile: teamALogo) - { - Image(uiImage: uiImageTeamA) - .resizable() - .frame(width: 80, height: 80) - .offset(y:0) - } - - Spacer() - - Text(teamAName) - .lineLimit(1) - .font(.subheadline) - .fontWeight(.bold) - .multilineTextAlignment(.center) - - Text(teamAState) - .lineLimit(1) - .font(.footnote) - .fontWeight(.bold) - .multilineTextAlignment(.center) - } - .frame(width: 70, height: 120) - .padding(.bottom, 8) - .padding(.top, 8) - - - } - DynamicIslandExpandedRegion(.trailing) { - VStack(alignment: .center, spacing: 2.0) { - - if let uiImageTeamB = UIImage(contentsOfFile: teamBLogo) - { - Image(uiImage: uiImageTeamB) - .resizable() - .frame(width: 80, height: 80) - .offset(y:0) - } - - Spacer() - - Text(teamBName) - .lineLimit(1) - .font(.subheadline) - .fontWeight(.bold) - .multilineTextAlignment(.center) - - Text(teamBState) - .lineLimit(1) - .font(.footnote) - .fontWeight(.bold) - .multilineTextAlignment(.center) - } - .frame(width: 70, height: 120) - .padding(.bottom, 8) - .padding(.top, 8) - - - } - DynamicIslandExpandedRegion(.center) { - VStack(alignment: .center, spacing: 6.0) { - HStack { - Text("\(teamAScore)") - .font(.title) - .fontWeight(.bold) - - Text(":") - .font(.title) - .fontWeight(.bold) - .foregroundStyle(.primary) - - Text("\(teamBScore)") - .font(.title) - .fontWeight(.bold) - } - .padding(.horizontal, 5.0) - .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 8, style: .continuous)) - - HStack(alignment: .center, spacing: 2.0) { - Text(timerInterval: matchRemainingTime, countsDown: true) - .multilineTextAlignment(.center) - .frame(width: 50) - .monospacedDigit() - .font(.footnote) - .foregroundStyle(.white) - } - - VStack(alignment: .center, spacing: 1.0) { - Link(destination: URL(string: "la://my.app/stats")!) { - Text("See stats 📊") - }.padding(.vertical, 5).padding(.horizontal, 5) - Text(matchName) - .font(.footnote) - .foregroundStyle(.white) - } - - } - .padding(.vertical, 6.0) - } - } compactLeading: { - HStack { - if let uiImageTeamA = UIImage(contentsOfFile: teamALogo) - { - Image(uiImage: uiImageTeamA) - .resizable() - .frame(width: 26, height: 26) - } - - Text("\(teamAScore)") - .font(.title) - .fontWeight(.bold) - } - } compactTrailing: { - HStack { - Text("\(teamBScore)") - .font(.title) - .fontWeight(.bold) - if let uiImageTeamB = UIImage(contentsOfFile: teamBLogo) - { - Image(uiImage: uiImageTeamB) - .resizable() - .frame(width: 26, height: 26) - } - } - } minimal: { - ZStack { - if let uiImageTeamA = UIImage(contentsOfFile: teamALogo) - { - Image(uiImage: uiImageTeamA) - .resizable() - .frame(width: 26, height: 26) - .offset(x:-6) - } - - if let uiImageTeamB = UIImage(contentsOfFile: teamBLogo) - { - Image(uiImage: uiImageTeamB) - .resizable() - .frame(width: 26, height: 26) - .offset(x:6) - } - } - } - } - } -} - -extension LiveActivitiesAppAttributes { - func prefixedKey(_ key: String) -> String { - return "\(id)_\(key)" - } -} - diff --git a/lib/core/cache_consts.dart b/lib/core/cache_consts.dart index c1e06aa..fefd45e 100644 --- a/lib/core/cache_consts.dart +++ b/lib/core/cache_consts.dart @@ -79,4 +79,6 @@ class CacheConst { static const String zoomRoomID = 'zoom-room-id'; static String isAppOpenedFromCall = "is_app_opened_from_call"; + + static const String patientQueueNoForLiveActivity = "QUEUENO_FOR_ACTIVITYID"; } diff --git a/lib/core/common_models/patient_queue.dart b/lib/core/common_models/patient_queue.dart index ba53cdc..82b3d3d 100644 --- a/lib/core/common_models/patient_queue.dart +++ b/lib/core/common_models/patient_queue.dart @@ -2,12 +2,16 @@ 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.queueNo, this.currentlyServingStatus, this.nextTicketStatus, this.callType, this.currentlyServingTitle,this.currentlyServingCallType, }); + 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. @@ -17,8 +21,10 @@ class PatientQueue { 'currentlyServingStatus': currentlyServingStatus, 'nextTicketStatus': nextTicketStatus, 'callType': callType, - 'currentlyServingTitle': currentlyServingTitle, + 'currentlyServingToken': currentlyServingToken, 'currentlyServingCallType': currentlyServingCallType, + 'yourTicketHeader':yourTicketHeader, + 'currentlyServingTitle':currentlyServingTitle, }; } } \ No newline at end of file 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 0000000..e59f30e --- /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 6bf7ed3..ef57b54 100644 --- a/lib/core/utils/push_notification_handler.dart +++ b/lib/core/utils/push_notification_handler.dart @@ -4,6 +4,7 @@ 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'; @@ -19,10 +20,14 @@ 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/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/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:permission_handler/permission_handler.dart'; import 'package:uuid/uuid.dart'; @@ -44,74 +49,110 @@ Future backgroundMessageHandler(dynamic message) async { } if (message.data['isLiveActivity'] == true || message.data['isLiveActivity'] == "true") { try { - print('Before WidgetsFlutterBinding'); // Initialize Firebase await Firebase.initializeApp(); WidgetsFlutterBinding.ensureInitialized(); DartPluginRegistrant.ensureInitialized(); await Future.delayed(Duration(seconds: 2)); - print('Before addLiveNotification'); addLiveNotification(message, isBackgroundMessage: true); - print('After addLiveNotification'); } catch (e, stackTrace) { - print('Error: $e'); - print('Stack trace: $stackTrace'); } } } -addLiveNotification(dynamic message, {bool isBackgroundMessage = false}) async{ - print("live activity called"); - // final methodChannel = const MethodChannel('live_activities'); - // methodChannel.invokeMethod('init', { - // 'appGroupId': "", - // 'urlScheme': "", - // }); - // print("After addLiveNotification local init run"); - var liveActivity = LiveActivities(); +// 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(); - var activityId = await Utils.getStringFromPrefs( message.data['queueNo'] ??""); + 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(message.data['callType']??"1"), message.data['roomNo']); + var buttonText = Utils.getCardButtonText(int.parse(data.data['callType']??"1"), data.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", + 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(message.data['callType']??"1"), - currentlyServingCallType: int.parse(message.data['servingCallType']??"1")); - if((activityId??"") != (message.data['queueNo']??"")){ + 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 = ""; } - print("the activity id is $activityId"); if( activityId == ""){ - String? id = await liveActivity.createActivity( + 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"); + await Utils.saveStringFromPrefs(_patientQueue.queueNo ??"", id??""); + await Utils.saveStringFromPrefs(CacheConst.patientQueueNoForLiveActivity ??"", _patientQueue.queueNo??""); return; } - - await liveActivity.updateActivity( + if(Platform.isIOS) { + await liveActivity.createOrUpdateActivity( activityId, - _patientQueue.toMap(), - ); - - print("the activity is is created or updated"); - + _patientQueue.toMap(), + ); + }else{ + await liveActivity.updateActivity( + activityId, + _patientQueue.toMap(), + ); + } } callPage(String sessionID, String token) async {} _incomingCall(Map data) async { - print('the value of the _incomingCall remote message is $data'); // LandingPage.incomingCallData = IncomingCallData.fromJson(data); // var dataItem = await AppSharedPreferences().getObject('call_data'); @@ -219,7 +260,6 @@ Future openCallPage(BuildContext context) async { // ); // } } catch (err) { - print(err); // await PlatformExceptionAlertDialog( // exception: Exception(err), // ).show(context); @@ -284,7 +324,6 @@ class PushNotificationHandler { // late HmsApiAvailability hmsApiAvailability; final voIPKit = FlutterIOSVoIPKit.instance; - late Timer timeOutTimer; bool isTalking = false; @@ -333,10 +372,8 @@ class PushNotificationHandler { final PermissionStatus status = await Permission.notification.request(); if (status.isGranted) { // Notification permissions granted - print("Notification permissions granted"); } else if (status.isDenied) { // Notification permissions denied - print("Notification permissions not granted"); } else if (status.isPermanentlyDenied) { // // Notification permissions permanently denied, open app settings @@ -344,19 +381,16 @@ class PushNotificationHandler { } if (Platform.isIOS) { voIPKit.getVoIPToken().then((value) { - print("🎈 APNS VOIP KIT TOKEN: $value"); Utils.saveStringFromPrefs(CacheConst.voipToken, value ?? ""); // AppSharedPreferences().setString(APNS_TOKEN, value!); }); voIPKit.onDidUpdatePushToken = (String token) { - print('🎈 example: onDidUpdatePushToken: $token'); }; voIPKit.onDidReceiveIncomingPush = ( Map payload, ) async { - print('🎈 example: onDidReceiveIncomingPush $payload'); // _timeOut(); }; @@ -365,7 +399,6 @@ class PushNotificationHandler { String callerId, ) async { try { - print('🎈 example: onDidRejectIncomingCall $uuid - $callerId'); timeOutTimer.cancel(); } catch (err) {} }; @@ -374,7 +407,6 @@ class PushNotificationHandler { String uuid, String callerId, ) async { - print('🎈 example: onDidAcceptIncomingCall $uuid - $callerId'); await voIPKit.acceptIncomingCall(callerState: CallStateType.calling); await voIPKit.callConnected(); await Future.delayed(Duration(seconds: 2)).then((val) async { @@ -394,6 +426,7 @@ class PushNotificationHandler { // timeOutTimer.cancel(); }; } + try { final fcmToken = await FirebaseMessaging.instance.getToken().catchError((err) { print(err); @@ -458,7 +491,6 @@ class PushNotificationHandler { }); FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async { - print("Firebase onMessageOpenedApp!!!"); if (Platform.isIOS) { await Future.delayed(Duration(milliseconds: 3000)).then((value) { newMessage(message); @@ -472,7 +504,6 @@ class PushNotificationHandler { print("Push Notification getToken: ${token!}"); onToken(token!); }).catchError((err) { - print(err); }); FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) { @@ -492,7 +523,6 @@ class PushNotificationHandler { } newMessage(RemoteMessage remoteMessage) async { - print("Remote Message 1: ${remoteMessage.data}"); if (remoteMessage.data.isEmpty) { return; } @@ -541,7 +571,6 @@ class PushNotificationHandler { } onToken(String token) async { - print("Push Notification Token: $token"); await Utils.saveStringFromPrefs(CacheConst.pushToken, token); } @@ -563,8 +592,6 @@ class PushNotificationHandler { // Permission.audio, // Permission.microphone, ].request(); - print("=-=-=-=-=-=-=-=-=-=-"); - print(statuses[Permission.notification]); } } catch (_) { debugPrint(_.toString()); diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index ea0bcb8..97721a6 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -876,5 +876,9 @@ 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'; } diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 60b3192..d3a8960 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -643,7 +643,7 @@ class _LandingPageState extends State { }), SizedBox(height: 16.h), Container( - height: 250.h, + height: 121.h, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), child: Column( children: [ diff --git a/lib/presentation/home/widgets/small_service_card.dart b/lib/presentation/home/widgets/small_service_card.dart index ffc5ed1..88365c6 100644 --- a/lib/presentation/home/widgets/small_service_card.dart +++ b/lib/presentation/home/widgets/small_service_card.dart @@ -1,10 +1,13 @@ +import 'dart:io'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/utils/live_activty_helper_channel.dart'; +import 'package:hmg_patient_app_new/core/utils/push_notification_handler.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'; import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart'; -import 'package:hmg_patient_app_new/features/hospital/hospital_selection_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.dart'; import 'package:hmg_patient_app_new/presentation/emergency_services/emergency_services_page.dart'; @@ -12,17 +15,13 @@ import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.d import 'package:hmg_patient_app_new/presentation/lab/lab_orders_page.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/patient_sickleaves_list_page.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescriptions_list_page.dart'; -import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; -import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; -import 'package:live_activities/live_activities.dart' show LiveActivities; +import 'package:live_activities/live_activities.dart'; import 'package:provider/provider.dart'; -import '../../../core/common_models/patient_queue.dart' show PatientQueue; -import '../../../core/dependencies.dart'; +import '../../../core/common_models/patient_queue.dart'; import '../../../core/utils/utils.dart'; import '../../../theme/colors.dart'; -import '../../emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart'; import '../../radiology/radiology_orders_page.dart' show RadiologyOrdersPage; class SmallServiceCard extends StatelessWidget { @@ -69,29 +68,14 @@ class SmallServiceCard extends StatelessWidget { ), ), ), - ).onPress(() async { + ).onPress(() { switch (serviceName) { case "lab_results": - { - LiveActivities().init(appGroupId: "group.alhabib.patientApp"); - PatientQueue _patientQueue = PatientQueue( - queueNo: "IME-1", - currentlyServingStatus: "Call for vital signs".needTranslation , - currentlyServingTitle:"IME-3", - nextTicketStatus: "dsds", - callType: 1, - currentlyServingCallType: 1); - - var activity = await LiveActivities().createActivity( - DateTime.now().millisecondsSinceEpoch.toString(), - _patientQueue.toMap(), - ); - } - // Navigator.of(context).push( - // CustomPageRoute( - // page: LabOrdersPage(), - // ), - // ); + Navigator.of(context).push( + CustomPageRoute( + page: LabOrdersPage(), + ), + ); break; case "radiology_results": Navigator.of(context).push( @@ -131,30 +115,15 @@ class SmallServiceCard extends StatelessWidget { ); break; case "emergency": - // context.read().flushData(); - // context.read().getTransportationOrders(showLoader: false,); - // context.read().getRRTOrders(showLoader: false,); - // Navigator.of(context).push( - // CustomPageRoute( - // page: EmergencyServicesPage(), - // settings: const RouteSettings(name: '/EmergencyServicesPage'), - // ), - // ); - { - LiveActivities().init(appGroupId: "group.alhabib.patientApp"); - PatientQueue _patientQueue = PatientQueue( - queueNo: "IME-1", - currentlyServingStatus: "Call for vital signs".needTranslation , - currentlyServingTitle:"IME-3", - nextTicketStatus: "dsds", - callType: 1, - currentlyServingCallType: 1); - - var activity = await LiveActivities().createActivity( - DateTime.now().millisecondsSinceEpoch.toString(), - _patientQueue.toMap(), + context.read().flushData(); + context.read().getTransportationOrders(showLoader: false,); + context.read().getRRTOrders(showLoader: false,); + Navigator.of(context).push( + CustomPageRoute( + page: EmergencyServicesPage(), + settings: const RouteSettings(name: '/EmergencyServicesPage'), + ), ); - } break; default: // Handle unknown service @@ -162,41 +131,4 @@ class SmallServiceCard extends StatelessWidget { } }); } - - void openIndoorNavigationBottomSheet(BuildContext context) { - showCommonBottomSheetWithoutHeight( - title: LocaleKeys.selectHospital.tr(), - context, - child: ChangeNotifierProvider( - create: (context) => HospitalSelectionBottomSheetViewModel(getIt()), - child: Consumer( - builder: (_, vm, __) => HospitalBottomSheetBody( - searchText: vm.searchController, - displayList: vm.displayList, - onFacilityClicked: (value) { - vm.setSelectedFacility(value); - vm.getDisplayList(); - }, - onHospitalClicked: (hospital) { - Navigator.pop(context); - vm.openPenguin(hospital); - }, - onHospitalSearch: (value) { - vm.searchHospitals(value ?? ""); - }, - selectedFacility: vm.selectedFacility, - hmcCount: vm.hmcCount, - hmgCount: vm.hmgCount, - ), - ), - ), - isFullScreen: false, - isCloseButtonVisible: true, - hasBottomPadding: false, - backgroundColor: AppColors.bottomSheetBgColor, - callBackFunc: () { - context.read().clearSearchText(); - }, - ); - } }