Files
divkit/client/ios/DivKit/DivAccessibilityElementsStorage.swift
feldspar 15a98c3f01 Added a11y voiceover support to modal tooltips
commit_hash:17faddeccb1cf2cf3464e14850d9d83eb9645e8e
2025-02-20 15:12:58 +03:00

84 lines
1.9 KiB
Swift

import VGSL
final class DivAccessibilityElementsStorage {
private var ids = [String]()
private var idToForwardId = [String: String]()
func put(id: String, nextId: String) {
ids.append(id)
idToForwardId[id] = nextId
}
func getOrderedIds() -> [String] {
var orderedIds = [String]()
var idsSet = Set<String>()
for elementId in ids {
if idsSet.contains(elementId) {
continue
}
var nodeId = elementId
while !idsSet.contains(nodeId) {
orderedIds.append(nodeId)
idsSet.insert(nodeId)
if let nextNodeId = idToForwardId[nodeId] {
nodeId = nextNodeId
}
}
}
return orderedIds
}
#if os(iOS)
func getAccessibilityElements(from view: ViewType) -> [Any]? {
let orderedIds = getOrderedIds()
guard !orderedIds.isEmpty else {
return []
}
var systemElements = [Any]()
if let parentElements = view.superview?.accessibilityElements {
systemElements = parentElements
}
var elements = [Any]()
for id in orderedIds {
if let element = findElement(withID: id, in: view),
let subview = element as? ViewType,
!subview.isHidden,
subview.alpha > 0,
subview.frame != .zero,
subview.isDescendant(of: view) {
elements.append(contentsOf: [element])
systemElements.removeAll {
($0 as? ViewType)?.accessibilityIdentifier == id
}
}
}
elements += systemElements
return elements
}
private func findElement(withID id: String, in view: ViewType) -> Any? {
if view.accessibilityIdentifier == id {
return view
}
for subview in view.subviews {
if let found = findElement(withID: id, in: subview) {
return found
}
}
return nil
}
#else
func getAccessibilityElements(from _: ViewType) -> [Any]? {
nil
}
#endif
}