@react-native-oh/react-native-harmony 0.72.14-lazy → 0.72.19
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/Libraries/Alert/Alert.harmony.js +1 -1
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.harmony.js +426 -0
- package/Libraries/Components/ScrollView/ScrollView.harmony.js +6 -5
- package/Libraries/Core/setUpReactDevTools.harmony.js +93 -0
- package/Libraries/Image/AssetSourceResolver.harmony.ts +46 -0
- package/Libraries/NativeComponent/BaseViewConfig.harmony.js +12 -0
- package/Libraries/ReactNative/UIManager.harmony.js +210 -0
- package/Libraries/StyleSheet/NativePlatformColor.ts +8 -0
- package/Libraries/StyleSheet/PlatformColorValueTypes.harmony.ts +14 -0
- package/Libraries/Vibration/Vibration.harmony.js +88 -0
- package/index.js +19 -5
- package/jest.config.js +6 -0
- package/metro.config.js +114 -35
- package/package.json +15 -6
- package/{rnoh-4.0.0.202-01-vmall.har → rnoh-4.1.0.401-vmall.har} +0 -0
- package/tsconfig.json +1 -0
- package/types/index.d.ts +6 -6
- package/Libraries/Core/setUpErrorHandling.harmony.js +0 -35
- package/Libraries/NativeModules/specs/NativeDevSettings.harmony.js +0 -10
|
@@ -41,7 +41,7 @@ class Alert {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// At most two buttons. Ignore rest.
|
|
44
|
-
const validButtons: Buttons = buttons.slice(0, 2)
|
|
44
|
+
const validButtons: Buttons = (buttons ?? [{text: "OK"}]).slice(0, 2)
|
|
45
45
|
const secondaryButton = validButtons.pop();
|
|
46
46
|
const primaryButton = validButtons.pop();
|
|
47
47
|
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// RNOH: patch
|
|
12
|
+
// COPIED FROM: https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js
|
|
13
|
+
|
|
14
|
+
import type { HostComponent } from "react-native/Libraries/Renderer/shims/ReactNativeTypes";
|
|
15
|
+
import type { EventSubscription } from "react-native/Libraries/vendor/emitter/EventEmitter";
|
|
16
|
+
import type { ElementRef } from "react";
|
|
17
|
+
|
|
18
|
+
// RNOH: patch - imports fixed
|
|
19
|
+
import RCTDeviceEventEmitter from "react-native/Libraries/EventEmitter/RCTDeviceEventEmitter";
|
|
20
|
+
import { sendAccessibilityEvent } from "react-native/Libraries/ReactNative/RendererProxy";
|
|
21
|
+
import Platform from "../../Utilities/Platform";
|
|
22
|
+
import legacySendAccessibilityEvent from "react-native/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent";
|
|
23
|
+
import NativeAccessibilityInfoAndroid from "react-native/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo";
|
|
24
|
+
import NativeAccessibilityManagerIOS from "react-native/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager";
|
|
25
|
+
|
|
26
|
+
// Events that are only supported on Android.
|
|
27
|
+
type AccessibilityEventDefinitionsAndroid = {
|
|
28
|
+
accessibilityServiceChanged: [boolean],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Events that are only supported on iOS.
|
|
32
|
+
type AccessibilityEventDefinitionsIOS = {
|
|
33
|
+
announcementFinished: [{ announcement: string, success: boolean }],
|
|
34
|
+
boldTextChanged: [boolean],
|
|
35
|
+
grayscaleChanged: [boolean],
|
|
36
|
+
invertColorsChanged: [boolean],
|
|
37
|
+
reduceTransparencyChanged: [boolean],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type AccessibilityEventDefinitions = {
|
|
41
|
+
...AccessibilityEventDefinitionsAndroid,
|
|
42
|
+
...AccessibilityEventDefinitionsIOS,
|
|
43
|
+
change: [boolean], // screenReaderChanged
|
|
44
|
+
reduceMotionChanged: [boolean],
|
|
45
|
+
screenReaderChanged: [boolean],
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
type AccessibilityEventTypes = "click" | "focus" | "viewHoverEnter";
|
|
49
|
+
|
|
50
|
+
// Mapping of public event names to platform-specific event names.
|
|
51
|
+
const EventNames: Map<
|
|
52
|
+
$Keys<AccessibilityEventDefinitions>,
|
|
53
|
+
string
|
|
54
|
+
> = Platform.OS === "android"
|
|
55
|
+
? new Map([
|
|
56
|
+
["change", "touchExplorationDidChange"],
|
|
57
|
+
["reduceMotionChanged", "reduceMotionDidChange"],
|
|
58
|
+
["screenReaderChanged", "touchExplorationDidChange"],
|
|
59
|
+
["accessibilityServiceChanged", "accessibilityServiceDidChange"],
|
|
60
|
+
])
|
|
61
|
+
: new Map([
|
|
62
|
+
["announcementFinished", "announcementFinished"],
|
|
63
|
+
["boldTextChanged", "boldTextChanged"],
|
|
64
|
+
["change", "screenReaderChanged"],
|
|
65
|
+
["grayscaleChanged", "grayscaleChanged"],
|
|
66
|
+
["invertColorsChanged", "invertColorsChanged"],
|
|
67
|
+
["reduceMotionChanged", "reduceMotionChanged"],
|
|
68
|
+
["reduceTransparencyChanged", "reduceTransparencyChanged"],
|
|
69
|
+
["screenReaderChanged", "screenReaderChanged"],
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sometimes it's useful to know whether or not the device has a screen reader
|
|
74
|
+
* that is currently active. The `AccessibilityInfo` API is designed for this
|
|
75
|
+
* purpose. You can use it to query the current state of the screen reader as
|
|
76
|
+
* well as to register to be notified when the state of the screen reader
|
|
77
|
+
* changes.
|
|
78
|
+
*
|
|
79
|
+
* See https://reactnative.dev/docs/accessibilityinfo
|
|
80
|
+
*/
|
|
81
|
+
const AccessibilityInfo = {
|
|
82
|
+
/**
|
|
83
|
+
* Query whether bold text is currently enabled.
|
|
84
|
+
*
|
|
85
|
+
* Returns a promise which resolves to a boolean.
|
|
86
|
+
* The result is `true` when bold text is enabled and `false` otherwise.
|
|
87
|
+
*
|
|
88
|
+
* See https://reactnative.dev/docs/accessibilityinfo#isBoldTextEnabled
|
|
89
|
+
*/
|
|
90
|
+
isBoldTextEnabled(): Promise<boolean> {
|
|
91
|
+
if (Platform.OS === "android") {
|
|
92
|
+
return Promise.resolve(false);
|
|
93
|
+
} else {
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
if (NativeAccessibilityManagerIOS != null) {
|
|
96
|
+
NativeAccessibilityManagerIOS.getCurrentBoldTextState(
|
|
97
|
+
resolve,
|
|
98
|
+
reject
|
|
99
|
+
);
|
|
100
|
+
} else {
|
|
101
|
+
reject(null);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Query whether grayscale is currently enabled.
|
|
109
|
+
*
|
|
110
|
+
* Returns a promise which resolves to a boolean.
|
|
111
|
+
* The result is `true` when grayscale is enabled and `false` otherwise.
|
|
112
|
+
*
|
|
113
|
+
* See https://reactnative.dev/docs/accessibilityinfo#isGrayscaleEnabled
|
|
114
|
+
*/
|
|
115
|
+
isGrayscaleEnabled(): Promise<boolean> {
|
|
116
|
+
if (Platform.OS === "android") {
|
|
117
|
+
return Promise.resolve(false);
|
|
118
|
+
} else {
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
if (NativeAccessibilityManagerIOS != null) {
|
|
121
|
+
NativeAccessibilityManagerIOS.getCurrentGrayscaleState(
|
|
122
|
+
resolve,
|
|
123
|
+
reject
|
|
124
|
+
);
|
|
125
|
+
} else {
|
|
126
|
+
reject(null);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Query whether inverted colors are currently enabled.
|
|
134
|
+
*
|
|
135
|
+
* Returns a promise which resolves to a boolean.
|
|
136
|
+
* The result is `true` when invert color is enabled and `false` otherwise.
|
|
137
|
+
*
|
|
138
|
+
* See https://reactnative.dev/docs/accessibilityinfo#isInvertColorsEnabled
|
|
139
|
+
*/
|
|
140
|
+
isInvertColorsEnabled(): Promise<boolean> {
|
|
141
|
+
if (Platform.OS === "android") {
|
|
142
|
+
return Promise.resolve(false);
|
|
143
|
+
} else {
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
if (NativeAccessibilityManagerIOS != null) {
|
|
146
|
+
NativeAccessibilityManagerIOS.getCurrentInvertColorsState(
|
|
147
|
+
resolve,
|
|
148
|
+
reject
|
|
149
|
+
);
|
|
150
|
+
} else {
|
|
151
|
+
reject(null);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Query whether reduced motion is currently enabled.
|
|
159
|
+
*
|
|
160
|
+
* Returns a promise which resolves to a boolean.
|
|
161
|
+
* The result is `true` when a reduce motion is enabled and `false` otherwise.
|
|
162
|
+
*
|
|
163
|
+
* See https://reactnative.dev/docs/accessibilityinfo#isReduceMotionEnabled
|
|
164
|
+
*/
|
|
165
|
+
isReduceMotionEnabled(): Promise<boolean> {
|
|
166
|
+
return new Promise((resolve, reject) => {
|
|
167
|
+
if (Platform.OS === "android") {
|
|
168
|
+
if (NativeAccessibilityInfoAndroid != null) {
|
|
169
|
+
NativeAccessibilityInfoAndroid.isReduceMotionEnabled(resolve);
|
|
170
|
+
} else {
|
|
171
|
+
reject(null);
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
if (NativeAccessibilityManagerIOS != null) {
|
|
175
|
+
NativeAccessibilityManagerIOS.getCurrentReduceMotionState(
|
|
176
|
+
resolve,
|
|
177
|
+
reject
|
|
178
|
+
);
|
|
179
|
+
} else {
|
|
180
|
+
reject(null);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Query whether reduce motion and prefer cross-fade transitions settings are currently enabled.
|
|
188
|
+
*
|
|
189
|
+
* Returns a promise which resolves to a boolean.
|
|
190
|
+
* The result is `true` when prefer cross-fade transitions is enabled and `false` otherwise.
|
|
191
|
+
*
|
|
192
|
+
* See https://reactnative.dev/docs/accessibilityinfo#prefersCrossFadeTransitions
|
|
193
|
+
*/
|
|
194
|
+
prefersCrossFadeTransitions(): Promise<boolean> {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
if (Platform.OS === "android") {
|
|
197
|
+
return Promise.resolve(false);
|
|
198
|
+
} else {
|
|
199
|
+
if (
|
|
200
|
+
NativeAccessibilityManagerIOS?.getCurrentPrefersCrossFadeTransitionsState !=
|
|
201
|
+
null
|
|
202
|
+
) {
|
|
203
|
+
NativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState(
|
|
204
|
+
resolve,
|
|
205
|
+
reject
|
|
206
|
+
);
|
|
207
|
+
} else {
|
|
208
|
+
reject(null);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Query whether reduced transparency is currently enabled.
|
|
216
|
+
*
|
|
217
|
+
* Returns a promise which resolves to a boolean.
|
|
218
|
+
* The result is `true` when a reduce transparency is enabled and `false` otherwise.
|
|
219
|
+
*
|
|
220
|
+
* See https://reactnative.dev/docs/accessibilityinfo#isReduceTransparencyEnabled
|
|
221
|
+
*/
|
|
222
|
+
isReduceTransparencyEnabled(): Promise<boolean> {
|
|
223
|
+
if (Platform.OS === "android") {
|
|
224
|
+
return Promise.resolve(false);
|
|
225
|
+
} else {
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
if (NativeAccessibilityManagerIOS != null) {
|
|
228
|
+
NativeAccessibilityManagerIOS.getCurrentReduceTransparencyState(
|
|
229
|
+
resolve,
|
|
230
|
+
reject
|
|
231
|
+
);
|
|
232
|
+
} else {
|
|
233
|
+
reject(null);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Query whether a screen reader is currently enabled.
|
|
241
|
+
*
|
|
242
|
+
* Returns a promise which resolves to a boolean.
|
|
243
|
+
* The result is `true` when a screen reader is enabled and `false` otherwise.
|
|
244
|
+
*
|
|
245
|
+
* See https://reactnative.dev/docs/accessibilityinfo#isScreenReaderEnabled
|
|
246
|
+
*/
|
|
247
|
+
isScreenReaderEnabled(): Promise<boolean> {
|
|
248
|
+
return new Promise((resolve, reject) => {
|
|
249
|
+
// RNOH: path to support open harmony
|
|
250
|
+
if (Platform.OS === "android" || Platform.OS === "harmony") {
|
|
251
|
+
if (NativeAccessibilityInfoAndroid != null) {
|
|
252
|
+
NativeAccessibilityInfoAndroid.isTouchExplorationEnabled(resolve);
|
|
253
|
+
} else {
|
|
254
|
+
reject(null);
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
if (NativeAccessibilityManagerIOS != null) {
|
|
258
|
+
NativeAccessibilityManagerIOS.getCurrentVoiceOverState(
|
|
259
|
+
resolve,
|
|
260
|
+
reject
|
|
261
|
+
);
|
|
262
|
+
} else {
|
|
263
|
+
reject(null);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Query whether Accessibility Service is currently enabled.
|
|
271
|
+
*
|
|
272
|
+
* Returns a promise which resolves to a boolean.
|
|
273
|
+
* The result is `true` when any service is enabled and `false` otherwise.
|
|
274
|
+
*
|
|
275
|
+
* @platform android
|
|
276
|
+
*
|
|
277
|
+
* See https://reactnative.dev/docs/accessibilityinfo/#isaccessibilityserviceenabled-android
|
|
278
|
+
*/
|
|
279
|
+
isAccessibilityServiceEnabled(): Promise<boolean> {
|
|
280
|
+
return new Promise((resolve, reject) => {
|
|
281
|
+
if (Platform.OS === "android") {
|
|
282
|
+
if (
|
|
283
|
+
NativeAccessibilityInfoAndroid != null &&
|
|
284
|
+
NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled != null
|
|
285
|
+
) {
|
|
286
|
+
NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled(resolve);
|
|
287
|
+
} else {
|
|
288
|
+
reject(null);
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
reject(null);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Add an event handler. Supported events:
|
|
298
|
+
*
|
|
299
|
+
* - `reduceMotionChanged`: Fires when the state of the reduce motion toggle changes.
|
|
300
|
+
* The argument to the event handler is a boolean. The boolean is `true` when a reduce
|
|
301
|
+
* motion is enabled (or when "Transition Animation Scale" in "Developer options" is
|
|
302
|
+
* "Animation off") and `false` otherwise.
|
|
303
|
+
* - `screenReaderChanged`: Fires when the state of the screen reader changes. The argument
|
|
304
|
+
* to the event handler is a boolean. The boolean is `true` when a screen
|
|
305
|
+
* reader is enabled and `false` otherwise.
|
|
306
|
+
*
|
|
307
|
+
* These events are only supported on iOS:
|
|
308
|
+
*
|
|
309
|
+
* - `boldTextChanged`: iOS-only event. Fires when the state of the bold text toggle changes.
|
|
310
|
+
* The argument to the event handler is a boolean. The boolean is `true` when a bold text
|
|
311
|
+
* is enabled and `false` otherwise.
|
|
312
|
+
* - `grayscaleChanged`: iOS-only event. Fires when the state of the gray scale toggle changes.
|
|
313
|
+
* The argument to the event handler is a boolean. The boolean is `true` when a gray scale
|
|
314
|
+
* is enabled and `false` otherwise.
|
|
315
|
+
* - `invertColorsChanged`: iOS-only event. Fires when the state of the invert colors toggle
|
|
316
|
+
* changes. The argument to the event handler is a boolean. The boolean is `true` when a invert
|
|
317
|
+
* colors is enabled and `false` otherwise.
|
|
318
|
+
* - `reduceTransparencyChanged`: iOS-only event. Fires when the state of the reduce transparency
|
|
319
|
+
* toggle changes. The argument to the event handler is a boolean. The boolean is `true`
|
|
320
|
+
* when a reduce transparency is enabled and `false` otherwise.
|
|
321
|
+
* - `announcementFinished`: iOS-only event. Fires when the screen reader has
|
|
322
|
+
* finished making an announcement. The argument to the event handler is a
|
|
323
|
+
* dictionary with these keys:
|
|
324
|
+
* - `announcement`: The string announced by the screen reader.
|
|
325
|
+
* - `success`: A boolean indicating whether the announcement was
|
|
326
|
+
* successfully made.
|
|
327
|
+
*
|
|
328
|
+
* See https://reactnative.dev/docs/accessibilityinfo#addeventlistener
|
|
329
|
+
*/
|
|
330
|
+
addEventListener<K: $Keys<AccessibilityEventDefinitions>>(
|
|
331
|
+
eventName: K,
|
|
332
|
+
// $FlowIssue[incompatible-type] - Flow bug with unions and generics (T128099423)
|
|
333
|
+
handler: (...$ElementType<AccessibilityEventDefinitions, K>) => void
|
|
334
|
+
): EventSubscription {
|
|
335
|
+
const deviceEventName = EventNames.get(eventName);
|
|
336
|
+
return deviceEventName == null
|
|
337
|
+
? { remove(): void {} }
|
|
338
|
+
: // $FlowFixMe[incompatible-call]
|
|
339
|
+
RCTDeviceEventEmitter.addListener(deviceEventName, handler);
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Set accessibility focus to a React component.
|
|
344
|
+
*
|
|
345
|
+
* See https://reactnative.dev/docs/accessibilityinfo#setaccessibilityfocus
|
|
346
|
+
*/
|
|
347
|
+
setAccessibilityFocus(reactTag: number): void {
|
|
348
|
+
legacySendAccessibilityEvent(reactTag, "focus");
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Send a named accessibility event to a HostComponent.
|
|
353
|
+
*/
|
|
354
|
+
sendAccessibilityEvent(
|
|
355
|
+
handle: ElementRef<HostComponent<mixed>>,
|
|
356
|
+
eventType: AccessibilityEventTypes
|
|
357
|
+
) {
|
|
358
|
+
// iOS only supports 'focus' event types
|
|
359
|
+
if (Platform.OS === "ios" && eventType === "click") {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
// route through React renderer to distinguish between Fabric and non-Fabric handles
|
|
363
|
+
sendAccessibilityEvent(handle, eventType);
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Post a string to be announced by the screen reader.
|
|
368
|
+
*
|
|
369
|
+
* See https://reactnative.dev/docs/accessibilityinfo#announceforaccessibility
|
|
370
|
+
*/
|
|
371
|
+
announceForAccessibility(announcement: string): void {
|
|
372
|
+
if (Platform.OS === "android") {
|
|
373
|
+
NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement);
|
|
374
|
+
} else {
|
|
375
|
+
NativeAccessibilityManagerIOS?.announceForAccessibility(announcement);
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Post a string to be announced by the screen reader.
|
|
381
|
+
* - `announcement`: The string announced by the screen reader.
|
|
382
|
+
* - `options`: An object that configures the reading options.
|
|
383
|
+
* - `queue`: The announcement will be queued behind existing announcements. iOS only.
|
|
384
|
+
*/
|
|
385
|
+
announceForAccessibilityWithOptions(
|
|
386
|
+
announcement: string,
|
|
387
|
+
options: { queue?: boolean }
|
|
388
|
+
): void {
|
|
389
|
+
if (Platform.OS === "android") {
|
|
390
|
+
NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement);
|
|
391
|
+
} else {
|
|
392
|
+
if (NativeAccessibilityManagerIOS?.announceForAccessibilityWithOptions) {
|
|
393
|
+
NativeAccessibilityManagerIOS?.announceForAccessibilityWithOptions(
|
|
394
|
+
announcement,
|
|
395
|
+
options
|
|
396
|
+
);
|
|
397
|
+
} else {
|
|
398
|
+
NativeAccessibilityManagerIOS?.announceForAccessibility(announcement);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Get the recommended timeout for changes to the UI needed by this user.
|
|
405
|
+
*
|
|
406
|
+
* See https://reactnative.dev/docs/accessibilityinfo#getrecommendedtimeoutmillis
|
|
407
|
+
*/
|
|
408
|
+
getRecommendedTimeoutMillis(originalTimeout: number): Promise<number> {
|
|
409
|
+
if (Platform.OS === "android") {
|
|
410
|
+
return new Promise((resolve, reject) => {
|
|
411
|
+
if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis) {
|
|
412
|
+
NativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis(
|
|
413
|
+
originalTimeout,
|
|
414
|
+
resolve
|
|
415
|
+
);
|
|
416
|
+
} else {
|
|
417
|
+
resolve(originalTimeout);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
} else {
|
|
421
|
+
return Promise.resolve(originalTimeout);
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
export default AccessibilityInfo;
|
|
@@ -1316,7 +1316,8 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
1316
1316
|
FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation
|
|
1317
1317
|
|
|
1318
1318
|
if (
|
|
1319
|
-
|
|
1319
|
+
// RNOH: patch - add support for OpenHarmony
|
|
1320
|
+
(Platform.OS === "android" || Platform.OS === "harmony") &&
|
|
1320
1321
|
this.props.keyboardDismissMode === "on-drag"
|
|
1321
1322
|
) {
|
|
1322
1323
|
dismissKeyboard();
|
|
@@ -1809,10 +1810,10 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
1809
1810
|
// default to true
|
|
1810
1811
|
snapToEnd: this.props.snapToEnd !== false,
|
|
1811
1812
|
// pagingEnabled is overridden by snapToInterval / snapToOffsets
|
|
1812
|
-
pagingEnabled:
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1813
|
+
pagingEnabled:
|
|
1814
|
+
this.props.pagingEnabled === true &&
|
|
1815
|
+
this.props.snapToInterval == null &&
|
|
1816
|
+
this.props.snapToOffsets == null,
|
|
1816
1817
|
};
|
|
1817
1818
|
|
|
1818
1819
|
const { decelerationRate } = this.props;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
if (__DEV__) {
|
|
14
|
+
let isWebSocketOpen = false;
|
|
15
|
+
let ws = null;
|
|
16
|
+
|
|
17
|
+
const reactDevTools = require('react-devtools-core');
|
|
18
|
+
const connectToDevTools = () => {
|
|
19
|
+
if (ws !== null && isWebSocketOpen) {
|
|
20
|
+
// If the DevTools backend is already connected, don't recreate the WebSocket.
|
|
21
|
+
// This would break the connection.
|
|
22
|
+
// If there isn't an active connection, a backend may be waiting to connect,
|
|
23
|
+
// in which case it's okay to make a new one.
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// not when debugging in chrome
|
|
28
|
+
// TODO(t12832058) This check is broken
|
|
29
|
+
if (!window.document) {
|
|
30
|
+
const AppState = require('react-native/Libraries/AppState/AppState');
|
|
31
|
+
const getDevServer = require('react-native/Libraries/Core/Devtools/getDevServer');
|
|
32
|
+
|
|
33
|
+
// Don't steal the DevTools from currently active app.
|
|
34
|
+
// Note: if you add any AppState subscriptions to this file,
|
|
35
|
+
// you will also need to guard against `AppState.isAvailable`,
|
|
36
|
+
// or the code will throw for bundles that don't have it.
|
|
37
|
+
const isAppActive = () => AppState.currentState !== 'background';
|
|
38
|
+
|
|
39
|
+
// RNOH patch: wait until appstate is active before connecting
|
|
40
|
+
if (!isAppActive()) {
|
|
41
|
+
const subscription = AppState.addEventListener('change', () => {
|
|
42
|
+
if (isAppActive()) {
|
|
43
|
+
connectToDevTools();
|
|
44
|
+
subscription.remove();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Get hostname from development server (packager)
|
|
51
|
+
const devServer = getDevServer();
|
|
52
|
+
const host = devServer.bundleLoadedFromServer
|
|
53
|
+
? devServer.url
|
|
54
|
+
.replace(/https?:\/\//, '')
|
|
55
|
+
.replace(/\/$/, '')
|
|
56
|
+
.split(':')[0]
|
|
57
|
+
: 'localhost';
|
|
58
|
+
|
|
59
|
+
// Read the optional global variable for backward compatibility.
|
|
60
|
+
// It was added in https://github.com/facebook/react-native/commit/bf2b435322e89d0aeee8792b1c6e04656c2719a0.
|
|
61
|
+
const port =
|
|
62
|
+
window.__REACT_DEVTOOLS_PORT__ != null
|
|
63
|
+
? window.__REACT_DEVTOOLS_PORT__
|
|
64
|
+
: 8097;
|
|
65
|
+
|
|
66
|
+
const WebSocket = require('react-native/Libraries/WebSocket/WebSocket');
|
|
67
|
+
ws = new WebSocket('ws://' + host + ':' + port);
|
|
68
|
+
ws.addEventListener('close', event => {
|
|
69
|
+
isWebSocketOpen = false;
|
|
70
|
+
});
|
|
71
|
+
ws.addEventListener('open', event => {
|
|
72
|
+
isWebSocketOpen = true;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const ReactNativeStyleAttributes = require('react-native/Libraries/Components/View/ReactNativeStyleAttributes');
|
|
76
|
+
const devToolsSettingsManager = require('react-native/Libraries/DevToolsSettings/DevToolsSettingsManager');
|
|
77
|
+
|
|
78
|
+
reactDevTools.connectToDevTools({
|
|
79
|
+
isAppActive,
|
|
80
|
+
resolveRNStyle: require('react-native/Libraries/StyleSheet/flattenStyle'),
|
|
81
|
+
nativeStyleEditorValidAttributes: Object.keys(
|
|
82
|
+
ReactNativeStyleAttributes,
|
|
83
|
+
),
|
|
84
|
+
websocket: ws,
|
|
85
|
+
devToolsSettingsManager,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const RCTNativeAppEventEmitter = require('react-native/Libraries/EventEmitter/RCTNativeAppEventEmitter');
|
|
91
|
+
RCTNativeAppEventEmitter.addListener('RCTDevMenuShown', connectToDevTools);
|
|
92
|
+
connectToDevTools(); // Try connecting once on load
|
|
93
|
+
}
|
|
@@ -2,6 +2,10 @@ import {
|
|
|
2
2
|
getAssetDestRelativePath,
|
|
3
3
|
Asset,
|
|
4
4
|
} from '@react-native-oh/react-native-harmony-cli/src/assetResolver';
|
|
5
|
+
import {
|
|
6
|
+
getBasePath,
|
|
7
|
+
} from '@react-native/assets-registry/path-support';
|
|
8
|
+
import { Platform } from 'react-native';
|
|
5
9
|
|
|
6
10
|
type ResolvedAssetSource = {
|
|
7
11
|
readonly __packager_asset: boolean;
|
|
@@ -11,6 +15,11 @@ type ResolvedAssetSource = {
|
|
|
11
15
|
readonly scale: number;
|
|
12
16
|
};
|
|
13
17
|
|
|
18
|
+
function getAssetPath(asset: Asset): string {
|
|
19
|
+
const assetDir = getBasePath(asset);
|
|
20
|
+
return assetDir + '/' + asset.name + '.' + asset.type;
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
class AssetSourceResolver {
|
|
15
24
|
constructor(
|
|
16
25
|
private serverUrl: string | undefined,
|
|
@@ -18,7 +27,15 @@ class AssetSourceResolver {
|
|
|
18
27
|
private asset: Asset
|
|
19
28
|
) {}
|
|
20
29
|
|
|
30
|
+
isLoadedFromServer(): boolean {
|
|
31
|
+
return !!this.serverUrl;
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
public defaultAsset(): ResolvedAssetSource {
|
|
35
|
+
if (this.isLoadedFromServer()) {
|
|
36
|
+
return this.assetServerURL();
|
|
37
|
+
}
|
|
38
|
+
|
|
22
39
|
return {
|
|
23
40
|
__packager_asset: this.asset.__packager_asset,
|
|
24
41
|
uri: `asset://${getAssetDestRelativePath(this.asset)}`,
|
|
@@ -27,6 +44,35 @@ class AssetSourceResolver {
|
|
|
27
44
|
height: this.asset.height,
|
|
28
45
|
};
|
|
29
46
|
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Returns an absolute URL which can be used to fetch the asset
|
|
50
|
+
* from the devserver
|
|
51
|
+
*/
|
|
52
|
+
assetServerURL(): ResolvedAssetSource {
|
|
53
|
+
if (!this.serverUrl) {
|
|
54
|
+
throw new Error('need server to load from');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return this.fromSource(
|
|
58
|
+
this.serverUrl +
|
|
59
|
+
getAssetPath(this.asset) +
|
|
60
|
+
'?platform=' +
|
|
61
|
+
Platform.OS +
|
|
62
|
+
'&hash=' +
|
|
63
|
+
this.asset.hash,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fromSource(source: string): ResolvedAssetSource {
|
|
68
|
+
return {
|
|
69
|
+
__packager_asset: true,
|
|
70
|
+
width: this.asset.width,
|
|
71
|
+
height: this.asset.height,
|
|
72
|
+
uri: source,
|
|
73
|
+
scale: 1,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
30
76
|
}
|
|
31
77
|
|
|
32
78
|
module.exports = AssetSourceResolver;
|
|
@@ -23,6 +23,18 @@ const bubblingEventTypes = {
|
|
|
23
23
|
bubbled: 'onChange',
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
|
+
topFocus: {
|
|
27
|
+
phasedRegistrationNames: {
|
|
28
|
+
bubbled: 'onFocus',
|
|
29
|
+
captured: 'onFocusCapture',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
topBlur: {
|
|
33
|
+
phasedRegistrationNames: {
|
|
34
|
+
bubbled: 'onBlur',
|
|
35
|
+
captured: 'onBlurCapture',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
26
38
|
topSelect: {
|
|
27
39
|
phasedRegistrationNames: {
|
|
28
40
|
captured: 'onSelectCapture',
|