@react-native-ohos/react-native-webview 13.16.2-beta.5 → 13.16.2

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/CHANGELOG.md CHANGED
@@ -1,33 +1,29 @@
1
1
  # Changelog
2
- ## 鸿蒙化Log
3
2
 
4
- ### 13.16.2-beta.5
5
- - fix: 修改web链接校验方案
3
+ ## [13.16.2] - 2026-08-17
6
4
 
7
- ### 13.16.2-rc.4
8
- - feat: 适配webview嵌套滚动
5
+ ### Added
6
+ - 适配webview嵌套滚动
7
+ - 新增renderMode属性
8
+ - react-native-webview适配文本长按禁用选择框
9
+ - react-native-webview适配mediaCapturePermissionGrantType属性
10
+ - add landscape/portrait switching for video([#122](https://gitcode.com/CPF-RN/rntpc_react-native-webview/pull/122))
9
11
 
10
- ### 13.16.2-rc.3
11
- - feat: 新增renderMode属性
12
+ ### Fixed
13
+ - 修改web链接校验方案
14
+ - 修改forceDarkOn属性颜色设置错误的问题([#103](https://gitcode.com/CPF-RN/rntpc_react-native-webview/issues/103))
15
+ - Resolve the stability issues and memory leaks ([#123](https://gitcode.com/CPF-RN/rntpc_react-native-webview/pull/123))
12
16
 
13
- ### 13.16.2-beta.2
14
- - feat: feat:react-native-webview适配文本长按禁用选择框
15
- - feat:react-native-webview适配mediaCapturePermissionGrantType属性
16
17
 
18
+ ## [13.16.1] - 2026-03-26
17
19
 
18
- ### 13.16.1
19
- - release version 13.16.1
20
+ ### Added
21
+ - Upgrade to the upstream community version
22
+ - add OpenHarmony support for react-native-webview
20
23
 
21
- ### 13.16.1-rc.1
22
- - pre-release version 13.16.1-rc.1
23
- - feat: Upgrade to the upstream community version
24
+ ### Changed
24
25
 
25
- ### v13.15.1-rc.2
26
- - pre-release: @react-native-ohos/react-native-webview@13.15.1-rc.2
27
-
28
- ### v13.15.1-rc.1
29
- - pre-release: @react-native-ohos/react-native-webview@13.15.1-rc.21
30
- - feat: add OpenHarmony support for react-native-webview
26
+ ### Fixed
31
27
 
32
28
  ## ReleaseLog
33
29
  ### v13.15.0
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- > 模板版本:v0.4.0
1
+ > 模板版本:v0.4.1
2
2
 
3
3
  <p align="center">
4
4
  <h1 align="center"> <code>react-native-webview</code> </h1>
@@ -12,7 +12,7 @@
12
12
  </a>
13
13
  </p>
14
14
 
15
- > [!TIP] [Github 地址](https://github.com/react-native-oh-library/react-native-webview)
15
+ 本项目基于 [react-native-webview](https://github.com/react-native-webview/react-native-webview)开发。
16
16
 
17
17
  ## 安装与使用
18
18
 
@@ -20,12 +20,9 @@
20
20
 
21
21
  | 三方库名称 | 三方库版本 | 发布信息 | 支持RN版本 | Autolink | 编译API版本 | 社区基线版本 | npm地址
22
22
  | ------------ |---------|---------------------------------------------------------------------------------------------|----------------------|--------------------|-------------------|----------------------------|----------------------------------|
23
- |@react-native-ohos/react-native-webview| ~13.16.1 | [Gitcode Releases](https://gitcode.com/openharmony-sig/rntpc_react-native-webview/releases) | 0.82.* | 否 | API20+ | 13.16.0 | [Npm Address](https://www.npmjs.com/package/@react-native-ohos/react-native-webview)|
24
- |@react-native-ohos/react-native-webview| ~13.15.1 | [Gitcode Releases](https://gitcode.com/openharmony-sig/rntpc_react-native-webview/releases) | 0.77.* | 否 | API20+ | 13.15.0 | [Npm Address](https://www.npmjs.com/package/@react-native-ohos/react-native-webview)|
25
- |@react-native-ohos/react-native-webview| ~13.10.5 | [Gitcode Releases](https://gitcode.com/openharmony-sig/rntpc_react-native-webview/releases) | 0.72.* | 是 |API20+ | 13.10.2 | [Npm Address](https://www.npmjs.com/package/@react-native-ohos/react-native-webview)|
26
- |@react-native-oh-tpl/react-native-webview| <=13.10.4@deprecated | [Github Releases(deprecated)](https://github.com/react-native-oh-library/react-native-webview/releases) | 0.72.* | 否 | API12+ | 13.10.2 | [Npm Address](https://www.npmjs.com/package/@react-native-oh-tpl/react-native-webview) |
23
+ |@react-native-ohos/react-native-webview| ~13.16.1 | [Gitcode Releases](https://gitcode.com/CPF-RN/rntpc_react-native-webview/releases) | 0.82.* | 否 | API20+ | 13.16.0 | [Npm Address](https://www.npmjs.com/package/@react-native-ohos/react-native-webview)|
27
24
 
28
- 对于未发布到npm的旧版本,请参考[安装指南](/tgz-usage.md)安装tgz包。
25
+ 对于未发布到npm的旧版本,请参考[安装指南](https://gitcode.com/CPF-RN/usage-docs/blob/master/zh-cn/tgz-usage.md)安装tgz包。
29
26
 
30
27
  进入到工程目录并输入以下命令:
31
28
 
@@ -62,18 +59,14 @@ export default function WebViewDemo() {
62
59
 
63
60
  ## Link
64
61
 
65
- | | Is supported autolink | Supported RN Version |
62
+ | | 是否支持 Autolink | 支持的 RN 版本 |
66
63
  |--------------------------------------|-----------------------|----------------------|
67
- | ~13.16.1 | No | 0.82 |
68
- | ~13.15.1 | No | 0.77 |
69
- | ~13.10.5 | Yes | 0.72 |
70
- | <= 13.10.4@deprecated | No | 0.72 |
64
+ | ~13.16.1 | | 0.82 |
71
65
 
72
- 使用AutoLink的工程需要根据该文档配置,Autolink框架指导文档:https://gitcode.com/openharmony-sig/ohos_react_native/blob/master/docs/zh-cn/Autolinking.md
66
+ 使用AutoLink的工程需要根据该文档配置,Autolink框架指导文档:https://gitcode.com/CPF-RN/ohos_react_native/blob/master/docs/zh-cn/Autolinking.md
73
67
 
74
68
  如您使用的版本支持 Autolink,并且工程已接入 Autolink,可跳过ManualLink配置。
75
- <details>
76
- <summary>ManualLink: 此步骤为手动配置原生依赖项的指导</summary>
69
+ ManualLink: 此步骤为手动配置原生依赖项的指导
77
70
 
78
71
  首先需要使用 DevEco Studio 打开项目里的 HarmonyOS 工程 `harmony`
79
72
 
@@ -120,7 +113,7 @@ ohpm install
120
113
 
121
114
  方法二:直接链接源码
122
115
 
123
- > [!TIP] 如需使用直接链接源码,请参考[直接链接源码说明](/link-source-code.md)
116
+ > [!TIP] 如需使用直接链接源码,请参考[直接链接源码说明](https://gitcode.com/CPF-RN/usage-docs/blob/master/zh-cn/link-source-code.md)
124
117
 
125
118
  ### 3.配置 CMakeLists 和引入 WebViewPackage
126
119
 
@@ -253,10 +246,75 @@ ohpm install
253
246
 
254
247
  在以下版本验证通过:
255
248
 
256
- 1. RNOH: 0.72.96; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
257
- 2. RNOH: 0.72.33; SDK: HarmonyOS NEXT B1; IDE: DevEco Studio: 5.0.3.900; ROM: Next.0.0.71;
258
- 3. RNOH: 0.77.18; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
259
- 4. RNOH: 0.82.1; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
249
+ 1. RNOH: 0.82.1; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
250
+
251
+ ### 权限要求
252
+
253
+ > [!TIP] 以下权限为按需申请:若不使用相关功能,无需配置。
254
+
255
+ | 权限名 | 触发场景 |
256
+ | --- | --- |
257
+ | `ohos.permission.APPROXIMATELY_LOCATION` | 设置 `geolocationEnabled={true}`,网页请求定位时。 |
258
+ | `ohos.permission.CAMERA` | 网页通过 `mediaCapturePermissionGrantType` 请求摄像头(`TYPE_VIDEO_CAPTURE`)时。 |
259
+ | `ohos.permission.MICROPHONE` | 网页通过 `mediaCapturePermissionGrantType` 请求麦克风(`TYPE_AUDIO_CAPTURE`)时。 |
260
+
261
+ 在 `entry` 目录下的 `module.json5` 中添加权限
262
+
263
+ ```
264
+ "requestPermissions": [
265
+ + {
266
+ + "name": "ohos.permission.APPROXIMATELY_LOCATION", // 定位权限名称
267
+ + "reason": "$string:webview_location_reason",
268
+ + "usedScene": {
269
+ + "abilities": [
270
+ + "EntryAbility"
271
+ + ],
272
+ + "when":"inuse"
273
+ + }
274
+ + },
275
+ + {
276
+ + "name": "ohos.permission.CAMERA", // 相机权限名称
277
+ + "reason": "$string:webview_camera_reason",
278
+ + "usedScene": {
279
+ + "abilities": [
280
+ + "EntryAbility"
281
+ + ],
282
+ + "when":"inuse"
283
+ + }
284
+ + },
285
+ + {
286
+ + "name": "ohos.permission.MICROPHONE", // 麦克风权限名称
287
+ + "reason": "$string:webview_microphone_reason",
288
+ + "usedScene": {
289
+ + "abilities": [
290
+ + "EntryAbility"
291
+ + ],
292
+ + "when":"inuse"
293
+ + }
294
+ + },
295
+ ]
296
+ ```
297
+
298
+ 在 entry 目录下添加申请以上权限的原因
299
+ 打开 `entry/src/main/resources/base/element/string.json`,添加:
300
+ ```
301
+ {
302
+ "string": [
303
+ + {
304
+ + "name": "webview_location_reason",
305
+ + "value": "用于网页获取地理位置"
306
+ + },
307
+ + {
308
+ + "name": "webview_camera_reason",
309
+ + "value": "用于网页访问摄像头"
310
+ + },
311
+ + {
312
+ + "name": "webview_microphone_reason",
313
+ + "value": "用于网页访问麦克风"
314
+ + },
315
+ ]
316
+ }
317
+ ```
260
318
 
261
319
  ## 属性
262
320
  > [!WARNING]ignoreSilentHardwareSwitch需要设置true网页播放才有声音
@@ -267,76 +325,79 @@ ohpm install
267
325
 
268
326
  详情请查看[webview 官方文档](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md)
269
327
 
270
- | Name | Description | Type | Required | Platform | HarmonyOS Support |
328
+ | 名称 | 描述 | 类型 | 必填 | 平台 | 鸿蒙支持 |
271
329
  |----------------------------------------------------------| ------------------------------------------------------------ | -------- |----------|---------------------|------------------------------------------------------------------------------------|
272
- | `source` | Loads static HTML or a URI (with optional headers) in the WebView | object | yes | All | partially (Only of: **Load uri :** uri headers **Static HTML :** html baseUrl) |
273
- | `ref` | Used to get a reference to a component instance | object | yes | All | yes |
274
- | `injectedJavaScript?` | Set this to provide JavaScript that will be injected into the web page after the document finishes loading | string | No | All | yes |
275
- | `originWhitelist?` | List of origin strings to allow being navigated to. | string[] | No | iOS,Android,macOS | No |
276
- | `scalesPageToFit?` | Boolean that controls whether the web content is scaled to fit the view and enables the user to change the scale. | boolean | No | Android | yes |
277
- | `startInLoadingState?` | Boolean value that forces the WebView to show the loading view on the first load. | boolean | No | iOS,Android,macOS | No |
278
- | `style?` | A style object that allow you to customize the WebView style. | Style | No | ALL | yes |
279
- | `domStorageEnabled?` | Boolean value to control whether DOM Storage is enabled. Used only in Android and harmony. | boolean | No | Android | yes |
280
- | `javaScriptEnabled?` | Boolean value to enable JavaScript in the WebView. | boolean | No | All | yes |
281
- | `showsHorizontalScrollIndicator?` | Boolean value that determines whether a horizontal scroll indicator is shown in the WebView. | boolean | No | iOS,Android,macOS | yes |
282
- | `showsVerticalScrollIndicator` | Boolean value that determines whether a vertical scroll indicator is shown in the WebView. | boolean | No | iOS,Android,macOS | yes |
283
- | `ignoreSilentHardwareSwitch` | Boolean value that When set to true the hardware silent switch is ignored. | boolean | No | iOS | yes |
284
- | `cacheEnabled?` | Sets whether WebView should use browser caching. | boolean | No | iOS,Android,macOS | yes |
285
- | `cacheMode?` | Overrides the way the cache is used. | string | No | Android | yes |
286
- | `textZoom?` | If the user has set a custom font size in the Android and harmony system, an undesirable scale of the site interface in WebView occurs. | number | No | Android | yes |
287
- | `incognito?` | Does not store any data within the lifetime of the WebView. | boolean | NO | All | yes |
288
- | `mediaPlaybackRequiresUserAction?` | Boolean that determines whether HTML5 audio and video requires the user to tap them before they start playing. The default value is `true`. (Android API minimum version 17). | boolean | NO | iOS,Android,macOS | yes |
289
- | `geolocationEnabled?` | Set whether Geolocation is enabled in the `WebView`. The default value is `false`. Used only in Android. | boolean | NO | Android | yes |
290
- | `fraudulentWebsiteWarningEnabled?` | A Boolean value that indicates whether the web view shows warnings for suspected fraudulent content, such as malware or phishing attempts. The default value is `true`. (iOS 13+) | boolean | NO | iOS | yes (该接口不生效,调用不会产生任何实际效果,非法和欺诈网站是强制启用的,鸿蒙OS当前实现如此。) |
291
- | `userAgent?` | Sets the user-agent for the `WebView`. | string | NO | iOS,Android,macOS | yes |
292
- | `minimumFontSize?` | Android enforces a minimum font size based on this value. A non-negative integer between 1 and 72. Any number outside the specified range will be pinned. Default value is 8. If you are using smaller font sizes and are having trouble fitting the whole window onto one screen, try setting this to a smaller value. | number | No | Android | yes |
293
- | `forceDarkOn?` | Configuring Dark Theme | boolean | No | Android | yes |
294
- | `injectedJavaScriptBeforeContentLoaded?` | Set this to provide JavaScript that will be injected into the web page after the document element is created, but before other subresources finish loading. | string | No | iOS,Android,macOS | yes |
295
- | `automaticallyAdjustContentInsets?` | Controls whether to adjust the content inset for web views that are placed behind a navigation bar, tab bar, or toolbar. The default value is `true` | boolean | No | iOS | No |
296
- | `automaticallyAdjustsScrollIndicatorInsets?` | Controls whether to adjust the scroll indicator inset for web views that are placed behind a navigation bar, tab bar, or toolbar. The default value `false`. (iOS 13+) | boolean | No | iOS | No |
297
- | `injectedJavaScriptBeforeContentLoadedForMainFrameOnly?` | If `true` (default; mandatory for Android), loads the `injectedJavaScriptBeforeContentLoaded` only into the main frame. | boolean | No | iOS | No |
298
- | `nativeConfig?` | Override the native component used to render the WebView. Enables a custom native WebView which uses the same JavaScript as the original WebView. | object | No | iOS, Android, macOS | No |
299
- | `decelerationRate?` | A floating-point number that determines how quickly the scroll view decelerates after the user lifts their finger. You may also use the string shortcuts `"normal"` and `"fast"` which match the underlying iOS | number | No | iOS | No |
300
- | `javaScriptCanOpenWindowsAutomatically?` | A Boolean value indicating whether JavaScript can open windows without user interaction. The default value is `false`. | boolean | No | iOS, Android, macOS | No |
301
- | `AndroidLayerType?` | Specifies the layer type. | string | No | Android | No |
302
- | `mixedContentMode?` |Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin. | string | No | Android | No |
303
- | `allowsFullscreenVideo?` | Boolean that determines whether videos are allowed to be played in fullscreen. The default value is false. | boolean | NO | Android | NO |
304
- | `allowsInlineMediaPlayback?` | Boolean that determines whether HTML5 videos play inline or use the native full-screen controller. The default value is `false`. | boolean | NO | iOS | NO |
305
- | `allowsAirPlayForMediaPlayback?` | A Boolean value indicating whether AirPlay is allowed. The default value is `false`. | boolean | NO | iOS and macOS | NO |
306
- | `contentInset?` | The amount by which the web view content is inset from the edges of the scroll view. Defaults to {top: 0, left: 0, bottom: 0, right: 0}. | object | NO | iOS | NO |
307
- | `contentInsetAdjustmentBehavior?` | This property specifies how the safe area insets are used to modify the content area of the scroll view. The default value of this property is "never". Available on iOS 11 and later. Defaults to `never`. | string | NO | iOS | NO |
308
- | `contentMode?` | Controls the type of content to load. Available on iOS 13 and later. Defaults to `recommended`, which loads mobile content on iPhone & iPad Mini but desktop content on larger iPads. | string | No | iOS | NO |
309
- | `dataDetectorTypes?` | Determines the types of data converted to clickable URLs in the web view's content. By default only phone numbers are detected. | string, or array | NO | ios | NO |
310
- | `setBuiltInZoomControls?` | Sets whether the WebView should use its built-in zoom mechanisms. The default value is `true`. Setting this to `false` will prevent the use of a pinch gesture to control zooming. | boolean | NO | Android | NO |
311
- | `setDisplayZoomControls?` | Sets whether the WebView should display on-screen zoom controls when using the built-in zoom mechanisms (see `setBuiltInZoomControls`). The default value is `false`. | boolean | NO | Android | NO |
312
- | `directionalLockEnabled?` | A Boolean value that determines whether scrolling is disabled in a particular direction. The default value is `true`. | boolean | NO | iOS | NO |
313
- | `allowFileAccessFromFileURLs?` | Boolean that sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from other file scheme URLs. The default value is `false`. | boolean | NO | iOS, Android, macOS | NO |
314
- | `allowUniversalAccessFromFileURLs?` | boolean | NO | No | iOS, Android, macOS | No |
315
- | `allowingReadAccessToURL` | A String value that indicates which URLs the WebView's file can then reference in scripts, AJAX requests, and CSS imports. This is only used in for WebViews that are loaded with a `source.uri` set to a `'file://'` URL. If not provided, the default is to only allow read access to the URL provided in `source.uri` itself. | string | NO | iOS and macOS | NO |
316
- | `keyboardDisplayRequiresUserAction?` | If `false`, web content can programmatically display the keyboard. The default value is `true`. | boolean | NO | iOS and macOS | NO |
317
- | `hideKeyboardAccessoryView?` | If `true`, this will hide the keyboard accessory view (< > and Done). | boolean | NO | iOS | NO |
318
- | `allowsBackForwardNavigationGestures?` | If `true`, this will be able horizontal swipe gestures. The default value is `false`. | boolean | NO | iOS | No |
319
- | `allowFileAccess?` | If `true`, this will allow access to the file system via `file://` URI's. The default value is `false`. | boolean | NO | Android | NO |
320
- | `saveFormDataDisabled?` | Sets whether the WebView should disable saving form data. The default value is `false`. This function does not have any effect from Android API level 26 onwards as there is an Autofill feature which stores form data. | boolean | NO | Android | NO |
321
- | `pagingEnabled?` | If the value of this property is `true`, the scroll view stops on multiples of the scroll view’s bounds when the user scrolls. The default value is `false`. | boolean | NO | iOS | NO |
322
- | `allowsLinkPreview?` | A Boolean value that determines whether pressing on a link displays a preview of the destination for the link. In iOS this property is available on devices that support 3D Touch. In iOS 10 and later, the default value is `true`; before that, the default value is `false` | boolean | NO | iOS and macOS | NO |
323
- | `sharedCookiesEnabled?` | Set `true` if shared cookies from `[NSHTTPCookieStorage sharedHTTPCookieStorage]` should be used for every load request in the WebView. The default value is `false`. For more on cookies, read the [Guide](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Guide.md#Managing-Cookies) | boolean | NO | iOS and macOS | NO |
324
- | `limitsNavigationsToAppBoundDomains?` | If `true` indicates to WebKit that a WKWebView will only navigate to app-bound domains. Only applicable for iOS 14 or greater. | boolean | NO | iOS | No |
325
- | `textInteractionEnabled?` | If false indicates to WebKit that a WKWebView will not interact with text, thus not showing a text selection loop. Only applicable for iOS 14.5 or greater. | boolean | NO | iOS | NO |
326
- | `suppressMenuItems?` | Allows to suppress menu item from the default context menu. | array of strings | NO | iOS | NO |
327
- | `mediaCapturePermissionGrantType?` | This property specifies how to handle media capture permission requests. Defaults to `prompt`, resulting in the user being prompted repeatedly. Available on iOS 15 and later. | string | NO | iOS | yes |
328
- | `autoManageStatusBarEnabled?` | If set to `true`, the status bar will be automatically hidden/shown by WebView, specifically when full screen video is being watched. If `false`, WebView will not manage the status bar at all. The default value is `true`. | boolean | NO | iOS | NO |
329
- | `basicAuthCredential`? | object that specifies the credentials of a user to be used for basic authentication. | object | NO | iOS, Android | NO |
330
- | `useWebView2?` | Use WinUI WebView2 control instead of WebView control as the native webview. The WebView2 control is a WinUI control that renders web content using the Microsoft Edge (Chromium) rendering engine. Option can be toggled at runtime and supports Fast Refresh. | boolean | NO | Windows | NO |
331
- | `applicationNameForUserAgent?` | Append to the existing user-agent. Setting `userAgent` will override this. | string | No | All | yes |
332
- | `thirdPartyCookiesEnabled?` | Boolean value to enable third party cookies in the `WebView`. Used on Android Lollipop and above only as third party cookies are enabled by default on Android Kitkat and below and on iOS. The default value is `true`. | boolean | No | All | yes |
333
- | `menuItems?` | An array of custom menu item objects that will be shown when selecting text. An empty array will suppress the menu | array of objects | No | iOS,Android | yes |
334
- | `paymentRequestEnabled<sup>13.15.1+</sup>` | Whether or not the webview has the Payment Request API enabled.The default value is `false`. | boolean | No | Android | No |
335
- | `allowsPictureInPictureMediaPlayback<sup>13.15.1+</sup>` | Boolean value that indicates whether HTML5 videos can play Picture in Picture.The default value is `false`. | boolean | No | Android | No |
336
- | `refreshControlLightMode<sup>13.15.1+</sup>` | (ios only) Boolean value that determines whether the refresh control color is white or not.The default value is `false`. | boolean | No | iOS | No |
337
- | `indicatorStyle <sup>13.15.1+</sup>` | The colorstyle of the scroll indicator. | string | No | iOS, Android | No |
338
- | `renderMode` | This property is used to control the rendering mode of web components and is a property unique to OpenHarmony. enum: `SYNC_RENDER`(default), `ASYNC_RENDER` | string | No | - | Yes |
339
- | `scrollEnabled` | Boolean value that determines whether scrolling is enabled in the WebView. The default value is true. Setting this to false will prevent the webview from moving the document body when the keyboard appears over an input. The default value is `false`. | boolean | No | iOS and macOS | Yes |
330
+ | `source` | WebView 中加载静态 HTML URI(可选附带 headers | object | | All | 部分支持(仅支持:**加载 URI:** uri headers **静态 HTML:** html baseUrl|
331
+ | `ref` | 用于获取组件实例的引用 | object | | All | |
332
+ | `injectedJavaScript?` | 设置在页面文档加载完成后注入到网页中的 JavaScript 代码 | string | | All | |
333
+ | `originWhitelist?` | 允许导航到的来源字符串列表。 | string[] | | iOS,Android,macOS | |
334
+ | `scalesPageToFit?` | 布尔值,控制网页内容是否缩放以适应视图,并允许用户改变缩放比例。 | boolean | | Android | |
335
+ | `startInLoadingState?` | 布尔值,强制 WebView 在首次加载时显示加载视图。 | boolean | | iOS,Android,macOS | |
336
+ | `style?` | 样式对象,用于自定义 WebView 的样式。 | Style | | ALL | |
337
+ | `domStorageEnabled?` | 布尔值,控制是否启用 DOM Storage。仅在 Android 和鸿蒙上使用。Harmony 中的默认值为 `false` | boolean | | Android | |
338
+ | `javaScriptEnabled?` | 布尔值,控制是否在 WebView 中启用 JavaScript | boolean | | All | |
339
+ | `showsHorizontalScrollIndicator?` | 布尔值,控制是否在 WebView 中显示水平滚动指示器。 | boolean | | iOS,Android,macOS | |
340
+ | `showsVerticalScrollIndicator` | 布尔值,控制是否在 WebView 中显示垂直滚动指示器。 | boolean | | iOS,Android,macOS | |
341
+ | `overScrollMode?` | 覆盖过滚动模式 | string | | Android | |
342
+ | `bounces?` | 布尔值,控制 WebView 内容滚动到边界时是否产生弹性回弹效果。默认值为 `true`。在未显式设置 `overScrollMode` 时生效,作为回弹开关的兜底。 | boolean | | iOS | |
343
+ | `ignoreSilentHardwareSwitch` | 布尔值,设置为 true 时将忽略硬件静音开关。 | boolean | | iOS | |
344
+ | `cacheEnabled?` | 设置 WebView 是否使用浏览器缓存。 | boolean | | iOS,Android,macOS | |
345
+ | `cacheMode?` | 覆盖缓存的使用方式。 | string | | Android | |
346
+ | `textZoom?` | 如果用户在 Android 和鸿蒙系统中设置了自定义字体大小,WebView 中的网页界面会发生不必要的缩放。 | number | | Android | |
347
+ | `incognito?` | WebView 的生命周期内不存储任何数据。 | boolean | | All | |
348
+ | `mediaPlaybackRequiresUserAction?` | 布尔值,决定 HTML5 音视频是否需要用户点击后才能开始播放。默认值为 `true`。(Android API 最低版本 17)。 | boolean | | iOS,Android,macOS | |
349
+ | `geolocationEnabled?` | 设置是否在 `WebView` 中启用地理位置功能。默认值为 `false`。仅在 Android 上使用。 | boolean | | Android | |
350
+ | `fraudulentWebsiteWarningEnabled?` | 布尔值,指示 Web 视图是否对可疑欺诈内容(如恶意软件或钓鱼攻击)显示警告。默认值为 `true`。(iOS 13+) | boolean | | iOS | 是(该接口不生效,调用不会产生任何实际效果,非法和欺诈网站是强制启用的,鸿蒙 OS 当前实现如此。) |
351
+ | `userAgent?` | `WebView` 设置 User-Agent。 | string | | iOS,Android,macOS | |
352
+ | `minimumFontSize?` | Android 根据此值强制设置最小字体大小。取值为 1 72 之间的非负整数。超出范围的值将被限定。默认值为 8。如果使用较小的字体大小且无法将整个窗口适配到一屏,尝试将此值设为更小的值。 | number | | Android | |
353
+ | `forceDarkOn?` | 配置深色主题 | boolean | | Android | 是(依赖系统开启深色模式) |
354
+ | `injectedJavaScriptBeforeContentLoaded?` | 设置在文档元素创建后、其他子资源完成加载前注入到网页中的 JavaScript 代码。 | string | | iOS,Android,macOS | |
355
+ | `automaticallyAdjustContentInsets?` | 控制是否为放置在导航栏、标签栏或工具栏后面的 Web 视图调整内容间距。默认值为 `true` | boolean | | iOS | |
356
+ | `automaticallyAdjustsScrollIndicatorInsets?` | 控制是否为放置在导航栏、标签栏或工具栏后面的 Web 视图调整滚动指示器间距。默认值为 `false`。(iOS 13+) | boolean | | iOS | |
357
+ | `injectedJavaScriptBeforeContentLoadedForMainFrameOnly?` | 如果为 `true`(默认值;Android 下为必填),仅在主框架中加载 `injectedJavaScriptBeforeContentLoaded`。 | boolean | | iOS | |
358
+ | `nativeConfig?` | 覆盖用于渲染 WebView 的原生组件。允许使用与原 WebView 相同 JavaScript 的自定义原生 WebView。 | object | | iOS, Android, macOS | |
359
+ | `decelerationRate?` | 浮点数,决定用户抬起手指后滚动视图减速的速度。也可使用字符串快捷方式 `"normal"` `"fast"`,对应 iOS 底层实现。 | number | | iOS | |
360
+ | `javaScriptCanOpenWindowsAutomatically?` | 布尔值,指示 JavaScript 是否可以在没有用户交互的情况下打开窗口。默认值为 `false`。 | boolean | | iOS, Android, macOS | |
361
+ | `AndroidLayerType?` | 指定图层类型。 | string | | Android | |
362
+ | `mixedContentMode?` |指定混合内容模式。即 WebView 是否允许安全来源加载来自任何其他来源的内容。 | string | | Android | |
363
+ | `allowsFullscreenVideo?` | 布尔值,决定是否允许视频全屏播放。默认值为 false | boolean | | Android | |
364
+ | `allowsInlineMediaPlayback?` | 布尔值,决定 HTML5 视频是内联播放还是使用原生全屏控制器。默认值为 `false`。 | boolean | | iOS | |
365
+ | `allowsAirPlayForMediaPlayback?` | 布尔值,指示是否允许 AirPlay。默认值为 `false`。 | boolean | | iOS and macOS | |
366
+ | `contentInset?` | Web 视图内容与滚动视图边缘的间距量。默认为 {top: 0, left: 0, bottom: 0, right: 0}。 | object | | iOS | |
367
+ | `contentInsetAdjustmentBehavior?` | 此属性指定如何使用安全区域间距来修改滚动视图的内容区域。此属性的默认值为 "never"。iOS 11 及以上可用。默认为 `never`。 | string | | iOS | |
368
+ | `contentMode?` | 控制加载的内容类型。iOS 13 及以上可用。默认为 `recommended`,即在 iPhone iPad Mini 上加载移动端内容,在更大的 iPad 上加载桌面端内容。 | string | | iOS | |
369
+ | `dataDetectorTypes?` | 决定 Web 视图内容中哪些类型的数据被转换为可点击的 URL。默认仅检测电话号码。 | string, or array | | ios | |
370
+ | `setBuiltInZoomControls?` | 设置 WebView 是否使用其内置缩放机制。默认值为 `true`。设置为 `false` 将阻止使用捏合手势控制缩放。 | boolean | | Android | |
371
+ | `setDisplayZoomControls?` | 设置使用内置缩放机制时 WebView 是否显示屏幕缩放控件(参见 `setBuiltInZoomControls`)。默认值为 `false`。 | boolean | | Android | |
372
+ | `directionalLockEnabled?` | 布尔值,决定是否在特定方向上禁用滚动。默认值为 `true`。 | boolean | | iOS | |
373
+ | `allowFileAccessFromFileURLs?` | 布尔值,设置在 file 协议 URL 上下文中运行的 JavaScript 是否允许访问其他 file 协议 URL 的内容。默认值为 `false`。 | boolean | | iOS, Android, macOS | |
374
+ | `allowUniversalAccessFromFileURLs?` | boolean | | | iOS, Android, macOS | |
375
+ | `allowingReadAccessToURL` | 字符串值,指示 WebView 的文件可以在脚本、AJAX 请求和 CSS 导入中引用哪些 URL。仅适用于通过 `source.uri` 设置为 `'file://'` URL 加载的 WebView。如未提供,默认仅允许对 `source.uri` 中提供的 URL 进行读取访问。 | string | | iOS and macOS | |
376
+ | `keyboardDisplayRequiresUserAction?` | 如果为 `false`,网页内容可以通过编程方式显示键盘。默认值为 `true`。 | boolean | | iOS and macOS | |
377
+ | `hideKeyboardAccessoryView?` | 如果为 `true`,将隐藏键盘附件视图(< > Done)。 | boolean | | iOS | |
378
+ | `allowsBackForwardNavigationGestures?` | 如果为 `true`,将支持水平滑动手势。默认值为 `false`。 | boolean | | iOS | |
379
+ | `allowFileAccess?` | 如果为 `true`,将允许通过 `file://` URI 访问文件系统。默认值为 `false`。 | boolean | | Android | |
380
+ | `saveFormDataDisabled?` | 设置 WebView 是否禁用保存表单数据。默认值为 `false`。从 Android API 26 级开始此功能不再有效,因为有自动填充功能来存储表单数据。 | boolean | | Android | |
381
+ | `pagingEnabled?` | 如果此属性值为 `true`,滚动视图在用户滚动时会停在滚动视图边界的倍数位置。默认值为 `false`。 | boolean | | iOS | |
382
+ | `allowsLinkPreview?` | 布尔值,决定点击链接时是否显示链接目标的预览。在 iOS 中,此属性在支持 3D Touch 的设备上可用。iOS 10 及以上默认值为 `true`;之前默认值为 `false`。 | boolean | | iOS and macOS | |
383
+ | `sharedCookiesEnabled?` | 如果为 `true`,每次 WebView 加载请求时将使用 `[NSHTTPCookieStorage sharedHTTPCookieStorage]` 中的共享 Cookie。默认值为 `false`。更多关于 Cookie 的信息,请阅读 [指南](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Guide.md#Managing-Cookies) | boolean | | iOS and macOS | |
384
+ | `limitsNavigationsToAppBoundDomains?` | 如果为 `true`,向 WebKit 表明 WKWebView 将仅在应用绑定的域中导航。仅适用于 iOS 14 或更高版本。 | boolean | | iOS | |
385
+ | `textInteractionEnabled?` | 如果为 false,向 WebKit 表明 WKWebView 不会与文本交互,因此不显示文本选择循环。仅适用于 iOS 14.5 或更高版本。 | boolean | | iOS | |
386
+ | `suppressMenuItems?` | 允许从默认上下文菜单中隐藏菜单项。 | array of strings | | iOS | |
387
+ | `mediaCapturePermissionGrantType?` | 此属性指定如何处理媒体捕获权限请求。默认为 `prompt`,即反复提示用户。iOS 15 及以上可用。 | string | | iOS | |
388
+ | `autoManageStatusBarEnabled?` | 如果设置为 `true`,WebView 将自动隐藏/显示状态栏,特别是在观看全屏视频时。如果为 `false`,WebView 将完全不管理状态栏。默认值为 `true`。 | boolean | | iOS | |
389
+ | `basicAuthCredential`? | 对象,指定用于基本身份验证的用户凭据。 | object | | iOS, Android | |
390
+ | `useWebView2?` | 使用 WinUI WebView2 控件代替 WebView 控件作为原生 Web 视图。WebView2 控件是使用 Microsoft Edge (Chromium) 渲染引擎渲染网页内容的 WinUI 控件。可在运行时切换并支持 Fast Refresh。 | boolean | | Windows | |
391
+ | `applicationNameForUserAgent?` | 追加到现有的 User-Agent。设置 `userAgent` 将覆盖此项。 | string | | All | |
392
+ | `thirdPartyCookiesEnabled?` | 布尔值,在 `WebView` 中启用第三方 Cookie。仅在 Android Lollipop 及以上使用,因为 Android Kitkat 及以下和 iOS 上默认启用第三方 Cookie。默认值为 `true`。 | boolean | | All | |
393
+ | `menuItems?` | 自定义菜单项对象数组,在选择文本时显示。空数组将隐藏菜单 | array of objects | | iOS,Android | |
394
+ | `paymentRequestEnabled` | 是否为 WebView 启用 Payment Request API。默认值为 `false`。 | boolean | | Android | |
395
+ | `webviewDebuggingEnabled?` | 布尔值,控制是否允许通过远程调试工具(如 DevTools)调试 WebView 中加载的网页。默认值为 `false`。建议仅在开发环境开启,生产环境关闭以避免安全风险。 | boolean | | Android | |
396
+ | `allowsPictureInPictureMediaPlayback` | 布尔值,指示 HTML5 视频是否可以画中画播放。默认值为 `false`。 | boolean | | Android | |
397
+ | `refreshControlLightMode` | (仅 iOS)布尔值,决定刷新控件颜色是否为白色。默认值为 `false`。 | boolean | | iOS | |
398
+ | `indicatorStyle ` | 滚动指示器的颜色样式。 | string | 否 | iOS, Android | 否 |
399
+ | `renderMode` | 此属性用于控制 Web 组件的渲染模式,是 OpenHarmony 特有属性。枚举值:`SYNC_RENDER`(默认)、`ASYNC_RENDER` | string | 否 | - | 是 |
400
+ | `scrollEnabled` | 布尔值,决定 WebView 中是否启用滚动。默认值为 true。设置为 false 将阻止键盘出现在输入框上方时 webview 移动文档正文。默认值为 `false`。 | boolean | 否 | iOS and macOS | 是 |
340
401
 
341
402
 
342
403
  ## 事件回调
@@ -345,47 +406,59 @@ ohpm install
345
406
 
346
407
  > [!TIP] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
347
408
 
348
- | Name | Description | Type | Required | Platform | HarmonyOS Support |
409
+ | 名称 | 描述 | 类型 | 必填 | 平台 | 鸿蒙支持 |
349
410
  |---------------------------------------------------------------| ------------------------------------------------------------ | -------- | -------- | ----------------------- |-------------------|
350
- | `onScroll?: (event) => void` | Function that is invoked when the scroll event is fired in the `WebView`. | function | No | iOS and macOS | yes |
351
- | `onHttpError?: (event) => void` | Function that is invoked when the `WebView` receives an http error. | function | No | yes | yes |
352
- | `onLoadStart?: (event) => void` | Function that is invoked when the `WebView` starts loading. | function | No | All | yes |
353
- | `onLoad?: (event) => void` | Function that is invoked when the `WebView` has finished loading. | function | No | All | yes |
354
- | `onOpenWindow?` | Function that is invoked when the `WebView` should open a new window. | function | No | iOS, Android, macOS | No |
355
- | `onLoadEnd?: (event) => void` | Function that is invoked when the WebView load succeeds or fails used. | function | No | All | yes |
356
- | `onLoadProgress?: (event) => void` | Function that is invoked when the WebView is loading. | function | No | All | yes |
357
- | `onMessage?: (event) => void` | Function that is invoked when the webview calls window.ReactNativeWebView.postMessage. | function | No | iOS,Android,macOS | yes |
358
- | `onShouldStartLoadWithRequest?: (event) => void` | Function that allows custom handling of any web view requests. This feature needs to be used in conjunction with worker threads, and the relevant configuration can be set according to step three of [the worker threads](https://gitcode.com/openharmony-sig/ohos_react_native/blob/master/docs/zh-cn/TurboModule.md#%E8%AE%BE%E7%BD%AE%E8%87%AA%E5%AE%9A%E4%B9%89turbomodule%E8%BF%90%E8%A1%8C%E5%9C%A8worker%E7%BA%BF%E7%A8%8B).| function | No | iOS,Android,macOS | yes |
359
- | `onContentProcessDidTerminate: (event) => void` | Function that is invoked when the `WebView` content process is terminated. | function | No | iOS and macOS WKWebView | No |
360
- | `renderLoading?` | Function that returns a loading indicator. The `startInLoadingState` prop must be set to `true` in order to use this prop. | function | No | iOS, Android, macOS | No |
361
- | `onCustomMenuSelection?` | Function called when a custom menu item is selected. It receives a Native event, which includes three custom keys: `label`, `key` and `selectedText`. | function | NO | iOS, Android | yes |
362
- | `onNavigationStateChange?: (event) => void` | Function that is invoked when the WebView loading starts or ends. | function | NO | iOS, Android | yes |
363
- | `onError: (event) => void` | Callback function for handling load errors. | function | NO | iOS,Android | yes |
364
- | `onLoadSubResourceError: (event) => void <sup>13.16.1+</sup>` | Function that is sub resource SSL error handling. | function | NO | Android | yes |
365
- ## 静态方法
411
+ | `onScroll?: (event) => void` | `WebView` 中触发滚动事件时调用的函数。 | function | | iOS and macOS | |
412
+ | `onHttpError?: (event) => void` | `WebView` 收到 HTTP 错误时调用的函数。 | function | | | |
413
+ | `onLoadStart?: (event) => void` | `WebView` 开始加载时调用的函数。 | function | | All | |
414
+ | `onLoad?: (event) => void` | `WebView` 完成加载时调用的函数。 | function | | All | |
415
+ | `onOpenWindow?` | `WebView` 需要打开新窗口时调用的函数。 | function | | iOS, Android, macOS | |
416
+ | `onLoadEnd?: (event) => void` | WebView 加载成功或失败时调用的函数。 | function | | All | |
417
+ | `onLoadProgress?: (event) => void` | WebView 正在加载时调用的函数。 | function | | All | |
418
+ | `onMessage?: (event) => void` | webview 调用 window.ReactNativeWebView.postMessage 时调用的函数。 | function | | iOS,Android,macOS | |
419
+ | `onShouldStartLoadWithRequest?: (event) => void` | 允许自定义处理任何 Web 视图请求的函数。此功能需要与 worker 线程结合使用,相关配置可参考 [worker 线程](https://gitcode.com/CPF-RN/ohos_react_native/blob/master/docs/zh-cn/TurboModule.md#%E8%AE%BE%E7%BD%AE%E8%87%AA%E5%AE%9A%E4%B9%89turbomodule%E8%BF%90%E8%A1%8C%E5%9C%A8worker%E7%BA%BF%E7%A8%8B)的第三步。| function | | iOS,Android,macOS | |
420
+ | `onContentProcessDidTerminate: (event) => void` | `WebView` 内容进程终止时调用的函数。 | function | | iOS and macOS WKWebView | |
421
+ | `onRenderProcessGone?: (event) => void` | WebView 的渲染进程崩溃或被系统回收时调用的函数。可用于感知页面渲染异常并做恢复处理(如 `reload`)。 | function | | Android | |
422
+ | `renderLoading?` | 返回加载指示器的函数。必须将 `startInLoadingState` 属性设置为 `true` 才能使用此属性。 | function | | iOS, Android, macOS | |
423
+ | `onCustomMenuSelection?` | 当选择自定义菜单项时调用的函数。接收一个 Native 事件,包含三个自定义键:`label`、`key` `selectedText`。 | function | | iOS, Android | |
424
+ | `onNavigationStateChange?: (event) => void` | WebView 开始或结束加载时调用的函数。 | function | | iOS, Android | |
425
+ | `onError: (event) => void` | 处理加载错误的回调函数。 | function | | iOS,Android | |
426
+ | `onLoadSubResourceError: (event) => void ` | 子资源 SSL 错误处理的函数。 | function | 否 | Android | 是 |
427
+ ## 函数
366
428
 
367
429
  > [!TIP] "Platform"列表示该属性在原三方库上支持的平台。
368
430
 
369
431
  > [!TIP] "HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
370
432
 
371
- | Name | Description | Type | Required | Platform | HarmonyOS Support |
433
+ > [!NOTE] 以下方法均为实例方法,需通过组件 `ref` 调用,例如:`ref.current?.goBack()`。
434
+
435
+ | 名称 | 描述 | 类型 | 必填 | 平台 | 鸿蒙支持 |
436
+ | ---------------------------------- | ------------------------------------------------------------ | -------- | -------- | -------- | ----------------- |
437
+ | `goForward()` | 在 Web 视图的历史记录中前进一页。 | function | 否 | All | 是 |
438
+ | `goBack()` | 在 Web 视图的历史记录中后退一页。 | function | 否 | All | 是 |
439
+ | `reload()` | 重新加载当前页面。 | function | 否 | All | 是 |
440
+ | `stopLoading()` | 停止加载当前页面。 | function | 否 | All | 是 |
441
+ | `injectJavaScript(script: string)` | 向 WebView 注入 JavaScript 代码。重要提示:此函数必须在调用 onRestoreUserInterfaceForPictureInPictureStop 之后调用。 | function | 否 | All | 是 |
442
+ | `requestFocus()` | 请求 WebView 获取焦点。(开发 TV 应用的用户可能需要关注此项!) | function | 否 | All | 是 |
443
+ | `postMessage(data:string)` | 向 WebView 发送消息,由 `onMessage` 处理。 | function | 否 | All | 是 |
444
+ | `clearFormData()` | 移除当前焦点表单字段上的自动填充弹窗(如果存在)。 | function | 否 | Android | 否 |
445
+ | `clearCache(status:boolean)` | 清除资源缓存。注意缓存是应用级别的,因此会清除所有使用的 WebView 的缓存。 | function | 否 | All | 是 |
446
+ | `clearHistory()` | 通知此 WebView 清除其内部的前进/后退列表。 | function | 否 | Android | 是 |
447
+ | `loadUrl(url: string)` | 加载URL。 | function | 否 | Android | 是 |
448
+
449
+ ## 静态方法
450
+
451
+ > [!NOTE] 静态方法无需 `ref`,直接通过 `WebView` 调用,例如:`WebView.isFileUploadSupported()`。
452
+
453
+ | 名称 | 描述 | 类型 | 必填 | 平台 | 鸿蒙支持 |
372
454
  | ---------------------------------- | ------------------------------------------------------------ | -------- | -------- | -------- | ----------------- |
373
- | `goForward()` | Go forward one page in the web view's history. | function | No | All | yes |
374
- | `goBack()` | Go back one page in the web view's history. | function | No | All | yes |
375
- | `reload()` | Reloads the current page. | function | No | All | yes |
376
- | `stopLoading()` | Stop loading the current page. | function | No | All | yes |
377
- | `injectJavaScript(script: string)` | This function corresponds to the completion handler in Apple's recovery user interface ForPictureInPictureStop. IMPORTANT: This function must be called after calling onRestoreUserInterfaceForPictureInPictureStop. | function | No | All | yes |
378
- | `requestFocus()` | Request the webView to ask for focus. (People working on TV apps might want having a look at this!) | function | No | All | yes |
379
- | `postMessage(data:string)` | Post a message to WebView, handled by `onMessage`. | function | No | All | yes |
380
- | `clearFormData()` | Removes the autocomplete popup from the currently focused form field, if present. | function | No | Android | No |
381
- | `clearCache(status:boolean)` | Clears the resource cache. Note that the cache is per-application, so this will clear the cache for all WebViews used. | function | No | All | yes |
382
- | `clearHistory()` | Tells this WebView to clear its internal back/forward list. | function | No | Android | yes |
455
+ | `isFileUploadSupported()` | 检查设备是否支持文件上传,返回 `Promise<boolean>`。 | function | | All | |
383
456
 
384
457
  ## 遗留问题
385
458
 
386
- - [ ] webview 部分属性未实现 HarmonyOS 化[issue#17](https://gitcode.com/openharmony-sig/rntpc_react-native-webview/issues/17)
459
+ - [ ] webview 部分属性未实现 HarmonyOS 化[issue#17](https://gitcode.com/CPF-RN/rntpc_react-native-webview/issues/17)
387
460
  - [ ] webview 部分属性未实现 HarmonyOS 化[issue#200](https://github.com/react-native-oh-library/react-native-webview/issues/200)
388
- - [ ] V13.15.1 新增属性未实现 HarmonyOS 化[issue#2](https://gitcode.com/openharmony-sig/rntpc_react-native-webview/issues/2)
461
+ - [ ] V13.15.1 新增属性未实现 HarmonyOS 化[issue#2](https://gitcode.com/CPF-RN/rntpc_react-native-webview/issues/2)
389
462
  - [X] 中文乱码[issue#18](https://github.com/react-native-oh-library/react-native-webview/issues/18)
390
463
 
391
464
  ## 其他
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Use these variables when you tailor your ArkTS code. They must be of the const type.
3
3
  */
4
- export const HAR_VERSION = '13.16.2-beta.5';
4
+ export const HAR_VERSION = '13.16.2';
5
5
  export const BUILD_MODE_NAME = 'debug';
6
6
  export const DEBUG = true;
7
7
  export const TARGET_NAME = 'default';
@@ -6,7 +6,7 @@
6
6
  "name": "@react-native-ohos/react-native-webview",
7
7
  "description": "main cpai architecture",
8
8
  "main": "index.ets",
9
- "version": "13.16.2-beta.5",
9
+ "version": "13.16.2",
10
10
  "dependencies": {
11
11
  "@rnoh/react-native-openharmony": "../react_native_openharmony.har"
12
12
  }
@@ -66,7 +66,9 @@ export interface WebViewProps extends ViewRawProps {
66
66
  pullToRefreshEnabled: boolean
67
67
  mediaCapturePermissionGrantType?: 'prompt' | 'grant' | 'deny' | 'grantIfSameHostElsePrompt' | 'grantIfSameHostElseDeny'
68
68
  menuItems?: Array<MenuItem> | undefined;
69
+ allowsFullscreenVideo?: boolean;
69
70
  renderMode?: 'SYNC_RENDER' | 'ASYNC_RENDER';
71
+ allowFileAccess?: boolean;
70
72
  }
71
73
 
72
74
  export interface MenuItem {
@@ -33,6 +33,7 @@ import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
33
33
  import { WebViewTurboModule, ShouldStartParams, ShouldOverrideCallbackState } from './WebViewTurboModule';
34
34
  import { AnyThreadRNInstance, WorkerTaskRunnable } from '@rnoh/react-native-openharmony/src/main/ets/RNOH';
35
35
  import buffer from '@ohos.buffer';
36
+ import { window } from '@kit.ArkUI';
36
37
 
37
38
  export const TAG = "WebView"
38
39
 
@@ -66,7 +67,6 @@ export struct RNCWebView {
66
67
  controller: webview.WebviewController = new webview.WebviewController();
67
68
  javaScriptEnable: boolean = true;
68
69
  allowFileAccess: boolean = true;
69
- forceDark: boolean = true;
70
70
  minFontSize: number = EIGHT;
71
71
  overScrollMode: OverScrollMode = OverScrollMode.NEVER;
72
72
  progress: number = ZERO;
@@ -87,23 +87,29 @@ export struct RNCWebView {
87
87
  @State webviewWidth: number = ZERO
88
88
  @State webviewHeight: number = ZERO
89
89
  @State isRefreshing: boolean = false
90
- @State mode: MixedMode = MixedMode.All;
90
+ @State isFullScreen: boolean = false
91
+ @State mode: MixedMode = MixedMode.None;
91
92
  private unregisterDescriptorChangesListener?: () => void = undefined
92
93
  private cleanupCommandCallback?: () => void = undefined
93
94
  private eventEmitter: RNC.RNCWebView.EventEmitter | undefined = undefined
94
- private cleanUpCallbacks: (() => void)[] = []
95
95
  private descriptorWrapper: WebViewDescriptor = Object() as WebViewDescriptor
96
96
  private webViewBaseOperate: BaseOperate | null = null
97
- private shouldInterceptLoad: boolean = true
98
- private callLoadTimer: number = -1
99
97
  static readonly SHOULD_OVERRIDE_URL_LOADING_TIMEOUT: number = 250
100
98
  private debounceTimer: number = -1
101
99
  static readonly DEBOUNCE_TIME: number = 100
102
100
  private isFirstDebounce: boolean = true
103
-
104
- aboutToAppear() {
101
+ private initialOrientation: window.Orientation = window.Orientation.PORTRAIT
102
+ private isOrientationSaved: boolean = false
103
+ private cachedWindow: window.Window | null = null
104
+ private allowsFullscreenVideo: boolean = false
105
+ private isProgrammaticLoad = false
106
+ private isComponentAlive: boolean = true
107
+
108
+ async aboutToAppear() {
109
+ this.isComponentAlive = true
105
110
  try {
106
111
  this.initVariable()
112
+ await this.saveInitialOrientation()
107
113
  this.getBundleName()
108
114
  this.url = this.source.uri as string;
109
115
  this.onDescriptorWrapperChange(this.descriptorWrapper)
@@ -118,13 +124,6 @@ export struct RNCWebView {
118
124
  if (this.hasIncognito()) {
119
125
  this.cacheMode = CacheMode.Online;
120
126
  }
121
- if (this.source.headers) {
122
- this.source.headers.forEach(item => {
123
- if (item.name && item.value) {
124
- this.headers.push({ headerKey: item.name, headerValue: item.value })
125
- }
126
- })
127
- }
128
127
  if (this.descriptorWrapper.rawProps.geolocationEnabled) {
129
128
  atManager.requestPermissionsFromUser(this.ctx.uiAbilityContext, ["ohos.permission.APPROXIMATELY_LOCATION"]).then((data) => {
130
129
  }).catch((error: BusinessError) => {
@@ -146,27 +145,58 @@ export struct RNCWebView {
146
145
  }
147
146
 
148
147
  aboutToDisappear() {
149
- this.getUIContext().getFocusController().clearFocus()
150
- this.cleanupCommandCallback?.()
148
+ this.isComponentAlive = false
151
149
  this.unregisterDescriptorChangesListener?.()
152
- this.cleanUpCallbacks.forEach(cb => cb())
150
+ this.cleanupCommandCallback?.()
151
+ if (this.debounceTimer !== -1) {
152
+ clearTimeout(this.debounceTimer)
153
+ this.debounceTimer = -1
154
+ }
155
+ // 恢复初始屏幕方向和沉浸式状态,防止全屏状态下组件销毁后状态残留
156
+ // 无论是否在全屏状态,都尝试恢复窗口状态(handleFullScreenEnter 异步操作可能在组件销毁后才完成)
157
+ if (this.cachedWindow) {
158
+ try {
159
+ this.cachedWindow.setPreferredOrientation(this.initialOrientation);
160
+ this.cachedWindow.setWindowLayoutFullScreen(false);
161
+ this.cachedWindow.setWindowSystemBarEnable(['status', 'navigation']);
162
+ Logger.debug(TAG, '[WebViewFullScreen] Restored window state in aboutToDisappear');
163
+ } catch (error) {
164
+ Logger.error(TAG, `[WebViewFullScreen] Failed to restore in aboutToDisappear: ${error.code}`);
165
+ }
166
+ }
167
+ this.eventEmitter = undefined
168
+ this.headers = []
169
+ this.isFullScreen = false;
170
+ this.cachedWindow = null;
171
+ this.getUIContext().getFocusController().clearFocus()
172
+
153
173
  try {
154
174
  if (this.hasIncognito()) {
155
175
  this.webViewBaseOperate?.setIncognito()
156
176
  }
157
- this.controller.deleteJavaScriptRegister(JAVASCRIPT_INTERFACE)
158
- this.controller.refresh()
159
- this.hasRegisterJavaScriptProxy = false
160
- this.webViewBaseOperate = null
161
177
  } catch (error) {
162
178
  Logger.error(TAG, `[RNOH]Errorcode: ${error.code}, Message: ${error.message}`);
179
+ } finally {
180
+ try {
181
+ this.controller.deleteJavaScriptRegister(JAVASCRIPT_INTERFACE)
182
+ this.controller.refresh()
183
+ } catch (e) {
184
+ Logger.error(TAG, `[RNOH] deleteJavaScriptRegister Errorcode: ${e.code}, Message: ${e.message}`);
185
+ }
186
+ this.hasRegisterJavaScriptProxy = false
187
+ this.webViewBaseOperate = null
163
188
  }
164
189
  }
165
190
 
166
191
  registerCommandCallback() {
167
192
  this.cleanupCommandCallback = this.ctx.componentCommandReceiver.registerCommandCallback(
168
193
  this.tag,
169
- (command: COMMAND_NAME, args: string[]) => this.webViewBaseOperate?.registerCommandCallback(command, args));
194
+ (command: string, args: string[]) => {
195
+ if (command === COMMAND_NAME.LOADURL) {
196
+ this.isProgrammaticLoad = true
197
+ }
198
+ this.webViewBaseOperate?.registerCommandCallback(command as COMMAND_NAME, args)
199
+ });
170
200
  }
171
201
 
172
202
  onLoadingStart() {
@@ -333,6 +363,7 @@ export struct RNCWebView {
333
363
  Logger.error(TAG,
334
364
  `[RNOH] getBundleInfoForSelf failed ErrorCode: ${error.code}, Message: ${error.message}`);
335
365
  } else {
366
+ if (!this.isComponentAlive) return
336
367
  this.bundleName = JSON.stringify(data.name)
337
368
  }
338
369
  });
@@ -397,7 +428,6 @@ export struct RNCWebView {
397
428
  Logger.debug('params.lockState res:' + params.lockState + `, wait time is ${Date.now() - startTime}`);
398
429
  return params.lockState === ShouldOverrideCallbackState.SHOULD_OVERRIDE;
399
430
  }
400
-
401
431
  onOverrideUrlLoading(event: WebResourceRequest) {
402
432
  this.webViewBaseOperate?.emitShouldStartLoadWithRequestOverrideUrlLoading(event)
403
433
  return false
@@ -480,7 +510,152 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
480
510
 
481
511
  await atManager.requestPermissionsFromUser(this.ctx.uiAbilityContext, permissionList);
482
512
  }
483
-
513
+
514
+ private async getWindow(): Promise<window.Window | null> {
515
+ try {
516
+ const win = await window.getLastWindow(getContext(this));
517
+ if (win) {
518
+ this.cachedWindow = win;
519
+ }
520
+ return win;
521
+ } catch (error) {
522
+ console.error(TAG, `[WebViewFullScreenTest] getWindow Errorcode: ${error.code}`);
523
+ return null;
524
+ }
525
+ }
526
+
527
+ private async saveInitialOrientation() {
528
+ const win = await this.getWindow();
529
+ if (win) {
530
+ try {
531
+ const orientation = win.getPreferredOrientation();
532
+ this.initialOrientation = orientation;
533
+ this.isOrientationSaved = true;
534
+ console.debug(TAG, `[WebViewFullScreenTest] Saved initial orientation: ${orientation}`);
535
+ } catch (error) {
536
+ console.error(TAG, `[WebViewFullScreenTest] saveInitialOrientation Errorcode: ${error.code}`);
537
+ }
538
+ }
539
+ }
540
+
541
+ private async setOrientation(orientation: window.Orientation): Promise<boolean> {
542
+ const win = await this.getWindow();
543
+ if (win) {
544
+ try {
545
+ await win.setPreferredOrientation(orientation);
546
+ console.debug(TAG, `[WebViewFullScreenTest] Set orientation to: ${orientation}`);
547
+ return true;
548
+ } catch (error) {
549
+ console.error(TAG, `[WebViewFullScreenTest] setOrientation Errorcode: ${error.code}`);
550
+ return false;
551
+ }
552
+ }
553
+ return false;
554
+ }
555
+
556
+ // 处理全屏进入(带状态保护和异步串行)
557
+ private async handleFullScreenEnter() {
558
+ if (!this.isComponentAlive || this.isFullScreen) {
559
+ Logger.debug(TAG, '[WebViewFullScreen] Already in full screen, skipping');
560
+ return;
561
+ }
562
+ if (!this.isOrientationSaved) {
563
+ Logger.warn(TAG, '[WebViewFullScreen] Initial orientation not saved yet, skipping full screen enter');
564
+ return;
565
+ }
566
+ try {
567
+ // 阶段1:设置方向
568
+ const orientationResult = await this.setOrientation(window.Orientation.AUTO_ROTATION);
569
+ if (!orientationResult) {
570
+ Logger.error(TAG, '[WebViewFullScreen] Failed to set orientation, aborting full screen enter');
571
+ return;
572
+ }
573
+ // 阶段2:设置沉浸式模式
574
+ const immersiveResult = await this.enterImmersiveMode();
575
+ if (!immersiveResult) {
576
+ Logger.error(TAG, '[WebViewFullScreen] Failed to enter immersive mode, rolling back');
577
+ // 回滚沉浸式模式(即使部分失败也要尝试恢复)
578
+ await this.exitImmersiveMode();
579
+ // 回滚方向设置
580
+ await this.setOrientation(this.initialOrientation);
581
+ return;
582
+ }
583
+ // 阶段3:所有操作成功,设置状态
584
+ this.isFullScreen = true;
585
+ } catch (error) {
586
+ Logger.error(TAG, `[WebViewFullScreen] Enter full screen failed: ${error}`);
587
+ // 异常时回滚所有操作
588
+ await this.exitImmersiveMode();
589
+ await this.setOrientation(this.initialOrientation);
590
+ }
591
+ }
592
+
593
+ // 处理全屏退出(带状态保护和异步串行)
594
+ private async handleFullScreenExit() {
595
+ if (!this.isComponentAlive ||!this.isFullScreen) {
596
+ Logger.debug(TAG, '[WebViewFullScreen] Not in full screen, skipping');
597
+ return;
598
+ }
599
+ try {
600
+ // 阶段1:恢复方向
601
+ const orientationResult = await this.setOrientation(this.initialOrientation);
602
+ if (!orientationResult) {
603
+ Logger.error(TAG, '[WebViewFullScreen] Failed to restore orientation, keeping full screen state');
604
+ return;
605
+ }
606
+ // 方向已恢复,清除 isFullScreen 让 UI 恢复原始布局
607
+ this.isFullScreen = false;
608
+ // 阶段2:退出沉浸式模式
609
+ const immersiveResult = await this.exitImmersiveMode();
610
+ if (!immersiveResult) {
611
+ Logger.error(TAG, '[WebViewFullScreen] Failed to exit immersive mode after restoring orientation');
612
+ // 沉浸式模式退出失败,但方向已恢复,isFullScreen 已清除,避免重复触发循环
613
+ }
614
+ } catch (error) {
615
+ Logger.error(TAG, `[WebViewFullScreen] Exit full screen failed: ${error}`);
616
+ // 异常时也应清除状态,避免卡死
617
+ this.isFullScreen = false;
618
+ }
619
+ }
620
+
621
+ // 进入沉浸式全屏模式(隐藏系统栏)
622
+ private async enterImmersiveMode(): Promise<boolean> {
623
+ const win = await this.getWindow();
624
+ if (win) {
625
+ try {
626
+ // 设置窗口为全屏布局模式,内容延伸到系统栏下方
627
+ await win.setWindowLayoutFullScreen(true);
628
+ // 隐藏系统导航栏和状态栏
629
+ await win.setWindowSystemBarEnable([]);
630
+ Logger.debug(TAG, '[WebViewFullScreen] Entered immersive mode');
631
+ return true;
632
+ } catch (error) {
633
+ console.error(TAG, `[WebViewFullScreen] enterImmersiveMode Errorcode: ${error.code}`);
634
+ return false;
635
+ }
636
+ }
637
+ return false;
638
+ }
639
+
640
+ // 退出沉浸式全屏模式(恢复系统栏)
641
+ private async exitImmersiveMode(): Promise<boolean> {
642
+ const win = await this.getWindow();
643
+ if (win) {
644
+ try {
645
+ // 关闭全屏布局模式
646
+ await win.setWindowLayoutFullScreen(false);
647
+ // 恢复显示系统导航栏和状态栏(默认显示所有系统栏)
648
+ await win.setWindowSystemBarEnable(['status', 'navigation']);
649
+ Logger.debug(TAG, '[WebViewFullScreen] Exited immersive mode');
650
+ return true;
651
+ } catch (error) {
652
+ console.error(TAG, `[WebViewFullScreen] exitImmersiveMode Errorcode: ${error.code}`);
653
+ return false;
654
+ }
655
+ }
656
+ return false;
657
+ }
658
+
484
659
  build() {
485
660
  Stack() {
486
661
  if ( deviceInfo.sdkApiVersion >= 20) {
@@ -533,8 +708,8 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
533
708
  }
534
709
  }
535
710
  })
536
- .width(this.webviewWidth)
537
- .height(this.webviewHeight)
711
+ .width(this.isFullScreen ? "100%" : this.webviewWidth)
712
+ .height(this.isFullScreen ? "100%" : this.webviewHeight)
538
713
  .fileAccess(this.allowFileAccess)
539
714
  .constraintSize({ minHeight: MINHEIGHT })
540
715
  .overScrollMode(this.overScrollMode)
@@ -545,9 +720,9 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
545
720
  .overviewModeAccess(this.descriptorWrapper.rawProps.scalesPageToFit)
546
721
  .textZoomRatio(this.descriptorWrapper.rawProps.textZoom)
547
722
  .backgroundColor(BaseOperate.getColorMode(this.ctx.uiAbilityContext,
548
- this.descriptorWrapper.rawProps.forceDarkOn) === WebDarkMode.On ? Color.White : Color.Transparent)
723
+ this.descriptorWrapper.rawProps.forceDarkOn) === WebDarkMode.On ? Color.Black : Color.Transparent)
549
724
  .darkMode(BaseOperate.getColorMode(this.ctx.uiAbilityContext, this.descriptorWrapper.rawProps.forceDarkOn))
550
- .forceDarkAccess(this.forceDark)
725
+ .forceDarkAccess(this.descriptorWrapper.rawProps.forceDarkOn)
551
726
  .cacheMode(this.cacheMode)
552
727
  .minFontSize(this.minFontSize)
553
728
  .domStorageAccess(this.descriptorWrapper.rawProps.domStorageEnabled)
@@ -579,6 +754,18 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
579
754
  .onLoadIntercept((event: OnLoadInterceptEvent) => this.onLoadIntercept(event))
580
755
  .onTitleReceive((event: OnTitleReceiveEvent) => this.webViewBaseOperate?.onTitleReceive(event))
581
756
  .onSslErrorEvent((event: SslErrorEvent) => this.onSslErrorEventCallback(event))
757
+ .onFullScreenEnter(async () => {
758
+ Logger.debug(TAG, '[WebViewFullScreen] onFullScreenEnter called');
759
+ if (this.allowsFullscreenVideo) {
760
+ await this.handleFullScreenEnter();
761
+ } else {
762
+ Logger.debug(TAG, '[WebViewFullScreen] Fullscreen video disabled by allowsFullscreenVideo');
763
+ }
764
+ })
765
+ .onFullScreenExit(async () => {
766
+ Logger.debug(TAG, '[WebViewFullScreen] onFullScreenExit called');
767
+ await this.handleFullScreenExit();
768
+ })
582
769
  .editMenuOptions({
583
770
  onCreateMenu: this.onCreateMenu.bind(this),
584
771
  onMenuItemClick: this.onMenuItemClick.bind(this),
@@ -634,8 +821,8 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
634
821
  }
635
822
  })
636
823
 
637
- .width(this.webviewWidth)
638
- .height(this.webviewHeight)
824
+ .width(this.isFullScreen ? "100%" : this.webviewWidth)
825
+ .height(this.isFullScreen ? "100%" : this.webviewHeight)
639
826
  .fileAccess(this.allowFileAccess)
640
827
  .constraintSize({ minHeight: MINHEIGHT })
641
828
  .overScrollMode(this.overScrollMode)
@@ -646,9 +833,9 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
646
833
  .overviewModeAccess(this.descriptorWrapper.rawProps.scalesPageToFit)
647
834
  .textZoomRatio(this.descriptorWrapper.rawProps.textZoom)
648
835
  .backgroundColor(BaseOperate.getColorMode(this.ctx.uiAbilityContext,
649
- this.descriptorWrapper.rawProps.forceDarkOn) === WebDarkMode.On ? Color.White : Color.Transparent)
836
+ this.descriptorWrapper.rawProps.forceDarkOn) === WebDarkMode.On ? Color.Black : Color.Transparent)
650
837
  .darkMode(BaseOperate.getColorMode(this.ctx.uiAbilityContext, this.descriptorWrapper.rawProps.forceDarkOn))
651
- .forceDarkAccess(this.forceDark)
838
+ .forceDarkAccess(this.descriptorWrapper.rawProps.forceDarkOn)
652
839
  .cacheMode(this.cacheMode)
653
840
  .minFontSize(this.minFontSize)
654
841
  .domStorageAccess(this.descriptorWrapper.rawProps.domStorageEnabled)
@@ -679,15 +866,27 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
679
866
  .onLoadIntercept((event: OnLoadInterceptEvent) => this.onLoadIntercept(event))
680
867
  .onTitleReceive((event: OnTitleReceiveEvent) => this.webViewBaseOperate?.onTitleReceive(event))
681
868
  .onSslErrorEvent((event: SslErrorEvent) => this.onSslErrorEventCallback(event))
869
+ .onFullScreenEnter(async () => {
870
+ Logger.debug(TAG, '[WebViewFullScreen] onFullScreenEnter called');
871
+ if (this.allowsFullscreenVideo) {
872
+ await this.handleFullScreenEnter();
873
+ } else {
874
+ Logger.debug(TAG, '[WebViewFullScreen] Fullscreen video disabled by allowsFullscreenVideo');
875
+ }
876
+ })
877
+ .onFullScreenExit(async () => {
878
+ Logger.debug(TAG, '[WebViewFullScreen] onFullScreenExit called');
879
+ await this.handleFullScreenExit();
880
+ })
682
881
  .editMenuOptions({
683
882
  onCreateMenu: this.onCreateMenu.bind(this),
684
883
  onMenuItemClick: this.onMenuItemClick.bind(this),
685
884
  })
686
885
  }
687
886
  }
688
- .width(this.webviewWidth)
689
- .height(this.webviewHeight)
690
- .position({
887
+ .width(this.isFullScreen ? "100%" : this.webviewWidth)
888
+ .height(this.isFullScreen ? "100%" : this.webviewHeight)
889
+ .position(this.isFullScreen ? undefined : {
691
890
  x: this.descriptorWrapper.layoutMetrics.frame.origin.x,
692
891
  y: this.descriptorWrapper.layoutMetrics.frame.origin.y
693
892
  })
@@ -778,12 +977,6 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
778
977
  this.source.uri = $rawfile(this.source.uri.toString().replace("asset://", this.ctx.rnInstance.getAssetsDest()));
779
978
  }
780
979
 
781
- if (this.descriptorWrapper.rawProps.overScrollMode === WebViewOverScrollMode.ALWAYS) {
782
- this.overScrollMode = OverScrollMode.ALWAYS
783
- } else if (this.descriptorWrapper.rawProps.overScrollMode === WebViewOverScrollMode.NEVER) {
784
- this.overScrollMode = OverScrollMode.NEVER
785
- }
786
-
787
980
  this.overScrollMode = this.descriptorWrapper.rawProps.bounces ? OverScrollMode.ALWAYS : OverScrollMode.NEVER;
788
981
 
789
982
  if (this.descriptorWrapper.rawProps.injectedJavaScriptBeforeContentLoaded) {
@@ -794,7 +987,8 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
794
987
 
795
988
  const renderModeStr = this.descriptorWrapper.rawProps.renderMode || "SYNC_RENDER"
796
989
  this.renderMode = (renderModeStr === "ASYNC_RENDER") ? RenderMode.ASYNC_RENDER : RenderMode.SYNC_RENDER
797
-
990
+ this.allowsFullscreenVideo = this.descriptorWrapper.rawProps.allowsFullscreenVideo ?? false;
991
+ this.allowFileAccess = this.descriptorWrapper.rawProps.allowFileAccess ?? true;
798
992
  }
799
993
 
800
994
  private registerPostMessage() {
@@ -803,15 +997,16 @@ onPermissionRequestAlert(event: OnPermissionRequestEvent){
803
997
  }
804
998
  this.messagingEnabled = this.descriptorWrapper.rawProps.messagingEnabled;
805
999
  if (this.messagingEnabled) {
1000
+ const self = this;
806
1001
  let bridge: RNCWebViewBridge = {
807
1002
  postMessage: (data: string) => {
808
1003
  Logger.debug(TAG, `[RNOH] bridge postMessage, ${JSON.stringify(data)}`);
809
- if (this.controller != null) {
810
- let result: WebViewEventParams = this.createWebViewEvent("onMessage")
1004
+ if (self.controller != null) {
1005
+ let result: WebViewEventParams = self.createWebViewEvent("onMessage")
811
1006
  if (result) {
812
1007
  result.data = data.toString()
813
- result.lockIdentifier = this.webViewBaseOperate?.getLockIdentifier()
814
- this.eventEmitter!.emit("message", result as ResultType);
1008
+ result.lockIdentifier = self.webViewBaseOperate?.getLockIdentifier()
1009
+ self.eventEmitter!.emit("message", result as ResultType);
815
1010
  }
816
1011
  }
817
1012
  }
@@ -21,7 +21,7 @@ interface CreateWebViewEventInterface {
21
21
  }
22
22
 
23
23
  export class BaseOperate {
24
- private static LOCK_IDENTIFIER = 0
24
+ private static LOCK_IDENTIFIER = new Int32Array([0])
25
25
  private eventEmitter: RNC.RNCWebView.EventEmitter
26
26
  private controller: webview.WebviewController
27
27
  private lockIdentifier: number = 0
@@ -51,8 +51,8 @@ export class BaseOperate {
51
51
  }
52
52
 
53
53
  static generateLockIdentifier(): number {
54
- BaseOperate.LOCK_IDENTIFIER = BaseOperate.LOCK_IDENTIFIER + 1
55
- return BaseOperate.LOCK_IDENTIFIER
54
+ const old = Atomics.add(BaseOperate.LOCK_IDENTIFIER, 0, 1);
55
+ return old + 1;
56
56
  }
57
57
 
58
58
  getLockIdentifier():number {
@@ -323,6 +323,9 @@ export class BaseOperate {
323
323
  }
324
324
 
325
325
  injectJavaScript(args: string[]) {
326
+ if (!args || args.length == 0) {
327
+ return;
328
+ }
326
329
  try {
327
330
  this.controller.runJavaScript(args[0])
328
331
  } catch (error) {
@@ -331,6 +334,9 @@ export class BaseOperate {
331
334
  }
332
335
 
333
336
  postMessage(args: string[]) {
337
+ if (!args || args.length == 0) {
338
+ return;
339
+ }
334
340
  let data = JSON.stringify({ data: args[0] })
335
341
  let result: string = "(function () {" +
336
342
  "var event;" +
@@ -383,6 +389,9 @@ export class BaseOperate {
383
389
  }
384
390
 
385
391
  clearCache(args: string[]) {
392
+ if (!args || args.length == 0) {
393
+ return;
394
+ }
386
395
  try {
387
396
  const removeFlag = !!args[0] === true;
388
397
  this.controller.removeCache(removeFlag);
@@ -408,6 +417,9 @@ export class BaseOperate {
408
417
  }
409
418
 
410
419
  loadUrl(args: string[]) {
420
+ if (!args || args.length == 0) {
421
+ return;
422
+ }
411
423
  try {
412
424
  this.controller.loadUrl(args[0]);
413
425
  } catch (error) {
@@ -434,8 +446,10 @@ export class BaseOperate {
434
446
  break
435
447
  case COMMAND_NAME.REQUESTFOCUS:
436
448
  this.requestFocus()
449
+ break
437
450
  case COMMAND_NAME.CLEARCACHE:
438
451
  this.clearCache(args)
452
+ break
439
453
  case COMMAND_NAME.CLEARHISTORY:
440
454
  this.clearHistory()
441
455
  break
@@ -22,8 +22,8 @@ export class WebViewTurboModule extends AnyThreadTurboModule implements TM.RNCWe
22
22
  if (shouldStartParams) {
23
23
  shouldStartParams.shouldStart = shouldStart
24
24
  shouldStartParams.lockState = shouldStart ? ShouldOverrideCallbackState.ALLOW_LOADING : ShouldOverrideCallbackState.SHOULD_OVERRIDE;
25
+ this.shouldStartParamsMap.delete(lockIdentifier)
25
26
  }
26
- this.shouldStartParamsMap.set(lockIdentifier,shouldStartParams || new ShouldStartParams())
27
27
  }
28
28
 
29
29
 
@@ -31,6 +31,10 @@ export class WebViewTurboModule extends AnyThreadTurboModule implements TM.RNCWe
31
31
  Logger.debug("setShouldStartParams:" + JSON.stringify(params))
32
32
  this.shouldStartParamsMap.set(params.lockIdentifier,params)
33
33
  }
34
+
35
+ __onDestroy__(): void {
36
+ this.shouldStartParamsMap.clear()
37
+ }
34
38
  }
35
39
 
36
40
  // 锁状态
@@ -60,4 +64,4 @@ export class ShouldStartParams {
60
64
  lockIdentifier: number = -1
61
65
  // 对应ShouldOverrideCallbackState
62
66
  lockState: number = ShouldOverrideCallbackState.DEFAULT
63
- }
67
+ }
Binary file
package/package.json CHANGED
@@ -9,8 +9,8 @@
9
9
  "Thibault Malbranche <malbranche.thibault@gmail.com>"
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "13.16.2-beta.5",
13
- "homepage": "https://gitcode.com/openharmony-sig/rntpc_react-native-webview/tree/br_rnoh0.77#readme",
12
+ "version": "13.16.2",
13
+ "homepage": "https://gitcode.com/openharmony-sig/rntpc_react-native-webview/tree/br_rnoh0.82#readme",
14
14
  "scripts": {
15
15
  "pack": "tsc --noEmit false --emitDeclarationOnly --declaration --rootDir src --outDir lib && babel --extensions \".ts,.tsx\" --out-dir lib src && npm pack --ignore-scripts",
16
16
  "macos": "react-native run-macos --scheme WebviewExample --project-path example/macos",
@@ -1,30 +0,0 @@
1
- // Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved
2
- // Use of this source code is governed by a Apache-2.0 license that can be
3
- // found in the LICENSE file.
4
-
5
- export class CustomReference {
6
- private atomicValue: number;
7
- private callBack!: Function;
8
- constructor(init: number) {
9
- this.atomicValue = init
10
- }
11
-
12
- getValue() {
13
- return this.atomicValue
14
- }
15
-
16
- setCallBack(callBack: Function) {
17
- this.callBack = callBack
18
- }
19
-
20
- getCallBack() {
21
- return this.callBack
22
- }
23
-
24
- setValue(newValue: number) {
25
- this.atomicValue = newValue
26
- if (this.callBack) {
27
- this.callBack()
28
- }
29
- }
30
- }
@@ -1,48 +0,0 @@
1
- // Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved
2
- // Use of this source code is governed by a Apache-2.0 license that can be
3
- // found in the LICENSE file.
4
-
5
- import { CustomReference } from './CutomReference';
6
- import HashMap from '@ohos.util.HashMap';
7
-
8
- export enum CallbackState {
9
- UNDECIDED,
10
- SHOULD_OVERRIDE,
11
- DO_NOT_OVERRIDE,
12
- }
13
-
14
- export class ShouldRequestUrl {
15
- private constructor() {
16
- }
17
-
18
- static nextLockIdentifier: number = 1;
19
- static ShouldRequestUrlLocks: HashMap<string, CustomReference> = new HashMap();
20
- static callBack: Function;
21
-
22
- static setCallBack(lockIdentifier: string, callBack: Function): void {
23
- let data: CustomReference = ShouldRequestUrl.ShouldRequestUrlLocks.get(lockIdentifier);
24
- data.setCallBack(callBack)
25
- }
26
-
27
- public static getNewData(): string {
28
- let lockIdentifier = ShouldRequestUrl.nextLockIdentifier++ + ''
29
- let custom = new CustomReference(CallbackState.UNDECIDED)
30
- ShouldRequestUrl.ShouldRequestUrlLocks.set(lockIdentifier, custom)
31
- return lockIdentifier
32
- }
33
-
34
- public static setValue(lockIdentifier: number, stateParam: CallbackState): void {
35
- let lock: string = lockIdentifier + '';
36
- if (ShouldRequestUrl.ShouldRequestUrlLocks.hasKey(lock)) {
37
- let data: CustomReference = ShouldRequestUrl.ShouldRequestUrlLocks.get(lock)
38
- data.setValue(stateParam)
39
- }
40
- }
41
-
42
- public static getValue(lockIdentifier: string): CallbackState {
43
- return ShouldRequestUrl.ShouldRequestUrlLocks.get(lockIdentifier).getValue()
44
- }
45
- public static removeData(lockIdentifier: string): void {
46
- ShouldRequestUrl.ShouldRequestUrlLocks.remove(lockIdentifier)
47
- }
48
- }