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
@@ -11,6 +11,7 @@ import android.widget.EditText;
11
11
  import androidx.annotation.NonNull;
12
12
 
13
13
  import com.externalkeyboard.events.EventHelper;
14
+ import com.externalkeyboard.helper.ReactNativeVersionChecker;
14
15
  import com.externalkeyboard.modules.ExternalKeyboardModule;
15
16
  import com.facebook.react.bridge.ReactContext;
16
17
  import com.facebook.react.views.textinput.ReactEditText;
@@ -28,24 +29,12 @@ public class TextInputFocusWrapper extends ViewGroup implements View.OnFocusChan
28
29
  private boolean multiline = false;
29
30
  private boolean keyboardFocusable = true;
30
31
  private static View focusedView = null;
31
- private static Boolean is80Version = null;
32
32
  public boolean getIsFocusByPress() {
33
33
  return focusType == FOCUS_BY_PRESS;
34
34
  }
35
35
 
36
36
  private boolean getIs80Version () {
37
- if (is80Version != null) {
38
- return is80Version;
39
- }
40
-
41
- try {
42
- Field field = (ReactEditText.class).getDeclaredField("dragAndDropFilter");
43
- is80Version = true;
44
- } catch (NoSuchFieldException e) {
45
- is80Version = false;
46
- }
47
-
48
- return is80Version;
37
+ return ReactNativeVersionChecker.isReactNative80OrLater();
49
38
  }
50
39
 
