react-native-external-keyboard 0.5.6 → 0.6.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.
Files changed (102) hide show
  1. package/README.md +277 -14
  2. package/android/src/main/java/com/externalkeyboard/delegates/FocusOrderDelegate.java +213 -0
  3. package/android/src/main/java/com/externalkeyboard/helper/FocusHelper.java +44 -0
  4. package/android/src/main/java/com/externalkeyboard/helper/Linking/A11yOrderLinking.java +81 -0
  5. package/android/src/main/java/com/externalkeyboard/helper/Linking/LinkingQueue.java +94 -0
  6. package/android/src/main/java/com/externalkeyboard/helper/ReactNativeVersionChecker.java +24 -0
  7. package/android/src/main/java/com/externalkeyboard/services/FocusLinkObserver/FocusLinkObserver.java +131 -0
  8. package/android/src/main/java/com/externalkeyboard/services/FocusLinkObserver/FocusLinkObserverSingleton.java +20 -0
  9. package/android/src/main/java/com/externalkeyboard/views/ExternalKeyboardView/ExternalKeyboardView.java +144 -0
  10. package/android/src/main/java/com/externalkeyboard/views/ExternalKeyboardView/ExternalKeyboardViewManager.java +128 -8
  11. package/android/src/main/java/com/externalkeyboard/views/KeyboardFocusGroup/KeyboardFocusGroupManager.java +7 -3
  12. package/android/src/main/java/com/externalkeyboard/views/TextInputFocusWrapper/TextInputFocusWrapper.java +2 -13
  13. package/android/src/oldarch/ExternalKeyboardViewManagerSpec.java +25 -0
  14. package/android/src/oldarch/KeyboardFocusGroupManagerSpec.java +8 -1
  15. package/ios/Delegates/RNCEKVFocusOrderDelegate/RNCEKVFocusOrderDelegate.h +33 -0
  16. package/ios/Delegates/RNCEKVFocusOrderDelegate/RNCEKVFocusOrderDelegate.mm +577 -0
  17. package/ios/Delegates/RNCEKVFocusOrderDelegate/RNCEKVFocusOrderProtocol.h +34 -0
  18. package/ios/Delegates/RNCEKVGroupIdentifierDelegate/RNCEKVGroupIdentifierDelegate.h +1 -0
  19. package/ios/Delegates/RNCEKVGroupIdentifierDelegate/RNCEKVGroupIdentifierDelegate.mm +9 -0
  20. package/ios/Helpers/RNCEKVPropHelper/RNCEKVPropHelper.h +22 -0
  21. package/ios/Helpers/RNCEKVPropHelper/RNCEKVPropHelper.mm +48 -0
  22. package/ios/Services/RNCEKVFocusLinkObserver.h +27 -0
  23. package/ios/Services/RNCEKVFocusLinkObserver.mm +101 -0
  24. package/ios/Services/RNCEKVFocusLinkObserverManager.h +23 -0
  25. package/ios/Services/RNCEKVFocusLinkObserverManager.mm +30 -0
  26. package/ios/Services/RNCEKVOrderLinking.h +33 -0
  27. package/ios/Services/RNCEKVOrderLinking.mm +143 -0
  28. package/ios/Services/RNCEKVOrderSubscriber.h +24 -0
  29. package/ios/Services/RNCEKVOrderSubscriber.mm +23 -0
  30. package/ios/Services/RNCEKVRelashioship.h +28 -0
  31. package/ios/Services/RNCEKVRelashioship.mm +61 -0
  32. package/ios/Services/RNCEKVSortedMap.h +22 -0
  33. package/ios/Services/RNCEKVSortedMap.mm +112 -0
  34. package/ios/Views/RNCEKVExternalKeyboardView/RNCEKVExternalKeyboardView.h +34 -3
  35. package/ios/Views/RNCEKVExternalKeyboardView/RNCEKVExternalKeyboardView.mm +214 -54
  36. package/ios/Views/RNCEKVExternalKeyboardView/RNCEKVExternalKeyboardViewManager.h +9 -0
  37. package/ios/Views/RNCEKVExternalKeyboardView/RNCEKVExternalKeyboardViewManager.mm +80 -55
  38. package/ios/Views/RNCEKVKeyboardFocusGroupView/RNCEKVKeyboardFocusGroup.h +2 -0
  39. package/ios/Views/RNCEKVKeyboardFocusGroupView/RNCEKVKeyboardFocusGroup.mm +161 -3
  40. package/ios/Views/RNCEKVKeyboardFocusGroupView/RNCEKVKeyboardFocusGroupManager.mm +6 -0
  41. package/lib/commonjs/components/BaseKeyboardView/BaseKeyboardView.js +56 -3
  42. package/lib/commonjs/components/BaseKeyboardView/BaseKeyboardView.js.map +1 -1
  43. package/lib/commonjs/components/KeyboardFocusGroup/KeyboardFocusGroup.android.js +30 -0
  44. package/lib/commonjs/components/KeyboardFocusGroup/KeyboardFocusGroup.android.js.map +1 -0
  45. package/lib/commonjs/components/KeyboardFocusGroup/KeyboardFocusGroup.ios.js.map +1 -1
  46. package/lib/commonjs/components/KeyboardFocusGroup/KeyboardFocusGroup.js.map +1 -1
  47. package/lib/commonjs/context/OrderFocusContext.js +23 -0
  48. package/lib/commonjs/context/OrderFocusContext.js.map +1 -0
  49. package/lib/commonjs/index.js +19 -0
  50. package/lib/commonjs/index.js.map +1 -1
  51. package/lib/commonjs/nativeSpec/ExternalKeyboardViewNativeComponent.js.map +1 -1
  52. package/lib/commonjs/nativeSpec/KeyboardFocusGroupNativeComponent.js.map +1 -1
  53. package/lib/commonjs/types/BaseKeyboardView.js +12 -0
  54. package/lib/commonjs/types/BaseKeyboardView.js.map +1 -1
  55. package/lib/commonjs/utils/withKeyboardFocus.js +25 -1
  56. package/lib/commonjs/utils/withKeyboardFocus.js.map +1 -1
  57. package/lib/module/components/BaseKeyboardView/BaseKeyboardView.js +55 -2
  58. package/lib/module/components/BaseKeyboardView/BaseKeyboardView.js.map +1 -1
  59. package/lib/module/components/KeyboardFocusGroup/KeyboardFocusGroup.android.js +23 -0
  60. package/lib/module/components/KeyboardFocusGroup/KeyboardFocusGroup.android.js.map +1 -0
  61. package/lib/module/components/KeyboardFocusGroup/KeyboardFocusGroup.ios.js.map +1 -1
  62. package/lib/module/components/KeyboardFocusGroup/KeyboardFocusGroup.js.map +1 -1
  63. package/lib/module/context/OrderFocusContext.js +14 -0
  64. package/lib/module/context/OrderFocusContext.js.map +1 -0
  65. package/lib/module/index.js +1 -0
  66. package/lib/module/index.js.map +1 -1
  67. package/lib/module/nativeSpec/ExternalKeyboardViewNativeComponent.js.map +1 -1
  68. package/lib/module/nativeSpec/KeyboardFocusGroupNativeComponent.js.map +1 -1
  69. package/lib/module/types/BaseKeyboardView.js +11 -1
  70. package/lib/module/types/BaseKeyboardView.js.map +1 -1
  71. package/lib/module/utils/withKeyboardFocus.js +25 -1
  72. package/lib/module/utils/withKeyboardFocus.js.map +1 -1
  73. package/lib/typescript/src/components/BaseKeyboardView/BaseKeyboardView.d.ts +1 -1
  74. package/lib/typescript/src/components/BaseKeyboardView/BaseKeyboardView.d.ts.map +1 -1
  75. package/lib/typescript/src/components/KeyboardFocusGroup/KeyboardFocusGroup.android.d.ts +24 -0
  76. package/lib/typescript/src/components/KeyboardFocusGroup/KeyboardFocusGroup.android.d.ts.map +1 -0
  77. package/lib/typescript/src/components/KeyboardFocusGroup/KeyboardFocusGroup.d.ts +1 -0
  78. package/lib/typescript/src/components/KeyboardFocusGroup/KeyboardFocusGroup.d.ts.map +1 -1
  79. package/lib/typescript/src/components/KeyboardFocusGroup/KeyboardFocusGroup.ios.d.ts +2 -0
  80. package/lib/typescript/src/components/KeyboardFocusGroup/KeyboardFocusGroup.ios.d.ts.map +1 -1
  81. package/lib/typescript/src/context/OrderFocusContext.d.ts +10 -0
  82. package/lib/typescript/src/context/OrderFocusContext.d.ts.map +1 -0
  83. package/lib/typescript/src/index.d.ts +1 -0
  84. package/lib/typescript/src/index.d.ts.map +1 -1
  85. package/lib/typescript/src/nativeSpec/ExternalKeyboardViewNativeComponent.d.ts +12 -0
  86. package/lib/typescript/src/nativeSpec/ExternalKeyboardViewNativeComponent.d.ts.map +1 -1
  87. package/lib/typescript/src/nativeSpec/KeyboardFocusGroupNativeComponent.d.ts +1 -0
  88. package/lib/typescript/src/nativeSpec/KeyboardFocusGroupNativeComponent.d.ts.map +1 -1
  89. package/lib/typescript/src/types/BaseKeyboardView.d.ts +24 -0
  90. package/lib/typescript/src/types/BaseKeyboardView.d.ts.map +1 -1
  91. package/lib/typescript/src/utils/withKeyboardFocus.d.ts.map +1 -1
  92. package/package.json +1 -1
  93. package/src/components/BaseKeyboardView/BaseKeyboardView.tsx +77 -4
  94. package/src/components/KeyboardFocusGroup/KeyboardFocusGroup.android.tsx +39 -0
  95. package/src/components/KeyboardFocusGroup/KeyboardFocusGroup.ios.tsx +1 -0
  96. package/src/components/KeyboardFocusGroup/KeyboardFocusGroup.tsx +1 -0
  97. package/src/context/OrderFocusContext.tsx +25 -0
  98. package/src/index.tsx +5 -0
  99. package/src/nativeSpec/ExternalKeyboardViewNativeComponent.ts +12 -0
  100. package/src/nativeSpec/KeyboardFocusGroupNativeComponent.ts +1 -0
  101. package/src/types/BaseKeyboardView.ts +26 -0
  102. package/src/utils/withKeyboardFocus.tsx +24 -0
