Wd:design updated for the live activity
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="40dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="40"
|
||||
android:viewportHeight="40">
|
||||
<path
|
||||
android:pathData="M8.333,31.667V36.667L31.667,36.667V31.667C31.667,25.223 26.444,20 20,20C13.557,20 8.333,25.223 8.333,31.667Z"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillColor="#9C9C9C"
|
||||
android:fillAlpha="0.4"/>
|
||||
<path
|
||||
android:pathData="M6.667,2.084C5.976,2.084 5.417,2.644 5.417,3.334C5.417,4.024 5.976,4.584 6.667,4.584H7.083L7.083,8.334C7.083,13.481 10.094,17.925 14.449,20.001C10.094,22.077 7.083,26.521 7.083,31.667L7.083,35.417H6.667C5.976,35.417 5.417,35.977 5.417,36.667C5.417,37.358 5.976,37.917 6.667,37.917L33.333,37.917C34.023,37.917 34.583,37.358 34.583,36.667C34.583,35.977 34.023,35.417 33.333,35.417H32.917V31.667C32.917,26.521 29.906,22.077 25.55,20.001C29.906,17.925 32.917,13.481 32.917,8.334V4.584H33.333C34.023,4.584 34.583,4.024 34.583,3.334C34.583,2.644 34.023,2.084 33.333,2.084L6.667,2.084ZM30.417,4.584L9.583,4.584L9.583,8.334C9.583,14.087 14.247,18.751 20,18.751C25.753,18.751 30.417,14.087 30.417,8.334V4.584ZM30.417,35.417V31.667C30.417,25.914 25.753,21.251 20,21.251C14.247,21.251 9.583,25.914 9.583,31.667V35.417L30.417,35.417Z"
|
||||
android:fillColor="#2E3039"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="14dp"
|
||||
android:height="14dp"
|
||||
android:viewportWidth="14"
|
||||
android:viewportHeight="14">
|
||||
<path
|
||||
android:pathData="M5.25,8.895C5.388,8.895 5.518,8.96 5.6,9.07L7,10.937L8.4,9.07C8.483,8.96 8.612,8.895 8.75,8.895C9.278,8.895 9.724,8.895 10.067,8.926C10.421,8.958 10.73,9.026 11.011,9.188C11.343,9.38 11.619,9.656 11.811,9.989C11.973,10.27 12.041,10.579 12.073,10.932C12.104,11.276 12.104,11.701 12.104,12.229V12.833C12.104,13.074 11.908,13.27 11.667,13.27H2.333C2.092,13.27 1.896,13.074 1.896,12.833V12.229C1.896,11.701 1.896,11.276 1.927,10.932C1.959,10.579 2.027,10.27 2.189,9.989C2.381,9.656 2.657,9.38 2.99,9.188C3.27,9.026 3.58,8.958 3.933,8.926C4.276,8.895 4.723,8.895 5.25,8.895Z"
|
||||
android:fillColor="#18C273"/>
|
||||
<path
|
||||
android:pathData="M9.734,4.719L10.316,2.358C10.517,1.539 9.908,0.729 9.055,0.729H4.945C4.092,0.729 3.483,1.539 3.685,2.358L4.266,4.719V5.833C4.266,7.356 5.483,8.604 7,8.604C8.517,8.604 9.734,7.356 9.734,5.833V4.719ZM5.141,5.103H8.859V5.833C8.859,6.886 8.02,7.729 7,7.729C5.98,7.729 5.141,6.886 5.141,5.833V5.103ZM7,1.604C7.242,1.604 7.438,1.799 7.438,2.041V2.478H7.875C8.117,2.478 8.313,2.674 8.313,2.916C8.313,3.158 8.117,3.353 7.875,3.353H7.438V3.791C7.438,4.033 7.242,4.229 7,4.229C6.758,4.229 6.563,4.033 6.563,3.791V3.353H6.125C5.884,3.353 5.688,3.158 5.688,2.916C5.688,2.674 5.884,2.478 6.125,2.478H6.563V2.041C6.563,1.799 6.758,1.604 7,1.604Z"
|
||||
android:fillColor="#18C273"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Background -->
|
||||
<item
|
||||
android:id="@android:id/background">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#E8E8E8" />
|
||||
<corners android:radius="3dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<!-- Progress -->
|
||||
<item
|
||||
android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#18C273" />
|
||||
<corners android:radius="3dp" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#00BFA5" />
|
||||
<size
|
||||
android:width="16dp"
|
||||
android:height="16dp" />
|
||||
<stroke
|
||||
android:color="#FFFFFF"
|
||||
android:width="2dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#FFFFFF" />
|
||||
<corners android:radius="24dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#FFFFFF" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="13"
|
||||
android:viewportHeight="13">
|
||||
<path
|
||||
android:pathData="M6.5,6.5m-5.5,0a5.5,5.5 0,1 1,11 0a5.5,5.5 0,1 1,-11 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#18C273"
|
||||
android:strokeColor="#ffffff"/>
|
||||
</vector>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#1A18C273" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@ -1,116 +1,176 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- 1. Changed root to a RemoteViews-compatible layout like RelativeLayout -->
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/container"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/whitebg_red_border_rounded_corner_widget"
|
||||
android:padding="@dimen/_12sdp">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/nextStep_ll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true">
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
<TextView
|
||||
android:id="@+id/countvalue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/nextStep_ll"
|
||||
android:layout_alignParentStart="true"
|
||||
android:paddingEnd="@dimen/_10sdp"
|
||||
android:text="it is a status"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:textColor="@color/black_text"
|
||||
android:gravity="top"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold" />
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/queue_card_background"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:src="@drawable/hmg" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight=".7"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/queue_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="You queue number"
|
||||
android:textColor="@color/queue_text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="normal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentlyserving_header"
|
||||
<!-- Queue Number: OB-212 -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/queue_number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="OB-212"
|
||||
android:textColor="@color/queue_text_primary"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
<!-- Hourglass Icon -->
|
||||
<ImageView
|
||||
android:id="@+id/hourglass_icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/icon" />
|
||||
</LinearLayout>
|
||||
<!-- Status Message in green box -->
|
||||
<LinearLayout
|
||||
android:id="@+id/status_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Currently Serving:"
|
||||
android:textColor="@color/black_text"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/status_box_background"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
android:layout_below="@id/nextStep_ll"
|
||||
android:layout_alignParentStart="true"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/status_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/profession" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Please got to room no. 5 for vital signs"
|
||||
android:textColor="@color/queue_status_green"
|
||||
android:textSize="10sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/currentlyserving_ll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/currentlyserving_header"
|
||||
android:layout_alignParentStart="true"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="6dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:max="100"
|
||||
android:progress="33"
|
||||
android:progressDrawable="@drawable/progress_bar_drawable" />
|
||||
|
||||
<!-- Bottom Section: Current Serving and Role -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="bottom|center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentlyserving"
|
||||
<!-- Current Serving -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:text="it is a status"
|
||||
android:textColor="@color/black_text"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center_vertical"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
android:gravity="start|center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/serving_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Current Serving"
|
||||
android:textColor="@color/queue_text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/serving_number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="3731"
|
||||
android:textColor="@color/queue_text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Visiting Nurse Badge -->
|
||||
<LinearLayout
|
||||
android:id="@+id/role_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/status_box_background"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="6dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/role_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/profession" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentServingStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:text="Visiting Nurse"
|
||||
android:textColor="@color/queue_status_green"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/red_rounded_corner_widget"
|
||||
android:paddingStart="@dimen/_10sdp"
|
||||
android:paddingTop="@dimen/_4sdp"
|
||||
android:paddingEnd="@dimen/_10sdp"
|
||||
android:paddingBottom="@dimen/_4sdp"
|
||||
android:text="it is a status"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:layout_gravity="end"
|
||||
android:textColor="@color/red_color_text" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextStep"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/currentlyserving_ll"
|
||||
android:layout_alignParentStart="true"
|
||||
android:background="@drawable/red_rounded_corner_widget"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:gravity="bottom"
|
||||
android:layout_marginTop="@dimen/_12sdp"
|
||||
android:paddingStart="@dimen/_10sdp"
|
||||
android:paddingTop="@dimen/_4sdp"
|
||||
android:paddingEnd="@dimen/_10sdp"
|
||||
android:paddingBottom="@dimen/_4sdp"
|
||||
android:text="it is a status" />
|
||||
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
|
||||
@ -1,32 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 1. Changed root to a RemoteViews-compatible layout like RelativeLayout -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/container"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/_12sdp"
|
||||
android:background="@drawable/whitebg_red_border_rounded_corner_widget">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/countvalue_collapsed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@+id/img"
|
||||
android:layout_alignBottom="@+id/img"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="it is a status"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/black_text"
|
||||
android:textSize="@dimen/_14ssp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img"
|
||||
android:layout_width="@dimen/_34sdp"
|
||||
android:layout_height="@dimen/_34sdp"
|
||||
android:src="@drawable/hmg"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
android:background="@drawable/queue_card_background_low_radius">
|
||||
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:padding="8dp"
|
||||
android:gravity="center"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight=".7"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/queue_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="You queue number"
|
||||
android:textColor="@color/queue_text_secondary"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="normal" />
|
||||
|
||||
<!-- Queue Number: OB-212 -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/queue_number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="OB-212"
|
||||
android:textColor="@color/queue_text_primary"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
<!-- Hourglass Icon -->
|
||||
<ImageView
|
||||
android:id="@+id/hourglass_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/icon" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.4" d="M8.3335 31.6667V36.6667L31.6668 36.6667V31.6667C31.6668 25.2233 26.4435 20 20.0002 20C13.5568 20 8.3335 25.2233 8.3335 31.6667Z" fill="#9C9C9C"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.6665 2.08398C5.97615 2.08398 5.4165 2.64363 5.4165 3.33398C5.4165 4.02434 5.97615 4.58398 6.6665 4.58398H7.08317L7.08317 8.33398C7.08317 13.4808 10.0935 17.9246 14.4494 20.0007C10.0935 22.0767 7.08317 26.5205 7.08317 31.6673L7.08317 35.4173H6.6665C5.97615 35.4173 5.4165 35.977 5.4165 36.6673C5.4165 37.3577 5.97615 37.9173 6.6665 37.9173L33.3332 37.9173C34.0235 37.9173 34.5832 37.3577 34.5832 36.6673C34.5832 35.977 34.0235 35.4173 33.3332 35.4173H32.9165V31.6673C32.9165 26.5205 29.9062 22.0767 25.5502 20.0007C29.9062 17.9246 32.9165 13.4808 32.9165 8.33398V4.58398H33.3332C34.0235 4.58398 34.5832 4.02434 34.5832 3.33398C34.5832 2.64363 34.0235 2.08398 33.3332 2.08398L6.6665 2.08398ZM30.4165 4.58398L9.58317 4.58398L9.58317 8.33398C9.58317 14.087 14.2469 18.7507 19.9998 18.7507C25.7528 18.7507 30.4165 14.087 30.4165 8.33398V4.58398ZM30.4165 35.4173V31.6673C30.4165 25.9144 25.7528 21.2507 19.9998 21.2507C14.2469 21.2507 9.58317 25.9143 9.58317 31.6673V35.4173L30.4165 35.4173Z" fill="#2E3039"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="14" height="14" rx="3" fill="#ED1C2B"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,5 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="14" height="14" rx="3" fill="#ED1C2B"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,5 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="14" height="14" rx="3" fill="#ED1C2B"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.25016 8.89518C5.38787 8.89518 5.51754 8.96002 5.60016 9.07018L7.00016 10.9368L8.40016 9.07018C8.48279 8.96002 8.61246 8.89518 8.75016 8.89518C9.27763 8.89518 9.72393 8.89517 10.0671 8.92628C10.4208 8.95833 10.7298 9.02617 11.0106 9.18825C11.3431 9.38025 11.6193 9.65639 11.8113 9.98893C11.9733 10.2697 12.0412 10.5787 12.0732 10.9324C12.1043 11.2756 12.1043 11.701 12.1043 12.2285V12.8327C12.1043 13.0743 11.9085 13.2702 11.6668 13.2702H2.3335C2.09187 13.2702 1.896 13.0743 1.896 12.8327V12.2285C1.89599 11.701 1.89599 11.2756 1.92709 10.9324C1.95915 10.5787 2.02699 10.2697 2.18907 9.98893C2.38106 9.65639 2.6572 9.38025 2.98975 9.18825C3.27048 9.02617 3.57953 8.95833 3.93323 8.92628C4.2764 8.89517 4.72269 8.89518 5.25016 8.89518Z" fill="#18C273"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.73438 4.71896L10.3155 2.3578C10.5171 1.53855 9.90831 0.728516 9.05507 0.728516H4.94519C4.09195 0.728516 3.48316 1.53855 3.68478 2.3578L4.26579 4.71859V5.83268C4.26579 7.35644 5.48349 8.60352 7.00009 8.60352C8.51668 8.60352 9.73438 7.35644 9.73438 5.83268V4.71896ZM5.14079 5.10323H8.85938V5.83268C8.85938 6.88626 8.02046 7.72852 7.00009 7.72852C5.97971 7.72852 5.14079 6.88626 5.14079 5.83268V5.10323ZM7.00002 1.60352C7.24164 1.60352 7.43752 1.79939 7.43752 2.04102V2.47837H7.87516C8.11679 2.47837 8.31266 2.67425 8.31266 2.91587C8.31266 3.1575 8.11679 3.35337 7.87516 3.35337H7.43752V3.79102C7.43752 4.03264 7.24164 4.22852 7.00002 4.22852C6.7584 4.22852 6.56252 4.03264 6.56252 3.79102V3.35337H6.12516C5.88354 3.35337 5.68766 3.1575 5.68766 2.91587C5.68766 2.67425 5.88354 2.47837 6.12516 2.47837H6.56252V2.04102C6.56252 1.79939 6.7584 1.60352 7.00002 1.60352Z" fill="#18C273"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widgetkit-extension</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.alhabib.patientApp</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="14" height="14" rx="3" fill="#ED1C2B"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,5 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="14" height="14" rx="3" fill="#ED1C2B"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,5 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="14" height="14" rx="3" fill="#ED1C2B"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
<path d="M2.54806 11.4469C2.54806 11.4469 2.98492 11.4437 3.29241 11.4437L5.6242 11.455C5.90252 11.455 6.13431 11.1634 6.14737 10.7422L6.15002 8.82227C6.15002 8.41291 6.3357 8.09262 6.6236 8.07432L7.33877 8.06869C7.62708 8.08618 7.825 8.4105 7.825 8.81725L7.82316 10.7474C7.83581 11.1685 8.03006 11.4433 8.30981 11.4433L11.4488 11.4518L11.4545 9.07923C11.4545 8.67107 11.2554 8.354 10.9648 8.3353L9.70382 8.32907C9.4249 8.32907 9.20555 8.03893 9.19372 7.6173L9.18882 6.97551C9.20269 6.55449 9.42326 6.26496 9.7028 6.26496L10.9707 6.26858C11.2588 6.25028 11.4465 5.91511 11.4465 5.50755L11.4496 2.5459C11.346 2.71309 11.2043 2.85421 11.0357 2.95807C10.8671 3.06193 10.6763 3.12568 10.4784 3.14426L8.34613 3.14245C8.06843 3.14245 7.83602 3.44083 7.82296 3.86185L7.82296 5.76371C7.8099 6.18393 7.59178 6.4813 7.31285 6.4813L6.66767 6.47647C6.38793 6.47647 6.1643 6.18875 6.15165 5.76974L6.15328 3.84698C6.14063 3.42575 5.91904 3.14326 5.63991 3.14326L2.54562 3.14466L2.54562 5.50997C2.54562 5.91853 2.73925 6.24565 3.02817 6.26455L4.29609 6.25933C4.58277 6.27782 4.78579 6.61481 4.78579 7.02115L4.78192 7.56865C4.78192 7.97701 4.58604 8.30373 4.29793 8.32223L3.02797 8.31921C2.73905 8.33932 2.54541 8.66102 2.54541 9.06938L2.54806 11.4469Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<SimpleEntry> {
|
||||
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<ConfigurationAppIntent> {
|
||||
// // 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)
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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)"
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class LiveActivityHelperChannel {
|
||||
static const MethodChannel _channel = MethodChannel('clear_data');
|
||||
|
||||
static Future<void> removeData() async {
|
||||
try {
|
||||
await _channel.invokeMethod('clearUserDefaultData');
|
||||
} on PlatformException catch (e) {
|
||||
print("Failed to removeData: '${e.message}'.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||