From ddf2d7cba92bc55b93e246a49a338622d011f170 Mon Sep 17 00:00:00 2001 From: Ryan Lintott Date: Wed, 17 Apr 2024 14:47:09 -0400 Subject: [PATCH] Fixed movement so destinationIndex works correctly in the code and movement is always reported correctly by VoiceOver. --- .../ILikeToMoveIt/AccessibilityMoveable.swift | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Sources/ILikeToMoveIt/AccessibilityMoveable.swift b/Sources/ILikeToMoveIt/AccessibilityMoveable.swift index 6d9387e..cf993e1 100644 --- a/Sources/ILikeToMoveIt/AccessibilityMoveable.swift +++ b/Sources/ILikeToMoveIt/AccessibilityMoveable.swift @@ -19,6 +19,14 @@ public enum AccessibilityMoveAction: Identifiable, Hashable, Sendable { case toBottom public var id: Self { self } + + /// True if up or isTop + var isMovingUp: Bool { + switch self { + case .up(_), .toTop: true + case .down(_), .toBottom: false + } + } } public extension AccessibilityMoveAction { @@ -170,24 +178,24 @@ struct AccessibilityMoveableListViewModifier: ViewModifier { case let .up(distance): destinationIndex = items.index(itemIndex, offsetBy: -distance) case let .down(distance): - destinationIndex = items.index(itemIndex, offsetBy: distance + 1) + destinationIndex = items.index(itemIndex, offsetBy: distance) case .toTop: destinationIndex = items.startIndex case .toBottom: - destinationIndex = items.endIndex + destinationIndex = items.endIndex - 1 } /// Clamp destination by start and end index - destinationIndex = min(max(items.startIndex, destinationIndex), items.endIndex) + destinationIndex = min(max(items.startIndex, destinationIndex), items.endIndex - 1) let thisItem = item var announcement = [String]() switch (destinationIndex, action) { - case (itemIndex, .up), (itemIndex, .toTop), (itemIndex + 1, .down), (itemIndex + 1, .toBottom): + case (itemIndex, _): announcement.append("Not moved.") case (itemIndex - 1, .up): announcement.append("Moved up.") - case (itemIndex + 2, .down): + case (itemIndex + 1, .down): announcement.append("Moved down.") case (_, .up), (_, .toTop): announcement.append("Moved up by \(itemIndex - destinationIndex).") @@ -197,26 +205,26 @@ struct AccessibilityMoveableListViewModifier: ViewModifier { if let label { switch (destinationIndex, action) { - case (itemIndex, .up), (itemIndex, .toTop), (itemIndex + 1, .down), (itemIndex + 1, .toBottom): + case (itemIndex, _): break case (_, .up), (_, .toTop): announcement.append("Above \(items[destinationIndex][keyPath: label]).") case (_, .down), (_, .toBottom): - announcement.append("Below \(items[destinationIndex - 1][keyPath: label]).") + announcement.append("Below \(items[destinationIndex][keyPath: label]).") } } switch destinationIndex { case items.startIndex: announcement.append("Item at top.") - case items.endIndex: + case items.endIndex - 1: announcement.append("Item at bottom.") default: break } if destinationIndex != itemIndex { - items.move(fromOffsets: [itemIndex], toOffset: destinationIndex) + items.move(fromOffsets: [itemIndex], toOffset: destinationIndex + (action.isMovingUp ? 0 : 1)) /// Even though accessibility focus appears to stay on the moved item, resetting it ensures the index and associated accessibility actions are also updated. accessibilityMoveManager.focus = thisItem }