Update: 2026-05-07 15:49:13

This commit is contained in:
Hamza-Ayed
2026-05-07 15:49:13 +03:00
parent 24ae4e2183
commit 3b5f490efc
17 changed files with 889 additions and 6 deletions

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -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
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -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>

View File

@@ -0,0 +1,84 @@
//
// MusadaqLiveActivity.swift
// MusadaqLiveActivity
//
// Created by Hamza Aleghwairyeen on 07/05/2026.
//
import WidgetKit
import SwiftUI
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), emoji: "😀")
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), emoji: "😀")
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, emoji: "😀")
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
// func relevances() async -> WidgetRelevances<Void> {
// // Generate a list containing the contexts this widget is relevant in.
// }
}
struct SimpleEntry: TimelineEntry {
let date: Date
let emoji: String
}
struct MusadaqLiveActivityEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Text("Time:")
Text(entry.date, style: .time)
Text("Emoji:")
Text(entry.emoji)
}
}
}
struct MusadaqLiveActivity: Widget {
let kind: String = "MusadaqLiveActivity"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
if #available(iOS 17.0, *) {
MusadaqLiveActivityEntryView(entry: entry)
.containerBackground(.fill.tertiary, for: .widget)
} else {
MusadaqLiveActivityEntryView(entry: entry)
.padding()
.background()
}
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
#Preview(as: .systemSmall) {
MusadaqLiveActivity()
} timeline: {
SimpleEntry(date: .now, emoji: "😀")
SimpleEntry(date: .now, emoji: "🤩")
}

View File

@@ -0,0 +1,86 @@
//
// MusadaqLiveActivityBundle.swift
// MusadaqLiveActivity
//
// Created by Hamza Aleghwairyeen on 07/05/2026.
//
import WidgetKit
import SwiftUI
import ActivityKit
// 1. Data Model
struct InvoiceBatchAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var current: Int
var total: Int
var isDone: Bool
}
var companyName: String
}
// 2. Bundle
@main
struct MusadaqLiveActivityBundle: WidgetBundle {
var body: some Widget {
MusadaqLiveActivityLiveActivity()
}
}
// 3. Widget
struct MusadaqLiveActivityLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: InvoiceBatchAttributes.self) { context in
// Lock Screen UI
ZStack {
Color(red: 0.043, green: 0.098, blue: 0.161) // #0B1929
HStack(spacing: 12) {
Image(systemName: context.state.isDone
? "checkmark.doc.fill" : "arrow.up.doc.fill")
.foregroundColor(Color(red: 0.831, green: 0.659, blue: 0.263)) // #D4A843
.font(.title2)
VStack(alignment: .leading, spacing: 4) {
Text(context.state.isDone ? "✅ تم الرفع بنجاح" : "مُصادَق — جارٍ الرفع...")
.font(.caption.bold())
.foregroundColor(.white)
ProgressView(
value: Double(context.state.current),
total: Double(context.state.total)
)
.tint(Color(red: 0.831, green: 0.659, blue: 0.263))
Text("\(context.state.current) / \(context.state.total) فاتورة — \(context.attributes.companyName)")
.font(.caption2)
.foregroundColor(.gray)
}
}
.padding()
}
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
Image(systemName: "arrow.up.doc.fill")
.foregroundColor(Color(red: 0.831, green: 0.659, blue: 0.263))
}
DynamicIslandExpandedRegion(.trailing) {
Text("\(context.state.current)/\(context.state.total)")
.font(.caption.bold()).foregroundColor(.white)
}
DynamicIslandExpandedRegion(.bottom) {
ProgressView(value: Double(context.state.current),
total: Double(context.state.total))
.tint(Color(red: 0.831, green: 0.659, blue: 0.263))
}
} compactLeading: {
Image(systemName: "arrow.up.doc.fill")
.foregroundColor(Color(red: 0.831, green: 0.659, blue: 0.263))
.font(.caption)
} compactTrailing: {
Text("\(context.state.current)/\(context.state.total)")
.font(.caption2.bold()).foregroundColor(.white)
} minimal: {
Image(systemName: "arrow.up.doc.fill")
.foregroundColor(Color(red: 0.831, green: 0.659, blue: 0.263))
}
}
}
}

View File

@@ -0,0 +1,54 @@
//
// MusadaqLiveActivityControl.swift
// MusadaqLiveActivity
//
// Created by Hamza Aleghwairyeen on 07/05/2026.
//
import AppIntents
import SwiftUI
import WidgetKit
struct MusadaqLiveActivityControl: ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(
kind: "com.example.musadaqApp.MusadaqLiveActivity",
provider: Provider()
) { value in
ControlWidgetToggle(
"Start Timer",
isOn: value,
action: StartTimerIntent()
) { isRunning in
Label(isRunning ? "On" : "Off", systemImage: "timer")
}
}
.displayName("Timer")
.description("A an example control that runs a timer.")
}
}
extension MusadaqLiveActivityControl {
struct Provider: ControlValueProvider {
var previewValue: Bool {
false
}
func currentValue() async throws -> Bool {
let isRunning = true // Check if the timer is running
return isRunning
}
}
}
struct StartTimerIntent: SetValueIntent {
static let title: LocalizedStringResource = "Start a timer"
@Parameter(title: "Timer is running")
var value: Bool
func perform() async throws -> some IntentResult {
// Start / stop the timer based on `value`.
return .result()
}
}

View File

@@ -0,0 +1,80 @@
//
// MusadaqLiveActivityLiveActivity.swift
// MusadaqLiveActivity
//
// Created by Hamza Aleghwairyeen on 07/05/2026.
//
import ActivityKit
import WidgetKit
import SwiftUI
struct MusadaqLiveActivityAttributes: 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
}
struct MusadaqLiveActivityLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: MusadaqLiveActivityAttributes.self) { context in
// Lock screen/banner UI goes here
VStack {
Text("Hello \(context.state.emoji)")
}
.activityBackgroundTint(Color.cyan)
.activitySystemActionForegroundColor(Color.black)
} dynamicIsland: { context in
DynamicIsland {
// Expanded UI goes here. Compose the expanded UI through
// various regions, like leading/trailing/center/bottom
DynamicIslandExpandedRegion(.leading) {
Text("Leading")
}
DynamicIslandExpandedRegion(.trailing) {
Text("Trailing")
}
DynamicIslandExpandedRegion(.bottom) {
Text("Bottom \(context.state.emoji)")
// more content
}
} compactLeading: {
Text("L")
} compactTrailing: {
Text("T \(context.state.emoji)")
} minimal: {
Text(context.state.emoji)
}
.widgetURL(URL(string: "http://www.apple.com"))
.keylineTint(Color.red)
}
}
}
extension MusadaqLiveActivityAttributes {
fileprivate static var preview: MusadaqLiveActivityAttributes {
MusadaqLiveActivityAttributes(name: "World")
}
}
extension MusadaqLiveActivityAttributes.ContentState {
fileprivate static var smiley: MusadaqLiveActivityAttributes.ContentState {
MusadaqLiveActivityAttributes.ContentState(emoji: "😀")
}
fileprivate static var starEyes: MusadaqLiveActivityAttributes.ContentState {
MusadaqLiveActivityAttributes.ContentState(emoji: "🤩")
}
}
#Preview("Notification", as: .content, using: MusadaqLiveActivityAttributes.preview) {
MusadaqLiveActivityLiveActivity()
} contentStates: {
MusadaqLiveActivityAttributes.ContentState.smiley
MusadaqLiveActivityAttributes.ContentState.starEyes
}