diff --git a/MVMCoreUI/Atomic/Atoms/Views/Star.swift b/MVMCoreUI/Atomic/Atoms/Views/Star.swift index f2a95b94..7f12d6f4 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Star.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Star.swift @@ -19,12 +19,14 @@ import Foundation return model as? StarModel } public var progressBar = UIProgressView(progressViewStyle: .bar) + public var percent: Int = 0 public var size: CGFloat = 30 { didSet { widthConstraint?.constant = size setNeedsDisplay() } } + public var borderColor: Color = Color(uiColor: .mvmBlack) //-------------------------------------------------- // MARK: - Constraints @@ -82,7 +84,7 @@ import Foundation shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.opacity = 1.0 shapeLayer.lineWidth = 1 - shapeLayer.strokeColor = starModel?.borderColor.cgColor + shapeLayer.strokeColor = borderColor.cgColor return shapeLayer } @@ -98,14 +100,27 @@ import Foundation widthConstraint?.isActive = true heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1) heightConstraint?.isActive = true + isAccessibilityElement = true + updateAccessibilityLabel() } public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? StarModel else { return } progressBar.progress = Float((model.percent) / 100.0) - progressBar.progressTintColor = model.fillColor.uiColor + percent = Int(model.percent) + progressBar.progressTintColor = (model.fillColor != nil) ? model.fillColor?.uiColor : .mvmBlack progressBar.trackTintColor = .mvmWhite + if let border = model.borderColor { + borderColor = border + } size = model.size + updateAccessibilityLabel() + } + + // MARK: - Accessibility + func updateAccessibilityLabel() { + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "star") + accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "star_percent") ?? "", percent) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift index 1d473b86..6ab85a3b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/StarModel.swift @@ -16,8 +16,8 @@ open class StarModel: MoleculeModelProtocol { public static var identifier: String = "star" public var backgroundColor: Color? @Percent public var percent: CGFloat = 0 - public var borderColor: Color = Color(uiColor: .mvmBlack) - public var fillColor: Color = Color(uiColor: .mvmBlack) + public var borderColor: Color? + public var fillColor: Color? public var size: CGFloat = 30.0 //-------------------------------------------------- @@ -42,12 +42,8 @@ open class StarModel: MoleculeModelProtocol { self.percent = percent } backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - if let borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) { - self.borderColor = borderColor - } - if let fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) { - self.fillColor = fillColor - } + borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) + fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) if let size = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .size) { self.size = size } @@ -58,8 +54,8 @@ open class StarModel: MoleculeModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(percent, forKey: .percent) - try container.encode(borderColor, forKey: .borderColor) - try container.encode(fillColor, forKey: .fillColor) + try container.encodeIfPresent(borderColor, forKey: .borderColor) + try container.encodeIfPresent(fillColor, forKey: .fillColor) try container.encode(size, forKey: .size) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Stars.swift b/MVMCoreUI/Atomic/Atoms/Views/Stars.swift index 42224d87..742dc580 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Stars.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Stars.swift @@ -20,6 +20,7 @@ open class Stars: View { private var delegateObject: MVMCoreUIDelegateObject? private let itemSpacing: CGFloat = 3.0 private var heightConstraint: NSLayoutConstraint? + private var starsFilledValue: Float = 0 //-------------------------------------------------- // MARK: - Lifecycle @@ -28,11 +29,16 @@ open class Stars: View { super.setupView() stack.translatesAutoresizingMaskIntoConstraints = false addSubview(stack) - NSLayoutConstraint.pinView(toSuperview: stack, useMargins: true) + NSLayoutConstraint.constraintPinSubview(toSuperview: stack) + let leading = stack.leadingAnchor.constraint(equalTo: self.leadingAnchor) + leading.priority = UILayoutPriority(rawValue: 1000) + leading.isActive = true heightConstraint = heightAnchor.constraint(equalToConstant: 30) heightConstraint?.isActive = true stack.axis = .horizontal stack.spacing = itemSpacing + isAccessibilityElement = true + updateAccessibilityLabel() } @objc override open func updateView(_ size: CGFloat) { @@ -45,6 +51,7 @@ open class Stars: View { self.delegateObject = delegateObject createStar() updateStar() + updateAccessibilityLabel() } //------------------------------------------------------ @@ -57,6 +64,17 @@ open class Stars: View { star.set(with: starModel, delegateObject, nil) stack.addArrangedSubview(star) starElements.append(star) + star.isAccessibilityElement = false + //Star model colors should take priority over stars. + if let borderColor = starsModel.borderColor, starModel.borderColor == nil { + star.borderColor = borderColor + } + if let fillColor = starsModel.fillColor, starModel.fillColor == nil { + star.progressBar.progressTintColor = fillColor.uiColor + } + if let backgroundColor = starsModel.starBackgroundColor, starModel.backgroundColor == nil { + star.backgroundColor = backgroundColor.uiColor + } } heightConstraint?.constant = starsModel.size } @@ -67,6 +85,7 @@ open class Stars: View { if let starsModel = starsModel { let percentRequiredToFillStarFully = CGFloat(100/(starElements.count)) let numberOfFilledStars = Int(starsModel.percent/percentRequiredToFillStarFully) + starsFilledValue = Float(numberOfFilledStars) for (index, star) in starElements.enumerated() { //Fill the stars based on percentage. Ex: if there were 4 stars, 75 percent is 3 full stars if index < numberOfFilledStars { @@ -74,6 +93,7 @@ open class Stars: View { } else if index == numberOfFilledStars { let remainingProgress = (starsModel.percent).truncatingRemainder(dividingBy: percentRequiredToFillStarFully) let fillPercent = remainingProgress/percentRequiredToFillStarFully + starsFilledValue += Float(fillPercent) star.progressBar.progress = Float(fillPercent) } else { star.progressBar.progress = 0 @@ -87,4 +107,9 @@ open class Stars: View { super.reset() stack.subviews.forEach({$0.removeFromSuperview()}) } + + // MARK: - Accessibility + func updateAccessibilityLabel() { + accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "stars_filled") ?? "", starsFilledValue, starElements.count) + } } diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index ee0b1849..f14fe02e 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -87,3 +87,8 @@ "CountDownHours" = " hours"; "CountDownMins" = " mins"; "CountDownSecs" = " secs"; + +// MARK: Star +"star" = "Star"; +"star_percent" = "%d percent progress"; +"stars_filled" = "%.1f out of %d stars"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings index 0a37e1a5..4d14292c 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings @@ -66,3 +66,7 @@ "CountDownHours" = " horas"; "CountDownMins" = " min"; "CountDownSecs" = " seg"; +// Star +"star" = "Estrella"; +"star_percent" = "%@ porcentaje de progreso"; +"stars_filled" = "%.1f de %d estrellas"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings index a64c3915..585e2c1a 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings @@ -70,3 +70,8 @@ "CountDownHours" = " horas"; "CountDownMins" = " min"; "CountDownSecs" = " seg"; + +// Star +"star" = "Estrella"; +"star_percent" = "%@ porcentaje de progreso"; +"stars_filled" = "%.1f de %d estrellas";