@totalpave/cordova-plugin-insets 0.1.10 → 0.3.0

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
@@ -4,6 +4,86 @@
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## 0.3.0 (TBD)
8
+
9
+ ### Breaking Changes:
10
+
11
+ #### Depluralize symbols
12
+
13
+ Several symbols were written in plural form which goes against common naming
14
+ conventions. In effort to make the API a bit cleaner, this was corrected.
15
+
16
+ |Old Name|New Name|
17
+ |---|---|
18
+ |`Insets`|`Inset`|
19
+ |`IInsets`|`IInset`|
20
+
21
+ `window.totalpave.Insets` has been renamed to `window.totalpave.Inset`
22
+
23
+ The typescript global typedefs have been updated accordingly.
24
+
25
+ #### IInsetAPI
26
+
27
+ This type interface was removed, the `Inset` class can be referenced instead.
28
+
29
+ #### Inset API is no longer static
30
+
31
+ The static `addListener`, `removeListener`, and `getInsets` APIs have been
32
+ removed and replaced with non-static versions. Two new static methods are introduced:
33
+
34
+ - `Inset.create`
35
+ - `Inset.free`
36
+
37
+ It is now the application's responsibility to create their own `Inset` instance via
38
+ `Inset.create`, passing
39
+ in their own configuration object. An instance of `Inset` will be returned that
40
+ can be used like before.
41
+
42
+ Once the inset instance is no longer needed it will be desirable to free resources
43
+ by calling `inset.free()` which will free up retained references allowing the
44
+ objects to be garbage collected.
45
+
46
+ Most use cases only calls for a single instance to be created for the application,
47
+ but it is valid to create several `Inset` instances with different configuration
48
+ parameters.
49
+
50
+ A non-static version of `getInsets` as noted above was introduced replacing the
51
+ static method. However `getInsets` is also deprecated in effort to de-pluralize
52
+ the API for better naming conventions. It will be removed in a future release.
53
+
54
+ Any usages of `getInsets` should use `getInset` instead.
55
+
56
+ ## 0.2.0 (December 6, 2023)
57
+
58
+ ### Breaking Changes:
59
+
60
+ These are the breaking changes in this release.
61
+
62
+ #### cordova-android@11 or later requirement
63
+
64
+ Starting with 0.2.0, we will need cordova-android@11 or later.
65
+ This is because we are using API 31+ APIs when available.
66
+ While we SDK guard our usage, we still need to compile with SDK 31+ and cordova-android@11 by default will compile with SDK 32.
67
+
68
+ #### Removal of Babel
69
+
70
+ TotalPave has been removing usage of Babel in their builds across several of their packages and instead letting Typescript transpile down to a sensible ES target.
71
+
72
+ Starting with 0.2.0, we will be targeting [ES 2017](https://caniuse.com/?search=es2017) which has pretty wide support on major browsers dating back about a decade.
73
+
74
+ We find that removing Babel leads to more simplified and less broken sourcemaps, as well as simplier dependency trees.
75
+
76
+ #### Rounded Corners
77
+
78
+ Starting with 0.2.0, coming back to the API 31+ usages, this plugin will now count for rounded corners on devices. If the screen has a rounded corner take the radius of the rounded corner and potentially use it for the inset value.
79
+
80
+ Insets from rounded corners are not additive. If there is an inset present already from a system bar or display cutout, we will use only one or the other, whichever is larger. This is because rounded corners are not resolved in the same way as system bars/display cutouts and any existing inset will likely already clear the rounded corner radius.
81
+
82
+ The API to get rounded corner information is available only on API 31 and later devices. Therefore, older devices, including devices that still have rounded corners but are running on an older API level will not have rounded corners counted for in the given insets.
83
+
84
+ ## 0.1.10 (November 2, 2023)
85
+ - Fixed insets to count for display cutouts, such as camera pinholes or islands.
86
+
7
87
  ## 0.1.7 (July 6, 2023)
8
88
  - Fixed clobbers namespace to merge instead, since this particular plugin targets a shared namespace.
9
89
 
package/README.md CHANGED
@@ -15,7 +15,7 @@ If your app suppots multiple platforms, the API calls to this plugin should be p
15
15
 
16
16
  ```javascript
17
17
  if (cordova.platform === 'android') {
18
- let insets = totalpave.Insets.getInsets();
18
+ let insets = await window.totalpave.Inset.create();
19
19
  }
20
20
  ```
21
21
 
package/docs.md CHANGED
@@ -8,15 +8,19 @@ This document describes the public API available to library consumers.
8
8
  - [1.0 - General Notes](#10---general-notes)
9
9
  - [1.1 - TypeScript](#11---typescript)
10
10
  - [2.0 - Interfaces](#20---interfaces)
11
- - [2.1 - IInsets](#21---iinsets)
12
- - [2.2 - IInsetCallbackFunc]()
13
- - [3.0 - Insets](#30---insets)
14
- - [3.1 - addListener](#31---addlistener)
15
- - [3.2 - removeListener](#32---removelistener)
16
- - [3.3 - getInsets](#33---getinsets)
11
+ - [2.1 - IInset](#21---iinset)
12
+ - [2.2 - IInsetCallbackFunc](#22---iinsertcallbackfunc)
13
+ - [2.3 - IInsetConfiguration](#23---iinsetconfiguration)
14
+ - [2.4 - InsetMask](#24---insetmask)
15
+ - [3.0 - Inset](#30---inset)
16
+ - [3.1 - create](#31---create)
17
+ - [3.2 - free](#32---free)
18
+ - [3.3 - addListener](#33---addlistener)
19
+ - [3.4 - removeListener](#34---removelistener)
20
+ - [3.5 - getInset](#35---getinset)
17
21
 
18
22
  ## 1.0 - General Notes
19
- The namespace of this plugin is `totalpave.Insets`. It will become available after the `deviceready` event. Throughout this document, I'll refer to the `totalpave.Insets` object as `Insets`.
23
+ The namespace of this plugin is `window.totalpave.Inset`. It will become available after the `deviceready` event. Throughout this document, I'll refer to the `totalpave.Inset` object as `Inset`.
20
24
 
21
25
  ### 1.1 - TypeScript
22
26
 
@@ -47,23 +51,102 @@ A type that describes the callback signature to [addListener](#31---addlistener)
47
51
  type IInsetCallbackFunc = (inset: IInsets) => void;
48
52
  ```
49
53
 
50
- ## 3.0 - Insets
54
+ ### 2.3 - IInsetConfiguration
51
55
 
52
- `Insets` is a static class that provides the APIs to retrieve and to listen for inset changes.
56
+ A type that describes the configuration object used when creating new `Inset` provider instances. All fields are optional.
53
57
 
54
- ### 3.1 - addListener
58
+ Structure:
59
+
60
+ ```typescript
61
+ interface IInsetConfiguration {
62
+ mask?: number;
63
+ includeRoundedCorners?: boolean;
64
+ }
65
+ ```
66
+
67
+ If `mask` is not set, the default will be `DISPLAY_CUTOUT | SYSTEM_BARS`.
68
+ If `includeRoundedCorners` is not set, the default will be `true`.
69
+
70
+ ### 2.4 - InsetMask
71
+
72
+ An enumeration of mask values. These correlate to [WindowInsetsCompat.Type](https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat.Type) though the values may not match, they are mapped during runtime.
73
+
74
+ Currently the following mask values are supported:
75
+
76
+ - CAPTION_BAR
77
+ - DISPLAY_CUTOUT
78
+ - IME
79
+ - MANDATORY_SYSTEM_GESTURES
80
+ - NAVIGATION_BARS
81
+ - STATUS_BARS
82
+ - SYSTEM_BARS
83
+ - SYSTEM_GESTURES
84
+ - TAPPABLE_ELEMENT
85
+
86
+ If the android SDK introduces any newer ones, feel free to open a PR.
87
+
88
+ ## 3.0 - Inset
89
+
90
+ `Inset` is a class that provides the APIs to retrieve and to listen for inset changes. It serves as a provider object and wil hold the configuration state as well as a collection of inset listeners. It is valid to have more than one `Inset` object alive in your application, with different configurations though it will be recommended to keep the instance count low for performance reasons.
91
+
92
+ Direct access to the `Inset` constructor is forbidden but an instance can be created via the static `create` method. If the `Inset` provider instance is no
93
+ longer used, it should be freed via `Insets.free(inset)` which will clean up
94
+ references to objects and allow them to be garbage collected, both in the webview
95
+ and in the Java/Native runtime. Additionally if your application holds any references to listener functions, they should also be cleaned up.
96
+
97
+ Note that the configuration parameters cannot be modified on an inset provider
98
+ instance.
99
+
100
+ ### 3.1 - create
101
+
102
+ Creates a new `Inset` provider object with the given configuration. If the configuration object is missing, default values are used as indicated in [IInsetConfiguration](#23---iinsetconfiguration).
103
+
104
+ The returned `Inset` instance can be used to attach listeners on for inset
105
+ update notifications. When the provider is no longer needed, it should be freed by calling [free()](#32---free).
106
+
107
+ Creating `Inset` objects will trigger a layout request, triggering an update on
108
+ all inset providers.
109
+
110
+ ##### Signature
111
+
112
+ ```typescript
113
+ static create(config?: IInsetConfiguration): Promise<Inset>;
114
+ ```
115
+
116
+ ### 3.2 - free
117
+
118
+ Frees an inset provider, cleaning up references to allow objects to be
119
+ garbage collected. Once freed, it will be unhooked from the global listener system
120
+ and that inset provider instance will no longer receive inset updates.
121
+
122
+ It's the applications responsibility to clean up any retained `IInsetCallbackFunc`
123
+ listener functions.
124
+
125
+ ##### Signature
126
+
127
+ ```typescript
128
+ static free(inset: Inset): Promise<void>;
129
+ ```
130
+
131
+ Alternatively, the inset can be freed by calling the instance member `free`.
132
+
133
+ ```typescript
134
+ free(): Promise<void>;
135
+ ```
136
+
137
+ ### 3.3 - addListener
55
138
 
56
139
  Attaches a new handler which will be invoked when the view layout/inset information changes. The reference of `callback` must be retained by the user for the [removeListener](#32---removelistener) call.
57
140
 
58
- When the callback is invoked, it will receive an [IInsets](#21---iinsets) object as an argument.
141
+ When the callback is invoked, it will receive an [IInset](#21---iinset) object as an argument.
59
142
 
60
143
  ##### Signature
61
144
 
62
145
  ```typescript
63
- static addListener(callback: IInsetCallbackFunc): void;
146
+ addListener(callback: IInsetCallbackFunc): void;
64
147
  ```
65
148
 
66
- ### 3.2 - removeListener
149
+ ### 3.4 - removeListener
67
150
 
68
151
  Removes an attached handler from the listener pool.
69
152
  This will be a no-op if the `callback` is not in the listener pool.
@@ -71,15 +154,15 @@ This will be a no-op if the `callback` is not in the listener pool.
71
154
  ##### Signature
72
155
 
73
156
  ```typescript
74
- static removeListener(callback: IInsetCallbackFunc): void;
157
+ removeListener(callback: IInsetCallbackFunc): void;
75
158
  ```
76
159
 
77
- ### 3.3 - getInsets
160
+ ### 3.5 - getInset
78
161
 
79
- Returns the last known [IInsets](#21---iinsets) object.
162
+ Returns the last known [IInset](#21---iinset) object.
80
163
 
81
164
  ##### Signature
82
165
 
83
166
  ```typescript
84
- getInsets(): IInsets;
167
+ getInset(): IInset;
85
168
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totalpave/cordova-plugin-insets",
3
- "version": "0.1.10",
3
+ "version": "0.3.0",
4
4
  "description": "Cordova Android Plugin to receive native information regarding the unsafe area insets.",
5
5
  "main": "www/insets.js",
6
6
  "types": "www/api.d.ts",
@@ -11,6 +11,7 @@
11
11
  "scripts": {
12
12
  "build": "rollup -c rollup.config.js --bundleConfigAsCjs",
13
13
  "version": "NODE_ENV=production npm run-script build",
14
+ "prepack": "ejs --output-file plugin.xml plugin.xml.ejs version=$npm_package_version",
14
15
  "postversion": "git push && git push --tags",
15
16
  "publish-dev": "npm publish --tag dev"
16
17
  },
@@ -25,24 +26,20 @@
25
26
  },
26
27
  "homepage": "https://github.com/totalpaveinc/cordova-plugin-insets#readme",
27
28
  "devDependencies": {
28
- "@babel/core": "7.23.2",
29
- "@babel/preset-env": "7.23.2",
30
- "@babel/preset-typescript": "7.23.2",
31
- "@babel/register": "7.22.15",
32
- "@rollup/plugin-babel": "6.0.3",
33
- "@rollup/plugin-commonjs": "25.0.2",
34
- "@rollup/plugin-node-resolve": "15.1.0",
35
- "@types/cordova": "11.0.2",
36
- "rollup": "3.26.2",
29
+ "@rollup/plugin-commonjs": "25.0.7",
30
+ "@rollup/plugin-node-resolve": "15.2.3",
31
+ "@types/cordova": "11.0.3",
32
+ "ejs": "3.1.9",
33
+ "rollup": "4.9.2",
37
34
  "rollup-plugin-progress": "1.1.2",
38
- "rollup-plugin-typescript2": "0.35.0",
39
- "ts-node": "10.9.1",
40
- "typescript": "5.2.2"
35
+ "rollup-plugin-typescript2": "0.36.0",
36
+ "ts-node": "10.9.2",
37
+ "typescript": "5.3.3"
41
38
  },
42
39
  "engines": {
43
40
  "cordovaDependencies": {
44
41
  "0.0.0": {
45
- "cordova-android": ">= 10"
42
+ "cordova-android": ">= 11"
46
43
  }
47
44
  }
48
45
  },
package/plugin.xml CHANGED
@@ -1,23 +1,27 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="@totalpave/cordova-plugin-insets" version="0.1.9">
2
+ <plugin
3
+ xmlns="http://apache.org/cordova/ns/plugins/1.0"
4
+ id="@totalpave/cordova-plugin-insets"
5
+ version="0.3.0"
6
+ >
3
7
  <name>cordova-plugin-insets</name>
4
8
  <description>Cordova Android Plugin to receive native information regarding the unsafe area insets</description>
5
9
  <author>Total Pave Inc.</author>
6
10
  <license>Apache 2.0</license>
7
11
  <keywords>cordova,cordova-android,unsafe-inset</keywords>
8
- <repo>https://github.com/totalpaveinc/cordova-plugin-unsafe-insets</repo>
12
+ <repo>https://github.com/totalpaveinc/cordova-plugin-insets</repo>
9
13
 
10
- <js-module src="www/insets.js" name="Insets">
14
+ <js-module src="www/insets.js" name="Inset">
11
15
  <merges target="totalpave" />
12
16
  </js-module>
13
17
 
14
18
  <platform name="android">
15
19
  <config-file target="res/xml/config.xml" parent="/*">
16
- <feature name="Insets">
17
- <param name="android-package" value="com.totalpave.cordova.insets.Insets" />
20
+ <feature name="Inset">
21
+ <param name="android-package" value="com.totalpave.cordova.inset.Inset" />
18
22
  </feature>
19
23
  </config-file>
20
24
 
21
- <source-file src="src/android/com/totalpave/cordova/insets/Insets.java" target-dir="src/com/totalpave/cordova/insets" />
25
+ <source-file src="src/android/com/totalpave/cordova/inset/Inset.java" target-dir="src/com/totalpave/cordova/inset" />
22
26
  </platform>
23
27
  </plugin>
package/plugin.xml.ejs ADDED
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <plugin
3
+ xmlns="http://apache.org/cordova/ns/plugins/1.0"
4
+ id="@totalpave/cordova-plugin-insets"
5
+ version="<%= version %>"
6
+ >
7
+ <name>cordova-plugin-insets</name>
8
+ <description>Cordova Android Plugin to receive native information regarding the unsafe area insets</description>
9
+ <author>Total Pave Inc.</author>
10
+ <license>Apache 2.0</license>
11
+ <keywords>cordova,cordova-android,unsafe-inset</keywords>
12
+ <repo>https://github.com/totalpaveinc/cordova-plugin-insets</repo>
13
+
14
+ <js-module src="www/insets.js" name="Inset">
15
+ <merges target="totalpave" />
16
+ </js-module>
17
+
18
+ <platform name="android">
19
+ <config-file target="res/xml/config.xml" parent="/*">
20
+ <feature name="Inset">
21
+ <param name="android-package" value="com.totalpave.cordova.inset.Inset" />
22
+ </feature>
23
+ </config-file>
24
+
25
+ <source-file src="src/android/com/totalpave/cordova/inset/Inset.java" target-dir="src/com/totalpave/cordova/inset" />
26
+ </platform>
27
+ </plugin>
@@ -0,0 +1,310 @@
1
+ /*
2
+ Copyright 2019 Total Pave Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ package com.totalpave.cordova.inset;
18
+
19
+ import android.content.Context;
20
+ import android.os.Build;
21
+ import android.view.RoundedCorner;
22
+ import android.view.WindowInsets;
23
+ import androidx.core.view.ViewCompat;
24
+ import androidx.core.view.WindowInsetsCompat;
25
+ import org.apache.cordova.CallbackContext;
26
+ import org.apache.cordova.CordovaPlugin;
27
+ import org.apache.cordova.PluginResult.Status;
28
+ import org.apache.cordova.PluginResult;
29
+ import org.json.JSONArray;
30
+ import org.json.JSONObject;
31
+ import org.json.JSONException;
32
+ import java.lang.NumberFormatException;
33
+ import java.util.ArrayList;
34
+ import java.util.HashMap;
35
+ import java.util.UUID;
36
+
37
+ public class Inset extends CordovaPlugin {
38
+ public static final int DEFAULT_INSET_MASK = WindowInsetsCompat.Type.displayCutout() | WindowInsetsCompat.Type.systemBars();
39
+ public static final boolean DEFAULT_INCLUDE_ROUNDED_CORNERS = true;
40
+
41
+ public static class WebviewMask {
42
+ private WebviewMask() {}
43
+
44
+ public static final int CAPTION_BAR = 1;
45
+ public static final int DISPLAY_CUTOUT = 1 << 1;
46
+ public static final int IME = 1 << 2;
47
+ public static final int MANDATORY_SYSTEM_GESTURES = 1 << 3;
48
+ public static final int NAVIGATION_BARS = 1 << 4;
49
+ public static final int STATUS_BARS = 1 << 5;
50
+ public static final int SYSTEM_BARS = 1 << 6;
51
+ public static final int SYSTEM_GESTURES = 1 << 7;
52
+ public static final int TAPPABLE_ELEMENT = 1 << 8;
53
+ }
54
+
55
+ public static class ListenerConfiguration {
56
+ public Integer mask;
57
+ public boolean includeRoundedCorners;
58
+
59
+ public ListenerConfiguration() {
60
+ mask = null;
61
+ includeRoundedCorners = DEFAULT_INCLUDE_ROUNDED_CORNERS;
62
+ }
63
+ }
64
+
65
+ public static class Listener {
66
+ private final Context $context;
67
+ private final CallbackContext $callback;
68
+ private JSONObject $currentInset;
69
+ private final int $mask;
70
+ private final boolean $includeRoundedCorners;
71
+ private final UUID $id;
72
+
73
+ public Listener(Context context, CallbackContext callback, ListenerConfiguration config) {
74
+ $id = UUID.randomUUID();
75
+ $context = context;
76
+ $callback = callback;
77
+ if (config.mask == null) {
78
+ $mask = DEFAULT_INSET_MASK;
79
+ }
80
+ else {
81
+ $mask = $mapMask(config.mask);
82
+ }
83
+ $includeRoundedCorners = config.includeRoundedCorners;
84
+ }
85
+
86
+ public String getID() {
87
+ return $id.toString();
88
+ }
89
+
90
+ public void onInsetUpdate(WindowInsetsCompat insetProvider) {
91
+ JSONObject result = new JSONObject();
92
+
93
+ try {
94
+ float density = $context.getResources().getDisplayMetrics().density;
95
+
96
+ // Ideally, we'd import this, but it shares the same name as our plugin
97
+ androidx.core.graphics.Insets insets = insetProvider.getInsets($mask);
98
+
99
+ double topLeftRadius = 0.0;
100
+ double topRightRadius = 0.0;
101
+ double botLeftRadius = 0.0;
102
+ double botRightRadius = 0.0;
103
+
104
+ if ($includeRoundedCorners && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
105
+ WindowInsets sourceInsets = insetProvider.toWindowInsets();
106
+ if (sourceInsets != null) {
107
+ RoundedCorner topLeft = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
108
+ RoundedCorner topRight = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
109
+ RoundedCorner botLeft = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
110
+ RoundedCorner botRight = sourceInsets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
111
+
112
+ if (topLeft != null) {
113
+ int radius = topLeft.getRadius();
114
+ topLeftRadius = (double) radius / density;
115
+ }
116
+
117
+ if (topRight != null) {
118
+ int radius = topRight.getRadius();
119
+ topRightRadius = (double) radius / density;
120
+ }
121
+
122
+ if (botLeft != null) {
123
+ int radius = botLeft.getRadius();
124
+ botLeftRadius = (double) radius / density;
125
+ }
126
+
127
+ if (botRight != null) {
128
+ int radius = botRight.getRadius();
129
+ botRightRadius = (double) radius / density;
130
+ }
131
+ }
132
+ }
133
+
134
+ double top = insets.top / density;
135
+ double right = insets.right / density;
136
+ double bottom = insets.bottom / density;
137
+ double left = insets.left / density;
138
+
139
+ // Insets do not include rounded corner radius. If an inset is present, it
140
+ // generally will be big enough to cover the rounded corner. This is a coincidence,
141
+ // not a designed thing. In either case, we need to determine how much space is
142
+ // required to cover the rounded corner and take the higher between the inset and
143
+ // the rounded corner.
144
+
145
+ top = Math.max(Math.max(top, topLeftRadius), topRightRadius);
146
+ bottom = Math.max(Math.max(bottom, botLeftRadius), botRightRadius);
147
+ left = Math.max(Math.max(left, topLeftRadius), botLeftRadius);
148
+ right = Math.max(Math.max(right, topRightRadius), botRightRadius);
149
+
150
+ result.put("top", top);
151
+ result.put("right", right);
152
+ result.put("bottom", bottom);
153
+ result.put("left", left);
154
+ }
155
+ catch (JSONException e) {
156
+ e.printStackTrace();
157
+ return;
158
+ }
159
+
160
+ this.$currentInset = result;
161
+
162
+ JSONObject update = new JSONObject();
163
+ try {
164
+ update.put("type", "update");
165
+ update.put("id", this.getID());
166
+ update.put("data", this.$currentInset);
167
+ }
168
+ catch (JSONException ex) {
169
+ throw new RuntimeException(ex);
170
+ }
171
+
172
+ PluginResult response = new PluginResult(Status.OK, update);
173
+ response.setKeepCallback(true);
174
+ $callback.sendPluginResult(response);
175
+ }
176
+
177
+ private int $mapMask(int webviewMask) {
178
+ int insetTypeMask = 0;
179
+
180
+ if ((webviewMask & WebviewMask.CAPTION_BAR) != 0) {
181
+ insetTypeMask |= WindowInsetsCompat.Type.captionBar();
182
+ }
183
+
184
+ if ((webviewMask & WebviewMask.DISPLAY_CUTOUT) != 0) {
185
+ insetTypeMask |= WindowInsetsCompat.Type.displayCutout();
186
+ }
187
+
188
+ if ((webviewMask & WebviewMask.IME) != 0) {
189
+ insetTypeMask |= WindowInsetsCompat.Type.ime();
190
+ }
191
+
192
+ if ((webviewMask & WebviewMask.MANDATORY_SYSTEM_GESTURES) != 0) {
193
+ insetTypeMask |= WindowInsetsCompat.Type.mandatorySystemGestures();
194
+ }
195
+
196
+ if ((webviewMask & WebviewMask.NAVIGATION_BARS) != 0) {
197
+ insetTypeMask |= WindowInsetsCompat.Type.navigationBars();
198
+ }
199
+
200
+ if ((webviewMask & WebviewMask.STATUS_BARS) != 0) {
201
+ insetTypeMask |= WindowInsetsCompat.Type.statusBars();
202
+ }
203
+
204
+ if ((webviewMask & WebviewMask.SYSTEM_BARS) != 0) {
205
+ insetTypeMask |= WindowInsetsCompat.Type.systemBars();
206
+ }
207
+
208
+ if ((webviewMask & WebviewMask.SYSTEM_GESTURES) != 0) {
209
+ insetTypeMask |= WindowInsetsCompat.Type.systemGestures();
210
+ }
211
+
212
+ if ((webviewMask & WebviewMask.TAPPABLE_ELEMENT) != 0) {
213
+ insetTypeMask |= WindowInsetsCompat.Type.tappableElement();
214
+ }
215
+
216
+ return insetTypeMask;
217
+ }
218
+ }
219
+
220
+ private ArrayList<Listener> $listeners;
221
+ private HashMap<String, Listener> $listenerMap;
222
+ private final Object $listenerLock = new Object();
223
+
224
+ @Override
225
+ protected void pluginInitialize() {
226
+ $listeners = new ArrayList<>();
227
+ $listenerMap = new HashMap<>();
228
+
229
+ ViewCompat.setOnApplyWindowInsetsListener(
230
+ this.cordova.getActivity().findViewById(android.R.id.content), (v, insetProvider) -> {
231
+
232
+ synchronized($listenerLock) {
233
+ for (Listener listener : $listeners) {
234
+ listener.onInsetUpdate(insetProvider);
235
+ }
236
+ }
237
+
238
+ return WindowInsetsCompat.CONSUMED;
239
+ }
240
+ );
241
+ }
242
+
243
+ private void $createNewListener(CallbackContext callback, JSONArray args) {
244
+ ListenerConfiguration config = new ListenerConfiguration();
245
+
246
+ try {
247
+ JSONObject params = args.getJSONObject(0);
248
+ if (params.has("mask")) {
249
+ config.mask = params.getInt("mask");
250
+ }
251
+ if (params.has("includeRoundedCorners")) {
252
+ config.includeRoundedCorners = params.getBoolean("includeRoundedCorners");
253
+ }
254
+ }
255
+ catch (JSONException ex) {
256
+ ex.printStackTrace();
257
+ callback.error(ex.getMessage());
258
+ return;
259
+ }
260
+ Listener listener = new Listener(cordova.getActivity(), callback, config);
261
+ synchronized ($listenerLock) {
262
+ $listeners.add(listener);
263
+ $listenerMap.put(listener.getID(), listener);
264
+ }
265
+
266
+ cordova.getActivity().runOnUiThread(() -> {
267
+ ViewCompat.requestApplyInsets(cordova.getActivity().findViewById(android.R.id.content));
268
+ });
269
+
270
+ JSONObject responseData = new JSONObject();
271
+ try {
272
+ responseData.put("type", "init");
273
+ responseData.put("data", listener.getID());
274
+ }
275
+ catch(JSONException e) {
276
+ throw new RuntimeException("Could not build listener creation response", e);
277
+ }
278
+
279
+ PluginResult result = new PluginResult(Status.OK, responseData);
280
+ result.setKeepCallback(true);
281
+ callback.sendPluginResult(result);
282
+ }
283
+
284
+ private void $freeListener(CallbackContext callback, JSONArray args) throws JSONException {
285
+ String id = args.getString(0);
286
+
287
+ synchronized ($listenerLock) {
288
+ Listener listener = $listenerMap.remove(id);
289
+ if (listener != null) {
290
+ $listeners.remove(listener);
291
+ }
292
+ }
293
+
294
+ callback.success();
295
+ }
296
+
297
+ @Override
298
+ public boolean execute(String action, JSONArray args, CallbackContext callback) throws JSONException, NumberFormatException {
299
+ if (action.equals("create")) {
300
+ $createNewListener(callback, args);
301
+ return true;
302
+ }
303
+ else if (action.equals("delete")) {
304
+ $freeListener(callback, args);
305
+ return true;
306
+ }
307
+
308
+ return false;
309
+ }
310
+ }