banyaro-ios/Shared/WalkActivityAttributes.swift
rene 500a645bfd Phase 4.A.1: Live Activity + Dynamic Island für laufende Gassi-Tour
Neues Widget-Extension-Target BanYaroGoWidgetExtension:
- Bundle-ID app.banyaro.ios.BanYaroGoWidget
- NSExtensionPointIdentifier = com.apple.widgetkit-extension
- Synced root group + explizite Info.plist + Embed-Phase in App-Target
- Cross-Membership der Shared/WalkActivityAttributes.swift in beiden Targets

Shared/WalkActivityAttributes.swift:
- ActivityAttributes mit startedAt (fix)
- ContentState mit distanceMeters, elapsedSeconds, pointCount, isPaused, isAutoPaused

BanYaroGoWidget/WalkLiveActivity.swift:
- Lock-Screen-View: Pfote-Icon + Status-Pille (Live/Pause/Auto-Pause) +
  Stats-Spalten (Distanz/Dauer/Punkte)
- Dynamic Island compact: Pfote leading, Distanz trailing
- Dynamic Island minimal: nur Pfote
- Dynamic Island expanded: Distanz/Dauer/Status mit Pfote zentriert

WalkActivityController:
- @MainActor Facade um ActivityKit
- start() prüft areActivitiesEnabled, killt orphaned current, request mit Initial-State
- update() async via Task
- end() mit dismissalPolicy.immediate

TrackingView:
- .onChange(of: tracker.isTracking) → Start/End
- persistTicker (5s) → update
- .onChange(of: tracker.isPaused/isAutoPaused) → sofort update für saubere UX

BanYaroGo-Info.plist: NSSupportsLiveActivities = true
2026-05-30 11:35:43 +02:00

38 lines
1.2 KiB
Swift

import Foundation
import ActivityKit
/// Live Activity attributes for a running Gassi-Tour. Lives in `Shared/` and
/// is compiled into both the app target (which starts/updates/ends activities)
/// and the widget extension (which renders the lock screen + Dynamic Island).
struct WalkActivityAttributes: ActivityAttributes {
public typealias ContentState = WalkActivityState
public struct WalkActivityState: Codable, Hashable {
public var distanceMeters: Double
public var elapsedSeconds: Int
public var pointCount: Int
public var isPaused: Bool
public var isAutoPaused: Bool
public init(
distanceMeters: Double,
elapsedSeconds: Int,
pointCount: Int,
isPaused: Bool,
isAutoPaused: Bool
) {
self.distanceMeters = distanceMeters
self.elapsedSeconds = elapsedSeconds
self.pointCount = pointCount
self.isPaused = isPaused
self.isAutoPaused = isAutoPaused
}
}
/// Walk start time fixed for the duration of the activity.
public var startedAt: Date
public init(startedAt: Date) {
self.startedAt = startedAt
}
}