From ca047099a48c7ac11f6f3f16a9b44b41b170d02a Mon Sep 17 00:00:00 2001 From: Rozeri Dilar Date: Wed, 22 Mar 2023 10:52:39 +0300 Subject: [PATCH] Add accessibleType to ActiveLabel Set label as accessible by default. --- ActiveLabel/ActiveLabel.swift | 69 ++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/ActiveLabel/ActiveLabel.swift b/ActiveLabel/ActiveLabel.swift index 073d4532..d6d19002 100644 --- a/ActiveLabel/ActiveLabel.swift +++ b/ActiveLabel/ActiveLabel.swift @@ -9,7 +9,7 @@ import Foundation import UIKit -public protocol ActiveLabelDelegate: class { +public protocol ActiveLabelDelegate: AnyObject { func didSelect(_ text: String, type: ActiveType) } @@ -23,6 +23,8 @@ typealias ElementTuple = (range: NSRange, element: ActiveElement, type: ActiveTy open var enabledTypes: [ActiveType] = [.mention, .hashtag, .url] + open var accessibleType: ActiveType? + open var urlMaximumLength: Int? open var configureLinkAttribute: ConfigureLinkAttribute? @@ -64,6 +66,10 @@ typealias ElementTuple = (range: NSRange, element: ActiveElement, type: ActiveTy didSet { updateTextStorage(parseText: false) } } + public var isAccessibilityEnabled: Bool = true { + didSet { updateAccessibility(isEnabled: isAccessibilityEnabled) } + } + // MARK: - Computed Properties private var hightlightFont: UIFont? { guard let highlightFontName = highlightFontName, let highlightFontSize = highlightFontSize else { return nil } @@ -145,6 +151,11 @@ typealias ElementTuple = (range: NSRange, element: ActiveElement, type: ActiveTy didSet { textContainer.lineBreakMode = lineBreakMode } } + open override func accessibilityActivate() -> Bool { + setAccessibilityElement() + return isAccessibilityEnabled + } + // MARK: - init functions override public init(frame: CGRect) { super.init(frame: frame) @@ -215,22 +226,7 @@ typealias ElementTuple = (range: NSRange, element: ActiveElement, type: ActiveTy selectedElement = nil } case .ended, .regionExited: - guard let selectedElement = selectedElement else { return avoidSuperCall } - - switch selectedElement.element { - case .mention(let userHandle): didTapMention(userHandle) - case .hashtag(let hashtag): didTapHashtag(hashtag) - case .url(let originalURL, _): didTapStringURL(originalURL) - case .custom(let element): didTap(element, for: selectedElement.type) - case .email(let element): didTapStringEmail(element) - } - - let when = DispatchTime.now() + Double(Int64(0.25 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC) - DispatchQueue.main.asyncAfter(deadline: when) { - self.updateAttributesWhenSelected(false) - self.selectedElement = nil - } - avoidSuperCall = true + avoidSuperCall = setSelectedElement(avoidSuperCall: avoidSuperCall) case .cancelled: updateAttributesWhenSelected(false) selectedElement = nil @@ -243,6 +239,38 @@ typealias ElementTuple = (range: NSRange, element: ActiveElement, type: ActiveTy return avoidSuperCall } + @discardableResult + private func setSelectedElement(avoidSuperCall: Bool) -> Bool { + guard let selectedElement = selectedElement else { return avoidSuperCall } + + switch selectedElement.element { + case .mention(let userHandle): didTapMention(userHandle) + case .hashtag(let hashtag): didTapHashtag(hashtag) + case .url(let originalURL, _): didTapStringURL(originalURL) + case .custom(let element): didTap(element, for: selectedElement.type) + case .email(let element): didTapStringEmail(element) + } + + let when = DispatchTime.now() + Double(Int64(0.25 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC) + DispatchQueue.main.asyncAfter(deadline: when) { + self.updateAttributesWhenSelected(false) + self.selectedElement = nil + } + + return true + } + + private func setAccessibilityElement() { + guard isAccessibilityEnabled else { return } + + if let accessibleType = accessibleType { + selectedElement = ElementTuple(range: NSRange(location: 0, length: 0), element: ActiveElement.create(with: accessibleType, text: ""), type: accessibleType) + } else { + selectedElement = activeElements.values.filter{ $0.count>0 }.flatMap{ $0 }.first + } + setSelectedElement(avoidSuperCall: true) + } + // MARK: - private properties fileprivate var _customizing: Bool = true fileprivate var defaultCustomColor: UIColor = .black @@ -300,6 +328,13 @@ typealias ElementTuple = (range: NSRange, element: ActiveElement, type: ActiveTy setNeedsDisplay() } + fileprivate func updateAccessibility(isEnabled: Bool) { + if isEnabled { + isAccessibilityElement = isEnabled + accessibilityTraits = UIAccessibilityTraits.button + } + } + fileprivate func clearActiveElements() { selectedElement = nil for (type, _) in activeElements {