From 40ff8d0a2ad4a400bfa9320937cd3231aa3072d7 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 5 Dec 2022 18:43:32 -0500 Subject: [PATCH] VoiceOver: improve description of gap cell, add actions to specify direction --- .../TimelineGapCollectionViewCell.swift | 32 +++++++++++++++++++ .../Timeline/TimelineViewController.swift | 5 ++- Tusker/TimelineLikeController.swift | 9 ++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Tusker/Screens/Timeline/TimelineGapCollectionViewCell.swift b/Tusker/Screens/Timeline/TimelineGapCollectionViewCell.swift index 4911384337..304a6ff946 100644 --- a/Tusker/Screens/Timeline/TimelineGapCollectionViewCell.swift +++ b/Tusker/Screens/Timeline/TimelineGapCollectionViewCell.swift @@ -15,6 +15,8 @@ class TimelineGapCollectionViewCell: UICollectionViewCell { private let indicator = UIActivityIndicatorView(style: .medium) private let chevronView = AnimatingChevronView() + var fillGap: ((TimelineGapDirection) async -> Void)? + override var isHighlighted: Bool { didSet { backgroundColor = isHighlighted ? .systemFill : .systemGroupedBackground @@ -100,6 +102,36 @@ class TimelineGapCollectionViewCell: UICollectionViewCell { } } + // MARK: Accessibility + + override var isAccessibilityElement: Bool { + get { true } + set {} + } + + override var accessibilityLabel: String? { + get { + "Load \(direction.accessibilityLabel)" + } + set {} + } + + override var accessibilityCustomActions: [UIAccessibilityCustomAction]? { + get { + [TimelineGapDirection.below, .above].map { dir in + UIAccessibilityCustomAction(name: "Load \(dir.accessibilityLabel)") { [unowned self] _ in + Task { + showsIndicator = true + await fillGap?(dir) + showsIndicator = false + } + return true + } + } + } + set {} + } + } private class AnimatingChevronView: UIView { diff --git a/Tusker/Screens/Timeline/TimelineViewController.swift b/Tusker/Screens/Timeline/TimelineViewController.swift index acabb7ac38..030baf3548 100644 --- a/Tusker/Screens/Timeline/TimelineViewController.swift +++ b/Tusker/Screens/Timeline/TimelineViewController.swift @@ -137,8 +137,11 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro } let zeroHeightCell = UICollectionView.CellRegistration { _, _, _ in } - let gapCell = UICollectionView.CellRegistration { cell, indexPath, _ in + let gapCell = UICollectionView.CellRegistration { [unowned self] cell, indexPath, _ in cell.showsIndicator = false + cell.fillGap = { [unowned self] direction in + await self.controller.fillGap(in: direction) + } } let timelineDescriptionCell = UICollectionView.CellRegistration { [unowned self] cell, indexPath, item in guard case .public(let local) = timeline else { diff --git a/Tusker/TimelineLikeController.swift b/Tusker/TimelineLikeController.swift index a29962019e..e8016d9c0b 100644 --- a/Tusker/TimelineLikeController.swift +++ b/Tusker/TimelineLikeController.swift @@ -379,4 +379,13 @@ enum TimelineGapDirection { case below /// Fill in above the gap. I.e., statuses that are immediately older than the status above the gap. case above + + var accessibilityLabel: String { + switch self { + case .below: + return "Newer" + case .above: + return "Older" + } + } }