| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883 |
- import Foundation
- import SwiftUI
- struct ContactPicture: View {
- private enum Config {
- static let lag: TimeInterval = 30
- }
- @Binding var contact: ContactTrickEntry
- @Binding var state: ContactTrickState
- private static let formatter: DateFormatter = {
- let formatter = DateFormatter()
- formatter.dateFormat = "HH:mm"
- return formatter
- }()
- static func getImage(
- contact: ContactTrickEntry,
- state: ContactTrickState
- ) -> UIImage {
- let width = 1024.0
- let height = 1024.0
- var rect = CGRect(x: 0, y: 0, width: width, height: height)
- let textColor: Color = contact.hasHighContrast ?
- Color(red: 250 / 256, green: 250 / 256, blue: 250 / 256) :
- Color(red: 20 / 256, green: 20 / 256, blue: 20 / 256)
- let secondaryTextColor: Color = contact.hasHighContrast ?
- Color(red: 220 / 256, green: 220 / 256, blue: 220 / 256) :
- Color(red: 40 / 256, green: 40 / 256, blue: 40 / 256)
- let fontWeight = contact.fontWeight
- UIGraphicsBeginImageContext(rect.size)
- if let context = UIGraphicsGetCurrentContext() {
- context.setShouldAntialias(true)
- context.setAllowsAntialiasing(true)
- }
- let ringWidth = Double(contact.ringWidth.rawValue) / 100.0
- let ringGap = Double(contact.ringGap.rawValue) / 100.0
- let outerGap = 0.03
- if contact.ring != .none {
- rect = CGRect(
- x: rect.minX + width * outerGap,
- y: rect.minY + height * outerGap,
- width: rect.width - width * outerGap * 2,
- height: rect.height - height * outerGap * 2
- )
- let ringRect = CGRect(
- x: rect.minX + width * ringWidth * 0.5,
- y: rect.minY + height * ringWidth * 0.5,
- width: rect.width - width * ringWidth,
- height: rect.height - height * ringWidth
- )
- drawRing(ring: contact.ring, contact: contact, state: state, rect: ringRect, strokeWidth: width * ringWidth)
- rect = CGRect(
- x: rect.minX + width * (ringWidth + ringGap),
- y: rect.minY + height * (ringWidth + ringGap),
- width: rect.width - width * (ringWidth + ringGap) * 2,
- height: rect.height - height * (ringWidth + ringGap) * 2
- )
- }
- switch contact.layout {
- case .single:
- let showTop = contact.top != .none
- let showBottom = contact.bottom != .none
- let centerX = rect.minX + rect.width / 2
- let centerY = rect.minY + rect.height / 2
- let radius = min(rect.width, rect.height) / 2
- var primaryHeight = radius * 0.8
- let topHeight = radius * 0.5
- var bottomHeight = radius * 0.5
- var primaryY = centerY - primaryHeight / 2
- if contact.bottom == .none, contact.top != .none {
- primaryY += radius * 0.2
- }
- if contact.bottom != .none, contact.top == .none {
- primaryY -= radius * 0.2
- }
- let topY = primaryY - topHeight
- var bottomY = primaryY + primaryHeight
- let primaryWidth = 2 * sqrt(radius * radius - (primaryHeight * 0.5) * (primaryHeight * 0.5))
- let topWidth = 2 *
- sqrt(radius * radius - (topHeight + primaryHeight * 0.5) * (topHeight + primaryHeight * 0.5))
- var bottomWidth = 2 *
- sqrt(radius * radius - (bottomHeight + primaryHeight * 0.5) * (bottomHeight + primaryHeight * 0.5))
- if contact.bottom != .none, contact.top == .none {
- // move things around a little bit to give more space to the bottom area
- // TODO: revisit rings for iob, cob and combined iob+cob with more user feedback
- if contact.bottom == .trend, contact.ring == .loop {
- // if contact.ring == .iob || contact.ring == .cob || contact.ring == .iobcob ||
- // (contact.bottom == .trend && contact.ring == .loop)
- // {
- bottomHeight = bottomHeight + height * ringWidth * 2
- bottomWidth = bottomWidth + width * ringWidth * 2
- } else if contact.ring == .loop {
- primaryHeight = primaryHeight - height * ringWidth
- bottomY = primaryY + primaryHeight
- bottomHeight = bottomHeight + height * ringWidth * 2
- bottomWidth = bottomWidth + width * ringWidth * 2
- }
- }
- let primaryRect = (showTop || showBottom) ? CGRect(
- x: centerX - primaryWidth * 0.5,
- y: primaryY,
- width: primaryWidth,
- height: primaryHeight
- ) : rect
- let topRect = CGRect(
- x: centerX - topWidth * 0.5,
- y: topY,
- width: topWidth,
- height: topHeight
- )
- let bottomRect = CGRect(
- x: centerX - bottomWidth * 0.5,
- y: bottomY,
- width: bottomWidth,
- height: bottomHeight
- )
- let secondaryFontSize = contact.secondaryFontSize
- displayPiece(
- value: contact.primary,
- contact: contact,
- state: state,
- rect: primaryRect,
- fitHeigh: false,
- fontSize: contact.fontSize.rawValue,
- fontWeight: fontWeight,
- fontWidth: contact.fontWidth,
- color: textColor
- )
- if showTop {
- displayPiece(
- value: contact.top,
- contact: contact,
- state: state,
- rect: topRect,
- fitHeigh: true,
- fontSize: secondaryFontSize.rawValue,
- fontWeight: fontWeight,
- fontWidth: contact.fontWidth,
- color: secondaryTextColor
- )
- }
- if showBottom {
- displayPiece(
- value: contact.bottom,
- contact: contact,
- state: state,
- rect: bottomRect,
- fitHeigh: true,
- fontSize: secondaryFontSize.rawValue,
- fontWeight: fontWeight,
- fontWidth: contact.fontWidth,
- color: secondaryTextColor
- )
- }
- case .split:
- let centerX = rect.origin.x + rect.size.width / 2
- let centerY = rect.origin.y + rect.size.height / 2
- let radius = min(rect.size.width, rect.size.height) / 2
- let rectangleHeight = radius * sqrt(2) / 2
- let rectangleWidth = sqrt(2) * radius
- let topY = centerY - rectangleHeight
- let bottomY = centerY
- let topRect = CGRect(
- x: centerX - rectangleWidth / 2,
- y: topY,
- width: rectangleWidth,
- height: rectangleHeight
- )
- let bottomRect = CGRect(
- x: centerX - rectangleWidth / 2,
- y: bottomY,
- width: rectangleWidth,
- height: rectangleHeight
- )
- let topFontSize = contact.fontSize
- let bottomFontSize = contact.secondaryFontSize
- displayPiece(
- value: contact.top,
- contact: contact,
- state: state,
- rect: topRect,
- fitHeigh: true,
- fontSize: topFontSize.rawValue,
- fontWeight: fontWeight,
- fontWidth: contact.fontWidth,
- color: textColor
- )
- displayPiece(
- value: contact.bottom,
- contact: contact,
- state: state,
- rect: bottomRect,
- fitHeigh: true,
- fontSize: bottomFontSize.rawValue,
- fontWeight: fontWeight,
- fontWidth: contact.fontWidth,
- color: textColor
- )
- }
- let image = UIGraphicsGetImageFromCurrentImageContext()
- UIGraphicsEndImageContext()
- return image ?? UIImage()
- }
- private static func displayPiece(
- value: ContactTrickValue,
- contact: ContactTrickEntry,
- state: ContactTrickState,
- rect: CGRect,
- fitHeigh: Bool,
- fontSize: Int,
- fontWeight: Font.Weight,
- fontWidth: Font.Width,
- color: Color
- ) {
- guard value != .none else { return }
- if value == .ring {
- drawRing(
- ring: .loop,
- contact: contact,
- state: state,
- rect: CGRect(
- x: rect.minX + rect.width * 0.10,
- y: rect.minY + rect.height * 0.10,
- width: rect.width * 0.80,
- height: rect.height * 0.80
- ),
- strokeWidth: 10.0
- )
- return
- }
- let text: String? = switch value {
- case .glucose: state.glucose
- case .eventualBG: state.eventualBG
- case .delta: state.delta
- case .trend: state.trend
- case .lastLoopDate: state.lastLoopDate.map({ formatter.string(from: $0) })
- case .cob: state.cobText
- case .iob: state.iobText
- default: nil
- }
- let glucoseValue = Decimal(string: state.glucose ?? "100") ?? 100
- let dynamicColor: Color = FreeAPS.getDynamicGlucoseColor(
- glucoseValue: glucoseValue,
- highGlucoseColorValue: state.highGlucoseColorValue,
- lowGlucoseColorValue: state.lowGlucoseColorValue,
- targetGlucose: state.targetGlucose,
- glucoseColorScheme: state.glucoseColorScheme
- )
- let textColor: Color = switch value {
- case .cob:
- .loopYellow
- case .glucose:
- dynamicColor
- default:
- color
- }
- if let text = text {
- drawText(
- text: text,
- rect: rect,
- fitHeigh: fitHeigh,
- fontSize: fontSize,
- fontWeight: fontWeight,
- fontWidth: fontWidth,
- color: textColor
- )
- }
- }
- private static func drawText(
- text: String,
- rect: CGRect,
- fitHeigh: Bool,
- fontSize: Int,
- fontWeight: Font.Weight,
- fontWidth: Font.Width,
- color: Color
- ) {
- var theFontSize = fontSize
- func makeAttributes(_ size: Int) -> [NSAttributedString.Key: Any] {
- let font = UIFont.systemFont(ofSize: CGFloat(size), weight: fontWeight.uiFontWeight)
- return [
- .font: font,
- .foregroundColor: UIColor(color),
- .kern: fontWidth.value * Double(fontSize) // `kern` is the correct key for tracking
- ]
- }
- var attributes: [NSAttributedString.Key: Any] = makeAttributes(theFontSize)
- var stringSize = text.size(withAttributes: attributes)
- while stringSize.width > rect.width * 0.90 || fitHeigh && (stringSize.height > rect.height * 0.95), theFontSize > 50 {
- theFontSize -= 10
- attributes = makeAttributes(theFontSize)
- stringSize = text.size(withAttributes: attributes)
- }
- text.draw(
- in: CGRect(
- x: rect.minX + (rect.width - stringSize.width) / 2,
- y: rect.minY + (rect.height - stringSize.height) / 2,
- width: stringSize.width,
- height: stringSize.height
- ),
- withAttributes: attributes
- )
- }
- private static func drawRing(
- ring: ContactTrickLargeRing,
- contact: ContactTrickEntry,
- state: ContactTrickState,
- rect: CGRect,
- strokeWidth: Double
- ) {
- guard let context = UIGraphicsGetCurrentContext() else {
- return
- }
- switch ring {
- case .loop:
- let color = ringColor(contact: contact, state: state)
- let strokeWidth = strokeWidth
- let center = CGPoint(x: rect.midX, y: rect.midY)
- let radius = min(rect.width, rect.height) / 2 - strokeWidth / 2
- context.setLineWidth(strokeWidth)
- context.setStrokeColor(UIColor(color).cgColor)
- context.addArc(center: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: false)
- context.strokePath()
- // case .iob:
- // if let iob = state.iob, state.maxIOB > 0.1 {
- // drawProgressBar(
- // rect: rect,
- // progress: Double(iob) / Double(state.maxIOB),
- // colors: [contact.hasHighContrast ? .blue : .blue, contact.hasHighContrast ? .pink : .red],
- // strokeWidth: strokeWidth
- // )
- // }
- // case .cob:
- // if let cob = state.cob, state.maxCOB > 0.01 {
- // drawProgressBar(
- // rect: rect,
- // progress: Double(cob) / Double(state.maxCOB),
- // colors: [.loopYellow, .red],
- // strokeWidth: strokeWidth
- // )
- // }
- // case .iobcob:
- // if state.maxIOB > 0.01, state.maxCOB > 0.01 {
- // drawDoubleProgressBar(
- // rect: rect,
- // progress1: state.iob.map { Double($0) / Double(state.maxIOB) },
- // progress2: state.cob.map { Double($0) / Double(state.maxCOB) },
- // colors1: [contact.hasHighContrast ? .blue : .blue, contact.hasHighContrast ? .pink : .red],
- // colors2: [.loopYellow, .red],
- // strokeWidth: strokeWidth
- // )
- // }
- default:
- break
- }
- }
- private static func drawProgressBar(
- rect: CGRect,
- progress: Double,
- colors: [Color],
- strokeWidth: Double
- ) {
- let startAngle: CGFloat = -(.pi + .pi / 4.0)
- let endAngle: CGFloat = .pi / 4.0
- drawGradientArc(
- rect: rect,
- progress: progress,
- colors: colors,
- strokeWidth: strokeWidth,
- startAngle: startAngle,
- endAngle: endAngle,
- gradientDirection: .leftToRight
- )
- }
- private static func drawDoubleProgressBar(
- rect: CGRect,
- progress1: Double?,
- progress2: Double?,
- colors1: [Color],
- colors2: [Color],
- strokeWidth: Double
- ) {
- if let progress1 = progress1 {
- let startAngle1: CGFloat = .pi / 2 + .pi / 5
- let endAngle1: CGFloat = 3 * .pi / 2 - .pi / 5
- drawGradientArc(
- rect: rect,
- progress: progress1,
- colors: colors1,
- strokeWidth: strokeWidth,
- startAngle: startAngle1,
- endAngle: endAngle1,
- gradientDirection: .bottomToTop
- )
- }
- if let progress2 = progress2 {
- let startAngle2: CGFloat = .pi / 2 - .pi / 5
- let endAngle2: CGFloat = -.pi / 2 + .pi / 5
- drawGradientArc(
- rect: rect,
- progress: progress2,
- colors: colors2,
- strokeWidth: strokeWidth,
- startAngle: startAngle2,
- endAngle: endAngle2,
- gradientDirection: .bottomToTop
- )
- }
- }
- private static func drawGradientArc(
- rect: CGRect,
- progress: Double,
- colors: [Color],
- strokeWidth: Double,
- startAngle: Double,
- endAngle: Double,
- gradientDirection: GradientDirection
- ) {
- guard let context = UIGraphicsGetCurrentContext() else {
- return
- }
- let colors = colors.map { c in UIColor(c).cgColor }
- let locations: [CGFloat] = [0.0, 1.0]
- guard let gradient = CGGradient(
- colorsSpace: CGColorSpaceCreateDeviceRGB(),
- colors: colors as CFArray,
- locations: locations
- ) else {
- return
- }
- context.saveGState()
- let center = CGPoint(x: rect.midX, y: rect.midY)
- let radius = min(rect.width, rect.height) / 2 - strokeWidth / 2
- // angle - The angle to the starting point of the arc, measured in radians from the positive x-axis.
- context.setLineWidth(strokeWidth)
- context.setLineCap(.round)
- let circumference = 2 * .pi * radius
- let offsetAngle = (strokeWidth / circumference * 1.1) * 2 * .pi
- let (start, middle, end) = if startAngle > endAngle {
- (
- endAngle,
- startAngle - (startAngle - endAngle) * max(min(progress, 1.0), 0.0),
- startAngle
- )
- } else {
- (
- startAngle,
- startAngle + (endAngle - startAngle) * max(min(progress, 1.0), 0.0),
- endAngle
- )
- }
- if start < middle - offsetAngle {
- let arcPath1 = UIBezierPath()
- arcPath1.addArc(
- withCenter: center,
- radius: radius,
- startAngle: start,
- endAngle: middle - offsetAngle,
- clockwise: true
- )
- context.addPath(arcPath1.cgPath)
- }
- if middle + offsetAngle < end {
- let arcPath2 = UIBezierPath()
- arcPath2.addArc(
- withCenter: center,
- radius: radius,
- startAngle: middle + offsetAngle,
- endAngle: end,
- clockwise: true
- )
- context.addPath(arcPath2.cgPath)
- }
- context.replacePathWithStrokedPath()
- context.clip()
- switch gradientDirection {
- case .bottomToTop:
- context.drawLinearGradient(
- gradient,
- start: CGPoint(x: rect.midX, y: rect.maxY),
- end: CGPoint(x: rect.midX, y: rect.minY),
- options: []
- )
- case .leftToRight:
- context.drawLinearGradient(
- gradient,
- start: CGPoint(x: rect.minX, y: rect.midY),
- end: CGPoint(x: rect.maxX, y: rect.midY),
- options: []
- )
- }
- context.resetClip()
- let circleCenter = CGPoint(
- x: center.x + radius * cos(middle),
- y: center.y + radius * sin(middle)
- )
- context.setLineWidth(strokeWidth * 0.7)
- context.setStrokeColor(UIColor.white.cgColor)
- context.addArc(
- center: circleCenter,
- radius: 0,
- startAngle: 0,
- endAngle: .pi * 2,
- clockwise: true
- )
- context.strokePath()
- context.restoreGState()
- }
- private static func ringColor(
- contact _: ContactTrickEntry,
- state: ContactTrickState
- ) -> Color {
- guard let lastLoopDate = state.lastLoopDate else {
- return .loopGray
- }
- let delta = Date().timeIntervalSince(lastLoopDate) - Config.lag
- if delta <= 5.minutes.timeInterval {
- return .loopGreen
- } else if delta <= 10.minutes.timeInterval {
- return .loopYellow
- } else {
- return .loopRed
- }
- }
- var uiImage: UIImage {
- ContactPicture.getImage(contact: contact, state: state)
- }
- var body: some View {
- Image(uiImage: uiImage)
- .frame(width: 256, height: 256)
- }
- }
- extension Font.Weight {
- var uiFontWeight: UIFont.Weight {
- switch self {
- case .ultraLight: return .ultraLight
- case .thin: return .thin
- case .light: return .light
- case .regular: return .regular
- case .medium: return .medium
- case .semibold: return .semibold
- case .bold: return .bold
- case .heavy: return .heavy
- case .black: return .black
- default: return .regular
- }
- }
- }
- enum GradientDirection: Int {
- case leftToRight
- case bottomToTop
- }
- struct ContactPicturePreview: View {
- @Binding var contact: ContactTrickEntry
- @Binding var state: ContactTrickState
- var body: some View {
- ZStack {
- ContactPicture(contact: $contact, state: $state)
- Circle()
- .stroke(lineWidth: 20)
- .foregroundColor(.white)
- }
- .frame(width: 256, height: 256)
- .clipShape(Circle())
- .preferredColorScheme($contact.wrappedValue.hasHighContrast ? .dark : .light)
- }
- }
- struct ContactPicture_Previews: PreviewProvider {
- struct Preview: View {
- @State var rangeIndicator: Bool = true
- @State var hasHighContrast: Bool = true
- @State var fontSize: ContactTrickEntry.FontSize = .small
- @State var fontWeight: UIFont.Weight = .bold
- @State var fontName: String? = "AmericanTypewriter"
- var body: some View {
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- primary: .glucose,
- top: .delta,
- bottom: .trend,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- glucose: "6.8",
- trend: "↗︎",
- delta: "+0.2",
- cob: 25,
- cobText: "25"
- ))
- ).previewDisplayName("bg + trend + delta")
- // ContactPicturePreview(
- // contact: .constant(
- // ContactTrickEntry(
- // ring: .iob,
- // primary: .glucose,
- // bottom: .trend,
- // fontSize: fontSize,
- // fontWeight: .medium
- // )
- // ),
- // state: .constant(ContactTrickState(
- // glucose: "6.8",
- // trend: "↗︎",
- // iob: 6.1,
- // iobText: "6.1",
- // maxIOB: 8.0
- // ))
- // ).previewDisplayName("bg + trend + iob ring")
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- primary: .glucose,
- top: .ring,
- bottom: .trend,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- glucose: "6.8",
- trend: "↗︎",
- lastLoopDate: .now
- ))
- ).previewDisplayName("bg + trend + ring")
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- ring: .loop,
- primary: .glucose,
- top: .none,
- bottom: .trend,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- glucose: "8.8",
- trend: "→",
- lastLoopDate: .now
- ))
- ).previewDisplayName("bg + trend + ring")
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- ring: .loop,
- primary: .glucose,
- top: .none,
- bottom: .eventualBG,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- glucose: "6.8",
- lastLoopDate: .now - 7.minutes,
- eventualBG: "6.2"
- ))
- ).previewDisplayName("bg + eventual + ring")
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- ring: .loop,
- primary: .lastLoopDate,
- top: .none,
- bottom: .none,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- glucose: "6.8",
- trend: "↗︎",
- lastLoopDate: .now - 2.minutes
- ))
- ).previewDisplayName("lastLoopDate + ring")
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- ring: .loop,
- primary: .glucose,
- top: .none,
- bottom: .none,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- glucose: "6.8",
- lastLoopDate: .now,
- iob: 6.1,
- iobText: "6.1",
- maxIOB: 8.0
- ))
- ).previewDisplayName("bg + ring + ring2")
- ContactPicturePreview(
- contact: .constant(
- ContactTrickEntry(
- layout: .split,
- top: .iob,
- bottom: .cob,
- fontSize: fontSize,
- fontWeight: .medium
- )
- ),
- state: .constant(ContactTrickState(
- iob: 1.5,
- iobText: "1.5",
- cob: 25,
- cobText: "25"
- ))
- ).previewDisplayName("iob + cob")
- // ContactPicturePreview(
- // contact: .constant(
- // ContactTrickEntry(
- // layout: .single,
- // ring: .iobcob,
- // primary: .none,
- // ringWidth: .regular,
- // ringGap: .regular,
- // fontSize: fontSize,
- // fontWeight: .medium
- // )
- // ),
- // state: .constant(ContactTrickState(
- // iob: 1,
- // iobText: "5.5",
- // cob: 25,
- // cobText: "25",
- // maxIOB: 10,
- // maxCOB: 120
- // ))
- // ).previewDisplayName("iobcob ring")
- //
- // ContactPicturePreview(
- // contact: .constant(
- // ContactTrickEntry(
- // layout: .single,
- // ring: .iobcob,
- // primary: .none,
- // fontSize: fontSize,
- // fontWeight: .medium
- // )
- // ),
- // state: .constant(ContactTrickState(
- // iob: -0.2,
- // iobText: "0.0",
- // cob: 0,
- // cobText: "0",
- // maxIOB: 10,
- // maxCOB: 120
- // ))
- // ).previewDisplayName("iobcob ring (0/0)")
- //
- // ContactPicturePreview(
- // contact: .constant(
- // ContactTrickEntry(
- // layout: .single,
- // ring: .iobcob,
- // primary: .none,
- // fontSize: fontSize,
- // fontWeight: .medium
- // )
- // ),
- // state: .constant(ContactTrickState(
- // iob: 10,
- // iobText: "0.0",
- // cob: 120,
- // cobText: "0",
- // maxIOB: 10,
- // maxCOB: 120
- // ))
- // ).previewDisplayName("iobcob ring (max/max)")
- //
- // ContactPicturePreview(
- // contact: .constant(
- // ContactTrickEntry(
- // layout: .single,
- // ring: .iobcob,
- // primary: .glucose,
- // bottom: .trend,
- // fontSize: fontSize,
- // fontWeight: .medium
- // )
- // ),
- // state: .constant(ContactTrickState(
- // glucose: "6.8",
- // trend: "↗︎",
- // iob: 5.5,
- // iobText: "5.5",
- // cob: 25,
- // cobText: "25",
- // maxIOB: 10,
- // maxCOB: 120
- // ))
- // ).previewDisplayName("bg + trend + iobcob ring")
- }
- }
- static var previews: some View {
- Preview()
- }
- }
|