@@ -0,0 +1,94 @@
1
+ package com.externalkeyboard.helper.Linking;
2
+
3
+ import android.view.View;
4
+
5
+ import java.util.Map;
6
+ import java.util.NavigableMap;
7
+ import java.util.NavigableSet;
8
+ import java.util.TreeMap;
9
+ import java.util.TreeSet;
10
+
11
+ public class LinkingQueue {
12
+ public NavigableSet<Integer> positions = new TreeSet<>();
13
+ public NavigableMap<Integer, View> viewMap = new TreeMap<>();
14
+
15
+
16
+ private void linkPosition(View prev, View next) {
17
+ if (prev != null && next != null) {
18
+ prev.setNextFocusForwardId(next.getId());
19
+ }
20
+ }
21
+
22
+ private void addWithLinking(int position, View currentView) {
23
+ viewMap.put(position, currentView);
24
+ Map.Entry<Integer, View> nextView = viewMap.higherEntry(position);
25
+ Map.Entry<Integer, View> prevView = viewMap.lowerEntry(position);
26
+
27
+ if (prevView != null) {
28
+ this.linkPosition(prevView.getValue(), currentView);
29
+ }
30
+
31
+ if (nextView != null) {
32
+ this.linkPosition(currentView, nextView.getValue());
33
+ }
34
+ }
35
+
36
+ private void unlinkLast() {
37
+ Map.Entry<Integer, View> lastView = viewMap.lastEntry();
38
+ if (lastView != null) {
39
+ lastView.getValue().setNextFocusForwardId(View.NO_ID);
40
+ }
41
+ }
42
+
43
+
44
+ private void reLinkWithRemove(int position) {
45
+ Map.Entry<Integer, View> nextView = viewMap.higherEntry(position);
46
+ Map.Entry<Integer, View> prevView = viewMap.lowerEntry(position);
47
+
48
+ if (prevView != null && nextView != null) {
49
+ this.linkPosition(prevView.getValue(), nextView.getValue());
50
+ }
51
+
52
+ boolean shouldUnlinkLast = nextView == null;
53
+ this.viewMap.remove(position);
54
+
55
+ if (shouldUnlinkLast) {
56
+ this.unlinkLast();
57
+ }
58
+ }
59
+
60
+ public void addPosition(View view, int position) {
61
+ if (this.viewMap.get(position) == view) {
62
+ return;
63
+ }
64
+
65
+ this.addWithLinking(position, view);
66
+ }
67
+
68
+ public void removeFromOrder(int position) {
69
+ if (!this.viewMap.containsKey(position)) return;
70
+ this.reLinkWithRemove(position);
71
+ }
72
+
73
+ public void refreshIndexes(View view, int position) {
74
+ this.viewMap.put(position, view);
75
+
76
+ for (Map.Entry<Integer, View> positionEntry : this.viewMap.entrySet()) {
77
+ if (positionEntry != null) {
78
+ View currentView = positionEntry.getValue();
79
+ Map.Entry<Integer, View> nextEntry = this.viewMap.higherEntry(positionEntry.getKey());
80
+
81
+ if (nextEntry != null) {
82
+ linkPosition(currentView, nextEntry.getValue());
83
+ }
84
+ }
85
+ }
86
+
87
+ unlinkLast();
88
+ }
89
+
90
+ public boolean isEmpty() {
91
+ return positions.isEmpty() && viewMap.isEmpty();
92
+ }
93
+
94
+ }
@@ -0,0 +1,24 @@
1
+ package com.externalkeyboard.helper;
2
+
3
+ import com.facebook.react.views.textinput.ReactEditText;
4
+
5
+ import java.lang.reflect.Field;
6
+
7
+ public class ReactNativeVersionChecker {
8
+ private static Boolean is80OrLaterVersion = null;
9
+
10
+ public static boolean isReactNative80OrLater() {
11
+ if (is80OrLaterVersion != null) {
12
+ return is80OrLaterVersion;
13
+ }
14
+
15
+ try {
16
+ Field field = ReactEditText.class.getDeclaredField("dragAndDropFilter");
17
+ is80OrLaterVersion = true;
18
+ } catch (NoSuchFieldException e) {
19
+ is80OrLaterVersion = false;
20
+ }
21
+
22
+ return is80OrLaterVersion;
23
+ }
24
+ }
@@ -0,0 +1,131 @@
1
+ package com.externalkeyboard.services.FocusLinkObserver;
2
+
3
+ import android.view.View;
4
+
5
+ import java.lang.ref.WeakReference;
6
+ import java.util.ArrayList;
7
+ import java.util.HashMap;
8
+ import java.util.List;
9
+ import java.util.Map;
10
+
11
+ public class FocusLinkObserver {
12
+ private final Map<String, View> links;
13
+ private final Map<String, List<Subscriber>> subscribers;
14
+
15
+ public FocusLinkObserver() {
16
+ links = new HashMap<>();
17
+ subscribers = new HashMap<>();
18
+ }
19
+
20
+ public void emit(String id, View link) {
21
+ if (id == null || link == null) {
22
+ throw new IllegalArgumentException("Both id and link are required");
23
+ }
24
+
25
+ links.put(id, link);
26
+ emitLinkUpdated(id, link);
27
+ }
28
+
29
+
30
+ public void emitRemove(String id) {
31
+ if (links.containsKey(id)) {
32
+ links.remove(id); // Remove the link
33
+ emitLinkRemoved(id); // Notify subscribers
34
+ subscribers.remove(id); // Clean up subscribers for the ID
35
+ }
36
+ }
37
+
38
+ public void subscribe(String id, LinkUpdatedCallback onLinkUpdated, LinkRemovedCallback onLinkRemoved) {
39
+ if (id == null || (onLinkUpdated == null && onLinkRemoved == null)) {
40
+ return;
41
+ }
42
+
43
+ subscribers.putIfAbsent(id, new ArrayList<>());
44
+ subscribers.get(id).add(new Subscriber(onLinkUpdated, onLinkRemoved));
45
+
46
+ if (onLinkUpdated != null && links.containsKey(id)) {
47
+ onLinkUpdated.onLinkUpdated(links.get(id));
48
+ }
49
+ }
50
+
51
+ public void unsubscribe(String id, LinkUpdatedCallback onLinkUpdated, LinkRemovedCallback onLinkRemoved) {
52
+ if (id == null || (onLinkUpdated == null && onLinkRemoved == null)) {
53
+ return;
54
+ }
55
+
56
+ List<Subscriber> subscriberList = subscribers.get(id);
57
+ if (subscriberList != null) {
58
+ subscriberList.removeIf(subscriber -> {
59
+ LinkUpdatedCallback updatedCallback = subscriber.onLinkUpdated.get();
60
+ LinkRemovedCallback removedCallback = subscriber.onLinkRemoved.get();
61
+ return updatedCallback == onLinkUpdated && removedCallback == onLinkRemoved;
62
+ });
63
+
64
+ if (subscriberList.isEmpty()) {
65
+ subscribers.remove(id);
66
+ }
67
+ }
68
+ }
69
+
70
+ private void emitLinkUpdated(String id, View link) {
71
+ List<Subscriber> subscriberList = subscribers.get(id);
72
+ if (subscriberList != null) {
73
+ subscriberList.removeIf(Subscriber::isEmpty);
74
+
75
+ for (Subscriber subscriber : subscriberList) {
76
+ subscriber.notifyLinkUpdated(link);
77
+ }
78
+ }
79
+ }
80
+
81
+ private void emitLinkRemoved(String id) {
82
+ List<Subscriber> subscriberList = subscribers.get(id);
83
+ if (subscriberList != null) {
84
+ // Remove stale subscribers (whose weak references were garbage-collected)
85
+ subscriberList.removeIf(Subscriber::isEmpty);
86
+
87
+ // Notify all valid subscribers
88
+ for (Subscriber subscriber : subscriberList) {
89
+ subscriber.notifyLinkRemoved();
90
+ }
91
+ }
92
+ }
93
+
94
+ @FunctionalInterface
95
+ public interface LinkUpdatedCallback {
96
+ void onLinkUpdated(View link);
97
+ }
98
+
99
+ @FunctionalInterface
100
+ public interface LinkRemovedCallback {
101
+ void onLinkRemoved();
102
+ }
103
+
104
+ private static class Subscriber {
105
+ private final WeakReference<LinkUpdatedCallback> onLinkUpdated;
106
+ private final WeakReference<LinkRemovedCallback> onLinkRemoved;
107
+
108
+ public Subscriber(LinkUpdatedCallback onLinkUpdated, LinkRemovedCallback onLinkRemoved) {
109
+ this.onLinkUpdated = new WeakReference<>(onLinkUpdated);
110
+ this.onLinkRemoved = new WeakReference<>(onLinkRemoved);
111
+ }
112
+
113
+ public void notifyLinkUpdated(View link) {
114
+ LinkUpdatedCallback callback = onLinkUpdated.get();
115
+ if (callback != null) {
116
+ callback.onLinkUpdated(link);
117
+ }
118
+ }
119
+
120
+ public void notifyLinkRemoved() {
121
+ LinkRemovedCallback callback = onLinkRemoved.get();
122
+ if (callback != null) {
123
+ callback.onLinkRemoved();
124
+ }
125
+ }
126
+
127
+ public boolean isEmpty() {
128
+ return onLinkUpdated.get() == null && onLinkRemoved.get() == null;
129
+ }
130
+ }
131
+ }
@@ -0,0 +1,20 @@
1
+ package com.externalkeyboard.services.FocusLinkObserver;
2
+
3
+ public final class FocusLinkObserverSingleton {
4
+
5
+ private static volatile FocusLinkObserver instance;
6
+
7
+ private FocusLinkObserverSingleton() {
8
+ }
9
+
10
+ public static FocusLinkObserver getInstance() {
11
+ if (instance == null) {
12
+ synchronized (FocusLinkObserverSingleton.class) {
13
+ if (instance == null) {
14
+ instance = new FocusLinkObserver();
15
+ }
16
+ }
17
+ }
18
+ return instance;
19
+ }
20
+ }
@@ -1,15 +1,18 @@
1
1
  package com.externalkeyboard.views.ExternalKeyboardView;
