| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- import ActivityKit
- import SwiftUI
- import WidgetKit
- struct LiveActivity: Widget {
- var body: some WidgetConfiguration {
- ActivityConfiguration(for: LiveActivityAttributes.self) { context in
- LiveActivityView(context: context)
- } dynamicIsland: { context in
- let hasStaticColorScheme = context.state.glucoseColorScheme == "staticColor"
- var glucoseColor: Color {
- let state = context.state
- let detailedState = state.detailedViewState
- let isMgdL = detailedState?.unit == "mg/dL"
- // TODO: workaround for now: set low value to 55, to have dynamic color shades between 55 and user-set low (approx. 70); same for high glucose
- let hardCodedLow = isMgdL ? Decimal(55) : 55.asMmolL
- let hardCodedHigh = isMgdL ? Decimal(220) : 220.asMmolL
- return Color.getDynamicGlucoseColor(
- glucoseValue: Decimal(string: state.bg) ?? 100,
- highGlucoseColorValue: !hasStaticColorScheme ? hardCodedHigh : state.highGlucose,
- lowGlucoseColorValue: !hasStaticColorScheme ? hardCodedLow : state.lowGlucose,
- targetGlucose: isMgdL ? state.target : state.target.asMmolL,
- glucoseColorScheme: state.glucoseColorScheme
- )
- }
- return DynamicIsland {
- DynamicIslandExpandedRegion(.leading) {
- LiveActivityExpandedLeadingView(context: context, glucoseColor: glucoseColor)
- }
- DynamicIslandExpandedRegion(.trailing) {
- LiveActivityExpandedTrailingView(
- context: context,
- glucoseColor: hasStaticColorScheme ? .primary : glucoseColor
- )
- }
- DynamicIslandExpandedRegion(.bottom) {
- LiveActivityExpandedBottomView(context: context)
- }
- DynamicIslandExpandedRegion(.center) {
- LiveActivityExpandedCenterView(context: context)
- }
- } compactLeading: {
- LiveActivityCompactLeadingView(context: context, glucoseColor: glucoseColor)
- } compactTrailing: {
- LiveActivityCompactTrailingView(context: context, glucoseColor: hasStaticColorScheme ? .primary : glucoseColor)
- } minimal: {
- LiveActivityMinimalView(context: context, glucoseColor: glucoseColor)
- }
- .widgetURL(URL(string: "Trio://"))
- .keylineTint(glucoseColor)
- .contentMargins(.horizontal, 0, for: .minimal)
- .contentMargins(.trailing, 0, for: .compactLeading)
- .contentMargins(.leading, 0, for: .compactTrailing)
- }
- }
- }
- // Mock structure to replace GlucoseData
- struct MockGlucoseData {
- var glucose: Int
- var date: Date
- var direction: String? // You can refine this based on your expected data
- }
- private extension LiveActivityAttributes {
- static var preview: LiveActivityAttributes {
- LiveActivityAttributes(startDate: Date())
- }
- }
- private extension LiveActivityAttributes.ContentState {
- static var chartData: [MockGlucoseData] = [
- MockGlucoseData(glucose: 120, date: Date().addingTimeInterval(-600), direction: "flat"),
- MockGlucoseData(glucose: 125, date: Date().addingTimeInterval(-300), direction: "flat"),
- MockGlucoseData(glucose: 130, date: Date(), direction: "flat")
- ]
- static var detailedViewState = LiveActivityAttributes.ContentAdditionalState(
- chart: chartData.map { Decimal($0.glucose) },
- chartDate: chartData.map(\.date),
- rotationDegrees: 0,
- cob: 20,
- iob: 1.5,
- unit: GlucoseUnits.mgdL.rawValue,
- isOverrideActive: false,
- overrideName: "Exercise",
- overrideDate: Date().addingTimeInterval(-3600),
- overrideDuration: 120,
- overrideTarget: 150,
- widgetItems: LiveActivityAttributes.LiveActivityItem.defaultItems
- )
- // 0 is the widest digit. Use this to get an upper bound on text width.
- // Use mmol/l notation with decimal point as well for the same reason, it uses up to 4 characters, while mg/dl uses up to 3
- static var testWide: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00.0",
- direction: "→",
- change: "+0.0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: nil,
- isInitialState: false
- )
- }
- static var testVeryWide: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00.0",
- direction: "↑↑",
- change: "+0.0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: nil,
- isInitialState: false
- )
- }
- static var testSuperWide: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00.0",
- direction: "↑↑↑",
- change: "+0.0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: nil,
- isInitialState: false
- )
- }
- // 2 characters for BG, 1 character for change is the minimum that will be shown
- static var testNarrow: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00",
- direction: "↑",
- change: "+0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: nil,
- isInitialState: false
- )
- }
- static var testMedium: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "000",
- direction: "↗︎",
- change: "+00",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: nil,
- isInitialState: false
- )
- }
- static var testExpired: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "--",
- direction: nil,
- change: "--",
- date: Date().addingTimeInterval(-60 * 60),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: nil,
- isInitialState: false
- )
- }
- static var testWideDetailed: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00.0",
- direction: "→",
- change: "+0.0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: detailedViewState,
- isInitialState: false
- )
- }
- static var testVeryWideDetailed: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00.0",
- direction: "↑↑",
- change: "+0.0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: detailedViewState,
- isInitialState: false
- )
- }
- static var testSuperWideDetailed: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00.0",
- direction: "↑↑↑",
- change: "+0.0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: detailedViewState,
- isInitialState: false
- )
- }
- // 2 characters for BG, 1 character for change is the minimum that will be shown
- static var testNarrowDetailed: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "00",
- direction: "↑",
- change: "+0",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: detailedViewState,
- isInitialState: false
- )
- }
- static var testMediumDetailed: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "000",
- direction: "↗︎",
- change: "+00",
- date: Date(),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: detailedViewState,
- isInitialState: false
- )
- }
- static var testExpiredDetailed: LiveActivityAttributes.ContentState {
- LiveActivityAttributes.ContentState(
- bg: "--",
- direction: nil,
- change: "--",
- date: Date().addingTimeInterval(-60 * 60),
- highGlucose: 180,
- lowGlucose: 70,
- target: 100,
- glucoseColorScheme: "staticColor",
- detailedViewState: detailedViewState,
- isInitialState: false
- )
- }
- }
- @available(iOS 17.0, iOSApplicationExtension 17.0, *)
- #Preview("Simple", as: .content, using: LiveActivityAttributes.preview) {
- LiveActivity()
- } contentStates: {
- LiveActivityAttributes.ContentState.testSuperWide
- LiveActivityAttributes.ContentState.testVeryWide
- LiveActivityAttributes.ContentState.testWide
- LiveActivityAttributes.ContentState.testMedium
- LiveActivityAttributes.ContentState.testNarrow
- LiveActivityAttributes.ContentState.testExpired
- }
- @available(iOS 17.0, iOSApplicationExtension 17.0, *)
- #Preview("Detailed", as: .content, using: LiveActivityAttributes.preview) {
- LiveActivity()
- } contentStates: {
- LiveActivityAttributes.ContentState.testSuperWideDetailed
- LiveActivityAttributes.ContentState.testVeryWideDetailed
- LiveActivityAttributes.ContentState.testWideDetailed
- LiveActivityAttributes.ContentState.testMediumDetailed
- LiveActivityAttributes.ContentState.testNarrowDetailed
- LiveActivityAttributes.ContentState.testExpiredDetailed
- }
|