51
40
  public void setKeyboardFocusable(boolean canBeFocusable) {
@@ -5,6 +5,7 @@ import android.view.ViewGroup;
5
5
  import androidx.annotation.Nullable;
6
6
 
7
7
  import com.externalkeyboard.views.ExternalKeyboardView.ExternalKeyboardView;
8
+ import com.facebook.react.uimanager.annotations.ReactProp;
8
9
  import com.facebook.react.views.view.ReactViewManager;
9
10
 
10
11
  public abstract class ExternalKeyboardViewManagerSpec<T extends ViewGroup> extends ReactViewManager {
@@ -39,4 +40,28 @@ public abstract class ExternalKeyboardViewManagerSpec<T extends ViewGroup> exten
39
40
  public abstract void setScreenAutoA11yFocus(ExternalKeyboardView wrapper, boolean enableA11yFocus);
40
41
 
41
42
  public abstract void setScreenAutoA11yFocusDelay(ExternalKeyboardView wrapper, int value);
43
+
44
+ public abstract void setOrderGroup(ExternalKeyboardView view, @Nullable String value);
45
+
46
+ public abstract void setOrderIndex(ExternalKeyboardView view, int value);
47
+
48
+ public abstract void setLockFocus(ExternalKeyboardView view, int value);
49
+
50
+ public abstract void setOrderId(ExternalKeyboardView view, @Nullable String value);
51
+
52
+ public abstract void setOrderLeft(ExternalKeyboardView view, @Nullable String value);
53
+
54
+ public abstract void setOrderRight(ExternalKeyboardView view, @Nullable String value);
55
+
56
+ public abstract void setOrderUp(ExternalKeyboardView view, @Nullable String value);
57
+
58
+ public abstract void setOrderDown(ExternalKeyboardView view, @Nullable String value);
59
+
60
+ public abstract void setOrderForward(ExternalKeyboardView view, @Nullable String value);
61
+
62
+ public abstract void setOrderBackward(ExternalKeyboardView view, @Nullable String value);
63
+
64
+ public abstract void setOrderFirst(ExternalKeyboardView view, @Nullable String value);
65
+
66
+ public abstract void setOrderLast(ExternalKeyboardView view, @Nullable String value);
42
67
  }
@@ -2,9 +2,16 @@ package com.externalkeyboard;
2
2
 
3
3
  import android.view.ViewGroup;
4
4
 
5
+ import androidx.annotation.Nullable;
6
+
7
+ import com.externalkeyboard.views.KeyboardFocusGroup.KeyboardFocusGroup;
5
8
  import com.facebook.react.uimanager.ViewGroupManager;
9
+ import com.facebook.react.uimanager.annotations.ReactProp;
6
10
 
7
11
  public abstract class KeyboardFocusGroupManagerSpec<T extends ViewGroup> extends ViewGroupManager<T> {
8
- public abstract void setTintColor(T wrapper, Integer value);
12
+ public abstract void setTintColor(KeyboardFocusGroup view, Integer value);
13
+
9
14
  public abstract void setGroupIdentifier(T wrapper, String groupIdentifier);
15
+
16
+ public abstract void setOrderGroup(KeyboardFocusGroup view, @Nullable String value);
10
17
  }
@@ -0,0 +1,33 @@
1
+ //
2
+ // RNCEKVFocusOrderDelegate.h
3
+ // Pods
4
+ //
5
+ // Created by Artur Kalach on 25/06/2025.
6
+ //
7
+
8
+ #ifndef RNCEKVFocusOrderDelegate_h
9
+ #define RNCEKVFocusOrderDelegate_h
10
+
11
+ #import <Foundation/Foundation.h>
12
+ #import "RNCEKVFocusOrderProtocol.h"
13
+
14
+ @interface RNCEKVFocusOrderDelegate : NSObject
15
+
16
+ - (instancetype _Nonnull)initWithView:(UIView<RNCEKVFocusOrderProtocol> *_Nonnull)view;
17
+
18
+ - (NSNumber*_Nullable)shouldUpdateFocusInContext:(UIFocusUpdateContext *_Nonnull)context;
19
+
20
+ - (void)linkId;
21
+ - (void)refreshId:(NSString*_Nullable)prev next:(NSString*_Nullable)next;
22
+ - (void)setIsFocused:(BOOL)value;
23
+
24
+ - (void)refreshLeft:(NSString*_Nullable)prev next:(NSString*_Nullable)next;
25
+ - (void)refreshRight:(NSString*_Nullable)prev next:(NSString*_Nullable)next;
26
+ - (void)refreshUp:(NSString*_Nullable)prev next:(NSString*_Nullable)next;
27
+ - (void)refreshDown:(NSString*_Nullable)prev next:(NSString*_Nullable)next;
28
+ - (void)clear;
29
+
30
+ @end
31
+
32
+
33
+ #endif /* RNCEKVFocusOrderDelegate_h */
@@ -0,0 +1,577 @@
1
+ //
2
+ // RNCEKVFocusOrderDelegate.mm
3
+ // react-native-external-keyboard
4
+ //
5
+ // Created by Artur Kalach on 25/06/2025.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+
11
+ #import "RNCEKVFocusOrderDelegate.h"
12
+ #import "RNCEKVFocusOrderProtocol.h"
13
+ #import "RNCEKVFocusEffectUtility.h"
14
+ #import "RNCEKVOrderLinking.h"
15
+ #import "RNCEKVExternalKeyboardView.h"
16
+ #import "UIViewController+RNCEKVExternalKeyboard.h"
17
+ #import "RNCEKVFocusLinkObserverManager.h"
18
+ #import "RNCEKVOrderSubscriber.h"
19
+
20
+ static NSNumber *const FOCUS_DEFAULT = nil;
21
+ static NSNumber *const FOCUS_LOCK = @0;
22
+ static NSNumber *const FOCUS_UPDATE = @1;
23
+
24
+ @implementation RNCEKVFocusOrderDelegate{
25
+ BOOL _isFocused;
26
+ UIView<RNCEKVFocusOrderProtocol>* _delegate;
27
+ UIView* _entry;
28
+ UIView* _exit;
29
+ UIView* _lock;
30
+ LinkUpdatedCallback _leftLinkUpdated;
31
+ LinkRemovedCallback _leftLinkRemoved;
32
+ LinkUpdatedCallback _rightLinkUpdated;
33
+ LinkRemovedCallback _rightLinkRemoved;
34
+ LinkUpdatedCallback _upLinkUpdated;
35
+ LinkRemovedCallback _upLinkRemoved;
36
+ LinkUpdatedCallback _downLinkUpdated;
37
+ LinkRemovedCallback _downLinkRemoved;
38
+
39
+ UIFocusGuide *_leftFocusGuide;
40
+ UIFocusGuide *_rightFocusGuide;
41
+ UIFocusGuide *_upFocusGuide;
42
+ UIFocusGuide *_downFocusGuide;
43
+ }
44
+
45
+ - (instancetype _Nonnull )initWithView:(UIView<RNCEKVFocusOrderProtocol> *_Nonnull)delegate{
46
+ self = [super init];
47
+ if (self) {
48
+ _delegate = delegate;
49
+ _isFocused = false;
50
+ }
51
+ return self;
52
+ }
53
+
54
+ #pragma mark - Get Order Focus List
55
+ - (NSArray<UIView *> *)getOrder {
56
+ RNCEKVRelashioship* orderRelationship = [[RNCEKVOrderLinking sharedInstance] getInfo: _delegate.orderGroup];
57
+ return [orderRelationship getArray];
58
+ }
59
+
60
+
61
+ #pragma mark - Find Index of Focus Order Element
62
+ - (int)findOrderIndex:(NSArray *)order element:(UIView*)el {
63
+ int resultIndex = -1;
64
+
65
+ for (int i = 0; i < order.count; i++) {
66
+ UIView *element = order[i];
67
+ if (element.subviews[0] == el) { //ToDo focus element
68
+ resultIndex = i;
69
+ break;
70
+ }
71
+ }
72
+
73
+ return resultIndex;
74
+ }
75
+
76
+ - (void)keyboardedViewFocus:(UIView *)view {
77
+ if ([view isKindOfClass:[RNCEKVExternalKeyboardView class]]) {
78
+ [(RNCEKVExternalKeyboardView*)view focus];
79
+ }
80
+ }
81
+
82
+ - (void)defaultViewFocus:(UIView *)view {
83
+ UIViewController *controller = _delegate.reactViewController;
84
+
85
+ if (controller != nil) {
86
+ controller.customFocusView = view;
87
+ dispatch_async(dispatch_get_main_queue(), ^{
88
+ [controller setNeedsFocusUpdate];
89
+ [controller updateFocusIfNeeded];
90
+ });
91
+ }
92
+ }
93
+
94
+
95
+ #pragma mark - Next Focus Handling
96
+ - (void)handleNextFocus:(UIView *)current currentIndex:(NSInteger)currentIndex {
97
+ NSArray<UIView *> * order = [self getOrder];
98
+ RNCEKVRelashioship* orderRelationship = [[RNCEKVOrderLinking sharedInstance] getInfo: _delegate.orderGroup];
99
+ UIView* _entry = orderRelationship.entry;
100
+ UIView* _exit = orderRelationship.exit;
101
+
102
+ BOOL isEntry = _entry == current;
103
+ if (isEntry) {
104
+ UIView* firstElement = order[0];
105
+ [self keyboardedViewFocus: firstElement];
106
+ }
107
+
108
+ BOOL isLast = currentIndex == order.count - 1 && _exit;
109
+ if (isLast) {
110
+ [self defaultViewFocus: _exit];
111
+ }
112
+
113
+ BOOL inOrderRange = currentIndex >= 0 && currentIndex < order.count - 1;
114
+ if (inOrderRange) {
115
+ UIView* nextElement = order[currentIndex + 1];
116
+ [self keyboardedViewFocus: nextElement];
117
+ }
118
+ }
119
+
120
+
121
+ #pragma mark - Prev Focus Handling
122
+ - (void)handlePrevFocus:(UIView *)current currentIndex:(NSInteger)currentIndex {
123
+ NSArray<UIView *> * order = [self getOrder];
124
+ RNCEKVRelashioship* orderRelationship = [[RNCEKVOrderLinking sharedInstance] getInfo: _delegate.orderGroup];
125
+
126
+ UIView* _exit = orderRelationship.exit;
127
+ UIView* _entry = orderRelationship.entry;
128
+
129
+ BOOL isExit = _exit == current;
130
+ if (isExit) {
131
+ UIView* lastElement = order[order.count - 1];
132
+ [self keyboardedViewFocus: lastElement];
133
+ }
134
+
135
+ BOOL isFirst = currentIndex == 0 && _entry;
136
+ if (isFirst) {
137
+ [self defaultViewFocus: _entry];
138
+ }
139
+
140
+ BOOL inRange = currentIndex > 0 && currentIndex <= order.count - 1;
141
+ if (inRange) {
142
+ UIView* prevElement = order[currentIndex - 1];
143
+ [self keyboardedViewFocus: prevElement];
144
+ }
145
+ }
146
+
147
+ #pragma mark - Focus Order Handler
148
+ - (NSNumber*)shouldUpdateFocusInContext:(UIFocusUpdateContext *)context {
149
+ UIFocusHeading movementHint = context.focusHeading;
150
+ UIView *next = (UIView *)context.nextFocusedItem;
151
+ UIView *current = (UIView *)context.previouslyFocusedItem;
152
+ UIView* targetView = [_delegate getFocusTargetView];
153
+
154
+ BOOL isTarget = current == targetView;
155
+ if (isTarget) {
156
+ NSMutableDictionary<NSNumber *, NSString *> *orderMapping = [NSMutableDictionary dictionary]; //Todo create custom structure
157
+ if (_delegate.orderLast) {
158
+ orderMapping[@(UIFocusHeadingLast)] = _delegate.orderLast;
159
+ }
160
+ if (_delegate.orderFirst) {
161
+ orderMapping[@(UIFocusHeadingFirst)] = _delegate.orderFirst;
162
+ }
163
+ if (_delegate.orderForward) {
164
+ orderMapping[@(UIFocusHeadingNext)] = _delegate.orderForward;
165
+ }
166
+ if (_delegate.orderBackward) {
167
+ orderMapping[@(UIFocusHeadingPrevious)] = _delegate.orderBackward;
168
+ }
169
+
170
+ NSString *orderKey = orderMapping[@(movementHint)];
171
+ if (orderKey) {
172
+ UIView *nextView = [[RNCEKVOrderLinking sharedInstance] getOrderView:orderKey];
173
+ [self keyboardedViewFocus:nextView];
174
+ return FOCUS_LOCK;
175
+ }
176
+ }
177
+
178
+
179
+ if (current == targetView) {
180
+ NSUInteger rawFocusLockValue = [_delegate.lockFocus unsignedIntegerValue];
181
+
182
+ BOOL isDirectionLock = (rawFocusLockValue & movementHint) != 0;
183
+ if (isDirectionLock) {
184
+ return FOCUS_LOCK;
185
+ }
186
+ }
187
+
188
+ if(_delegate.orderGroup && _delegate.orderPosition != nil) {
189
+ RNCEKVRelashioship* orderRelationship = [[RNCEKVOrderLinking sharedInstance] getInfo: _delegate.orderGroup];
190
+ NSArray *order = [orderRelationship getArray];
191
+ if(order.count == 0) {
192
+ return FOCUS_DEFAULT;
193
+ }
194
+
195
+ UIView* _exit = orderRelationship.exit;
196
+ UIView* _entry = orderRelationship.entry;
197
+ int currentIndex = [self findOrderIndex:order element:current];
198
+ int nextIndex = [self findOrderIndex:order element:next];
199
+
200
+ BOOL isEntryElement = _entry == nil && currentIndex == -1 && movementHint == UIFocusHeadingNext;
201
+
202
+ if(isEntryElement) {
203
+ orderRelationship.entry = current;
204
+ }
205
+
206
+ BOOL isExit = _exit == nil && nextIndex == -1 && movementHint == UIFocusHeadingNext;
207
+ if(isExit) {
208
+ orderRelationship.exit = next;
209
+ }
210
+
211
+ if(context.focusHeading == UIFocusHeadingNext) {
212
+ [self handleNextFocus:current currentIndex: currentIndex];
213
+ return FOCUS_UPDATE;
214
+ }
215
+
216
+
217
+ if(context.focusHeading == UIFocusHeadingPrevious) {
218
+ [self handlePrevFocus:current currentIndex: currentIndex];
219
+ return FOCUS_UPDATE;
220
+ }
221
+ }
222
+
223
+ return FOCUS_DEFAULT;
224
+ }
225
+
226
+
227
+
228
+ - (void)setLeftGuide:(UIView *)view {
229
+ if (!view) {
230
+ return;
231
+ }
232
+
233
+ [self removeLeftGuide];
234
+
235
+ _leftFocusGuide = [[UIFocusGuide alloc] init];
236
+ [_delegate addLayoutGuide:_leftFocusGuide];
237
+
238
+ [NSLayoutConstraint activateConstraints:@[
239
+ [_leftFocusGuide.topAnchor constraintEqualToAnchor:_delegate.topAnchor],
240
+ [_leftFocusGuide.bottomAnchor constraintEqualToAnchor:_delegate.bottomAnchor],
241
+ [_leftFocusGuide.rightAnchor constraintEqualToAnchor:_delegate.leftAnchor],
242
+ [_leftFocusGuide.widthAnchor constraintEqualToConstant:1]
243
+ ]];
244
+
245
+ _leftFocusGuide.preferredFocusEnvironments = @[view];
246
+
247
+ _leftFocusGuide.enabled = _isFocused;
248
+ }
249
+
250
+ - (void)setRightGuide:(UIView *)view {
251
+ if (!view) return;
252
+
253
+ [self removeRightGuide];
254
+
255
+ _rightFocusGuide = [[UIFocusGuide alloc] init];
256
+ [_delegate addLayoutGuide: _rightFocusGuide];
257
+
258
+ [NSLayoutConstraint activateConstraints:@[
259
+ [_rightFocusGuide.topAnchor constraintEqualToAnchor: _delegate.topAnchor],
260
+ [_rightFocusGuide.bottomAnchor constraintEqualToAnchor: _delegate.bottomAnchor],
261
+ [_rightFocusGuide.leftAnchor constraintEqualToAnchor: _delegate.rightAnchor],
262
+ [_rightFocusGuide.widthAnchor constraintEqualToConstant: 1]
263
+ ]];
264
+
265
+ _rightFocusGuide.preferredFocusEnvironments = @[view];
266
+
267
+ _rightFocusGuide.enabled = _isFocused;
268
+ }
269
+
270
+ - (void)setUpGuide:(UIView *)view {
271
+ if (!view) return;
272
+
273
+ [self removeUpGuide];
274
+
275
+ _upFocusGuide = [[UIFocusGuide alloc] init];
276
+ [_delegate addLayoutGuide: _upFocusGuide];
277
+
278
+ [NSLayoutConstraint activateConstraints:@[
279
+ [_upFocusGuide.leftAnchor constraintEqualToAnchor:_delegate.leftAnchor],
280
+ [_upFocusGuide.rightAnchor constraintEqualToAnchor:_delegate.rightAnchor],
281
+ [_upFocusGuide.bottomAnchor constraintEqualToAnchor:_delegate.topAnchor],
282
+ [_upFocusGuide.heightAnchor constraintEqualToConstant:1]
283
+ ]];
284
+
285
+ _upFocusGuide.preferredFocusEnvironments = @[view];
286
+
287
+ _upFocusGuide.enabled = _isFocused;
288
+ }
289
+
290
+ - (void)setDownGuide:(UIView *)view {
291
+ if (!view) return;
292
+
293
+ [self removeDownGuide];
294
+
295
+ _downFocusGuide = [[UIFocusGuide alloc] init];
296
+ [_delegate addLayoutGuide:_downFocusGuide];
297
+
298
+ [NSLayoutConstraint activateConstraints:@[
299
+ [_downFocusGuide.leftAnchor constraintEqualToAnchor:_delegate.leftAnchor],
300
+ [_downFocusGuide.rightAnchor constraintEqualToAnchor:_delegate.rightAnchor],
301
+ [_downFocusGuide.topAnchor constraintEqualToAnchor:_delegate.bottomAnchor],
302
+ [_downFocusGuide.heightAnchor constraintEqualToConstant:1]
303
+ ]];
304
+
305
+ _downFocusGuide.preferredFocusEnvironments = @[view];
306
+
307
+ _downFocusGuide.enabled = _isFocused;
308
+ }
309
+
310
+ - (void)setIsFocused:(BOOL)value {
311
+ _isFocused = value;
312
+
313
+ if(_leftFocusGuide != nil) {
314
+ _leftFocusGuide.enabled = value;
315
+ }
316
+
317
+ if(_rightFocusGuide != nil) {
318
+ _rightFocusGuide.enabled = value;
319
+ }
320
+
321
+ if(_upFocusGuide != nil) {
322
+ _upFocusGuide.enabled = value;
323
+ }
324
+
325
+ if(_downFocusGuide != nil) {
326
+ _downFocusGuide.enabled = value;
327
+ }
328
+ }
329
+
330
+ - (void)removeLeftGuide {
331
+ if (_leftFocusGuide) {
332
+ [_delegate removeLayoutGuide: _leftFocusGuide];
333
+ _leftFocusGuide = nil;
334
+ }
335
+ }
336
+
337
+ - (void)removeRightGuide {
338
+ if (_rightFocusGuide) {
339
+ [_delegate removeLayoutGuide: _rightFocusGuide];
340
+ _rightFocusGuide = nil;
341
+ }
342
+ }
343
+
344
+ - (void)removeUpGuide {
345
+ if (_upFocusGuide) {
346
+ [_delegate removeLayoutGuide:_upFocusGuide];
347
+ _upFocusGuide = nil;
348
+ }
349
+ }
350
+
351
+ - (void)removeDownGuide {
352
+ if (_downFocusGuide) {
353
+ [_delegate removeLayoutGuide:_downFocusGuide];
354
+ _downFocusGuide = nil;
355
+ }
356
+ }
357
+
358
+ - (void)orderLeftLink:(NSString*) linkId {
359
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
360
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
361
+
362
+ if(linkId != nil && !_leftLinkUpdated && !_leftLinkRemoved) {
363
+ __typeof(self) __weak weakSelf = self;
364
+
365
+ _leftLinkUpdated = ^(UIView *link) {
366
+ if (!weakSelf) return;
367
+ [weakSelf setLeftGuide:link];
368
+ };
369
+
370
+ _leftLinkRemoved = ^{
371
+ if (!weakSelf) return;
372
+ [weakSelf removeLeftGuide];
373
+ };
374
+
375
+ [focusLinkObserver subscribeWithId: linkId
376
+ onLinkUpdated:_leftLinkUpdated
377
+ onLinkRemoved:_leftLinkRemoved];
378
+ }
379
+ }
380
+
381
+ -(void)orderUpLink:(NSString*) linkId {
382
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
383
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
384
+
385
+ if(linkId != nil && !_upLinkUpdated && !_upLinkRemoved) {
386
+ __typeof(self) __weak weakSelf = self;
387
+ _upLinkUpdated = ^(UIView *link) {
388
+ if (!weakSelf) return;
389
+ [weakSelf setUpGuide: link];
390
+ };
391
+ _upLinkRemoved = ^{
392
+ if (!weakSelf) return;
393
+ [weakSelf removeUpGuide];
394
+ };
395
+ [focusLinkObserver subscribeWithId: linkId
396
+ onLinkUpdated:_upLinkUpdated
397
+ onLinkRemoved:_upLinkRemoved];
398
+ }
399
+ }
400
+
401
+ -(void)orderDownLink:(NSString*) linkId {
402
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
403
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
404
+
405
+ if(linkId != nil && !_downLinkUpdated && !_downLinkRemoved) {
406
+ __typeof(self) __weak weakSelf = self;
407
+ _downLinkUpdated = ^(UIView *link) {
408
+ if (!weakSelf) return;
409
+ [weakSelf setDownGuide: link];
410
+ };
411
+ _downLinkRemoved = ^{
412
+ if (!weakSelf) return;
413
+ [weakSelf removeDownGuide];
414
+ };
415
+ [focusLinkObserver subscribeWithId: linkId
416
+ onLinkUpdated:_downLinkUpdated
417
+ onLinkRemoved:_downLinkRemoved];
418
+ }
419
+ }
420
+
421
+ -(void)orderRightLink: (NSString*) linkId {
422
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
423
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
424
+
425
+
426
+ if(linkId != nil && !_rightLinkUpdated && !_rightLinkRemoved) {
427
+ __typeof(self) __weak weakSelf = self;
428
+ _rightLinkUpdated = ^(UIView *link) {
429
+ if (!weakSelf) return;
430
+ [weakSelf setRightGuide: link];
431
+ };
432
+ _rightLinkRemoved = ^{
433
+ if (!weakSelf) return;
434
+ [weakSelf removeRightGuide];
435
+ };
436
+ [focusLinkObserver subscribeWithId: linkId
437
+ onLinkUpdated:_rightLinkUpdated
438
+ onLinkRemoved:_rightLinkRemoved];
439
+ }
440
+ }
441
+
442
+ - (void)linkId {
443
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
444
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
445
+
446
+ NSString* orderId = _delegate.orderId;
447
+ UIView* view = [_delegate getFocusTargetView];
448
+
449
+ if(orderId != nil) {
450
+ [focusLinkObserver emitWithId:orderId link:view];
451
+ }
452
+
453
+
454
+
455
+ [self orderLeftLink: _delegate.orderLeft];
456
+ [self orderRightLink: _delegate.orderRight];
457
+ [self orderUpLink: _delegate.orderUp];
458
+ [self orderDownLink: _delegate.orderDown];
459
+ }
460
+
461
+ - (void)refreshId: (NSString*)prev next:(NSString*)next {
462
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
463
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
464
+ UIView* view = [_delegate getFocusTargetView];
465
+
466
+
467
+ if(prev != nil) {
468
+ [[RNCEKVOrderLinking sharedInstance] cleanOrderId: prev];
469
+ [focusLinkObserver emitRemoveWithId: prev];
470
+ }
471
+
472
+ if(next != nil && view != nil) {
473
+ [[RNCEKVOrderLinking sharedInstance] storeOrderId: next withView:_delegate];
474
+ [focusLinkObserver emitWithId:next link:view];
475
+ }
476
+ };
477
+
478
+ - (void) clearLeftLink: (NSString*) linkId {
479
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
480
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
481
+
482
+ if(linkId != nil && _leftLinkUpdated != nil && _leftLinkRemoved != nil) {
483
+ [focusLinkObserver unsubscribeWithId:linkId
484
+ onLinkUpdated:_leftLinkUpdated
485
+ onLinkRemoved:_leftLinkRemoved];
486
+ _leftLinkUpdated = nil;
487
+ _leftLinkRemoved = nil;
488
+ [self removeLeftGuide];
489
+ }
490
+ }
491
+
492
+ -(void)clearRightLink: (NSString*) linkId {
493
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
494
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
495
+
496
+ if(linkId != nil && _rightLinkUpdated != nil && _rightLinkRemoved != nil) {
497
+ [focusLinkObserver unsubscribeWithId:linkId
498
+ onLinkUpdated:_rightLinkUpdated
499
+ onLinkRemoved:_rightLinkRemoved];
500
+
501
+ _rightLinkUpdated = nil;
502
+ _rightLinkRemoved = nil;
503
+ [self removeRightGuide];
504
+ }
505
+ }
506
+
507
+ -(void)clearUpLink: (NSString*) linkId {
508
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
509
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
510
+
511
+ if(linkId != nil && _upLinkUpdated != nil && _upLinkRemoved != nil) {
512
+ [focusLinkObserver unsubscribeWithId:linkId
513
+ onLinkUpdated:_upLinkUpdated
514
+ onLinkRemoved:_upLinkRemoved];
515
+ _upLinkUpdated = nil;
516
+ _upLinkRemoved = nil;
517
+
518
+ [self removeUpGuide];
519
+ }
520
+ }
521
+
522
+ -(void)clearDownLink: (NSString*) linkId {
523
+ RNCEKVFocusLinkObserverManager *manager = [RNCEKVFocusLinkObserverManager sharedManager];
524
+ RNCEKVFocusLinkObserver *focusLinkObserver = manager.focusLinkObserver;
525
+
526
+ if(linkId != nil && _downLinkUpdated != nil && _downLinkRemoved != nil) {
527
+ [focusLinkObserver unsubscribeWithId:linkId
528
+ onLinkUpdated:_downLinkUpdated
529
+ onLinkRemoved:_downLinkRemoved];
530
+
531
+ _downLinkUpdated = nil;
532
+ _downLinkRemoved = nil;
533
+
534
+ [self removeDownGuide];
535
+ }
536
+
537
+ }
538
+
539
+ - (void)refreshLeft:(NSString*)prev next:(NSString*)next {
540
+ [self clearLeftLink: prev];
541
+ [self orderLeftLink: next];
542
+ }
543
+
544
+ - (void)refreshRight:(NSString*)prev next:(NSString*)next{
545
+
546
+ [self clearRightLink: prev];
547
+ [self orderRightLink: next];
548
+ }
549
+
550
+ - (void)refreshUp:(NSString*)prev next:(NSString*)next{
551
+ [self clearUpLink: prev];
552
+ [self orderUpLink: next];
553
+ }
554
+
555
+ - (void)refreshDown:(NSString*)prev next:(NSString*)next{
556
+ [self clearDownLink: prev];
557
+ [self orderDownLink: next];
558
+ }
559
+
560
+ - (void)clear {
561
+ NSString* orderId = _delegate.orderId;
562
+ if(orderId != nil) {
563
+ [[RNCEKVOrderLinking sharedInstance] cleanOrderId: orderId];
564
+ }
565
+
566
+ [self clearLeftLink: _delegate.orderLeft];
567
+ [self clearRightLink: _delegate.orderRight];
568
+ [self clearUpLink: _delegate.orderUp];
569
+ [self clearDownLink: _delegate.orderDown];
570
+
571
+ [self refreshId: _delegate.orderId next:nil];
572
+
573
+ }
574
+
575
+
576
+
577
+ @end