@@ -14,61 +14,47 @@ class ContactImageUpdater {
1414 private let contactStore = CNContactStore ( )
1515 private let queue = DispatchQueue ( label: " ContactImageUpdaterQueue " )
1616
17- //convert the saved strings to UI Color
18- private var savedBackgroundUIColor : UIColor {
19- switch ObservableUserDefaults . shared. contactBackgroundColor. value {
20- case " red " : return . red
21- case " blue " : return . blue
22- case " cyan " : return . cyan
23- case " green " : return . green
24- case " yellow " : return . yellow
25- case " orange " : return . orange
26- case " purple " : return . purple
27- case " white " : return . white
28- case " black " : return . black
29- default : return . black
30- }
31- }
32-
33- private var savedTextUIColor : UIColor {
34- switch ObservableUserDefaults . shared. contactTextColor. value {
35- case " red " : return . red
36- case " blue " : return . blue
37- case " cyan " : return . cyan
38- case " green " : return . green
39- case " yellow " : return . yellow
40- case " orange " : return . orange
41- case " purple " : return . purple
42- case " white " : return . white
43- case " black " : return . black
44- default : return . white
45- }
46- }
17+ private var savedBackgroundUIColor : UIColor {
18+ let rawValue = Storage . shared. contactBackgroundColor. value
19+ return ContactColorOption ( rawValue: rawValue) ? . uiColor ?? . black
20+ }
4721
48- func updateContactImage( bgValue: String , extra: String , extraTrend: String , extraDelta: String , stale: Bool ) {
49- let contactSuffixes = [ " BG " , " Trend " , " Delta " ]
22+ private var savedTextUIColor : UIColor {
23+ let rawValue = Storage . shared. contactTextColor. value
24+ return ContactColorOption ( rawValue: rawValue) ? . uiColor ?? . white
25+ }
26+
27+ func updateContactImage( bgValue: String , trend: String , delta: String , stale: Bool ) {
5028 queue. async {
5129 guard CNContactStore . authorizationStatus ( for: . contacts) == . authorized else {
52- print ( " Access to contacts is not authorized. " )
30+ LogManager . shared . log ( category : . contact , message : " Access to contacts is not authorized. " )
5331 return
5432 }
55-
33+
5634 let bundleDisplayName = Bundle . main. object ( forInfoDictionaryKey: " CFBundleDisplayName " ) as? String ?? " LoopFollow "
57-
58- for suffix in contactSuffixes {
59- let contactName = " \( bundleDisplayName) - \( suffix) "
60- let contactType = suffix
61- guard let imageData = self . generateContactImage ( bgValue: bgValue, extra: extra, extraTrend: extraTrend, extraDelta: extraDelta, stale: stale, contactType: contactType) ? . pngData ( ) else {
62- print ( " Failed to generate contact image for \( contactName) . " )
35+
36+ for contactType in ContactType . allCases {
37+ if contactType == . Delta && Storage . shared. contactDelta. value != . separate {
6338 continue
6439 }
65-
40+
41+ if contactType == . Trend && Storage . shared. contactTrend. value != . separate {
42+ continue
43+ }
44+
45+ let contactName = " \( bundleDisplayName) - \( contactType. rawValue) "
46+
47+ guard let imageData = self . generateContactImage ( bgValue: bgValue, trend: trend, delta: delta, stale: stale, contactType: contactType) ? . pngData ( ) else {
48+ LogManager . shared. log ( category: . contact, message: " Failed to generate contact image for \( contactName) . " )
49+ continue
50+ }
51+
6652 let predicate = CNContact . predicateForContacts ( matchingName: contactName)
6753 let keysToFetch = [ CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataKey] as [ CNKeyDescriptor ]
68-
54+
6955 do {
7056 let contacts = try self . contactStore. unifiedContacts ( matching: predicate, keysToFetch: keysToFetch)
71-
57+
7258 if let contact = contacts. first, let mutableContact = contact. mutableCopy ( ) as? CNMutableContact {
7359 mutableContact. imageData = imageData
7460 let saveRequest = CNSaveRequest ( )
@@ -85,93 +71,87 @@ class ContactImageUpdater {
8571 print ( " New contact created with updated image for \( contactName) . " )
8672 }
8773 } catch {
88- print ( " Failed to update or create contact for \( contactName) : \( error) " )
74+ LogManager . shared . log ( category : . contact , message : " Failed to update or create contact for \( contactName) : \( error) " )
8975 }
9076 }
9177 }
9278 }
9379
94- private func generateContactImage( bgValue: String , extra : String , extraTrend : String , extraDelta : String , stale: Bool , contactType: String ) -> UIImage ? {
95- let size = CGSize ( width: 300 , height: 300 )
96- UIGraphicsBeginImageContextWithOptions ( size, false , 0 )
97- guard let context = UIGraphicsGetCurrentContext ( ) else { return nil }
80+ private func generateContactImage( bgValue: String , trend : String , delta : String , stale: Bool , contactType: ContactType ) -> UIImage ? {
81+ let size = CGSize ( width: 300 , height: 300 )
82+ UIGraphicsBeginImageContextWithOptions ( size, false , 0 )
83+ guard let context = UIGraphicsGetCurrentContext ( ) else { return nil }
9884
99- savedBackgroundUIColor. setFill ( )
100- context. fill ( CGRect ( origin: . zero, size: size) )
85+ savedBackgroundUIColor. setFill ( )
86+ context. fill ( CGRect ( origin: . zero, size: size) )
10187
102- let paragraphStyle = NSMutableParagraphStyle ( )
103- paragraphStyle. alignment = . center
88+ let paragraphStyle = NSMutableParagraphStyle ( )
89+ paragraphStyle. alignment = . center
10490
105- let maxFontSize : CGFloat = extra. isEmpty ? 200 : 160
106- let fontSize = maxFontSize - CGFloat( bgValue. count * 15 )
107- var bgAttributes : [ NSAttributedString . Key : Any ] = [
108- . font: UIFont . boldSystemFont ( ofSize: fontSize) ,
109- . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
110- . paragraphStyle: paragraphStyle
111- ]
91+ // Format extraDelta based on the user's unit preference
92+ let unitPreference = UserDefaultsRepository . units. value
93+ let yOffset : CGFloat = 48
94+ if contactType == . Trend && Storage . shared. contactTrend. value == . separate {
95+ let trendRect = CGRect ( x: 0 , y: 46 , width: size. width, height: size. height - 80 )
96+ let trendFontSize = max ( 40 , 200 - CGFloat( trend. count * 15 ) )
11297
113- if stale {
114- // Force background color back to black if stale
115- UIColor . black. setFill ( )
116- context. fill ( CGRect ( origin: . zero, size: size) )
117- bgAttributes [ . strikethroughStyle] = NSUnderlineStyle . single. rawValue
118- }
98+ let trendAttributes : [ NSAttributedString . Key : Any ] = [
99+ . font: UIFont . boldSystemFont ( ofSize: trendFontSize) ,
100+ . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
101+ . paragraphStyle: paragraphStyle
102+ ]
119103
120- let extraAttributes : [ NSAttributedString . Key : Any ] = [
121- . font: UIFont . systemFont ( ofSize: 90 ) ,
122- . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
123- . paragraphStyle: paragraphStyle
124- ]
125-
126- let trendFontSize = max ( 40 , 200 - CGFloat( extraTrend. count * 15 ) )
127- let deltaFontSize = max ( 40 , 200 - CGFloat( extraDelta. count * 15 ) )
128-
129- let trendAttributes : [ NSAttributedString . Key : Any ] = [
130- . font: UIFont . boldSystemFont ( ofSize: trendFontSize) ,
131- . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
132- . paragraphStyle: paragraphStyle
133- ]
134-
135- let deltaAttributes : [ NSAttributedString . Key : Any ] = [
136- . font: UIFont . boldSystemFont ( ofSize: deltaFontSize) ,
137- . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
138- . paragraphStyle: paragraphStyle
139- ]
140-
141- // Format extraDelta based on the user's unit preference
142- let unitPreference = UserDefaultsRepository . units. value
143- let formattedExtraDelta : String
144- let yOffset : CGFloat = unitPreference == " mg/dL " ? 46 : 61 // Add 15 if mmol is selected
145- if unitPreference == " mg/dL " {
146- formattedExtraDelta = String ( format: " %.0f " , ( extraDelta as NSString ) . doubleValue)
147- } else {
148- formattedExtraDelta = String ( format: " %.1f " , ( extraDelta as NSString ) . doubleValue)
149- }
150-
151- if contactType == " Trend " && ObservableUserDefaults . shared. contactTrend. value == " Separate " {
152- // Customizing image for Trend contact when value is Separate
153- let trendRect = CGRect ( x: 0 , y: 46 , width: size. width, height: size. height - 80 )
154- extraTrend. draw ( in: trendRect, withAttributes: trendAttributes)
155- } else if contactType == " Delta " && ObservableUserDefaults . shared. contactDelta. value == " Separate " {
156- // Customizing image for Delta contact when value is Separate
157- let deltaRect = CGRect ( x: 0 , y: yOffset, width: size. width, height: size. height - 80 )
158- formattedExtraDelta. draw ( in: deltaRect, withAttributes: deltaAttributes)
159- } else if contactType == " BG " {
160- // Customizing image for BG contact
161- let bgRect = extra. isEmpty
162- ? CGRect ( x: 0 , y: yOffset, width: size. width, height: size. height - 80 )
163- : CGRect ( x: 0 , y: yOffset - 20 , width: size. width, height: size. height / 2 )
164-
165- bgValue. draw ( in: bgRect, withAttributes: bgAttributes)
166-
167- if !extra. isEmpty {
168- let extraRect = CGRect ( x: 0 , y: size. height / 2 + 6 , width: size. width, height: size. height / 2 - 20 )
169- extra. draw ( in: extraRect, withAttributes: extraAttributes)
104+ trend. draw ( in: trendRect, withAttributes: trendAttributes)
105+ } else if contactType == . Delta && Storage . shared. contactDelta. value == . separate {
106+ let deltaRect = CGRect ( x: 0 , y: yOffset, width: size. width, height: size. height - 80 )
107+ let deltaFontSize = max ( 40 , 200 - CGFloat( delta. count * 15 ) )
108+
109+ let deltaAttributes : [ NSAttributedString . Key : Any ] = [
110+ . font: UIFont . boldSystemFont ( ofSize: deltaFontSize) ,
111+ . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
112+ . paragraphStyle: paragraphStyle
113+ ]
114+
115+ delta. draw ( in: deltaRect, withAttributes: deltaAttributes)
116+ } else if contactType == . BG {
117+ let includesExtra = Storage . shared. contactDelta. value == . include || Storage . shared. contactTrend. value == . include
118+
119+ let maxFontSize : CGFloat = includesExtra ? 160 : 200
120+ let fontSize = maxFontSize - CGFloat( bgValue. count * 15 )
121+ var bgAttributes : [ NSAttributedString . Key : Any ] = [
122+ . font: UIFont . boldSystemFont ( ofSize: fontSize) ,
123+ . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
124+ . paragraphStyle: paragraphStyle
125+ ]
126+
127+ if stale {
128+ // Force background color back to black if stale
129+ UIColor . black. setFill ( )
130+ context. fill ( CGRect ( origin: . zero, size: size) )
131+ bgAttributes [ . strikethroughStyle] = NSUnderlineStyle . single. rawValue
132+ }
133+
134+ let bgRect : CGRect = includesExtra
135+ ? CGRect ( x: 0 , y: yOffset - 20 , width: size. width, height: size. height / 2 )
136+ : CGRect ( x: 0 , y: yOffset, width: size. width, height: size. height - 80 )
137+
138+ bgValue. draw ( in: bgRect, withAttributes: bgAttributes)
139+
140+ if includesExtra {
141+ let extraRect = CGRect ( x: 0 , y: size. height / 2 + 6 , width: size. width, height: size. height / 2 - 20 )
142+ let extraAttributes : [ NSAttributedString . Key : Any ] = [
143+ . font: UIFont . systemFont ( ofSize: 90 ) ,
144+ . foregroundColor: stale ? UIColor . gray : savedTextUIColor,
145+ . paragraphStyle: paragraphStyle
146+ ]
147+
148+ let extra = Storage . shared. contactDelta. value == . include ? delta : trend
149+ extra. draw ( in: extraRect, withAttributes: extraAttributes)
150+ }
170151 }
171- }
172152
173- let image = UIGraphicsGetImageFromCurrentImageContext ( )
174- UIGraphicsEndImageContext ( )
175- return image
176- }
153+ let image = UIGraphicsGetImageFromCurrentImageContext ( )
154+ UIGraphicsEndImageContext ( )
155+ return image
156+ }
177157}
0 commit comments