iOS/Sources/Shared/API/Models/WatchComplication.swift

993 lines
35 KiB
Swift

import Foundation
import ObjectMapper
import RealmSwift
import UIColor_Hex_Swift
import UIKit
#if os(watchOS)
import ClockKit
#endif
public class WatchComplication: Object, ImmutableMappable {
@objc public dynamic var identifier: String = UUID().uuidString
@objc public dynamic var serverIdentifier: String?
@objc private dynamic var rawFamily: String = ""
public var Family: ComplicationGroupMember {
get {
// Current.Log.verbose("GET Family for str '\(rawFamily)'")
if let f = ComplicationGroupMember(rawValue: rawFamily) {
return f
}
return ComplicationGroupMember.modularSmall
}
set {
rawFamily = newValue.rawValue
}
}
@objc private dynamic var rawTemplate: String = ""
public var Template: ComplicationTemplate {
get {
// Current.Log.verbose("GET Template for str '\(rawTemplate)'")
if let t = ComplicationTemplate(rawValue: rawTemplate) {
return t
}
return Family.templates.first!
}
set {
rawTemplate = newValue.rawValue
}
}
@objc public dynamic var Data: [String: Any] {
get {
guard let dictionaryData = complicationData else {
return [String: Any]()
}
do {
let dict = try JSONSerialization.jsonObject(with: dictionaryData) as? [String: Any]
return dict!
} catch {
return [String: Any]()
}
}
set {
do {
let data = try JSONSerialization.data(withJSONObject: newValue)
complicationData = data
} catch {
complicationData = nil
}
}
}
@objc fileprivate dynamic var complicationData: Data?
@objc public dynamic var CreatedAt = Date()
@objc public dynamic var name: String?
public var displayName: String {
name ?? Template.style
}
@objc public dynamic var IsPublic: Bool = true
override public static func primaryKey() -> String? {
"identifier"
}
override public static func ignoredProperties() -> [String] {
["Family", "Template"]
}
override public required init() {
super.init()
}
public required init(map: ObjectMapper.Map) throws {
// this is used for watch<->app syncing
self.CreatedAt = try map.value("CreatedAt", using: DateTransform())
super.init()
self.Template = try map.value("Template")
self.Data = try map.value("Data")
self.Family = try map.value("Family")
self.identifier = try map.value("identifier")
self.name = try map.value("name")
self.IsPublic = try map.value("IsPublic")
self.serverIdentifier = try map.value("serverIdentifier")
}
public func mapping(map: ObjectMapper.Map) {
Template >>> map["Template"]
Data >>> map["Data"]
CreatedAt >>> (map["CreatedAt"], DateTransform())
Family >>> map["Family"]
identifier >>> map["identifier"]
name >>> map["name"]
IsPublic >>> map["IsPublic"]
serverIdentifier >>> map["serverIdentifier"]
}
enum RenderedValueType: Hashable {
case textArea(String)
case gauge
case ring
init?(stringValue: String) {
let values = stringValue.components(separatedBy: ",")
guard values.count >= 1 else {
return nil
}
switch values[0] {
case "textArea" where values.count >= 2:
self = .textArea(values[1])
case "gauge":
self = .gauge
case "ring":
self = .ring
default:
return nil
}
}
var stringValue: String {
switch self {
case let .textArea(value): return "textArea,\(value)"
case .gauge: return "gauge"
case .ring: return "ring"
}
}
}
func renderedValues() -> [RenderedValueType: Any] {
(Data["rendered"] as? [String: Any] ?? [:])
.compactMapKeys(RenderedValueType.init(stringValue:))
}
func updateRawRendered(from response: [String: Any]) {
Data["rendered"] = response
}
func rawRendered() -> [String: String] {
var renders = [RenderedValueType: String]()
if let textAreas = Data["textAreas"] as? [String: [String: Any]], textAreas.isEmpty == false {
let toAdd = textAreas.compactMapValues { $0["text"] as? String }
.filter { $1.containsJinjaTemplate }
.mapKeys { RenderedValueType.textArea($0) }
renders.merge(toAdd, uniquingKeysWith: { a, _ in a })
}
if let gaugeDict = Data["gauge"] as? [String: String],
let gauge = gaugeDict["gauge"], gauge.containsJinjaTemplate {
renders[.gauge] = gauge
}
if let ringDict = Data["ring"] as? [String: String],
let ringValue = ringDict["ring_value"], ringValue.containsJinjaTemplate {
renders[.ring] = ringValue
}
return renders.mapKeys { $0.stringValue }
}
public static func percentileNumber(from value: Any) -> Float? {
switch value {
case let value as String:
// a bit more forgiving than Float(_:)
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
for locale in [
// in HA prior to 0.117 (which returns floats), the return type of a float is a string in templates
// but it's a non-locale-aware string, so we need to parse `0.33` even if the locale expects `0,33`
Locale(identifier: "en_US_POSIX"),
// but since it's free-form text, the user may also have typed `0,33` expecting it to work
Locale.current,
] {
formatter.locale = locale
if let value = formatter.number(from: value)?.floatValue {
return value
}
}
return nil
case let value as Int:
return Float(value)
case let value as Double:
return Float(value)
case let value as Float:
return value
default:
Current.Log.info("unsure how to float-ify \(type(of: value)), trying as a string")
return percentileNumber(from: String(describing: value))
}
}
#if os(watchOS)
public var complicationDescriptor: CLKComplicationDescriptor {
CLKComplicationDescriptor(
identifier: identifier,
displayName: displayName,
supportedFamilies: [
Family.family,
]
)
}
public var textDataProviders: [String: CLKTextProvider] {
var providers = [String: CLKTextProvider]()
if let textAreas = Data["textAreas"] as? [String: [String: Any]] {
let rendered = renderedValues()
for (key, textArea) in textAreas {
let renderedText = rendered[.textArea(key)].flatMap(String.init(describing:))
guard let text = renderedText ?? textArea["text"] as? String else {
Current.Log.warning("TextArea \(key) doesn't have any text!")
continue
}
guard let color = textArea["color"] as? String else {
Current.Log.warning("TextArea \(key) doesn't have a text color!")
continue
}
providers[key] = with(CLKSimpleTextProvider(text: text)) {
$0.tintColor = UIColor(color)
}
}
}
return providers
}
public var iconProvider: CLKImageProvider? {
if let iconDict = Data["icon"] as? [String: String], let iconName = iconDict["icon"],
let iconColor = iconDict["icon_color"], let iconSize = Template.imageSize {
let iconColor = UIColor(iconColor)
let icon = MaterialDesignIcons(named: iconName)
let image = icon.image(ofSize: iconSize, color: iconColor)
let provider = CLKImageProvider(onePieceImage: image)
provider.tintColor = iconColor
return provider
}
return nil
}
public var fullColorImageProvider: CLKFullColorImageProvider? {
if let iconDict = Data["icon"] as? [String: String], let iconName = iconDict["icon"],
let iconColor = iconDict["icon_color"], let iconSize = Template.imageSize {
let icon = MaterialDesignIcons(named: iconName)
let image = icon.image(ofSize: iconSize, color: UIColor(iconColor))
return CLKFullColorImageProvider(fullColorImage: image)
}
return nil
}
public var gaugeProvider: CLKSimpleGaugeProvider? {
guard let info = Data["gauge"] as? [String: String] else {
return nil
}
let fraction: Float
if let renderedFraction = renderedValues()[.gauge], let value = Self.percentileNumber(from: renderedFraction) {
fraction = value
} else if let stringFraction = info["gauge"], let value = Self.percentileNumber(from: stringFraction) {
fraction = value
} else {
fraction = 0
}
let color: UIColor
if let string = info["gauge_color"] {
color = UIColor(string)
} else {
color = .red
}
let style: CLKGaugeProviderStyle
if info["gauge_style"]?.lowercased() == "fill" {
style = .fill
} else {
style = .ring
}
return CLKSimpleGaugeProvider(
style: style,
gaugeColor: color,
fillFraction: fraction
)
}
public typealias RingData = (fraction: Float, style: CLKComplicationRingStyle, color: UIColor)
public var ringData: RingData {
guard let info = Data["ring"] as? [String: String] else {
return (fraction: 0, style: .closed, color: .red)
}
let fraction: Float
if let renderedFraction = renderedValues()[.ring], let value = Self.percentileNumber(from: renderedFraction) {
fraction = value
} else if let stringFraction = info["ring_value"], let value = Self.percentileNumber(from: stringFraction) {
fraction = value
} else {
fraction = 0
}
let color: UIColor
if let string = info["ring_color"] {
color = UIColor(string)
} else {
color = .red
}
let style: CLKComplicationRingStyle
if info["ring_type"]?.lowercased() == "open" {
style = .open
} else {
style = .closed
}
return (fraction: fraction, style: style, color: color)
}
public var column2Alignment: CLKComplicationColumnAlignment {
let alignment: CLKComplicationColumnAlignment
if let info = Data["column2alignment"] as? [String: String], let value = info["column2alignment"] {
alignment = value.lowercased() == "leading" ? .leading : .trailing
} else {
alignment = .leading
}
return alignment
}
// swiftlint:disable:next cyclomatic_complexity
public func CLKComplicationTemplate(family: CLKComplicationFamily) -> CLKComplicationTemplate? {
if Template.groupMember != ComplicationGroupMember(family: family) {
Current.Log.warning("Would have returned template (\(Template)) outside expected family (\(family)")
return nil
}
switch Template {
case .CircularSmallRingImage:
let template = CLKComplicationTemplateCircularSmallRingImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .CircularSmallSimpleImage:
let template = CLKComplicationTemplateCircularSmallSimpleImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
return template
case .CircularSmallStackImage:
let template = CLKComplicationTemplateCircularSmallStackImage()
if let iconProvider {
template.line1ImageProvider = iconProvider
} else {
return nil
}
if let textProvider = textDataProviders["Line2"] {
template.line2TextProvider = textProvider
} else {
return nil
}
return template
case .CircularSmallRingText:
let template = CLKComplicationTemplateCircularSmallRingText()
if let textProvider = textDataProviders["InsideRing"] {
template.textProvider = textProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .CircularSmallSimpleText:
let template = CLKComplicationTemplateCircularSmallSimpleText()
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
return nil
}
return template
case .CircularSmallStackText:
let template = CLKComplicationTemplateCircularSmallStackText()
if let textProvider = textDataProviders["Line1"] {
template.line1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Line2"] {
template.line2TextProvider = textProvider
} else {
return nil
}
return template
case .ExtraLargeRingImage:
let template = CLKComplicationTemplateExtraLargeRingImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .ExtraLargeSimpleImage:
let template = CLKComplicationTemplateExtraLargeSimpleImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
return template
case .ExtraLargeStackImage:
let template = CLKComplicationTemplateExtraLargeStackImage()
if let iconProvider {
template.line1ImageProvider = iconProvider
} else {
return nil
}
if let textProvider = textDataProviders["Line2"] {
template.line2TextProvider = textProvider
} else {
return nil
}
return template
case .ExtraLargeColumnsText:
let template = CLKComplicationTemplateExtraLargeColumnsText()
if let textProvider = textDataProviders["Row1Column1"] {
template.row1Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row1Column2"] {
template.row1Column2TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column1"] {
template.row2Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column2"] {
template.row2Column2TextProvider = textProvider
} else {
return nil
}
template.column2Alignment = column2Alignment
return template
case .ExtraLargeRingText:
let template = CLKComplicationTemplateExtraLargeRingText()
if let textProvider = textDataProviders["InsideRing"] {
template.textProvider = textProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .ExtraLargeSimpleText:
let template = CLKComplicationTemplateExtraLargeSimpleText()
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
return nil
}
return template
case .ExtraLargeStackText:
let template = CLKComplicationTemplateExtraLargeStackText()
if let textProvider = textDataProviders["Line1"] {
template.line1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Line2"] {
template.line2TextProvider = textProvider
} else {
return nil
}
return template
case .ModularSmallRingImage:
let template = CLKComplicationTemplateModularSmallRingImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .ModularSmallSimpleImage:
let template = CLKComplicationTemplateModularSmallSimpleImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
return template
case .ModularSmallStackImage:
let template = CLKComplicationTemplateModularSmallStackImage()
if let iconProvider {
template.line1ImageProvider = iconProvider
} else {
return nil
}
if let textProvider = textDataProviders["Line2"] {
template.line2TextProvider = textProvider
} else {
return nil
}
return template
case .ModularSmallColumnsText:
let template = CLKComplicationTemplateModularSmallColumnsText()
if let textProvider = textDataProviders["Row1Column1"] {
template.row1Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row1Column2"] {
template.row1Column2TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column1"] {
template.row2Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column2"] {
template.row2Column2TextProvider = textProvider
} else {
return nil
}
template.column2Alignment = column2Alignment
return template
case .ModularSmallRingText:
let template = CLKComplicationTemplateModularSmallRingText()
if let textProvider = textDataProviders["InsideRing"] {
template.textProvider = textProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .ModularSmallSimpleText:
let template = CLKComplicationTemplateModularSmallSimpleText()
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
return nil
}
return template
case .ModularSmallStackText:
let template = CLKComplicationTemplateModularSmallStackText()
if let textProvider = textDataProviders["Line1"] {
template.line1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Line2"] {
template.line2TextProvider = textProvider
} else {
return nil
}
return template
case .ModularLargeStandardBody:
let template = CLKComplicationTemplateModularLargeStandardBody()
if let textProvider = textDataProviders["Header"] {
template.headerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Body1"] {
template.body1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Body2"] {
template.body2TextProvider = textProvider
} else {
// optional, allowed to be nil and makes body1 wrap
}
return template
case .ModularLargeTallBody:
let template = CLKComplicationTemplateModularLargeTallBody()
if let textProvider = textDataProviders["Header"] {
template.headerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.bodyTextProvider = textProvider
} else {
return nil
}
return template
case .ModularLargeColumns:
let template = CLKComplicationTemplateModularLargeColumns()
if let textProvider = textDataProviders["Row1Column1"] {
template.row1Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row1Column2"] {
template.row1Column2TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column1"] {
template.row2Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column2"] {
template.row2Column2TextProvider = textProvider
} else {
return nil
}
template.column2Alignment = column2Alignment
return template
case .ModularLargeTable:
let template = CLKComplicationTemplateModularLargeTable()
if let textProvider = textDataProviders["Header"] {
template.headerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row1Column1"] {
template.row1Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row1Column2"] {
template.row1Column2TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column1"] {
template.row2Column1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Row2Column2"] {
template.row2Column2TextProvider = textProvider
} else {
return nil
}
template.column2Alignment = column2Alignment
return template
case .UtilitarianSmallFlat:
let template = CLKComplicationTemplateUtilitarianSmallFlat()
if let iconProvider {
template.imageProvider = iconProvider
} else {
// optional
}
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
return nil
}
return template
case .UtilitarianSmallRingImage:
let template = CLKComplicationTemplateUtilitarianSmallRingImage()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .UtilitarianSmallRingText:
let template = CLKComplicationTemplateUtilitarianSmallRingText()
if let textProvider = textDataProviders["InsideRing"] {
template.textProvider = textProvider
} else {
return nil
}
let ringData = ringData
template.fillFraction = ringData.fraction
template.ringStyle = ringData.style
template.tintColor = ringData.color
return template
case .UtilitarianSmallSquare:
let template = CLKComplicationTemplateUtilitarianSmallSquare()
if let iconProvider {
template.imageProvider = iconProvider
} else {
return nil
}
return template
case .UtilitarianLargeFlat:
let template = CLKComplicationTemplateUtilitarianLargeFlat()
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
return nil
}
if let iconProvider {
template.imageProvider = iconProvider
} else {
// optional
}
return template
case .GraphicCornerCircularImage:
let template = CLKComplicationTemplateGraphicCornerCircularImage()
if let iconProvider = fullColorImageProvider {
template.imageProvider = iconProvider
} else {
return nil
}
return template
case .GraphicCornerGaugeImage:
let template = CLKComplicationTemplateGraphicCornerGaugeImage()
if let iconProvider = fullColorImageProvider {
template.imageProvider = iconProvider
} else {
return nil
}
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Leading"] {
template.leadingTextProvider = textProvider
} else {
// optional
}
if let textProvider = textDataProviders["Trailing"] {
template.trailingTextProvider = textProvider
} else {
// optional
}
return template
case .GraphicCornerGaugeText:
let template = CLKComplicationTemplateGraphicCornerGaugeText()
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Outer"] {
template.outerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Leading"] {
template.leadingTextProvider = textProvider
} else {
// optional
}
if let textProvider = textDataProviders["Trailing"] {
template.trailingTextProvider = textProvider
} else {
// optional
}
return template
case .GraphicCornerStackText:
let template = CLKComplicationTemplateGraphicCornerStackText()
if let textProvider = textDataProviders["Outer"] {
template.outerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Inner"] {
template.innerTextProvider = textProvider
} else {
return nil
}
return template
case .GraphicCornerTextImage:
let template = CLKComplicationTemplateGraphicCornerTextImage()
if let iconProvider = fullColorImageProvider {
template.imageProvider = iconProvider
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
return nil
}
return template
case .GraphicCircularImage:
let template = CLKComplicationTemplateGraphicCircularImage()
if let iconProvider = fullColorImageProvider {
template.imageProvider = iconProvider
} else {
return nil
}
return template
case .GraphicCircularClosedGaugeImage:
let template = CLKComplicationTemplateGraphicCircularClosedGaugeImage()
if let iconProvider = fullColorImageProvider {
template.imageProvider = iconProvider
} else {
return nil
}
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
return template
case .GraphicCircularOpenGaugeImage:
let template = CLKComplicationTemplateGraphicCircularOpenGaugeImage()
if let iconProvider = fullColorImageProvider {
template.bottomImageProvider = iconProvider
} else {
return nil
}
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.centerTextProvider = textProvider
} else {
return nil
}
return template
case .GraphicCircularClosedGaugeText:
let template = CLKComplicationTemplateGraphicCircularClosedGaugeText()
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.centerTextProvider = textProvider
} else {
return nil
}
return template
case .GraphicCircularOpenGaugeSimpleText:
let template = CLKComplicationTemplateGraphicCircularOpenGaugeSimpleText()
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.centerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Bottom"] {
template.bottomTextProvider = textProvider
} else {
return nil
}
return template
case .GraphicCircularOpenGaugeRangeText:
let template = CLKComplicationTemplateGraphicCircularOpenGaugeRangeText()
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.centerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Leading"] {
template.leadingTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Trailing"] {
template.trailingTextProvider = textProvider
} else {
return nil
}
return template
case .GraphicBezelCircularText:
let template = CLKComplicationTemplateGraphicBezelCircularText()
if let iconProvider = fullColorImageProvider {
template.circularTemplate = with(CLKComplicationTemplateGraphicCircularImage()) {
$0.imageProvider = iconProvider
}
} else {
return nil
}
if let textProvider = textDataProviders["Center"] {
template.textProvider = textProvider
} else {
// optional
}
return template
case .GraphicRectangularStandardBody:
let template = CLKComplicationTemplateGraphicRectangularStandardBody()
if let textProvider = textDataProviders["Header"] {
template.headerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Body1"] {
template.body1TextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Body2"] {
template.body2TextProvider = textProvider
} else {
// optional
}
return template
case .GraphicRectangularTextGauge:
let template = CLKComplicationTemplateGraphicRectangularTextGauge()
if let gaugeProvider {
template.gaugeProvider = gaugeProvider
} else {
return nil
}
if let textProvider = textDataProviders["Header"] {
template.headerTextProvider = textProvider
} else {
return nil
}
if let textProvider = textDataProviders["Body1"] {
template.body1TextProvider = textProvider
} else {
return nil
}
return template
case .GraphicRectangularLargeImage:
let template = CLKComplicationTemplateGraphicRectangularLargeImage()
if let iconProvider = fullColorImageProvider {
template.imageProvider = iconProvider
} else {
return nil
}
if let textProvider = textDataProviders["Header"] {
template.textProvider = textProvider
} else {
return nil
}
return template
}
}
#endif
}