@totalpave/cordova-plugin-insets 0.1.4 → 0.1.6

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 ADDED
@@ -0,0 +1,14 @@
1
+
2
+ @totalpave/cordova-plugin-insets
3
+ --------------------------------
4
+
5
+ # Changelog
6
+
7
+ ## 0.1.6 (April 20, 2023)
8
+ - Replaced `insets.getSystemWindowInset*` usages that was deprecated in API 30.
9
+ - Replaced `insets.consumeSystemWindowInsets` usages that was deprecated in API 30.
10
+ - Fix an issue on API 30 and earlier devices where the inset provided on launch may be incorrect.
11
+
12
+ ## 0.1.5 (April 13, 2023)
13
+
14
+ - Initial Release to NPM
package/README.md CHANGED
@@ -1,14 +1,28 @@
1
1
  cordova-plugin-insets
2
2
  =====================
3
3
 
4
- Cordova Plugin for cordova Android.
5
-
6
4
  This plugin provides access to Android's native unsafe area insets. Normally these insets are accessed through the CSS env variables, unsafe-area-inset-* (where * is top, right, bottom, or left).
7
5
 
8
6
  These env variables are recognized by Android's webviews but are not properly implemented. They always resolve to 0.
9
7
 
10
8
  This plugin provides a work around to obtain these values in javascript. You will have to implement your own javascript code to actually start using these values in your CSS.
11
9
 
10
+ ## Supported Platforms
11
+
12
+ Android.
13
+
14
+ If your app suppots multiple platforms, the API calls to this plugin should be platform guarded.
15
+
16
+ ```javascript
17
+ if (cordova.platform === 'android') {
18
+ let insets = totalpave.Insets.getInsets();
19
+ }
20
+ ```
21
+
22
+ ## Documentation
23
+
24
+ See [Docs](./docs.md)
25
+
12
26
  ## Licenses
13
27
 
14
28
  This plugin is licensed under Apache 2.0. See [LICENSE](./LICENSE) for more information.
