diff --git a/CHANGES.rst b/CHANGES.rst index 6ac2fef4f..bf9bfa3ca 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ Changes in 0.9.5 (2019-09-18) Bug fix: * VoiceOver: RoomVC: Fix some missing accessibility labels for buttons (#2722). * VoiceOver: RoomVC: Make VoiceOver focus on the contextual menu when selecting an event (#2721). + * VoiceOver: RoomVC: Do not lose the focus on the timeline when paginating (with 3 fingers) (#2720). Changes in 0.9.4 (2019-09-13) =============================================== diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index a8d4b9fef..974fe125e 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -123,7 +123,7 @@ #import "Riot-Swift.h" -@interface RoomViewController () { @@ -813,6 +813,92 @@ [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; } +#pragma mark - Accessibility + +// Handle scrolling when VoiceOver is on because it does not work well if we let the system do: +// VoiceOver loses the focus on the tableview +- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction +{ + BOOL canScroll = YES; + + // Scroll by one page + CGFloat tableViewHeight = self.bubblesTableView.frame.size.height; + + CGPoint offset = self.bubblesTableView.contentOffset; + switch (direction) + { + case UIAccessibilityScrollDirectionUp: + offset.y -= tableViewHeight; + break; + + case UIAccessibilityScrollDirectionDown: + offset.y += tableViewHeight; + break; + + default: + break; + } + + if (offset.y < 0 && ![self.roomDataSource.timeline canPaginate:MXTimelineDirectionBackwards]) + { + // Can't paginate more. Let's stick on the first item + UIView *focusedView = [self firstCellWithAccessibilityDataInCells:self.bubblesTableView.visibleCells.objectEnumerator]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, focusedView); + canScroll = NO; + } + else if (offset.y > self.bubblesTableView.contentSize.height - tableViewHeight + && ![self.roomDataSource.timeline canPaginate:MXTimelineDirectionForwards]) + { + // Can't paginate more. Let's stick on the last item with accessibility + UIView *focusedView = [self firstCellWithAccessibilityDataInCells:self.bubblesTableView.visibleCells.reverseObjectEnumerator]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, focusedView); + canScroll = NO; + } + else + { + // Disable VoiceOver while scrolling + self.bubblesTableView.accessibilityElementsHidden = YES; + + [self.bubblesTableView setContentOffset:offset animated:NO]; + + NSEnumerator *cells; + if (direction == UIAccessibilityScrollDirectionUp) + { + cells = self.bubblesTableView.visibleCells.objectEnumerator; + } + else + { + cells = self.bubblesTableView.visibleCells.reverseObjectEnumerator; + } + UIView *cell = [self firstCellWithAccessibilityDataInCells:cells]; + + self.bubblesTableView.accessibilityElementsHidden = NO; + + // Force VoiceOver to focus on a visible item + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, cell); + } + + // If we cannot scroll, let VoiceOver indicates the border + return canScroll; +} + +- (UIView*)firstCellWithAccessibilityDataInCells:(NSEnumerator*)cells +{ + UIView *view; + + for (UITableViewCell *cell in cells) + { + if (![cell isKindOfClass:[RoomEmptyBubbleCell class]]) + { + view = cell; + break; + } + } + + return view; +} + + #pragma mark - Override MXKRoomViewController - (void)onMatrixSessionChange