react-native-a11y-order 0.8.2 → 0.9.1-rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -152
- package/android/build.gradle +0 -18
- package/android/src/main/java/com/a11yorder/services/focus/A11yFocusDelegate.java +10 -32
- package/android/src/main/java/com/a11yorder/services/order/A11yOrderService.java +70 -65
- package/android/src/main/java/com/a11yorder/services/order/linking/A11yLinkingQueue.java +37 -63
- package/android/src/main/java/com/a11yorder/services/order/linking/A11yOrderLinking.java +11 -14
- package/android/src/main/java/com/a11yorder/services/order/linking/WeakTreeMap.java +53 -31
- package/android/src/main/java/com/a11yorder/utils/A11yHelper.java +39 -59
- package/android/src/main/java/com/a11yorder/utils/ChoreographerUtils.java +7 -12
- package/android/src/main/java/com/a11yorder/utils/FragmentUtils.java +8 -48
- package/android/src/main/java/com/a11yorder/views/A11yIndexView/A11yIndexView.java +1 -1
- package/android/src/main/java/com/a11yorder/views/A11yLockView/A11yLockViewManager.java +5 -0
- package/android/src/main/java/com/a11yorder/views/A11yView/A11yView.java +1 -1
- package/android/src/oldarch/A11yLockViewManagerSpec.java +2 -0
- package/ios/delegates/RNAOViewItemDelegate/RNAOViewItemDelegate.mm +1 -1
- package/ios/extensions/RCTModalHostViewComponentView+RNAOA11yOrder.mm +21 -21
- package/ios/extensions/UIView+RNAOA11yOrder.mm +17 -20
- package/ios/extensions/UIViewController+RNAOA11yOrder.mm +8 -8
- package/ios/helpers/RNAOSwizzleInstall.h +30 -0
- package/ios/services/RNAOA11yItemDelegate/RNAOA11yItemDelegate.h +4 -6
- package/ios/services/RNAOA11yItemDelegate/RNAOA11yItemDelegate.mm +98 -87
- package/ios/services/RNAOA11yOrderLinking/RNAOA11yOrderLinking.h +5 -3
- package/ios/services/RNAOA11yOrderLinking/RNAOA11yOrderLinking.mm +49 -49
- package/ios/services/RNAOA11yRelationship/RNAOA11yRelationship.h +1 -0
- package/ios/services/RNAOA11yRelationship/RNAOA11yRelationship.mm +42 -36
- package/ios/services/RNAOSortedMap/RNAOSortedMap.h +2 -1
- package/ios/services/RNAOSortedMap/RNAOSortedMap.mm +48 -47
- package/ios/views/RNAOA11yLockView/RNAOA11yLockView.h +4 -2
- package/ios/views/RNAOA11yLockView/RNAOA11yLockView.mm +89 -3
- package/ios/views/RNAOA11yLockView/RNAOA11yLockViewManager.mm +3 -0
- package/lib/commonjs/components/A11yLock/A11yBaseLock/A11yBaseLock.js +18 -2
- package/lib/commonjs/components/A11yLock/A11yBaseLock/A11yBaseLock.js.map +1 -1
- package/lib/commonjs/components/A11yLock/A11yFocusTrap/A11yFocusTrap.js +23 -7
- package/lib/commonjs/components/A11yLock/A11yFocusTrap/A11yFocusTrap.js.map +1 -1
- package/lib/commonjs/nativeSpecs/A11yLockNativeComponent.ts +1 -0
- package/lib/module/components/A11yLock/A11yBaseLock/A11yBaseLock.js +17 -2
- package/lib/module/components/A11yLock/A11yBaseLock/A11yBaseLock.js.map +1 -1
- package/lib/module/components/A11yLock/A11yFocusTrap/A11yFocusTrap.js +23 -7
- package/lib/module/components/A11yLock/A11yFocusTrap/A11yFocusTrap.js.map +1 -1
- package/lib/module/nativeSpecs/A11yLockNativeComponent.ts +1 -0
- package/lib/typescript/src/components/A11yLock/A11yBaseLock/A11yBaseLock.d.ts +2 -1
- package/lib/typescript/src/components/A11yLock/A11yBaseLock/A11yBaseLock.d.ts.map +1 -1
- package/lib/typescript/src/components/A11yLock/A11yFocusTrap/A11yFocusTrap.d.ts +1 -1
- package/lib/typescript/src/components/A11yLock/A11yFocusTrap/A11yFocusTrap.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/nativeSpecs/A11yLockNativeComponent.d.ts +1 -0
- package/lib/typescript/src/nativeSpecs/A11yLockNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/types/A11yLock.types.d.ts +1 -0
- package/lib/typescript/src/types/A11yLock.types.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/components/A11yLock/A11yBaseLock/A11yBaseLock.tsx +20 -3
- package/src/components/A11yLock/A11yFocusTrap/A11yFocusTrap.tsx +24 -5
- package/src/nativeSpecs/A11yLockNativeComponent.ts +1 -0
- package/src/types/A11yLock.types.ts +1 -0
- package/lib/commonjs/components/A11yLock/A11yBaseLock/A11yBaseLock.android.js +0 -23
- package/lib/commonjs/components/A11yLock/A11yBaseLock/A11yBaseLock.android.js.map +0 -1
- package/lib/module/components/A11yLock/A11yBaseLock/A11yBaseLock.android.js +0 -18
- package/lib/module/components/A11yLock/A11yBaseLock/A11yBaseLock.android.js.map +0 -1
- package/lib/typescript/src/components/A11yLock/A11yBaseLock/A11yBaseLock.android.d.ts +0 -4
- package/lib/typescript/src/components/A11yLock/A11yBaseLock/A11yBaseLock.android.d.ts.map +0 -1
- package/src/components/A11yLock/A11yBaseLock/A11yBaseLock.android.tsx +0 -16
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
package com.a11yorder.services.order.linking;
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
import android.view.View;
|
|
5
4
|
|
|
6
5
|
import java.util.HashMap;
|
|
7
6
|
import java.util.Map;
|
|
8
7
|
|
|
9
8
|
public class A11yOrderLinking {
|
|
10
|
-
|
|
11
9
|
private static A11yOrderLinking instance;
|
|
12
|
-
private final Map<String, A11yLinkingQueue> relationships;
|
|
10
|
+
private final Map<String, A11yLinkingQueue> relationships = new HashMap<>();
|
|
13
11
|
|
|
14
|
-
private A11yOrderLinking() {
|
|
15
|
-
relationships = new HashMap<>();
|
|
16
|
-
}
|
|
12
|
+
private A11yOrderLinking() {}
|
|
17
13
|
|
|
18
14
|
public static synchronized A11yOrderLinking getInstance() {
|
|
19
15
|
if (instance == null) {
|
|
@@ -21,24 +17,25 @@ public class A11yOrderLinking {
|
|
|
21
17
|
}
|
|
22
18
|
return instance;
|
|
23
19
|
}
|
|
24
|
-
public void addViewRelationship(View view, String key, int position) {
|
|
25
|
-
A11yLinkingQueue queue = relationships.get(key);
|
|
26
20
|
|
|
21
|
+
private A11yLinkingQueue getOrCreateQueue(String key) {
|
|
22
|
+
A11yLinkingQueue queue = relationships.get(key);
|
|
27
23
|
if (queue == null) {
|
|
28
24
|
queue = new A11yLinkingQueue();
|
|
29
25
|
relationships.put(key, queue);
|
|
30
26
|
}
|
|
31
|
-
|
|
32
|
-
queue.addPosition(view, position);
|
|
27
|
+
return queue;
|
|
33
28
|
}
|
|
34
29
|
|
|
30
|
+
public void addViewRelationship(View view, String key, int position) {
|
|
31
|
+
getOrCreateQueue(key).addPosition(view, position);
|
|
32
|
+
}
|
|
35
33
|
|
|
36
|
-
public void removeRelationship(String key, int
|
|
34
|
+
public void removeRelationship(String key, int position) {
|
|
37
35
|
A11yLinkingQueue queue = relationships.get(key);
|
|
38
36
|
if (queue == null) return;
|
|
39
|
-
|
|
40
|
-
queue.
|
|
41
|
-
if(queue.isEmpty()) {
|
|
37
|
+
queue.removeFromOrder(position);
|
|
38
|
+
if (queue.isEmpty()) {
|
|
42
39
|
relationships.remove(key);
|
|
43
40
|
}
|
|
44
41
|
}
|
|
@@ -5,58 +5,80 @@ import android.view.View;
|
|
|
5
5
|
import java.lang.ref.WeakReference;
|
|
6
6
|
import java.util.Map;
|
|
7
7
|
import java.util.NavigableMap;
|
|
8
|
-
import java.util.Set;
|
|
9
8
|
import java.util.TreeMap;
|
|
10
9
|
|
|
11
10
|
public class WeakTreeMap {
|
|
12
|
-
|
|
11
|
+
private final NavigableMap<Integer, WeakReference<View>> viewMap = new TreeMap<>();
|
|
13
12
|
|
|
14
|
-
public
|
|
15
|
-
|
|
16
|
-
return viewRef.getValue().get();
|
|
13
|
+
public void put(int position, View view) {
|
|
14
|
+
viewMap.put(position, new WeakReference<>(view));
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
public View
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return view.getValue().get();
|
|
17
|
+
public View get(int position) {
|
|
18
|
+
WeakReference<View> ref = viewMap.get(position);
|
|
19
|
+
return ref != null ? ref.get() : null;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
public
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
public void remove(int position) {
|
|
23
|
+
viewMap.remove(position);
|
|
24
|
+
// Purge zombie entries left by GC while we're already mutating the map.
|
|
25
|
+
viewMap.values().removeIf(ref -> ref.get() == null);
|
|
29
26
|
}
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Returns the nearest live view at a position strictly greater than {@code position},
|
|
30
|
+
* skipping any GC'd entries along the way.
|
|
31
|
+
*/
|
|
32
|
+
public View getNext(int position) {
|
|
33
|
+
for (WeakReference<View> ref : viewMap.tailMap(position, false).values()) {
|
|
34
|
+
View v = ref.get();
|
|
35
|
+
if (v != null) return v;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Returns the nearest live view at a position strictly less than {@code position},
|
|
42
|
+
* skipping any GC'd entries along the way.
|
|
43
|
+
*/
|
|
44
|
+
public View getPrev(int position) {
|
|
45
|
+
for (WeakReference<View> ref : viewMap.headMap(position, false).descendingMap().values()) {
|
|
46
|
+
View v = ref.get();
|
|
47
|
+
if (v != null) return v;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
39
50
|
}
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
/** Returns the live view with the highest position, skipping any GC'd entries. */
|
|
53
|
+
public View last() {
|
|
54
|
+
for (WeakReference<View> ref : viewMap.descendingMap().values()) {
|
|
55
|
+
View v = ref.get();
|
|
56
|
+
if (v != null) return v;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
43
59
|
}
|
|
44
60
|
|
|
45
|
-
public
|
|
46
|
-
|
|
47
|
-
if(viewRef == null) return null;
|
|
48
|
-
return viewRef.get();
|
|
61
|
+
public boolean containsKey(int position) {
|
|
62
|
+
return viewMap.containsKey(position);
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
/** Returns {@code true} only if there are no live (non-GC'd) views in the map. */
|
|
66
|
+
public boolean isEmpty() {
|
|
67
|
+
for (WeakReference<View> ref : viewMap.values()) {
|
|
68
|
+
if (ref.get() != null) return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
53
71
|
}
|
|
54
72
|
|
|
55
|
-
|
|
56
|
-
|
|
73
|
+
/** Visits every live entry in ascending position order. */
|
|
74
|
+
public void forEachLive(LiveEntryAction action) {
|
|
75
|
+
for (Map.Entry<Integer, WeakReference<View>> entry : viewMap.entrySet()) {
|
|
76
|
+
View v = entry.getValue().get();
|
|
77
|
+
if (v != null) action.run(entry.getKey(), v);
|
|
78
|
+
}
|
|
57
79
|
}
|
|
58
80
|
|
|
59
|
-
public
|
|
60
|
-
|
|
81
|
+
public interface LiveEntryAction {
|
|
82
|
+
void run(int position, View view);
|
|
61
83
|
}
|
|
62
84
|
}
|
|
@@ -6,102 +6,82 @@ import android.view.ViewGroup;
|
|
|
6
6
|
import android.view.accessibility.AccessibilityEvent;
|
|
7
7
|
import android.view.accessibility.AccessibilityManager;
|
|
8
8
|
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
9
10
|
import androidx.annotation.Nullable;
|
|
10
11
|
import androidx.core.view.ViewCompat;
|
|
11
12
|
|
|
12
13
|
public class A11yHelper {
|
|
14
|
+
|
|
13
15
|
public static boolean isAccessible(@Nullable View view) {
|
|
14
16
|
return view != null && ViewCompat.isImportantForAccessibility(view);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
public static
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!ignoreRoot && isAccessible(viewGroup)) {
|
|
23
|
-
return viewGroup;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
|
27
|
-
View child = viewGroup.getChildAt(i);
|
|
28
|
-
if (isAccessible(child)) {
|
|
29
|
-
return child;
|
|
30
|
-
}
|
|
19
|
+
public static boolean isFocused(@Nullable View view) {
|
|
20
|
+
return view != null && view.isAccessibilityFocused();
|
|
21
|
+
}
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
public static void focus(@Nullable View view) {
|
|
24
|
+
if (view == null || isFocused(view)) return;
|
|
25
|
+
ChoreographerUtils.run(() -> {
|
|
26
|
+
if (!isFocused(view)) {
|
|
27
|
+
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
|
37
28
|
}
|
|
38
|
-
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
39
31
|
|
|
40
|
-
|
|
32
|
+
public static boolean isA11yServiceEnabled(@NonNull Context context) {
|
|
33
|
+
AccessibilityManager accessibilityManager =
|
|
34
|
+
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
|
35
|
+
return accessibilityManager != null
|
|
36
|
+
&& accessibilityManager.isEnabled()
|
|
37
|
+
&& accessibilityManager.isTouchExplorationEnabled();
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
public static View findFirstAccessible(@Nullable ViewGroup viewGroup) {
|
|
44
41
|
return findFirstAccessible(viewGroup, false);
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
public static
|
|
48
|
-
if (
|
|
49
|
-
return view.isAccessibilityFocused();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private static void baseFocus(@Nullable View view) {
|
|
53
|
-
if (view != null) {
|
|
54
|
-
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
44
|
+
public static View findFirstAccessible(@Nullable ViewGroup viewGroup, boolean ignoreRoot) {
|
|
45
|
+
if (viewGroup == null) return null;
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
if (view == null || isFocused(view)) return;
|
|
60
|
-
ChoreographerUtils.run(() -> baseFocus(view));
|
|
61
|
-
}
|
|
47
|
+
if (!ignoreRoot && isAccessible(viewGroup)) return viewGroup;
|
|
62
48
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
(
|
|
49
|
+
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
|
50
|
+
View child = viewGroup.getChildAt(i);
|
|
51
|
+
if (isAccessible(child)) return child;
|
|
66
52
|
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
if (child instanceof ViewGroup) {
|
|
54
|
+
View accessibleChild = findFirstAccessible((ViewGroup) child, true);
|
|
55
|
+
if (accessibleChild != null) return accessibleChild;
|
|
56
|
+
}
|
|
69
57
|
}
|
|
70
58
|
|
|
71
|
-
return
|
|
59
|
+
return null;
|
|
72
60
|
}
|
|
73
61
|
|
|
74
|
-
public static View findFirstFocusable(@Nullable ViewGroup viewGroup
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
62
|
+
public static View findFirstFocusable(@Nullable ViewGroup viewGroup) {
|
|
63
|
+
return findFirstFocusable(viewGroup, false);
|
|
64
|
+
}
|
|
78
65
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
private static View findFirstFocusable(@Nullable ViewGroup viewGroup, boolean ignoreRoot) {
|
|
67
|
+
if (viewGroup == null) return null;
|
|
68
|
+
|
|
69
|
+
if (!ignoreRoot && isKeyboardFocusable(viewGroup)) return viewGroup;
|
|
82
70
|
|
|
83
71
|
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
|
84
72
|
View child = viewGroup.getChildAt(i);
|
|
85
|
-
if (isKeyboardFocusable(child))
|
|
86
|
-
return child;
|
|
87
|
-
}
|
|
73
|
+
if (isKeyboardFocusable(child)) return child;
|
|
88
74
|
|
|
89
75
|
if (child instanceof ViewGroup) {
|
|
90
76
|
View focusableChild = findFirstFocusable((ViewGroup) child, true);
|
|
91
|
-
if (focusableChild != null)
|
|
92
|
-
return focusableChild;
|
|
93
|
-
}
|
|
77
|
+
if (focusableChild != null) return focusableChild;
|
|
94
78
|
}
|
|
95
79
|
}
|
|
96
80
|
|
|
97
81
|
return null;
|
|
98
82
|
}
|
|
99
83
|
|
|
100
|
-
|
|
101
|
-
return findFirstFocusable(viewGroup, false);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private static boolean isKeyboardFocusable(View view) {
|
|
84
|
+
private static boolean isKeyboardFocusable(@NonNull View view) {
|
|
105
85
|
return view.isFocusable() && view.getVisibility() == View.VISIBLE && view.isEnabled();
|
|
106
86
|
}
|
|
107
87
|
}
|
|
@@ -1,34 +1,29 @@
|
|
|
1
1
|
package com.a11yorder.utils;
|
|
2
2
|
|
|
3
3
|
import android.view.Choreographer;
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
5
6
|
|
|
6
7
|
public class ChoreographerUtils {
|
|
7
8
|
|
|
8
|
-
public static void run(@
|
|
9
|
+
public static void run(@NonNull Runnable task) {
|
|
9
10
|
runAfterFrames(2, task);
|
|
10
11
|
}
|
|
11
|
-
public static void runAfterFrames(int frameCount, @Nullable Runnable task) {
|
|
12
|
-
if (frameCount <= 0 || task == null) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
12
|
|
|
13
|
+
private static void runAfterFrames(int frameCount, @NonNull Runnable task) {
|
|
16
14
|
Choreographer choreographer = Choreographer.getInstance();
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
choreographer.postFrameCallback(new Choreographer.FrameCallback() {
|
|
19
17
|
private int frameCounter = frameCount;
|
|
20
18
|
|
|
21
19
|
@Override
|
|
22
20
|
public void doFrame(long frameTimeNanos) {
|
|
23
|
-
frameCounter
|
|
24
|
-
if (frameCounter <= 0) {
|
|
21
|
+
if (--frameCounter <= 0) {
|
|
25
22
|
task.run();
|
|
26
23
|
} else {
|
|
27
24
|
choreographer.postFrameCallback(this);
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
choreographer.postFrameCallback(frameCallback);
|
|
27
|
+
});
|
|
33
28
|
}
|
|
34
29
|
}
|
|
@@ -1,68 +1,28 @@
|
|
|
1
1
|
package com.a11yorder.utils;
|
|
2
2
|
|
|
3
|
-
import android.app.Activity;
|
|
4
3
|
import android.view.View;
|
|
5
|
-
import android.view.animation.Animation;
|
|
6
4
|
|
|
7
5
|
import androidx.annotation.NonNull;
|
|
8
6
|
import androidx.annotation.Nullable;
|
|
9
7
|
import androidx.fragment.app.Fragment;
|
|
10
|
-
import androidx.fragment.app.FragmentActivity;
|
|
11
8
|
import androidx.fragment.app.FragmentManager;
|
|
9
|
+
import androidx.lifecycle.DefaultLifecycleObserver;
|
|
10
|
+
import androidx.lifecycle.LifecycleOwner;
|
|
12
11
|
|
|
13
12
|
public class FragmentUtils {
|
|
14
13
|
|
|
15
|
-
public static void
|
|
16
|
-
|
|
14
|
+
public static void waitForFragmentResume(@NonNull Fragment fragment, @NonNull Runnable onReady) {
|
|
15
|
+
fragment.getLifecycle().addObserver(new DefaultLifecycleObserver() {
|
|
17
16
|
@Override
|
|
18
|
-
public void
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@Override
|
|
22
|
-
public void onAnimationEnd(Animation animation) {
|
|
23
|
-
onAnimationEnd.run();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
@Override
|
|
27
|
-
public void onAnimationRepeat(Animation animation) {
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public static void waitForFragmentAnimation (@NonNull Fragment fragment, @NonNull Runnable onReady) {
|
|
33
|
-
View fragmentView = fragment.getView();
|
|
34
|
-
if (fragmentView != null) {
|
|
35
|
-
Animation fragmentAnimation = fragmentView.getAnimation();
|
|
36
|
-
if (fragmentAnimation != null) {
|
|
37
|
-
waitForAnimationEnd(fragmentAnimation, onReady);
|
|
38
|
-
} else {
|
|
17
|
+
public void onResume(@NonNull LifecycleOwner owner) {
|
|
18
|
+
owner.getLifecycle().removeObserver(this);
|
|
39
19
|
onReady.run();
|
|
40
20
|
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
public static void waitForFragment(Activity activity, Fragment current, @NonNull Runnable onReady) {
|
|
45
|
-
if (!(activity instanceof FragmentActivity)) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
FragmentManager fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager();
|
|
50
|
-
fragmentManager.registerFragmentLifecycleCallbacks(
|
|
51
|
-
new FragmentManager.FragmentLifecycleCallbacks() {
|
|
52
|
-
@Override
|
|
53
|
-
public void onFragmentResumed(@NonNull FragmentManager fm, @NonNull Fragment f) {
|
|
54
|
-
super.onFragmentResumed(fm, f);
|
|
55
|
-
if (f == current) {
|
|
56
|
-
waitForFragmentAnimation(f, onReady);
|
|
57
|
-
fragmentManager.unregisterFragmentLifecycleCallbacks(this); // Unregister to prevent future callbacks
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}, false);
|
|
21
|
+
});
|
|
61
22
|
}
|
|
62
23
|
|
|
63
24
|
@Nullable
|
|
64
|
-
public static
|
|
65
|
-
Fragment findFragmentSafely(View view) {
|
|
25
|
+
public static Fragment findFragmentSafely(View view) {
|
|
66
26
|
try {
|
|
67
27
|
return FragmentManager.findFragment(view);
|
|
68
28
|
} catch (Exception ignored) {
|
|
@@ -35,4 +35,9 @@ public class A11yLockViewManager extends com.a11yorder.A11yLockViewManagerSpec<A
|
|
|
35
35
|
public void setLockDisabled(A11yLockView view, boolean value) {
|
|
36
36
|
view.setLockDisabled(value);
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public void setForceLock(A11yLockView view, boolean value) {
|
|
41
|
+
//stub
|
|
42
|
+
}
|
|
38
43
|
}
|
|
@@ -64,7 +64,7 @@ public class A11yView extends A11yViewGroup implements A11yFocusProtocol {
|
|
|
64
64
|
|
|
65
65
|
if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED && autoFocus && !hasBeenFocused) {
|
|
66
66
|
hasBeenFocused = true;
|
|
67
|
-
a11yFocusDelegate.
|
|
67
|
+
a11yFocusDelegate.onFocused();
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED && isSubChild) {
|
|
@@ -9,5 +9,7 @@ public abstract class A11yLockViewManagerSpec<T extends A11yLockView> extends Re
|
|
|
9
9
|
public abstract void setContainerKey(T view, String value);
|
|
10
10
|
|
|
11
11
|
public abstract void setLockDisabled(T view, boolean value);
|
|
12
|
+
|
|
13
|
+
public abstract void setForceLock(A11yLockView view, boolean value);
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#import <Foundation/Foundation.h>
|
|
9
9
|
#import "RNAOSwizzleInstanceMethod.h"
|
|
10
|
+
#import "RNAOSwizzleInstall.h"
|
|
10
11
|
#import <objc/runtime.h>
|
|
11
12
|
#import "RNAOA11yAnnounceService.h"
|
|
12
13
|
#import "RCTModalHostViewComponentView+RNAOA11yOrder.h"
|
|
@@ -16,20 +17,19 @@
|
|
|
16
17
|
|
|
17
18
|
@implementation RCTModalHostViewComponentView (RNAOA11yOrder)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@selector(rnaoDismissViewController:animated:completion:));
|
|
27
|
-
RNAOSwizzleInstanceMethod([self class],
|
|
20
|
+
static void RNAORegisterModalPresentationSwizzles(void) {
|
|
21
|
+
Class cls = objc_getClass("RCTModalHostViewComponentView");
|
|
22
|
+
if (!cls) return;
|
|
23
|
+
RNAOSwizzleInstanceMethod(cls,
|
|
24
|
+
@selector(dismissViewController:animated:completion:),
|
|
25
|
+
@selector(rnaoDismissViewController:animated:completion:));
|
|
26
|
+
RNAOSwizzleInstanceMethod(cls,
|
|
28
27
|
@selector(presentViewController:animated:completion:),
|
|
29
28
|
@selector(rnaoPresentViewController:animated:completion:));
|
|
30
|
-
});
|
|
31
29
|
}
|
|
32
30
|
|
|
31
|
+
RNAO_INSTALL_SWIZZLES(RNAORegisterModalPresentationSwizzles)
|
|
32
|
+
|
|
33
33
|
- (void)rnaoPresentViewController:(UIViewController *)modalViewController
|
|
34
34
|
animated:(BOOL)animated
|
|
35
35
|
completion:(void (^)(void))completion
|
|
@@ -52,19 +52,19 @@
|
|
|
52
52
|
|
|
53
53
|
@implementation RCTModalHostView (RNAOA11yOrder)
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@selector(rnao_dismissModalViewController));
|
|
65
|
-
});
|
|
55
|
+
static void RNAORegisterModalPresentationSwizzles(void) {
|
|
56
|
+
Class cls = objc_getClass("RCTModalHostView");
|
|
57
|
+
if (!cls) return;
|
|
58
|
+
RNAOSwizzleInstanceMethod(cls,
|
|
59
|
+
@selector(ensurePresentedOnlyIfNeeded),
|
|
60
|
+
@selector(rnao_ensurePresentedOnlyIfNeeded));
|
|
61
|
+
RNAOSwizzleInstanceMethod(cls,
|
|
62
|
+
@selector(dismissModalViewController),
|
|
63
|
+
@selector(rnao_dismissModalViewController));
|
|
66
64
|
}
|
|
67
65
|
|
|
66
|
+
RNAO_INSTALL_SWIZZLES(RNAORegisterModalPresentationSwizzles)
|
|
67
|
+
|
|
68
68
|
- (void)rnao_ensurePresentedOnlyIfNeeded
|
|
69
69
|
{
|
|
70
70
|
[self rnao_ensurePresentedOnlyIfNeeded];
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#import "UIView+RNAOA11yOrder.h"
|
|
11
11
|
#import "RNAOSwizzleInstanceMethod.h"
|
|
12
|
+
#import "RNAOSwizzleInstall.h"
|
|
12
13
|
#import <objc/runtime.h>
|
|
13
14
|
|
|
14
15
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
@@ -55,28 +56,24 @@ static char kRNAOScreenReaderFocusDelegate;
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
RNAOSwizzleInstanceMethod(
|
|
73
|
-
swizzleClass,
|
|
74
|
-
@selector(accessibilityElementDidLoseFocus),
|
|
75
|
-
@selector(rnao_accessibilityElementDidLoseFocus)
|
|
76
|
-
);
|
|
77
|
-
});
|
|
59
|
+
static void RNAORegisterViewFocusSwizzles(void) {
|
|
60
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
61
|
+
Class swizzleClass = objc_getClass("RCTViewComponentView");
|
|
62
|
+
#else
|
|
63
|
+
Class swizzleClass = objc_getClass("RCTView");
|
|
64
|
+
#endif
|
|
65
|
+
if (!swizzleClass) return;
|
|
66
|
+
|
|
67
|
+
RNAOSwizzleInstanceMethod(swizzleClass,
|
|
68
|
+
@selector(accessibilityElementDidBecomeFocused),
|
|
69
|
+
@selector(rnao_accessibilityElementDidBecomeFocused));
|
|
70
|
+
RNAOSwizzleInstanceMethod(swizzleClass,
|
|
71
|
+
@selector(accessibilityElementDidLoseFocus),
|
|
72
|
+
@selector(rnao_accessibilityElementDidLoseFocus));
|
|
78
73
|
}
|
|
79
74
|
|
|
75
|
+
RNAO_INSTALL_SWIZZLES(RNAORegisterViewFocusSwizzles)
|
|
76
|
+
|
|
80
77
|
- (void)rnao_accessibilityElementDidBecomeFocused {
|
|
81
78
|
[self rnao_accessibilityElementDidBecomeFocused];
|
|
82
79
|
[self trigerScreenReaderFocusDelegate: true];
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#import "UIViewController+RNAOA11yOrder.h"
|
|
11
11
|
#import "RNAOSwizzleInstanceMethod.h"
|
|
12
|
+
#import "RNAOSwizzleInstall.h"
|
|
12
13
|
#import "RNAOA11yAnnounceService.h"
|
|
13
14
|
#import <objc/runtime.h>
|
|
14
15
|
|
|
@@ -34,16 +35,15 @@ static char kRnaoFocusRestoreKey;
|
|
|
34
35
|
return [objc_getAssociatedObject(self, &kRnaoFocusRestoreKey) boolValue];
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
RNAOSwizzleInstanceMethod([self class], @selector(viewDidAppear:), @selector(rnaoViewDidAppear:));
|
|
43
|
-
RNAOSwizzleInstanceMethod([self class], @selector(viewWillDisappear:), @selector(rnaoViewWillDisappear:));
|
|
44
|
-
});
|
|
38
|
+
static void RNAORegisterViewControllerSwizzles(void) {
|
|
39
|
+
Class cls = objc_getClass("UIViewController");
|
|
40
|
+
if (!cls) return;
|
|
41
|
+
RNAOSwizzleInstanceMethod(cls, @selector(viewDidAppear:), @selector(rnaoViewDidAppear:));
|
|
42
|
+
RNAOSwizzleInstanceMethod(cls, @selector(viewWillDisappear:), @selector(rnaoViewWillDisappear:));
|
|
45
43
|
}
|
|
46
44
|
|
|
45
|
+
RNAO_INSTALL_SWIZZLES(RNAORegisterViewControllerSwizzles);
|
|
46
|
+
|
|
47
47
|
|
|
48
48
|
- (void)saveAccessibilityFocusedView
|
|
49
49
|
{
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNAOSwizzleInstall.h
|
|
3
|
+
// react-native-a11y-order
|
|
4
|
+
//
|
|
5
|
+
// Created by Artur Kalach on 03/05/2026.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#ifndef RNAOSwizzleInstall_h
|
|
9
|
+
#define RNAOSwizzleInstall_h
|
|
10
|
+
|
|
11
|
+
#define RNAO_CONCAT_(a, b) a##b
|
|
12
|
+
#define RNAO_CONCAT(a, b) RNAO_CONCAT_(a, b)
|
|
13
|
+
|
|
14
|
+
#ifdef RCT_DYNAMIC_FRAMEWORKS
|
|
15
|
+
|
|
16
|
+
#define RNAO_INSTALL_SWIZZLES(registerFn) \
|
|
17
|
+
__attribute__((constructor)) \
|
|
18
|
+
static void RNAO_CONCAT(RNAOInstall_, registerFn)(void) { registerFn(); }
|
|
19
|
+
|
|
20
|
+
#else
|
|
21
|
+
|
|
22
|
+
#define RNAO_INSTALL_SWIZZLES(registerFn) \
|
|
23
|
+
+(void)load { \
|
|
24
|
+
static dispatch_once_t RNAO_CONCAT(once_, registerFn); \
|
|
25
|
+
dispatch_once(&RNAO_CONCAT(once_, registerFn), ^{ registerFn(); }); \
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#endif /* RNAOSwizzleInstall_h */
|