2
2
 
3
3
  import android.content.Context;
4
+ import android.view.FocusFinder;
4
5
  import android.view.KeyEvent;
5
6
  import android.view.View;
6
7
  import android.view.ViewGroup;
7
8
  import android.view.ViewTreeObserver;
8
9
  import android.view.accessibility.AccessibilityEvent;
9
10
 
11
+ import com.externalkeyboard.delegates.FocusOrderDelegate;
10
12
  import com.externalkeyboard.events.EventHelper;
11
13
 
12
14
  import com.externalkeyboard.helper.FocusHelper;
15
+ import com.externalkeyboard.helper.ReactNativeVersionChecker;
13
16
  import com.externalkeyboard.services.KeyboardKeyPressHandler;
14
17
  import com.facebook.react.bridge.ReactContext;
15
18
  import com.facebook.react.uimanager.UIManagerHelper;
@@ -28,20 +31,159 @@ public class ExternalKeyboardView extends ReactViewGroup {
28
31
  public boolean enableA11yFocus = false;
29
32
  public boolean screenAutoA11yFocus = false;
30
33
  public int screenAutoA11yFocusDelay = 500;
34
+ public int lockFocus = 0;
35
+ public String orderForward;
36
+ public String orderBackward;
37
+ public String orderId;
38
+
39
+
40
+ private FocusOrderDelegate focusOrderDelegate = null;
31
41
  private EventDispatcher a11yViewAppearDispatcher = null;
32
42
  private EventDispatcherListener eventA11yViewAppearListener = null;
33
43
  private final KeyboardKeyPressHandler keyboardKeyPressHandler;
34
44
  private final Context context;
35
45
  private View listeningView;
36
46
 
47
+ private Integer orderIndex;
48
+ private String orderGroup;
49
+ private View firstChild;
50
+
51
+ private String orderUp;
52
+ private String orderDown;
53
+ private String orderLeft;
54
+
55
+ public String getOrderRight() {
56
+ return orderRight;
57
+ }
58
+
59
+ public void setOrderRight(String orderRight) {
60
+ focusOrderDelegate.refreshRight(this.orderRight, orderRight);
61
+ this.orderRight = orderRight;
62
+ }
63
+
64
+ public String getOrderLeft() {
65
+ return orderLeft;
66
+ }
67
+
68
+ public void setOrderLeft(String orderLeft) {
69
+ focusOrderDelegate.refreshLeft(this.orderLeft, orderLeft);
70
+ this.orderLeft = orderLeft;
71
+ }
72
+
73
+ public String getOrderDown() {
74
+ return orderDown;
75
+ }
76
+
77
+ public void setOrderDown(String orderDown) {
78
+ focusOrderDelegate.refreshDown(this.orderDown, orderDown);
79
+ this.orderDown = orderDown;
80
+ }
81
+
82
+ public String getOrderUp() {
83
+ return orderUp;
84
+ }
85
+
86
+ public void setOrderUp(String orderUp) {
87
+ focusOrderDelegate.refreshUp(this.orderUp, orderUp);
88
+ this.orderUp = orderUp;
89
+ }
90
+
91
+ private String orderRight;
92
+
37
93
  public ExternalKeyboardView(Context context) {
38
94
  super(context);
39
95
  this.context = context;
96
+ this.focusOrderDelegate = new FocusOrderDelegate(this);
40
97
  this.keyboardKeyPressHandler = new KeyboardKeyPressHandler();
41
98
  }
42
99
 
100
+ public View getFirstChild() {
101
+ return this.firstChild;
102
+ }
103
+
104
+ public String getOrderGroup() {
105
+ return this.orderGroup;
106
+ }
107
+
108
+ public String getOrderId() {
109
+ return this.orderId;
110
+ }
111
+
112
+ public void setOrderGroup(String orderGroup) {
113
+ focusOrderDelegate.updateOrderGroup(this.orderGroup, orderGroup);
114
+ this.orderGroup = orderGroup;
115
+ }
116
+
117
+ public Integer getOrderIndex() {
118
+ return this.orderIndex;
119
+ }
120
+
121
+ public void setOrderIndex(int orderIndex) {
122
+ if (this.orderIndex == null) {
123
+ this.orderIndex = orderIndex;
124
+ } else {
125
+ this.orderIndex = orderIndex;
126
+ focusOrderDelegate.refreshOrder();
127
+ }
128
+ }
129
+
130
+ public void linkAddView(View child) {
131
+ if (firstChild == null) {
132
+ firstChild = child;
133
+ focusOrderDelegate.link();
134
+ }
135
+ }
136
+
137
+ public void linkRemoveView(View view) {
138
+ if (view == firstChild) {
139
+ firstChild = null;
140
+ focusOrderDelegate.unlink(view);
141
+ }
142
+ }
143
+
144
+ @Override
145
+ public View focusSearch(View focused, int direction) {
146
+ if (lockFocus == 0 && orderGroup == null && orderIndex == null && orderForward == null && orderBackward == null) {
147
+ return super.focusSearch(focused, direction);
148
+ }
149
+
150
+ boolean isLocked = FocusHelper.isLocked(direction, lockFocus);
151
+ if (isLocked) {
152
+ return this;
153
+ }
154
+
155
+ if (direction == FOCUS_FORWARD && orderForward != null) {
156
+ View nextView = this.focusOrderDelegate.getLink(orderForward);
157
+ if (nextView != null) {
158
+ return nextView;
159
+ }
160
+ }
161
+
162
+ if (direction == FOCUS_BACKWARD && orderBackward != null) {
163
+ View prevView = this.focusOrderDelegate.getLink(orderBackward);
164
+ if (prevView != null) {
165
+ return prevView;
166
+ }
167
+ }
168
+
169
+ if(ReactNativeVersionChecker.isReactNative80OrLater()) {
170
+ if(orderGroup != null && orderIndex != null && (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD)){
171
+ return FocusFinder.getInstance().findNextFocus((ViewGroup) this.getParent(), focused, direction);
172
+ }
173
+ }
174
+
175
+ return super.focusSearch(focused, direction);
176
+ }
177
+
43
178
  @Override
44
179
  public boolean dispatchKeyEvent(KeyEvent keyEvent) {
180
+ if(lockFocus != 0) {
181
+ int keyCode = keyEvent.getKeyCode();
182
+ boolean isLocked = FocusHelper.isKeyLocked(keyCode, lockFocus);
183
+ if(isLocked) {
184
+ return true;
185
+ }
186
+ }
45
187
  if (!this.hasKeyUpListener && !this.hasKeyDownListener) {
46
188
  return super.dispatchKeyEvent(keyEvent);
47
189
  }
@@ -141,6 +283,8 @@ public class ExternalKeyboardView extends ReactViewGroup {
141
283
  if (this.listeningView != null) {
142
284
  this.listeningView.setOnFocusChangeListener(null);
143
285
  }
286
+
287
+ // this.focusOrderDelegate.clear(firstChild); // ToDO check how to clean
144
288
  }
145
289
 
146
290
  private View getFocusingView() {
@@ -1,5 +1,8 @@
1
1
  package com.externalkeyboard.views.ExternalKeyboardView;
2
2
 
3
+ import android.view.View;
4
+
5
+ import androidx.annotation.NonNull;
3
6
  import androidx.annotation.Nullable;
4
7
 
5
8
  import com.externalkeyboard.events.FocusChangeEvent;
@@ -13,6 +16,7 @@ import com.facebook.react.views.view.ReactViewGroup;
13
16
 
14
17
  import java.util.HashMap;
15
18
  import java.util.Map;
19
+ import java.util.Objects;
16
20
 
17
21
 
18
22
  @ReactModule(name = ExternalKeyboardViewManager.NAME)
@@ -25,9 +29,23 @@ public class ExternalKeyboardViewManager extends com.externalkeyboard.ExternalKe
25
29
  return NAME;
26
30
  }
27
31
 
32
+ @NonNull
28
33
  @Override
29
- public ExternalKeyboardView createViewInstance(ThemedReactContext context) {
30
- return new ExternalKeyboardView(context);
34
+ public ExternalKeyboardView createViewInstance(@NonNull ThemedReactContext context) {
35
+ ExternalKeyboardView viewGroup = new ExternalKeyboardView(context);
36
+
37
+ viewGroup.setOnHierarchyChangeListener(new ExternalKeyboardView.OnHierarchyChangeListener() {
38
+ @Override
39
+ public void onChildViewAdded(View parent, View child) {
40
+ viewGroup.linkAddView(child);
41
+ }
42
+
43
+ @Override
44
+ public void onChildViewRemoved(View parent, View child) {
45
+ viewGroup.linkRemoveView(child);
46
+ }
47
+ });
48
+ return viewGroup;
31
49
  }
32
50
 
33
51
  public static Map<String, Object> buildDirectEventMap(String registrationName) {
@@ -69,31 +87,41 @@ public class ExternalKeyboardViewManager extends com.externalkeyboard.ExternalKe
69
87
  @Override
70
88
  @ReactProp(name = "enableA11yFocus", defaultBoolean = false)
71
89
  public void setEnableA11yFocus(ExternalKeyboardView wrapper, boolean enableA11yFocus) {
72
- wrapper.enableA11yFocus = enableA11yFocus;
90
+ if(wrapper.enableA11yFocus != enableA11yFocus) {
91
+ wrapper.enableA11yFocus = enableA11yFocus;
92
+ }
73
93
  }
74
94
 
75
95
  @Override
76
96
  @ReactProp(name = "screenAutoA11yFocus", defaultBoolean = false)
77
97
  public void setScreenAutoA11yFocus(ExternalKeyboardView wrapper, boolean enableA11yFocus) {
78
- wrapper.screenAutoA11yFocus = enableA11yFocus;
98
+ if(wrapper.screenAutoA11yFocus != enableA11yFocus) {
99
+ wrapper.screenAutoA11yFocus = enableA11yFocus;
100
+ }
79
101
  }
80
102
 
81
103
  @Override
82
104
  @ReactProp(name = "screenAutoA11yFocusDelay", defaultInt = 500)
83
105
  public void setScreenAutoA11yFocusDelay(ExternalKeyboardView wrapper, int value) {
84
- wrapper.screenAutoA11yFocusDelay = value;
106
+ if(wrapper.screenAutoA11yFocusDelay != value) {
107
+ wrapper.screenAutoA11yFocusDelay = value;
108
+ }
85
109
  }
86
110
 
87
111
  @Override
88
112
  @ReactProp(name = "hasKeyDownPress")
89
113
  public void setHasKeyDownPress(ExternalKeyboardView view, boolean value) {
90
- view.hasKeyDownListener = value;
114
+ if(view.hasKeyDownListener != value) {
115
+ view.hasKeyDownListener = value;
116
+ }
91
117
  }
92
118
 
93
119
  @Override
94
120
  @ReactProp(name = "hasKeyUpPress")
95
121
  public void setHasKeyUpPress(ExternalKeyboardView view, boolean value) {
96
- view.hasKeyUpListener = value;
122
+ if(view.hasKeyUpListener != value) {
123
+ view.hasKeyUpListener = value;
124
+ }
97
125
  }
98
126
 
99
127
  @Override
@@ -104,7 +132,9 @@ public class ExternalKeyboardViewManager extends com.externalkeyboard.ExternalKe
104
132
  @Override
105
133
  @ReactProp(name = "autoFocus")
106
134
  public void setAutoFocus(ExternalKeyboardView view, @Nullable boolean value) {
107
- view.autoFocus = value;
135
+ if(view.autoFocus != value) {
136
+ view.autoFocus = value;
137
+ }
108
138
  }
109
139
 
110
140
  @Override
@@ -134,7 +164,97 @@ public class ExternalKeyboardViewManager extends com.externalkeyboard.ExternalKe
134
164
  @Override
135
165
  @ReactProp(name = "tintColor")
136
166
  public void setTintColor(ExternalKeyboardView view, @Nullable Integer value) {
167
+ //stub
168
+ }
169
+
170
+ @Override
171
+ @ReactProp(name = "orderGroup")
172
+ public void setOrderGroup(ExternalKeyboardView view, @Nullable String value) {
173
+ if(!Objects.equals(view.getOrderGroup(), value)) {
174
+ view.setOrderGroup(value);
175
+ }
176
+ }
177
+
178
+ @Override
179
+ @ReactProp(name = "orderIndex")
180
+ public void setOrderIndex(ExternalKeyboardView view, int value) {
181
+ if(!Objects.equals(view.getOrderIndex(), value)) {
182
+ view.setOrderIndex(value);
183
+ }
184
+ }
185
+
186
+ @Override
187
+ @ReactProp(name = "lockFocus")
188
+ public void setLockFocus(ExternalKeyboardView view, int value) {
189
+ if(view.lockFocus != value) {
190
+ view.lockFocus = value;
191
+ }
192
+ }
137
193
 
194
+ @Override
195
+ @ReactProp(name = "orderId")
196
+ public void setOrderId(ExternalKeyboardView view, @Nullable String value) {
197
+ if(!Objects.equals(view.orderId, value)) {
198
+ view.orderId = value;
199
+ }
200
+ }
201
+
202
+ @Override
203
+ @ReactProp(name = "orderLeft")
204
+ public void setOrderLeft(ExternalKeyboardView view, @Nullable String value) {
205
+ if(!Objects.equals(view.getOrderLeft(), value)) {
206
+ view.setOrderLeft(value);
207
+ }
208
+ }
209
+
210
+ @Override
211
+ @ReactProp(name = "orderRight")
212
+ public void setOrderRight(ExternalKeyboardView view, @Nullable String value) {
213
+ if(!Objects.equals(view.getOrderRight(), value)) {
214
+ view.setOrderRight(value);
215
+ }
216
+ }
217
+
218
+ @Override
219
+ @ReactProp(name = "orderUp")
220
+ public void setOrderUp(ExternalKeyboardView view, @Nullable String value) {
221
+ if(!Objects.equals(view.getOrderUp(), value)) {
222
+ view.setOrderUp(value);
223
+ }
224
+ }
225
+
226
+ @Override
227
+ @ReactProp(name = "orderDown")
228
+ public void setOrderDown(ExternalKeyboardView view, @Nullable String value) {
229
+ if(!Objects.equals(view.getOrderDown(), value)) {
230
+ view.setOrderDown(value);
231
+ }
232
+ }
233
+
234
+ @Override
235
+ @ReactProp(name = "orderForward")
236
+ public void setOrderForward(ExternalKeyboardView view, @Nullable String value) {
237
+ if(!Objects.equals(view.orderForward, value)) {
238
+ view.orderForward = value;
239
+ }
240
+ }
241
+
242
+ @Override
243
+ @ReactProp(name = "orderBackward")
244
+ public void setOrderBackward(ExternalKeyboardView view, @Nullable String value) {
245
+ if(!Objects.equals(view.orderBackward, value)) {
246
+ view.orderBackward = value;
247
+ }
248
+ }
249
+
250
+ @Override
251
+ public void setOrderFirst(ExternalKeyboardView view, @Nullable String value) {
252
+ //stub
253
+ }
254
+
255
+ @Override
256
+ public void setOrderLast(ExternalKeyboardView view, @Nullable String value) {
257
+ //stub
138
258
  }
139
259
 
140
260
  @Override
@@ -20,10 +20,8 @@ public class KeyboardFocusGroupManager extends com.externalkeyboard.KeyboardFocu
20
20
  return new KeyboardFocusGroup(context);
21
21
  }
22
22
 
23
-
24
23
  @Override
25
- @ReactProp(name = "tintColor")
26
- public void setTintColor(KeyboardFocusGroup view, @Nullable Integer value) {
24
+ public void setTintColor(KeyboardFocusGroup view, Integer value) {
27
25
  //stub
28
26
  }
29
27
 
@@ -32,4 +30,10 @@ public class KeyboardFocusGroupManager extends com.externalkeyboard.KeyboardFocu
32
30
  public void setGroupIdentifier(KeyboardFocusGroup wrapper, String groupIdentifier) {
33
31
  //stub
34
32
  }
33
+
34
+ @Override
35
+ @ReactProp(name = "orderGroup")
36
+ public void setOrderGroup(KeyboardFocusGroup view, @Nullable String value) {
37
+ //stub
38
+ }
35
39
  }