package/docs.md ADDED
@@ -0,0 +1,85 @@
1
+
2
+ Cordova Android Insets Listener Plugin
3
+ ======================================
4
+
5
+ This document describes the public API available to library consumers.
6
+
7
+ # Table of Contents
8
+ - [1.0 - General Notes](#10---general-notes)
9
+ - [1.1 - TypeScript](#11---typescript)
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)
17
+
18
+ ## 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`.
20
+
21
+ ### 1.1 - TypeScript
22
+
23
+ This library is authored in TypeScript and provides TypeScript typings, however consuming this package as typescript is experimental. If you use bundlers, you may get duplicate runtimes. Changes to how the library is consumed may change without warning.
24
+
25
+ ## 2.0 - Interfaces
26
+
27
+ This section describes the interfaces that will be encountered when using this API.
28
+
29
+ ### 2.1 - IInsets
30
+
31
+ IInsets is an interface that describes an Inset dataset. It has the following structure:
32
+
33
+ ```typescript
34
+ interface IInsets {
35
+ top: number;
36
+ left: number;
37
+ right: number;
38
+ bottom: number;
39
+ }
40
+ ```
41
+
42
+ ### 2.2 - IInsertCallbackFunc
43
+
44
+ A type that describes the callback signature to [addListener](#31---addlistener)/[removeListener](#32---removelistener). It contains the following signature:
45
+
46
+ ```typescript
47
+ type IInsetCallbackFunc = (inset: IInsets) => void;
48
+ ```
49
+
50
+ ## 3.0 - Insets
51
+
52
+ `Insets` is a static class that provides the APIs to retrieve and to listen for inset changes.
53
+
54
+ ### 3.1 - addListener
55
+
56
+ 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
+
58
+ When the callback is invoked, it will receive an [IInsets](#21---iinsets) object as an argument.
59
+
60
+ ##### Signature
61
+
62
+ ```typescript
63
+ static addListener(callback: IInsetCallbackFunc): void;
64
+ ```
65
+
66
+ ### 3.2 - removeListener
67
+
68
+ Removes an attached handler from the listener pool.
69
+ This will be a no-op if the `callback` is not in the listener pool.
70
+
71
+ ##### Signature
72
+
73
+ ```typescript
74
+ static removeListener(callback: IInsetCallbackFunc): void;
75
+ ```
76
+
77
+ ### 3.3 - getInsets
78
+
79
+ Returns the last known [IInsets](#21---iinsets) object.
80
+
81
+ ##### Signature
82
+
83
+ ```typescript
84
+ getInsets(): IInsets;
85
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totalpave/cordova-plugin-insets",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
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",
@@ -33,7 +33,7 @@
33
33
  "@rollup/plugin-commonjs": "24.1.0",
34
34
  "@rollup/plugin-node-resolve": "15.0.2",
35
35
  "@types/cordova": "11.0.0",
36
- "rollup": "3.20.2",
36
+ "rollup": "3.20.6",
37
37
  "rollup-plugin-progress": "1.1.2",
38
38
  "rollup-plugin-typescript2": "0.34.1",
39
39
  "ts-node": "10.9.1",
package/plugin.xml CHANGED
@@ -1,5 +1,5 @@
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.3">
2
+ <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="@totalpave/cordova-plugin-insets" version="0.1.6">
3
3
  <name>cordova-plugin-insets</name>
4
4
  <description>Cordova Android Plugin to receive native information regarding the unsafe area insets</description>
5
5
  <author>Total Pave Inc.</author>
@@ -36,18 +36,22 @@ public class Insets extends CordovaPlugin {
36
36
  @Override
37
37
  protected void pluginInitialize() {
38
38
  ViewCompat.setOnApplyWindowInsetsListener(
39
- this.cordova.getActivity().findViewById(android.R.id.content), (v, insets) -> {
39
+ this.cordova.getActivity().findViewById(android.R.id.content), (v, insetProvider) -> {
40
40
  JSONObject result = new JSONObject();
41
+
41
42
  try {
42
43
  float density = this.cordova.getActivity().getResources().getDisplayMetrics().density;
43
- result.put("top", insets.getSystemWindowInsetTop() / density);
44
- result.put("right", insets.getSystemWindowInsetRight() / density);
45
- result.put("bottom", insets.getSystemWindowInsetBottom() / density);
46
- result.put("left", insets.getSystemWindowInsetLeft() / density);
47
44
 
45
+ // Ideally, we'd import this, but it shares the same name as our plugin
46
+ androidx.core.graphics.Insets insets = insetProvider.getInsets(WindowInsetsCompat.Type.systemBars());
47
+
48
+ result.put("top", insets.top / density);
49
+ result.put("right", insets.right / density);
50
+ result.put("bottom", insets.bottom / density);
51
+ result.put("left", insets.left / density);
48
52
  } catch (JSONException e) {
49
53
  e.printStackTrace();
50
- return insets.consumeSystemWindowInsets();
54
+ return insetProvider.CONSUMED; // Stop dispatching to child views
51
55
  }
52
56
  this.insets = result;
53
57
  if (listener != null) {
@@ -55,7 +59,7 @@ public class Insets extends CordovaPlugin {
55
59
  presult.setKeepCallback(true);
56
60
  listener.sendPluginResult(presult);
57
61
  }
58
- return insets.consumeSystemWindowInsets();
62
+ return insetProvider.CONSUMED; // Stop dispatching to child views
59
63
  }
60
64
  );
61
65
  }
@@ -64,29 +68,17 @@ public class Insets extends CordovaPlugin {
64
68
  public boolean execute(String action, JSONArray args, CallbackContext callback) throws JSONException, NumberFormatException {
65
69
  if (action.equals("setListener")) {
66
70
  listener = callback;
67
- if (this.insets == null) {
68
- WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(this.cordova.getActivity().findViewById(android.R.id.content));
69
- if (insets != null) {
70
- JSONObject result = new JSONObject();
71
- try {
72
- float density = this.cordova.getActivity().getResources().getDisplayMetrics().density;
73
- result.put("top", insets.getSystemWindowInsetTop() / density);
74
- result.put("right", insets.getSystemWindowInsetRight() / density);
75
- result.put("bottom", insets.getSystemWindowInsetBottom() / density);
76
- result.put("left", insets.getSystemWindowInsetLeft() / density);
77
- this.insets = result;
78
- } catch (JSONException e) {
79
- e.printStackTrace();
80
- listener.error(e.getMessage());
81
- return true;
82
- }
71
+ cordova.getActivity().runOnUiThread(() -> {
72
+ if (this.insets == null) {
73
+ // Trigger a inset dispatch (will eventually jump to the ApplyWindowInsetsListener above)
74
+ ViewCompat.requestApplyInsets(cordova.getActivity().findViewById(android.R.id.content));
83
75
  }
84
- }
85
- if (this.insets != null) {
86
- PluginResult presult = new PluginResult(Status.OK, this.insets);
87
- presult.setKeepCallback(true);
88
- listener.sendPluginResult(presult);
89
- }
76
+ else {
77
+ PluginResult presult = new PluginResult(Status.OK, this.insets);
78
+ presult.setKeepCallback(true);
79
+ listener.sendPluginResult(presult);
80
+ }
81
+ });
90
82
  return true;
91
83
  }
92
84
  return false;
package/src/www/Insets.ts CHANGED
@@ -23,6 +23,8 @@ export interface IInsets {
23
23
  left: number;
24
24
  }
25
25
 
26
+ export type IInsetCallbackFunc = (inset: IInsets) => void;
27
+
26
28
  export class Insets {
27
29
  private static initPromise: Promise<void>;
28
30
  private static listeners: Array<Function> = [];
@@ -37,8 +39,9 @@ export class Insets {
37
39
  * Initializes javascript side of the plugin.
38
40
  *
39
41
  * This function is called automatically on deviceready.
42
+ * @internal
40
43
  */
41
- public static init(): Promise<void> {
44
+ public static __init(): Promise<void> {
42
45
  if (this.initPromise) {
43
46
  return this.initPromise;
44
47
  }
@@ -67,11 +70,11 @@ export class Insets {
67
70
  });
68
71
  }
69
72
 
70
- public static addListener(callback: Function) {
73
+ public static addListener(callback: IInsetCallbackFunc) {
71
74
  this.listeners.push(callback);
72
75
  }
73
76
 
74
- public static removeListener(callback: Function) {
77
+ public static removeListener(callback: IInsetCallbackFunc) {
75
78
  let index = this.listeners.indexOf(callback);
76
79
  if (index === -1) {
77
80
  return;
@@ -88,5 +91,5 @@ export class Insets {
88
91
  };
89
92
 
90
93
  document.addEventListener('deviceready', function() {
91
- Insets.init();
94
+ Insets.__init();
92
95
  });
package/src/www/api.ts CHANGED
@@ -1,3 +1,7 @@
1
1
 
2
2
  // Core API
3
- export {Insets} from './Insets';
3
+ export {
4
+ Insets,
5
+ IInsets,
6
+ IInsetCallbackFunc
7
+ } from './Insets';
package/www/Insets.d.ts CHANGED
@@ -5,6 +5,7 @@ export interface IInsets {
5
5
  bottom: number;
6
6
  left: number;
7
7
  }
8
+ export type IInsetCallbackFunc = (inset: IInsets) => void;
8
9
  export declare class Insets {
9
10
  private static initPromise;
10
11
  private static listeners;
@@ -13,10 +14,11 @@ export declare class Insets {
13
14
  * Initializes javascript side of the plugin.
14
15
  *
15
16
  * This function is called automatically on deviceready.
17
+ * @internal
16
18
  */
17
- static init(): Promise<void>;
18
- static addListener(callback: Function): void;
19
- static removeListener(callback: Function): void;
19
+ static __init(): Promise<void>;
20
+ static addListener(callback: IInsetCallbackFunc): void;
21
+ static removeListener(callback: IInsetCallbackFunc): void;
20
22
  /**
21
23
  * @returns Last emitted insets.
22
24
  */
package/www/api.d.ts CHANGED
@@ -1 +1 @@
1
- export { Insets } from './Insets';
1
+ export { Insets, IInsets, IInsetCallbackFunc } from './Insets';
package/www/insets.js CHANGED
@@ -21,8 +21,9 @@ class Insets {
21
21
  * Initializes javascript side of the plugin.
22
22
  *
23
23
  * This function is called automatically on deviceready.
24
+ * @internal
24
25
  */
25
- static init() {
26
+ static __init() {
26
27
  if (this.initPromise) {
27
28
  return this.initPromise;
28
29
  }
@@ -68,7 +69,7 @@ Insets.insets = {
68
69
  left: 0
69
70
  };
70
71
  document.addEventListener('deviceready', function () {
71
- Insets.init();
72
+ Insets.__init();
72
73
  });
73
74
 
74
75
  exports.Insets = Insets;
package/www/insets.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"insets.js","sources":["../src/www/Insets.ts"],"sourcesContent":["/*\n Copyright 2022 Total Pave Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n\nexport const SERVICE_NAME: string = \"Insets\";\n\nexport interface IInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport class Insets {\n private static initPromise: Promise<void>;\n private static listeners: Array<Function> = [];\n private static insets: IInsets = {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n\n /**\n * Initializes javascript side of the plugin.\n * \n * This function is called automatically on deviceready.\n */\n public static init(): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n this.initPromise = new Promise<void>((resolve, reject) => {\n // Setup promise resolving mechanism.\n // We don't use the cordova callback functions as they will be called multiple times over the lifespan of an app.\n let func = () => {\n resolve();\n Insets.removeListener(func);\n }\n Insets.addListener(func);\n\n // Setup cordova callback.\n cordova.exec(\n (insets: IInsets) => {\n Insets.insets = insets;\n for (let i = 0, listeners = Insets.listeners.slice(), length = listeners.length; i < length; ++i) {\n listeners[i](insets);\n }\n },\n reject,\n SERVICE_NAME,\n \"setListener\",\n []\n );\n });\n }\n\n public static addListener(callback: Function) {\n this.listeners.push(callback);\n }\n\n public static removeListener(callback: Function) {\n let index = this.listeners.indexOf(callback);\n if (index === -1) {\n return;\n }\n this.listeners.splice(index, 1);\n }\n\n /**\n * @returns Last emitted insets.\n */ \n public static getInsets(): IInsets {\n return Insets.insets;\n }\n};\n\ndocument.addEventListener('deviceready', function() {\n Insets.init();\n});\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;AAcE;AAEK,MAAM,YAAY,GAAW,QAAQ,CAAC;AAS7C,MAAa,MAAM,CAAA;AAUf;;;;AAIG;AACI,IAAA,OAAO,IAAI,GAAA;QACd,IAAI,IAAI,CAAC,WAAW,EAAE;YAClB,OAAO,IAAI,CAAC,WAAW,CAAC;AAC3B,SAAA;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;;;YAGrD,IAAI,IAAI,GAAG,MAAK;AACZ,gBAAA,OAAO,EAAE,CAAC;AACV,gBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAChC,aAAC,CAAA;AACD,YAAA,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;;AAGzB,YAAA,OAAO,CAAC,IAAI,CACR,CAAC,MAAe,KAAI;AAChB,gBAAA,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;gBACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE;AAC9F,oBAAA,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACxB,iBAAA;aACJ,EACD,MAAM,EACN,YAAY,EACZ,aAAa,EACb,EAAE,CACL,CAAC;AACN,SAAC,CAAC,CAAC;KACN;IAEM,OAAO,WAAW,CAAC,QAAkB,EAAA;AACxC,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KACjC;IAEM,OAAO,cAAc,CAAC,QAAkB,EAAA;QAC3C,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7C,QAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACd,OAAO;AACV,SAAA;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;KACnC;AAED;;AAEG;AACI,IAAA,OAAO,SAAS,GAAA;QACnB,OAAO,MAAM,CAAC,MAAM,CAAC;KACxB;;AA3Dc,MAAS,CAAA,SAAA,GAAoB,EAAE,CAAC;AAChC,MAAA,CAAA,MAAM,GAAY;AAC7B,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,KAAK,EAAE,CAAC;AACR,IAAA,MAAM,EAAE,CAAC;AACT,IAAA,IAAI,EAAE,CAAC;CACV,CAAC;AAwDN,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAA;IACrC,MAAM,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC,CAAC;;;;"}
1
+ {"version":3,"file":"insets.js","sources":["../src/www/Insets.ts"],"sourcesContent":["/*\n Copyright 2022 Total Pave Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\n\nexport const SERVICE_NAME: string = \"Insets\";\n\nexport interface IInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport type IInsetCallbackFunc = (inset: IInsets) => void;\n\nexport class Insets {\n private static initPromise: Promise<void>;\n private static listeners: Array<Function> = [];\n private static insets: IInsets = {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n\n /**\n * Initializes javascript side of the plugin.\n * \n * This function is called automatically on deviceready.\n * @internal\n */\n public static __init(): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n this.initPromise = new Promise<void>((resolve, reject) => {\n // Setup promise resolving mechanism.\n // We don't use the cordova callback functions as they will be called multiple times over the lifespan of an app.\n let func = () => {\n resolve();\n Insets.removeListener(func);\n }\n Insets.addListener(func);\n\n // Setup cordova callback.\n cordova.exec(\n (insets: IInsets) => {\n Insets.insets = insets;\n for (let i = 0, listeners = Insets.listeners.slice(), length = listeners.length; i < length; ++i) {\n listeners[i](insets);\n }\n },\n reject,\n SERVICE_NAME,\n \"setListener\",\n []\n );\n });\n }\n\n public static addListener(callback: IInsetCallbackFunc) {\n this.listeners.push(callback);\n }\n\n public static removeListener(callback: IInsetCallbackFunc) {\n let index = this.listeners.indexOf(callback);\n if (index === -1) {\n return;\n }\n this.listeners.splice(index, 1);\n }\n\n /**\n * @returns Last emitted insets.\n */ \n public static getInsets(): IInsets {\n return Insets.insets;\n }\n};\n\ndocument.addEventListener('deviceready', function() {\n Insets.__init();\n});\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;AAcE;AAEK,MAAM,YAAY,GAAW,QAAQ,CAAC;AAW7C,MAAa,MAAM,CAAA;AAUf;;;;;AAKG;AACI,IAAA,OAAO,MAAM,GAAA;QAChB,IAAI,IAAI,CAAC,WAAW,EAAE;YAClB,OAAO,IAAI,CAAC,WAAW,CAAC;AAC3B,SAAA;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;;;YAGrD,IAAI,IAAI,GAAG,MAAK;AACZ,gBAAA,OAAO,EAAE,CAAC;AACV,gBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAChC,aAAC,CAAA;AACD,YAAA,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;;AAGzB,YAAA,OAAO,CAAC,IAAI,CACR,CAAC,MAAe,KAAI;AAChB,gBAAA,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;gBACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE;AAC9F,oBAAA,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACxB,iBAAA;aACJ,EACD,MAAM,EACN,YAAY,EACZ,aAAa,EACb,EAAE,CACL,CAAC;AACN,SAAC,CAAC,CAAC;KACN;IAEM,OAAO,WAAW,CAAC,QAA4B,EAAA;AAClD,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KACjC;IAEM,OAAO,cAAc,CAAC,QAA4B,EAAA;QACrD,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7C,QAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACd,OAAO;AACV,SAAA;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;KACnC;AAED;;AAEG;AACI,IAAA,OAAO,SAAS,GAAA;QACnB,OAAO,MAAM,CAAC,MAAM,CAAC;KACxB;;AA5Dc,MAAS,CAAA,SAAA,GAAoB,EAAE,CAAC;AAChC,MAAA,CAAA,MAAM,GAAY;AAC7B,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,KAAK,EAAE,CAAC;AACR,IAAA,MAAM,EAAE,CAAC;AACT,IAAA,IAAI,EAAE,CAAC;CACV,CAAC;AAyDN,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAA;IACrC,MAAM,CAAC,MAAM,EAAE,CAAC;AACpB,CAAC,CAAC;;;;"}