@thiagobueno/rn-selectable-text 1.0.2 → 1.0.4
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/ios/SelectableTextView.mm +43 -12
- package/package.json +2 -2
|
@@ -18,8 +18,25 @@ using namespace facebook::react;
|
|
|
18
18
|
|
|
19
19
|
@implementation SelectableUITextView
|
|
20
20
|
|
|
21
|
+
- (void)didMoveToWindow {
|
|
22
|
+
[super didMoveToWindow];
|
|
23
|
+
// FIX: iOS 16+ text selection bug after navigation.
|
|
24
|
+
// When returning to the screen, we force iOS to re-evaluate the interaction state.
|
|
25
|
+
if (self.window) {
|
|
26
|
+
BOOL wasSelectable = self.selectable;
|
|
27
|
+
self.selectable = NO;
|
|
28
|
+
self.selectable = wasSelectable;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
21
32
|
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
|
22
33
|
{
|
|
34
|
+
// FIX: We explicitly tell iOS that we can perform standard actions.
|
|
35
|
+
// This prevents the "[UIKitCore] The edit menu did not have performable commands" warning.
|
|
36
|
+
if (action == @selector(copy:) || action == @selector(selectAll:)) {
|
|
37
|
+
return YES;
|
|
38
|
+
}
|
|
39
|
+
|
|
23
40
|
if (self.parentSelectableTextView) {
|
|
24
41
|
return [self.parentSelectableTextView canPerformAction:action withSender:sender];
|
|
25
42
|
}
|
|
@@ -46,10 +63,10 @@ using namespace facebook::react;
|
|
|
46
63
|
}
|
|
47
64
|
}
|
|
48
65
|
|
|
49
|
-
//
|
|
66
|
+
// Intercepts physical keyboard "Copy" and nullifies the action to keep it custom
|
|
50
67
|
- (void)copy:(id)sender
|
|
51
68
|
{
|
|
52
|
-
//
|
|
69
|
+
// Silently blocked
|
|
53
70
|
}
|
|
54
71
|
|
|
55
72
|
@end
|
|
@@ -125,13 +142,19 @@ using namespace facebook::react;
|
|
|
125
142
|
- (void)prepareForRecycle {
|
|
126
143
|
[super prepareForRecycle];
|
|
127
144
|
|
|
145
|
+
// FIX: Force drop focus when leaving screen
|
|
146
|
+
[_customTextView resignFirstResponder];
|
|
147
|
+
|
|
128
148
|
[[UIMenuController sharedMenuController] hideMenuFromView:_customTextView];
|
|
129
149
|
[UIMenuController sharedMenuController].menuItems = nil;
|
|
130
150
|
|
|
131
151
|
_customTextView.text = nil;
|
|
132
152
|
_customTextView.selectedTextRange = nil;
|
|
133
|
-
|
|
134
|
-
|
|
153
|
+
|
|
154
|
+
// CRITICAL FIX: Do NOT clear _menuOptions here. Fabric's prop diffing will handle updates.
|
|
155
|
+
// If we clear it here, navigating away and back will result in an empty menu and crash iOS.
|
|
156
|
+
// _menuOptions = @[];
|
|
157
|
+
// _menuOptionsVector.clear();
|
|
135
158
|
|
|
136
159
|
[self unhideAllViews:self];
|
|
137
160
|
}
|
|
@@ -222,9 +245,18 @@ using namespace facebook::react;
|
|
|
222
245
|
#pragma mark - UITextViewDelegate
|
|
223
246
|
|
|
224
247
|
// ====================================================================
|
|
225
|
-
//
|
|
248
|
+
// THE NEW IOS 16+ API
|
|
226
249
|
// ====================================================================
|
|
227
250
|
- (UIMenu *)textView:(UITextView *)textView editMenuForTextInRange:(NSRange)range suggestedActions:(NSArray<UIMenuElement *> *)suggestedActions API_AVAILABLE(ios(16.0)) {
|
|
251
|
+
|
|
252
|
+
// FORCING THE FOCUS: ensures the system doesn't dismiss our menu unexpectedly
|
|
253
|
+
[textView becomeFirstResponder];
|
|
254
|
+
|
|
255
|
+
// SAFETY NET: If options are empty (due to async loading), return standard copy to avoid crash
|
|
256
|
+
if (_menuOptions.count == 0) {
|
|
257
|
+
return [UIMenu menuWithTitle:@"" children:suggestedActions];
|
|
258
|
+
}
|
|
259
|
+
|
|
228
260
|
NSMutableArray<UIMenuElement *> *customActions = [[NSMutableArray alloc] init];
|
|
229
261
|
|
|
230
262
|
for (NSString *option in _menuOptions) {
|
|
@@ -234,7 +266,7 @@ using namespace facebook::react;
|
|
|
234
266
|
[customActions addObject:action];
|
|
235
267
|
}
|
|
236
268
|
|
|
237
|
-
//
|
|
269
|
+
// Returns only our custom menu. The native "Copy" action required by the system is swallowed and doesn't appear.
|
|
238
270
|
return [UIMenu menuWithTitle:@"" children:customActions];
|
|
239
271
|
}
|
|
240
272
|
|
|
@@ -291,7 +323,7 @@ using namespace facebook::react;
|
|
|
291
323
|
}
|
|
292
324
|
|
|
293
325
|
// ====================================================================
|
|
294
|
-
//
|
|
326
|
+
// THE TRICK TO FORCE THE MENU TO OPEN AND PREVENT UIKIT WARNINGS
|
|
295
327
|
// ====================================================================
|
|
296
328
|
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
|
297
329
|
{
|
|
@@ -300,11 +332,10 @@ using namespace facebook::react;
|
|
|
300
332
|
return YES;
|
|
301
333
|
}
|
|
302
334
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
335
|
+
// We tell iOS that we can perform standard actions.
|
|
336
|
+
// This convinces the system not to abort the menu rendering.
|
|
337
|
+
if (action == @selector(copy:) || action == @selector(selectAll:)) {
|
|
338
|
+
return YES;
|
|
308
339
|
}
|
|
309
340
|
|
|
310
341
|
return NO;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thiagobueno/rn-selectable-text",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A library for custom text selection menus",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -164,4 +164,4 @@
|
|
|
164
164
|
"type": "fabric-view",
|
|
165
165
|
"version": "0.54.2"
|
|
166
166
|
}
|
|
167
|
-
}
|
|
167
|
+
}
|