瀏覽代碼

init: web3-1234567 0.1

0210464 2 月之前
當前提交
64cae65e30
共有 100 個文件被更改,包括 9118 次插入0 次删除
  1. 3 0
      .vscode/settings.json
  2. 101 0
      app-angular/.angular/android/.gitignore
  3. 2 0
      app-angular/.angular/android/app/.gitignore
  4. 54 0
      app-angular/.angular/android/app/build.gradle
  5. 21 0
      app-angular/.angular/android/app/proguard-rules.pro
  6. 26 0
      app-angular/.angular/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java
  7. 41 0
      app-angular/.angular/android/app/src/main/AndroidManifest.xml
  8. 5 0
      app-angular/.angular/android/app/src/main/java/huanmeng/app/MainActivity.java
  9. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-land-hdpi/splash.png
  10. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-land-mdpi/splash.png
  11. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-land-xhdpi/splash.png
  12. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-land-xxhdpi/splash.png
  13. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-land-xxxhdpi/splash.png
  14. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-port-hdpi/splash.png
  15. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-port-mdpi/splash.png
  16. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-port-xhdpi/splash.png
  17. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-port-xxhdpi/splash.png
  18. 二進制
      app-angular/.angular/android/app/src/main/res/drawable-port-xxxhdpi/splash.png
  19. 34 0
      app-angular/.angular/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  20. 170 0
      app-angular/.angular/android/app/src/main/res/drawable/ic_launcher_background.xml
  21. 二進制
      app-angular/.angular/android/app/src/main/res/drawable/splash.png
  22. 12 0
      app-angular/.angular/android/app/src/main/res/layout/activity_main.xml
  23. 5 0
      app-angular/.angular/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  24. 5 0
      app-angular/.angular/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  25. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  26. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
  27. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  28. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  29. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
  30. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  31. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  32. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
  33. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  34. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  35. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
  36. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  37. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  38. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
  39. 二進制
      app-angular/.angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  40. 4 0
      app-angular/.angular/android/app/src/main/res/values/ic_launcher_background.xml
  41. 7 0
      app-angular/.angular/android/app/src/main/res/values/strings.xml
  42. 22 0
      app-angular/.angular/android/app/src/main/res/values/styles.xml
  43. 5 0
      app-angular/.angular/android/app/src/main/res/xml/file_paths.xml
  44. 18 0
      app-angular/.angular/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java
  45. 29 0
      app-angular/.angular/android/build.gradle
  46. 22 0
      app-angular/.angular/android/gradle.properties
  47. 二進制
      app-angular/.angular/android/gradle/wrapper/gradle-wrapper.jar
  48. 7 0
      app-angular/.angular/android/gradle/wrapper/gradle-wrapper.properties
  49. 248 0
      app-angular/.angular/android/gradlew
  50. 92 0
      app-angular/.angular/android/gradlew.bat
  51. 5 0
      app-angular/.angular/android/settings.gradle
  52. 16 0
      app-angular/.angular/android/variables.gradle
  53. 9 0
      app-angular/.angular/capacitor.config.ts
  54. 17 0
      app-angular/.angular/node_modules/.bin/cap
  55. 12 0
      app-angular/.angular/node_modules/.bin/cap.CMD
  56. 41 0
      app-angular/.angular/node_modules/.bin/cap.ps1
  57. 17 0
      app-angular/.angular/node_modules/.bin/capacitor
  58. 12 0
      app-angular/.angular/node_modules/.bin/capacitor.CMD
  59. 41 0
      app-angular/.angular/node_modules/.bin/capacitor.ps1
  60. 3 0
      app-angular/.angular/node_modules/.recently_updates.txt
  61. 21 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/LICENSE
  62. 96 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/build.gradle
  63. 136 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/lint-baseline.xml
  64. 9 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/lint.xml
  65. 28 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/proguard-rules.pro
  66. 3 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/AndroidManifest.xml
  67. 1030 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/assets/native-bridge.js
  68. 94 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/AndroidProtocolHandler.java
  69. 61 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/App.java
  70. 65 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/AppUUID.java
  71. 1568 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/Bridge.java
  72. 197 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java
  73. 134 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeFragment.java
  74. 510 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java
  75. 111 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeWebViewClient.java
  76. 670 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/CapConfig.java
  77. 52 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java
  78. 292 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java
  79. 8 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/InvalidPluginException.java
  80. 16 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/InvalidPluginMethodException.java
  81. 51 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSArray.java
  82. 193 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSExport.java
  83. 16 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSExportException.java
  84. 107 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSInjector.java
  85. 164 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSObject.java
  86. 65 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSValue.java
  87. 103 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/Logger.java
  88. 159 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/MessageHandler.java
  89. 37 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/NativePlugin.java
  90. 31 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PermissionState.java
  91. 1046 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/Plugin.java
  92. 440 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginCall.java
  93. 116 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java
  94. 160 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java
  95. 16 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginInvocationException.java
  96. 19 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginLoadException.java
  97. 56 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginManager.java
  98. 15 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginMethod.java
  99. 33 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginMethodHandle.java
  100. 84 0
      app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginResult.java

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+    "java.configuration.updateBuildConfiguration": "interactive"
+}

+ 101 - 0
app-angular/.angular/android/.gitignore

@@ -0,0 +1,101 @@
+# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
+
+# Built application files
+*.apk
+*.aar
+*.ap_
+*.aab
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+#  Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+# Android Profiling
+*.hprof
+
+# Cordova plugins for Capacitor
+capacitor-cordova-android-plugins
+
+# Copied web assets
+app/src/main/assets/public
+
+# Generated Config files
+app/src/main/assets/capacitor.config.json
+app/src/main/assets/capacitor.plugins.json
+app/src/main/res/xml/config.xml

+ 2 - 0
app-angular/.angular/android/app/.gitignore

@@ -0,0 +1,2 @@
+/build/*
+!/build/.npmkeep

+ 54 - 0
app-angular/.angular/android/app/build.gradle

@@ -0,0 +1,54 @@
+apply plugin: 'com.android.application'
+
+android {
+    namespace "huanmeng.app"
+    compileSdk rootProject.ext.compileSdkVersion
+    defaultConfig {
+        applicationId "huanmeng.app"
+        minSdkVersion rootProject.ext.minSdkVersion
+        targetSdkVersion rootProject.ext.targetSdkVersion
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        aaptOptions {
+             // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
+             // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
+            ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
+        }
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+repositories {
+    flatDir{
+        dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
+    }
+}
+
+dependencies {
+    implementation fileTree(include: ['*.jar'], dir: 'libs')
+    implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
+    implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
+    implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
+    implementation project(':capacitor-android')
+    testImplementation "junit:junit:$junitVersion"
+    androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
+    androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
+    implementation project(':capacitor-cordova-android-plugins')
+}
+
+apply from: 'capacitor.build.gradle'
+
+try {
+    def servicesJSON = file('google-services.json')
+    if (servicesJSON.text) {
+        apply plugin: 'com.google.gms.google-services'
+    }
+} catch(Exception e) {
+    logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
+}

+ 21 - 0
app-angular/.angular/android/app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
app-angular/.angular/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.getcapacitor.myapp;
+
+import static org.junit.Assert.*;
+
+import android.content.Context;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+        assertEquals("com.getcapacitor.app", appContext.getPackageName());
+    }
+}

+ 41 - 0
app-angular/.angular/android/app/src/main/AndroidManifest.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+
+        <activity
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
+            android:name=".MainActivity"
+            android:label="@string/title_activity_main"
+            android:theme="@style/AppTheme.NoActionBarLaunch"
+            android:launchMode="singleTask"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+        </activity>
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="${applicationId}.fileprovider"
+            android:exported="false"
+            android:grantUriPermissions="true">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_paths"></meta-data>
+        </provider>
+    </application>
+
+    <!-- Permissions -->
+
+    <uses-permission android:name="android.permission.INTERNET" />
+</manifest>

+ 5 - 0
app-angular/.angular/android/app/src/main/java/huanmeng/app/MainActivity.java

@@ -0,0 +1,5 @@
+package huanmeng.app;
+
+import com.getcapacitor.BridgeActivity;
+
+public class MainActivity extends BridgeActivity {}

二進制
app-angular/.angular/android/app/src/main/res/drawable-land-hdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-land-mdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-land-xhdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-land-xxhdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-land-xxxhdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-port-hdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-port-mdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-port-xhdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-port-xxhdpi/splash.png


二進制
app-angular/.angular/android/app/src/main/res/drawable-port-xxxhdpi/splash.png


+ 34 - 0
app-angular/.angular/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml

@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="78.5885"
+                android:endY="90.9159"
+                android:startX="48.7653"
+                android:startY="61.0927"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1" />
+</vector>

+ 170 - 0
app-angular/.angular/android/app/src/main/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillColor="#26A69A"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+</vector>

二進制
app-angular/.angular/android/app/src/main/res/drawable/splash.png


+ 12 - 0
app-angular/.angular/android/app/src/main/res/layout/activity_main.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity">
+
+    <WebView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</androidx.coordinatorlayout.widget.CoordinatorLayout>

+ 5 - 0
app-angular/.angular/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/ic_launcher_background"/>
+    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
+</adaptive-icon>

+ 5 - 0
app-angular/.angular/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/ic_launcher_background"/>
+    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
+</adaptive-icon>

二進制
app-angular/.angular/android/app/src/main/res/mipmap-hdpi/ic_launcher.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-mdpi/ic_launcher.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png


二進制
app-angular/.angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png


+ 4 - 0
app-angular/.angular/android/app/src/main/res/values/ic_launcher_background.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="ic_launcher_background">#FFFFFF</color>
+</resources>

+ 7 - 0
app-angular/.angular/android/app/src/main/res/values/strings.xml

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<resources>
+    <string name="app_name">huanmeng</string>
+    <string name="title_activity_main">huanmeng</string>
+    <string name="package_name">huanmeng.app</string>
+    <string name="custom_url_scheme">huanmeng.app</string>
+</resources>

+ 22 - 0
app-angular/.angular/android/app/src/main/res/values/styles.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+
+    <style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+        <item name="android:background">@null</item>
+    </style>
+
+
+    <style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
+        <item name="android:background">@drawable/splash</item>
+    </style>
+</resources>

+ 5 - 0
app-angular/.angular/android/app/src/main/res/xml/file_paths.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <external-path name="my_images" path="." />
+    <cache-path name="my_cache_images" path="." />
+</paths>

+ 18 - 0
app-angular/.angular/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java

@@ -0,0 +1,18 @@
+package com.getcapacitor.myapp;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 29 - 0
app-angular/.angular/android/build.gradle

@@ -0,0 +1,29 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:8.2.1'
+        classpath 'com.google.gms:google-services:4.4.0'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+apply from: "variables.gradle"
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 22 - 0
app-angular/.angular/android/gradle.properties

@@ -0,0 +1,22 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true

二進制
app-angular/.angular/android/gradle/wrapper/gradle-wrapper.jar


+ 7 - 0
app-angular/.angular/android/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists

+ 248 - 0
app-angular/.angular/android/gradlew

@@ -0,0 +1,248 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"

+ 92 - 0
app-angular/.angular/android/gradlew.bat

@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 5 - 0
app-angular/.angular/android/settings.gradle

@@ -0,0 +1,5 @@
+include ':app'
+include ':capacitor-cordova-android-plugins'
+project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
+
+apply from: 'capacitor.settings.gradle'

+ 16 - 0
app-angular/.angular/android/variables.gradle

@@ -0,0 +1,16 @@
+ext {
+    minSdkVersion = 22
+    compileSdkVersion = 34
+    targetSdkVersion = 34
+    androidxActivityVersion = '1.8.0'
+    androidxAppCompatVersion = '1.6.1'
+    androidxCoordinatorLayoutVersion = '1.2.0'
+    androidxCoreVersion = '1.12.0'
+    androidxFragmentVersion = '1.6.2'
+    coreSplashScreenVersion = '1.0.1'
+    androidxWebkitVersion = '1.9.0'
+    junitVersion = '4.13.2'
+    androidxJunitVersion = '1.1.5'
+    androidxEspressoCoreVersion = '3.5.1'
+    cordovaAndroidVersion = '10.1.1'
+}

+ 9 - 0
app-angular/.angular/capacitor.config.ts

@@ -0,0 +1,9 @@
+import type { CapacitorConfig } from '@capacitor/cli';
+
+const config: CapacitorConfig = {
+  appId: 'com.example.app',
+  appName: 'huanmeng',
+  webDir: 'www'
+};
+
+export default config;

+ 17 - 0
app-angular/.angular/node_modules/.bin/cap

@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+  export NODE_PATH="$basedir/D:/web3/web-0210462/app-angular/.angular/node_modules/.store/@capacitor+cli@6.1.0/node_modules/@capacitor"
+else
+  export NODE_PATH="$NODE_PATH:$basedir/D:/web3/web-0210462/app-angular/.angular/node_modules/.store/@capacitor+cli@6.1.0/node_modules/@capacitor"
+fi
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" "$@"
+else
+  exec node  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" "$@"
+fi

+ 12 - 0
app-angular/.angular/node_modules/.bin/cap.CMD

@@ -0,0 +1,12 @@
+@SETLOCAL
+@IF NOT DEFINED NODE_PATH (
+  @SET "NODE_PATH=%~dp0\D:\web3\web-0210462\app-angular\.angular\node_modules\.store\@capacitor+cli@6.1.0\node_modules\@capacitor"
+) ELSE (
+  @SET "NODE_PATH=%NODE_PATH%;%~dp0\D:\web3\web-0210462\app-angular\.angular\node_modules\.store\@capacitor+cli@6.1.0\node_modules\@capacitor"
+)
+@IF EXIST "%~dp0\node.exe" (
+  "%~dp0\node.exe"  "%~dp0\..\.store\@capacitor+cli@6.1.0\node_modules\@capacitor\cli\bin\capacitor" %*
+) ELSE (
+  @SET PATHEXT=%PATHEXT:;.JS;=;%
+  node  "%~dp0\..\.store\@capacitor+cli@6.1.0\node_modules\@capacitor\cli\bin\capacitor" %*
+)

+ 41 - 0
app-angular/.angular/node_modules/.bin/cap.ps1

@@ -0,0 +1,41 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+$pathsep=":"
+$env_node_path=$env:NODE_PATH
+$new_node_path="$basedir\D:\web3\web-0210462\app-angular\.angular\node_modules\.store\@capacitor+cli@6.1.0\node_modules\@capacitor"
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+  $pathsep=";"
+} else {
+  $new_node_path="$basedir/D:/web3/web-0210462/app-angular/.angular/node_modules/.store/@capacitor+cli@6.1.0/node_modules/@capacitor"
+}
+if ([string]::IsNullOrEmpty($env_node_path)) {
+  $env:NODE_PATH=$new_node_path
+} else {
+  $env:NODE_PATH="$env_node_path$pathsep$new_node_path"
+}
+
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  } else {
+    & "node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  }
+  $ret=$LASTEXITCODE
+}
+$env:NODE_PATH=$env_node_path
+exit $ret

+ 17 - 0
app-angular/.angular/node_modules/.bin/capacitor

@@ -0,0 +1,17 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -z "$NODE_PATH" ]; then
+  export NODE_PATH="$basedir/D:/web3/web-0210462/app-angular/.angular/node_modules/.store/@capacitor+cli@6.1.0/node_modules/@capacitor"
+else
+  export NODE_PATH="$NODE_PATH:$basedir/D:/web3/web-0210462/app-angular/.angular/node_modules/.store/@capacitor+cli@6.1.0/node_modules/@capacitor"
+fi
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" "$@"
+else
+  exec node  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" "$@"
+fi

+ 12 - 0
app-angular/.angular/node_modules/.bin/capacitor.CMD

@@ -0,0 +1,12 @@
+@SETLOCAL
+@IF NOT DEFINED NODE_PATH (
+  @SET "NODE_PATH=%~dp0\D:\web3\web-0210462\app-angular\.angular\node_modules\.store\@capacitor+cli@6.1.0\node_modules\@capacitor"
+) ELSE (
+  @SET "NODE_PATH=%NODE_PATH%;%~dp0\D:\web3\web-0210462\app-angular\.angular\node_modules\.store\@capacitor+cli@6.1.0\node_modules\@capacitor"
+)
+@IF EXIST "%~dp0\node.exe" (
+  "%~dp0\node.exe"  "%~dp0\..\.store\@capacitor+cli@6.1.0\node_modules\@capacitor\cli\bin\capacitor" %*
+) ELSE (
+  @SET PATHEXT=%PATHEXT:;.JS;=;%
+  node  "%~dp0\..\.store\@capacitor+cli@6.1.0\node_modules\@capacitor\cli\bin\capacitor" %*
+)

+ 41 - 0
app-angular/.angular/node_modules/.bin/capacitor.ps1

@@ -0,0 +1,41 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+$pathsep=":"
+$env_node_path=$env:NODE_PATH
+$new_node_path="$basedir\D:\web3\web-0210462\app-angular\.angular\node_modules\.store\@capacitor+cli@6.1.0\node_modules\@capacitor"
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+  $pathsep=";"
+} else {
+  $new_node_path="$basedir/D:/web3/web-0210462/app-angular/.angular/node_modules/.store/@capacitor+cli@6.1.0/node_modules/@capacitor"
+}
+if ([string]::IsNullOrEmpty($env_node_path)) {
+  $env:NODE_PATH=$new_node_path
+} else {
+  $env:NODE_PATH="$env_node_path$pathsep$new_node_path"
+}
+
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  } else {
+    & "node$exe"  "$basedir/../.store/@capacitor+cli@6.1.0/node_modules/@capacitor/cli/bin/capacitor" $args
+  }
+  $ret=$LASTEXITCODE
+}
+$env:NODE_PATH=$env_node_path
+exit $ret

+ 3 - 0
app-angular/.angular/node_modules/.recently_updates.txt

@@ -0,0 +1,3 @@
+Recently updated (since 2024-03-07)
+  2024-03-13
+    → @capacitor/cli@5.7.2 › @ionic/utils-fs@3.1.7 › @types/fs-extra@8.1.5 › @types/node@*(20.11.27) (21:35:56)

+ 21 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present Drifty Co.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 96 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/build.gradle

@@ -0,0 +1,96 @@
+ext {
+    androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.7.0'
+    androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
+    androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.2.0'
+    androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.10.0'
+    androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.5.6'
+    androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.6.1'
+    junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
+    androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
+    androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
+    cordovaAndroidVersion = project.hasProperty('cordovaAndroidVersion') ? rootProject.ext.cordovaAndroidVersion : '10.1.1'
+}
+
+
+buildscript {
+    ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.8.20'
+    repositories {
+        google()
+        mavenCentral()
+        maven {
+            url "https://plugins.gradle.org/m2/"
+        }
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:8.0.0'
+
+        if (System.getenv("CAP_PUBLISH") == "true") {
+            classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
+        }
+    }
+}
+
+tasks.withType(Javadoc).all { enabled = false }
+
+apply plugin: 'com.android.library'
+
+if (System.getenv("CAP_PUBLISH") == "true") {
+    apply plugin: 'io.github.gradle-nexus.publish-plugin'
+    apply from: file('../scripts/publish-root.gradle')
+    apply from: file('../scripts/publish-module.gradle')
+}
+
+android {
+    namespace "com.getcapacitor.android"
+    compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 33
+    defaultConfig {
+        minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
+        targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 33
+        versionCode 1
+        versionName "1.0"
+        consumerProguardFiles 'proguard-rules.pro'
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    lintOptions {
+        baseline file("lint-baseline.xml")
+        abortOnError true
+        warningsAsErrors true
+        lintConfig file('lint.xml')
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
+    }
+    publishing {
+        singleVariant("release")
+    }
+}
+
+repositories {
+    google()
+    mavenCentral()
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version")
+    implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
+    implementation "androidx.core:core:$androidxCoreVersion"
+    implementation "androidx.activity:activity:$androidxActivityVersion"
+    implementation "androidx.fragment:fragment:$androidxFragmentVersion"
+    implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
+    implementation "androidx.webkit:webkit:$androidxWebkitVersion"
+    testImplementation "junit:junit:$junitVersion"
+    androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
+    androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
+    implementation "org.apache.cordova:framework:$cordovaAndroidVersion"
+    testImplementation 'org.json:json:20231013'
+    testImplementation 'org.mockito:mockito-inline:5.2.0'
+}
+

+ 136 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/lint-baseline.xml

@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.1.1" client="gradle" variant="all" version="4.1.1">
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+        errorLine1="            String msg = String.format("
+        errorLine2="                         ^">
+        <location
+            file="src/main/java/com/getcapacitor/BridgeWebChromeClient.java"
+            line="474"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toUpperCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="                return mask.toUpperCase().equals(string.toUpperCase());"
+        errorLine2="                            ~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/util/HostMask.java"
+            line="110"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toUpperCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="                return mask.toUpperCase().equals(string.toUpperCase());"
+        errorLine2="                                                        ~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/util/HostMask.java"
+            line="110"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="                switch (spinnerStyle.toLowerCase()) {"
+        errorLine2="                                     ~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/Splash.java"
+            line="127"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="DefaultLocale"
+        message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+        errorLine1="                    if (header.getKey().equalsIgnoreCase(&quot;Accept&quot;) &amp;&amp; header.getValue().toLowerCase().contains(&quot;text/html&quot;)) {"
+        errorLine2="                                                                                        ~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/WebViewLocalServer.java"
+            line="327"
+            column="89"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="        String timeStamp = new SimpleDateFormat(&quot;yyyyMMdd_HHmmss&quot;).format(new Date());"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/BridgeWebChromeClient.java"
+            line="511"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="SimpleDateFormat"
+        message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+        errorLine1="        DateFormat df = new SimpleDateFormat(&quot;yyyy-MM-dd&apos;T&apos;HH:mm&apos;Z&apos;&quot;);"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/PluginResult.java"
+            line="44"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="SetJavaScriptEnabled"
+        message="Using `setJavaScriptEnabled` can introduce XSS vulnerabilities into your application, review carefully"
+        errorLine1="        settings.setJavaScriptEnabled(true);"
+        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/Bridge.java"
+            line="384"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="Recycle"
+        message="This `TypedArray` should be recycled after use with `#recycle()`"
+        errorLine1="        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.bridge_fragment);"
+        errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/BridgeFragment.java"
+            line="84"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields; this is a memory leak"
+        errorLine1="    private static ImageView splashImage;"
+        errorLine2="            ~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/Splash.java"
+            line="41"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="StaticFieldLeak"
+        message="Do not place Android context classes in static fields; this is a memory leak"
+        errorLine1="    private static ProgressBar spinnerBar;"
+        errorLine2="            ~~~~~~">
+        <location
+            file="src/main/java/com/getcapacitor/Splash.java"
+            line="42"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="Overdraw"
+        message="Possible overdraw: Root element paints background `#F0FF1414` with a theme that also paints a background (inferred theme is `@android:style/Theme.Holo`)"
+        errorLine1="    android:background=&quot;#F0FF1414&quot;"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/layout/fragment_bridge.xml"
+            line="5"
+            column="5"/>
+    </issue>
+
+</issues>

+ 9 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/lint.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+    <issue id="GradleDependency" severity="ignore" />
+    <issue id="AndroidGradlePluginVersion" severity="ignore" />
+    <issue id="DiscouragedApi">
+        <ignore path="src/main/java/com/getcapacitor/plugin/util/AssetUtil.java" />
+    </issue>
+    <issue id="ObsoleteSdkInt" severity="informational" />
+</lint>

+ 28 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/proguard-rules.pro

@@ -0,0 +1,28 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Rules for Capacitor v3 plugins and annotations
+ -keep @com.getcapacitor.annotation.CapacitorPlugin public class * {
+     @com.getcapacitor.annotation.PermissionCallback <methods>;
+     @com.getcapacitor.annotation.ActivityCallback <methods>;
+     @com.getcapacitor.annotation.Permission <methods>;
+     @com.getcapacitor.PluginMethod public <methods>;
+ }
+
+ -keep public class * extends com.getcapacitor.Plugin { *; }
+
+# Rules for Capacitor v2 plugins and annotations
+# These are deprecated but can still be used with Capacitor for now
+-keep @com.getcapacitor.NativePlugin public class * {
+  @com.getcapacitor.PluginMethod public <methods>;
+}
+
+# Rules for Cordova plugins
+-keep public class * extends org.apache.cordova.* {
+  public <methods>;
+  public <fields>;
+}

+ 3 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/AndroidManifest.xml

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+</manifest>

+ 1030 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/assets/native-bridge.js

@@ -0,0 +1,1030 @@
+
+/*! Capacitor: https://capacitorjs.com/ - MIT License */
+/* Generated File. Do not edit. */
+
+var nativeBridge = (function (exports) {
+    'use strict';
+
+    var ExceptionCode;
+    (function (ExceptionCode) {
+        /**
+         * API is not implemented.
+         *
+         * This usually means the API can't be used because it is not implemented for
+         * the current platform.
+         */
+        ExceptionCode["Unimplemented"] = "UNIMPLEMENTED";
+        /**
+         * API is not available.
+         *
+         * This means the API can't be used right now because:
+         *   - it is currently missing a prerequisite, such as network connectivity
+         *   - it requires a particular platform or browser version
+         */
+        ExceptionCode["Unavailable"] = "UNAVAILABLE";
+    })(ExceptionCode || (ExceptionCode = {}));
+    class CapacitorException extends Error {
+        constructor(message, code, data) {
+            super(message);
+            this.message = message;
+            this.code = code;
+            this.data = data;
+        }
+    }
+
+    // For removing exports for iOS/Android, keep let for reassignment
+    // eslint-disable-next-line
+    let dummy = {};
+    const readFileAsBase64 = (file) => new Promise((resolve, reject) => {
+        const reader = new FileReader();
+        reader.onloadend = () => {
+            const data = reader.result;
+            resolve(btoa(data));
+        };
+        reader.onerror = reject;
+        reader.readAsBinaryString(file);
+    });
+    const convertFormData = async (formData) => {
+        const newFormData = [];
+        for (const pair of formData.entries()) {
+            const [key, value] = pair;
+            if (value instanceof File) {
+                const base64File = await readFileAsBase64(value);
+                newFormData.push({
+                    key,
+                    value: base64File,
+                    type: 'base64File',
+                    contentType: value.type,
+                    fileName: value.name,
+                });
+            }
+            else {
+                newFormData.push({ key, value, type: 'string' });
+            }
+        }
+        return newFormData;
+    };
+    const convertBody = async (body, contentType) => {
+        if (body instanceof ReadableStream) {
+            const reader = body.getReader();
+            const chunks = [];
+            while (true) {
+                const { done, value } = await reader.read();
+                if (done)
+                    break;
+                chunks.push(value);
+            }
+            const concatenated = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
+            let position = 0;
+            for (const chunk of chunks) {
+                concatenated.set(chunk, position);
+                position += chunk.length;
+            }
+            let data = new TextDecoder().decode(concatenated);
+            let type;
+            if (contentType === 'application/json') {
+                try {
+                    data = JSON.parse(data);
+                }
+                catch (ignored) {
+                    // ignore
+                }
+                type = 'json';
+            }
+            else if (contentType === 'multipart/form-data') {
+                type = 'formData';
+            }
+            else if (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('image')) {
+                type = 'image';
+            }
+            else if (contentType === 'application/octet-stream') {
+                type = 'binary';
+            }
+            else {
+                type = 'text';
+            }
+            return {
+                data,
+                type,
+                headers: { 'Content-Type': contentType || 'application/octet-stream' },
+            };
+        }
+        else if (body instanceof FormData) {
+            const formData = await convertFormData(body);
+            const boundary = `${Date.now()}`;
+            return {
+                data: formData,
+                type: 'formData',
+                headers: {
+                    'Content-Type': `multipart/form-data; boundary=--${boundary}`,
+                },
+            };
+        }
+        else if (body instanceof File) {
+            const fileData = await readFileAsBase64(body);
+            return {
+                data: fileData,
+                type: 'file',
+                headers: { 'Content-Type': body.type },
+            };
+        }
+        return { data: body, type: 'json' };
+    };
+    const CAPACITOR_HTTP_INTERCEPTOR = '/_capacitor_http_interceptor_';
+    const CAPACITOR_HTTPS_INTERCEPTOR = '/_capacitor_https_interceptor_';
+    // TODO: export as Cap function
+    const isRelativeOrProxyUrl = (url) => !url ||
+        !(url.startsWith('http:') || url.startsWith('https:')) ||
+        url.indexOf(CAPACITOR_HTTP_INTERCEPTOR) > -1 ||
+        url.indexOf(CAPACITOR_HTTPS_INTERCEPTOR) > -1;
+    // TODO: export as Cap function
+    const createProxyUrl = (url, win) => {
+        var _a, _b;
+        if (isRelativeOrProxyUrl(url))
+            return url;
+        let proxyUrl = new URL(url);
+        const isHttps = proxyUrl.protocol === 'https:';
+        const originalHost = encodeURIComponent(proxyUrl.host);
+        const originalPathname = proxyUrl.pathname;
+        proxyUrl = new URL((_b = (_a = win.Capacitor) === null || _a === void 0 ? void 0 : _a.getServerUrl()) !== null && _b !== void 0 ? _b : '');
+        proxyUrl.pathname = `${isHttps ? CAPACITOR_HTTPS_INTERCEPTOR : CAPACITOR_HTTP_INTERCEPTOR}/${originalHost}${originalPathname}`;
+        return proxyUrl.toString();
+    };
+    const initBridge = (w) => {
+        const getPlatformId = (win) => {
+            var _a, _b;
+            if (win === null || win === void 0 ? void 0 : win.androidBridge) {
+                return 'android';
+            }
+            else if ((_b = (_a = win === null || win === void 0 ? void 0 : win.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) {
+                return 'ios';
+            }
+            else {
+                return 'web';
+            }
+        };
+        const convertFileSrcServerUrl = (webviewServerUrl, filePath) => {
+            if (typeof filePath === 'string') {
+                if (filePath.startsWith('/')) {
+                    return webviewServerUrl + '/_capacitor_file_' + filePath;
+                }
+                else if (filePath.startsWith('file://')) {
+                    return (webviewServerUrl + filePath.replace('file://', '/_capacitor_file_'));
+                }
+                else if (filePath.startsWith('content://')) {
+                    return (webviewServerUrl +
+                        filePath.replace('content:/', '/_capacitor_content_'));
+                }
+            }
+            return filePath;
+        };
+        const initEvents = (win, cap) => {
+            cap.addListener = (pluginName, eventName, callback) => {
+                const callbackId = cap.nativeCallback(pluginName, 'addListener', {
+                    eventName: eventName,
+                }, callback);
+                return {
+                    remove: async () => {
+                        var _a;
+                        (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.debug('Removing listener', pluginName, eventName);
+                        cap.removeListener(pluginName, callbackId, eventName, callback);
+                    },
+                };
+            };
+            cap.removeListener = (pluginName, callbackId, eventName, callback) => {
+                cap.nativeCallback(pluginName, 'removeListener', {
+                    callbackId: callbackId,
+                    eventName: eventName,
+                }, callback);
+            };
+            cap.createEvent = (eventName, eventData) => {
+                const doc = win.document;
+                if (doc) {
+                    const ev = doc.createEvent('Events');
+                    ev.initEvent(eventName, false, false);
+                    if (eventData && typeof eventData === 'object') {
+                        for (const i in eventData) {
+                            // eslint-disable-next-line no-prototype-builtins
+                            if (eventData.hasOwnProperty(i)) {
+                                ev[i] = eventData[i];
+                            }
+                        }
+                    }
+                    return ev;
+                }
+                return null;
+            };
+            cap.triggerEvent = (eventName, target, eventData) => {
+                const doc = win.document;
+                const cordova = win.cordova;
+                eventData = eventData || {};
+                const ev = cap.createEvent(eventName, eventData);
+                if (ev) {
+                    if (target === 'document') {
+                        if (cordova === null || cordova === void 0 ? void 0 : cordova.fireDocumentEvent) {
+                            cordova.fireDocumentEvent(eventName, eventData);
+                            return true;
+                        }
+                        else if (doc === null || doc === void 0 ? void 0 : doc.dispatchEvent) {
+                            return doc.dispatchEvent(ev);
+                        }
+                    }
+                    else if (target === 'window' && win.dispatchEvent) {
+                        return win.dispatchEvent(ev);
+                    }
+                    else if (doc === null || doc === void 0 ? void 0 : doc.querySelector) {
+                        const targetEl = doc.querySelector(target);
+                        if (targetEl) {
+                            return targetEl.dispatchEvent(ev);
+                        }
+                    }
+                }
+                return false;
+            };
+            win.Capacitor = cap;
+        };
+        const initLegacyHandlers = (win, cap) => {
+            // define cordova if it's not there already
+            win.cordova = win.cordova || {};
+            const doc = win.document;
+            const nav = win.navigator;
+            if (nav) {
+                nav.app = nav.app || {};
+                nav.app.exitApp = () => {
+                    var _a;
+                    if (!((_a = cap.Plugins) === null || _a === void 0 ? void 0 : _a.App)) {
+                        win.console.warn('App plugin not installed');
+                    }
+                    else {
+                        cap.nativeCallback('App', 'exitApp', {});
+                    }
+                };
+            }
+            if (doc) {
+                const docAddEventListener = doc.addEventListener;
+                doc.addEventListener = (...args) => {
+                    var _a;
+                    const eventName = args[0];
+                    const handler = args[1];
+                    if (eventName === 'deviceready' && handler) {
+                        Promise.resolve().then(handler);
+                    }
+                    else if (eventName === 'backbutton' && cap.Plugins.App) {
+                        // Add a dummy listener so Capacitor doesn't do the default
+                        // back button action
+                        if (!((_a = cap.Plugins) === null || _a === void 0 ? void 0 : _a.App)) {
+                            win.console.warn('App plugin not installed');
+                        }
+                        else {
+                            cap.Plugins.App.addListener('backButton', () => {
+                                // ignore
+                            });
+                        }
+                    }
+                    return docAddEventListener.apply(doc, args);
+                };
+            }
+            // deprecated in v3, remove from v4
+            cap.platform = cap.getPlatform();
+            cap.isNative = cap.isNativePlatform();
+            win.Capacitor = cap;
+        };
+        const initVendor = (win, cap) => {
+            const Ionic = (win.Ionic = win.Ionic || {});
+            const IonicWebView = (Ionic.WebView = Ionic.WebView || {});
+            const Plugins = cap.Plugins;
+            IonicWebView.getServerBasePath = (callback) => {
+                var _a;
+                (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.getServerBasePath().then((result) => {
+                    callback(result.path);
+                });
+            };
+            IonicWebView.setServerAssetPath = (path) => {
+                var _a;
+                (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerAssetPath({ path });
+            };
+            IonicWebView.setServerBasePath = (path) => {
+                var _a;
+                (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerBasePath({ path });
+            };
+            IonicWebView.persistServerBasePath = () => {
+                var _a;
+                (_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.persistServerBasePath();
+            };
+            IonicWebView.convertFileSrc = (url) => cap.convertFileSrc(url);
+            win.Capacitor = cap;
+            win.Ionic.WebView = IonicWebView;
+        };
+        const initLogger = (win, cap) => {
+            const BRIDGED_CONSOLE_METHODS = [
+                'debug',
+                'error',
+                'info',
+                'log',
+                'trace',
+                'warn',
+            ];
+            const createLogFromNative = (c) => (result) => {
+                if (isFullConsole(c)) {
+                    const success = result.success === true;
+                    const tagStyles = success
+                        ? 'font-style: italic; font-weight: lighter; color: gray'
+                        : 'font-style: italic; font-weight: lighter; color: red';
+                    c.groupCollapsed('%cresult %c' +
+                        result.pluginId +
+                        '.' +
+                        result.methodName +
+                        ' (#' +
+                        result.callbackId +
+                        ')', tagStyles, 'font-style: italic; font-weight: bold; color: #444');
+                    if (result.success === false) {
+                        c.error(result.error);
+                    }
+                    else {
+                        c.dir(result.data);
+                    }
+                    c.groupEnd();
+                }
+                else {
+                    if (result.success === false) {
+                        c.error('LOG FROM NATIVE', result.error);
+                    }
+                    else {
+                        c.log('LOG FROM NATIVE', result.data);
+                    }
+                }
+            };
+            const createLogToNative = (c) => (call) => {
+                if (isFullConsole(c)) {
+                    c.groupCollapsed('%cnative %c' +
+                        call.pluginId +
+                        '.' +
+                        call.methodName +
+                        ' (#' +
+                        call.callbackId +
+                        ')', 'font-weight: lighter; color: gray', 'font-weight: bold; color: #000');
+                    c.dir(call);
+                    c.groupEnd();
+                }
+                else {
+                    c.log('LOG TO NATIVE: ', call);
+                }
+            };
+            const isFullConsole = (c) => {
+                if (!c) {
+                    return false;
+                }
+                return (typeof c.groupCollapsed === 'function' ||
+                    typeof c.groupEnd === 'function' ||
+                    typeof c.dir === 'function');
+            };
+            const serializeConsoleMessage = (msg) => {
+                if (typeof msg === 'object') {
+                    try {
+                        msg = JSON.stringify(msg);
+                    }
+                    catch (e) {
+                        // ignore
+                    }
+                }
+                return String(msg);
+            };
+            const platform = getPlatformId(win);
+            if (platform == 'android' || platform == 'ios') {
+                // patch document.cookie on Android/iOS
+                win.CapacitorCookiesDescriptor =
+                    Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
+                        Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
+                let doPatchCookies = false;
+                // check if capacitor cookies is disabled before patching
+                if (platform === 'ios') {
+                    // Use prompt to synchronously get capacitor cookies config.
+                    // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
+                    const payload = {
+                        type: 'CapacitorCookies.isEnabled',
+                    };
+                    const isCookiesEnabled = prompt(JSON.stringify(payload));
+                    if (isCookiesEnabled === 'true') {
+                        doPatchCookies = true;
+                    }
+                }
+                else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
+                    const isCookiesEnabled = win.CapacitorCookiesAndroidInterface.isEnabled();
+                    if (isCookiesEnabled === true) {
+                        doPatchCookies = true;
+                    }
+                }
+                if (doPatchCookies) {
+                    Object.defineProperty(document, 'cookie', {
+                        get: function () {
+                            var _a, _b, _c;
+                            if (platform === 'ios') {
+                                // Use prompt to synchronously get cookies.
+                                // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
+                                const payload = {
+                                    type: 'CapacitorCookies.get',
+                                };
+                                const res = prompt(JSON.stringify(payload));
+                                return res;
+                            }
+                            else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
+                                // return original document.cookie since Android does not support filtering of `httpOnly` cookies
+                                return (_c = (_b = (_a = win.CapacitorCookiesDescriptor) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(document)) !== null && _c !== void 0 ? _c : '';
+                            }
+                        },
+                        set: function (val) {
+                            const cookiePairs = val.split(';');
+                            const domainSection = val.toLowerCase().split('domain=')[1];
+                            const domain = cookiePairs.length > 1 &&
+                                domainSection != null &&
+                                domainSection.length > 0
+                                ? domainSection.split(';')[0].trim()
+                                : '';
+                            if (platform === 'ios') {
+                                // Use prompt to synchronously set cookies.
+                                // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
+                                const payload = {
+                                    type: 'CapacitorCookies.set',
+                                    action: val,
+                                    domain,
+                                };
+                                prompt(JSON.stringify(payload));
+                            }
+                            else if (typeof win.CapacitorCookiesAndroidInterface !== 'undefined') {
+                                win.CapacitorCookiesAndroidInterface.setCookie(domain, val);
+                            }
+                        },
+                    });
+                }
+                // patch fetch / XHR on Android/iOS
+                // store original fetch & XHR functions
+                win.CapacitorWebFetch = window.fetch;
+                win.CapacitorWebXMLHttpRequest = {
+                    abort: window.XMLHttpRequest.prototype.abort,
+                    constructor: window.XMLHttpRequest.prototype.constructor,
+                    fullObject: window.XMLHttpRequest,
+                    getAllResponseHeaders: window.XMLHttpRequest.prototype.getAllResponseHeaders,
+                    getResponseHeader: window.XMLHttpRequest.prototype.getResponseHeader,
+                    open: window.XMLHttpRequest.prototype.open,
+                    prototype: window.XMLHttpRequest.prototype,
+                    send: window.XMLHttpRequest.prototype.send,
+                    setRequestHeader: window.XMLHttpRequest.prototype.setRequestHeader,
+                };
+                let doPatchHttp = false;
+                // check if capacitor http is disabled before patching
+                if (platform === 'ios') {
+                    // Use prompt to synchronously get capacitor http config.
+                    // https://stackoverflow.com/questions/29249132/wkwebview-complex-communication-between-javascript-native-code/49474323#49474323
+                    const payload = {
+                        type: 'CapacitorHttp',
+                    };
+                    const isHttpEnabled = prompt(JSON.stringify(payload));
+                    if (isHttpEnabled === 'true') {
+                        doPatchHttp = true;
+                    }
+                }
+                else if (typeof win.CapacitorHttpAndroidInterface !== 'undefined') {
+                    const isHttpEnabled = win.CapacitorHttpAndroidInterface.isEnabled();
+                    if (isHttpEnabled === true) {
+                        doPatchHttp = true;
+                    }
+                }
+                if (doPatchHttp) {
+                    // fetch patch
+                    window.fetch = async (resource, options) => {
+                        const request = new Request(resource, options);
+                        if (request.url.startsWith(`${cap.getServerUrl()}/`)) {
+                            return win.CapacitorWebFetch(resource, options);
+                        }
+                        if (!(options === null || options === void 0 ? void 0 : options.method) ||
+                            options.method.toLocaleUpperCase() === 'GET' ||
+                            options.method.toLocaleUpperCase() === 'HEAD' ||
+                            options.method.toLocaleUpperCase() === 'OPTIONS' ||
+                            options.method.toLocaleUpperCase() === 'TRACE') {
+                            const modifiedResource = createProxyUrl(resource.toString(), win);
+                            const response = await win.CapacitorWebFetch(modifiedResource, options);
+                            return response;
+                        }
+                        const tag = `CapacitorHttp fetch ${Date.now()} ${resource}`;
+                        console.time(tag);
+                        try {
+                            // intercept request & pass to the bridge
+                            const { body, method } = request;
+                            const optionHeaders = Object.fromEntries(request.headers.entries());
+                            const { data: requestData, type, headers, } = await convertBody((options === null || options === void 0 ? void 0 : options.body) || body || undefined, optionHeaders['Content-Type'] || optionHeaders['content-type']);
+                            const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
+                                url: request.url,
+                                method: method,
+                                data: requestData,
+                                dataType: type,
+                                headers: Object.assign(Object.assign({}, headers), optionHeaders),
+                            });
+                            const contentType = nativeResponse.headers['Content-Type'] ||
+                                nativeResponse.headers['content-type'];
+                            let data = (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('application/json'))
+                                ? JSON.stringify(nativeResponse.data)
+                                : nativeResponse.data;
+                            // use null data for 204 No Content HTTP response
+                            if (nativeResponse.status === 204) {
+                                data = null;
+                            }
+                            // intercept & parse response before returning
+                            const response = new Response(data, {
+                                headers: nativeResponse.headers,
+                                status: nativeResponse.status,
+                            });
+                            /*
+                             * copy url to response, `cordova-plugin-ionic` uses this url from the response
+                             * we need `Object.defineProperty` because url is an inherited getter on the Response
+                             * see: https://stackoverflow.com/a/57382543
+                             * */
+                            Object.defineProperty(response, 'url', {
+                                value: nativeResponse.url,
+                            });
+                            console.timeEnd(tag);
+                            return response;
+                        }
+                        catch (error) {
+                            console.timeEnd(tag);
+                            return Promise.reject(error);
+                        }
+                    };
+                    window.XMLHttpRequest = function () {
+                        const xhr = new win.CapacitorWebXMLHttpRequest.constructor();
+                        Object.defineProperties(xhr, {
+                            _headers: {
+                                value: {},
+                                writable: true,
+                            },
+                            _method: {
+                                value: xhr.method,
+                                writable: true,
+                            },
+                            readyState: {
+                                get: function () {
+                                    var _a;
+                                    return (_a = this._readyState) !== null && _a !== void 0 ? _a : 0;
+                                },
+                                set: function (val) {
+                                    this._readyState = val;
+                                    setTimeout(() => {
+                                        this.dispatchEvent(new Event('readystatechange'));
+                                    });
+                                },
+                            },
+                        });
+                        xhr.readyState = 0;
+                        const prototype = win.CapacitorWebXMLHttpRequest.prototype;
+                        const isProgressEventAvailable = () => typeof ProgressEvent !== 'undefined' &&
+                            ProgressEvent.prototype instanceof Event;
+                        // XHR patch abort
+                        prototype.abort = function () {
+                            if (isRelativeOrProxyUrl(this._url)) {
+                                return win.CapacitorWebXMLHttpRequest.abort.call(this);
+                            }
+                            this.readyState = 0;
+                            setTimeout(() => {
+                                this.dispatchEvent(new Event('abort'));
+                                this.dispatchEvent(new Event('loadend'));
+                            });
+                        };
+                        // XHR patch open
+                        prototype.open = function (method, url) {
+                            this._method = method.toLocaleUpperCase();
+                            this._url = url;
+                            if (!this._method ||
+                                this._method === 'GET' ||
+                                this._method === 'HEAD' ||
+                                this._method === 'OPTIONS' ||
+                                this._method === 'TRACE') {
+                                if (isRelativeOrProxyUrl(url)) {
+                                    return win.CapacitorWebXMLHttpRequest.open.call(this, method, url);
+                                }
+                                this._url = createProxyUrl(this._url, win);
+                                return win.CapacitorWebXMLHttpRequest.open.call(this, method, this._url);
+                            }
+                            setTimeout(() => {
+                                this.dispatchEvent(new Event('loadstart'));
+                            });
+                            this.readyState = 1;
+                        };
+                        // XHR patch set request header
+                        prototype.setRequestHeader = function (header, value) {
+                            if (isRelativeOrProxyUrl(this._url)) {
+                                return win.CapacitorWebXMLHttpRequest.setRequestHeader.call(this, header, value);
+                            }
+                            this._headers[header] = value;
+                        };
+                        // XHR patch send
+                        prototype.send = function (body) {
+                            if (isRelativeOrProxyUrl(this._url)) {
+                                return win.CapacitorWebXMLHttpRequest.send.call(this, body);
+                            }
+                            const tag = `CapacitorHttp XMLHttpRequest ${Date.now()} ${this._url}`;
+                            console.time(tag);
+                            try {
+                                this.readyState = 2;
+                                Object.defineProperties(this, {
+                                    response: {
+                                        value: '',
+                                        writable: true,
+                                    },
+                                    responseText: {
+                                        value: '',
+                                        writable: true,
+                                    },
+                                    responseURL: {
+                                        value: '',
+                                        writable: true,
+                                    },
+                                    status: {
+                                        value: 0,
+                                        writable: true,
+                                    },
+                                });
+                                convertBody(body).then(({ data, type, headers }) => {
+                                    const otherHeaders = this._headers != null && Object.keys(this._headers).length > 0
+                                        ? this._headers
+                                        : undefined;
+                                    // intercept request & pass to the bridge
+                                    cap
+                                        .nativePromise('CapacitorHttp', 'request', {
+                                        url: this._url,
+                                        method: this._method,
+                                        data: data !== null ? data : undefined,
+                                        headers: Object.assign(Object.assign({}, headers), otherHeaders),
+                                        dataType: type,
+                                    })
+                                        .then((nativeResponse) => {
+                                        var _a;
+                                        // intercept & parse response before returning
+                                        if (this.readyState == 2) {
+                                            //TODO: Add progress event emission on native side
+                                            if (isProgressEventAvailable()) {
+                                                this.dispatchEvent(new ProgressEvent('progress', {
+                                                    lengthComputable: true,
+                                                    loaded: nativeResponse.data.length,
+                                                    total: nativeResponse.data.length,
+                                                }));
+                                            }
+                                            this._headers = nativeResponse.headers;
+                                            this.status = nativeResponse.status;
+                                            const responseString = typeof nativeResponse.data !== 'string'
+                                                ? JSON.stringify(nativeResponse.data)
+                                                : nativeResponse.data;
+                                            if (this.responseType === '' ||
+                                                this.responseType === 'text') {
+                                                this.response = responseString;
+                                            }
+                                            else if (this.responseType === 'blob') {
+                                                this.response = new Blob([responseString], {
+                                                    type: 'application/json',
+                                                });
+                                            }
+                                            else if (this.responseType === 'arraybuffer') {
+                                                const encoder = new TextEncoder();
+                                                const uint8Array = encoder.encode(responseString);
+                                                this.response = uint8Array.buffer;
+                                            }
+                                            else {
+                                                this.response = nativeResponse.data;
+                                            }
+                                            this.responseText = ((_a = nativeResponse.headers['Content-Type']) === null || _a === void 0 ? void 0 : _a.startsWith('application/json'))
+                                                ? JSON.stringify(nativeResponse.data)
+                                                : nativeResponse.data;
+                                            this.responseURL = nativeResponse.url;
+                                            this.readyState = 4;
+                                            setTimeout(() => {
+                                                this.dispatchEvent(new Event('load'));
+                                                this.dispatchEvent(new Event('loadend'));
+                                            });
+                                        }
+                                        console.timeEnd(tag);
+                                    })
+                                        .catch((error) => {
+                                        this.status = error.status;
+                                        this._headers = error.headers;
+                                        this.response = error.data;
+                                        this.responseText = JSON.stringify(error.data);
+                                        this.responseURL = error.url;
+                                        this.readyState = 4;
+                                        if (isProgressEventAvailable()) {
+                                            this.dispatchEvent(new ProgressEvent('progress', {
+                                                lengthComputable: false,
+                                                loaded: 0,
+                                                total: 0,
+                                            }));
+                                        }
+                                        setTimeout(() => {
+                                            this.dispatchEvent(new Event('error'));
+                                            this.dispatchEvent(new Event('loadend'));
+                                        });
+                                        console.timeEnd(tag);
+                                    });
+                                });
+                            }
+                            catch (error) {
+                                this.status = 500;
+                                this._headers = {};
+                                this.response = error;
+                                this.responseText = error.toString();
+                                this.responseURL = this._url;
+                                this.readyState = 4;
+                                if (isProgressEventAvailable()) {
+                                    this.dispatchEvent(new ProgressEvent('progress', {
+                                        lengthComputable: false,
+                                        loaded: 0,
+                                        total: 0,
+                                    }));
+                                }
+                                setTimeout(() => {
+                                    this.dispatchEvent(new Event('error'));
+                                    this.dispatchEvent(new Event('loadend'));
+                                });
+                                console.timeEnd(tag);
+                            }
+                        };
+                        // XHR patch getAllResponseHeaders
+                        prototype.getAllResponseHeaders = function () {
+                            if (isRelativeOrProxyUrl(this._url)) {
+                                return win.CapacitorWebXMLHttpRequest.getAllResponseHeaders.call(this);
+                            }
+                            let returnString = '';
+                            for (const key in this._headers) {
+                                if (key.toLowerCase() !== 'set-cookie') {
+                                    returnString += key + ': ' + this._headers[key] + '\r\n';
+                                }
+                            }
+                            return returnString;
+                        };
+                        // XHR patch getResponseHeader
+                        prototype.getResponseHeader = function (name) {
+                            if (isRelativeOrProxyUrl(this._url)) {
+                                return win.CapacitorWebXMLHttpRequest.getResponseHeader.call(this, name);
+                            }
+                            for (const key in this._headers) {
+                                if (key.toLowerCase() === name.toLowerCase()) {
+                                    return this._headers[key];
+                                }
+                            }
+                            return null;
+                        };
+                        Object.setPrototypeOf(xhr, prototype);
+                        return xhr;
+                    };
+                    Object.assign(window.XMLHttpRequest, win.CapacitorWebXMLHttpRequest.fullObject);
+                }
+            }
+            // patch window.console on iOS and store original console fns
+            const isIos = getPlatformId(win) === 'ios';
+            if (win.console && isIos) {
+                Object.defineProperties(win.console, BRIDGED_CONSOLE_METHODS.reduce((props, method) => {
+                    const consoleMethod = win.console[method].bind(win.console);
+                    props[method] = {
+                        value: (...args) => {
+                            const msgs = [...args];
+                            cap.toNative('Console', 'log', {
+                                level: method,
+                                message: msgs.map(serializeConsoleMessage).join(' '),
+                            });
+                            return consoleMethod(...args);
+                        },
+                    };
+                    return props;
+                }, {}));
+            }
+            cap.logJs = (msg, level) => {
+                switch (level) {
+                    case 'error':
+                        win.console.error(msg);
+                        break;
+                    case 'warn':
+                        win.console.warn(msg);
+                        break;
+                    case 'info':
+                        win.console.info(msg);
+                        break;
+                    default:
+                        win.console.log(msg);
+                }
+            };
+            cap.logToNative = createLogToNative(win.console);
+            cap.logFromNative = createLogFromNative(win.console);
+            cap.handleError = err => win.console.error(err);
+            win.Capacitor = cap;
+        };
+        function initNativeBridge(win) {
+            const cap = win.Capacitor || {};
+            // keep a collection of callbacks for native response data
+            const callbacks = new Map();
+            const webviewServerUrl = typeof win.WEBVIEW_SERVER_URL === 'string' ? win.WEBVIEW_SERVER_URL : '';
+            cap.getServerUrl = () => webviewServerUrl;
+            cap.convertFileSrc = filePath => convertFileSrcServerUrl(webviewServerUrl, filePath);
+            // Counter of callback ids, randomized to avoid
+            // any issues during reloads if a call comes back with
+            // an existing callback id from an old session
+            let callbackIdCount = Math.floor(Math.random() * 134217728);
+            let postToNative = null;
+            const isNativePlatform = () => true;
+            const getPlatform = () => getPlatformId(win);
+            cap.getPlatform = getPlatform;
+            cap.isPluginAvailable = name => Object.prototype.hasOwnProperty.call(cap.Plugins, name);
+            cap.isNativePlatform = isNativePlatform;
+            // create the postToNative() fn if needed
+            if (getPlatformId(win) === 'android') {
+                // android platform
+                postToNative = data => {
+                    var _a;
+                    try {
+                        win.androidBridge.postMessage(JSON.stringify(data));
+                    }
+                    catch (e) {
+                        (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.error(e);
+                    }
+                };
+            }
+            else if (getPlatformId(win) === 'ios') {
+                // ios platform
+                postToNative = data => {
+                    var _a;
+                    try {
+                        data.type = data.type ? data.type : 'message';
+                        win.webkit.messageHandlers.bridge.postMessage(data);
+                    }
+                    catch (e) {
+                        (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.error(e);
+                    }
+                };
+            }
+            cap.handleWindowError = (msg, url, lineNo, columnNo, err) => {
+                const str = msg.toLowerCase();
+                if (str.indexOf('script error') > -1) ;
+                else {
+                    const errObj = {
+                        type: 'js.error',
+                        error: {
+                            message: msg,
+                            url: url,
+                            line: lineNo,
+                            col: columnNo,
+                            errorObject: JSON.stringify(err),
+                        },
+                    };
+                    if (err !== null) {
+                        cap.handleError(err);
+                    }
+                    postToNative(errObj);
+                }
+                return false;
+            };
+            if (cap.DEBUG) {
+                window.onerror = cap.handleWindowError;
+            }
+            initLogger(win, cap);
+            /**
+             * Send a plugin method call to the native layer
+             */
+            cap.toNative = (pluginName, methodName, options, storedCallback) => {
+                var _a, _b;
+                try {
+                    if (typeof postToNative === 'function') {
+                        let callbackId = '-1';
+                        if (storedCallback &&
+                            (typeof storedCallback.callback === 'function' ||
+                                typeof storedCallback.resolve === 'function')) {
+                            // store the call for later lookup
+                            callbackId = String(++callbackIdCount);
+                            callbacks.set(callbackId, storedCallback);
+                        }
+                        const callData = {
+                            callbackId: callbackId,
+                            pluginId: pluginName,
+                            methodName: methodName,
+                            options: options || {},
+                        };
+                        if (cap.isLoggingEnabled && pluginName !== 'Console') {
+                            cap.logToNative(callData);
+                        }
+                        // post the call data to native
+                        postToNative(callData);
+                        return callbackId;
+                    }
+                    else {
+                        (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.warn(`implementation unavailable for: ${pluginName}`);
+                    }
+                }
+                catch (e) {
+                    (_b = win === null || win === void 0 ? void 0 : win.console) === null || _b === void 0 ? void 0 : _b.error(e);
+                }
+                return null;
+            };
+            if (win === null || win === void 0 ? void 0 : win.androidBridge) {
+                win.androidBridge.onmessage = function (event) {
+                    returnResult(JSON.parse(event.data));
+                };
+            }
+            /**
+             * Process a response from the native layer.
+             */
+            cap.fromNative = result => {
+                returnResult(result);
+            };
+            const returnResult = (result) => {
+                var _a, _b;
+                if (cap.isLoggingEnabled && result.pluginId !== 'Console') {
+                    cap.logFromNative(result);
+                }
+                // get the stored call, if it exists
+                try {
+                    const storedCall = callbacks.get(result.callbackId);
+                    if (storedCall) {
+                        // looks like we've got a stored call
+                        if (result.error) {
+                            // ensure stacktraces by copying error properties to an Error
+                            result.error = Object.keys(result.error).reduce((err, key) => {
+                                // use any type to avoid importing util and compiling most of .ts files
+                                err[key] = result.error[key];
+                                return err;
+                            }, new cap.Exception(''));
+                        }
+                        if (typeof storedCall.callback === 'function') {
+                            // callback
+                            if (result.success) {
+                                storedCall.callback(result.data);
+                            }
+                            else {
+                                storedCall.callback(null, result.error);
+                            }
+                        }
+                        else if (typeof storedCall.resolve === 'function') {
+                            // promise
+                            if (result.success) {
+                                storedCall.resolve(result.data);
+                            }
+                            else {
+                                storedCall.reject(result.error);
+                            }
+                            // no need to keep this stored callback
+                            // around for a one time resolve promise
+                            callbacks.delete(result.callbackId);
+                        }
+                    }
+                    else if (!result.success && result.error) {
+                        // no stored callback, but if there was an error let's log it
+                        (_a = win === null || win === void 0 ? void 0 : win.console) === null || _a === void 0 ? void 0 : _a.warn(result.error);
+                    }
+                    if (result.save === false) {
+                        callbacks.delete(result.callbackId);
+                    }
+                }
+                catch (e) {
+                    (_b = win === null || win === void 0 ? void 0 : win.console) === null || _b === void 0 ? void 0 : _b.error(e);
+                }
+                // always delete to prevent memory leaks
+                // overkill but we're not sure what apps will do with this data
+                delete result.data;
+                delete result.error;
+            };
+            cap.nativeCallback = (pluginName, methodName, options, callback) => {
+                if (typeof options === 'function') {
+                    console.warn(`Using a callback as the 'options' parameter of 'nativeCallback()' is deprecated.`);
+                    callback = options;
+                    options = null;
+                }
+                return cap.toNative(pluginName, methodName, options, { callback });
+            };
+            cap.nativePromise = (pluginName, methodName, options) => {
+                return new Promise((resolve, reject) => {
+                    cap.toNative(pluginName, methodName, options, {
+                        resolve: resolve,
+                        reject: reject,
+                    });
+                });
+            };
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            cap.withPlugin = (_pluginId, _fn) => dummy;
+            cap.Exception = CapacitorException;
+            initEvents(win, cap);
+            initLegacyHandlers(win, cap);
+            initVendor(win, cap);
+            win.Capacitor = cap;
+        }
+        initNativeBridge(w);
+    };
+    initBridge(typeof globalThis !== 'undefined'
+        ? globalThis
+        : typeof self !== 'undefined'
+            ? self
+            : typeof window !== 'undefined'
+                ? window
+                : typeof global !== 'undefined'
+                    ? global
+                    : {});
+
+    dummy = initBridge;
+
+    Object.defineProperty(exports, '__esModule', { value: true });
+
+    return exports;
+
+})({});

+ 94 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/AndroidProtocolHandler.java

@@ -0,0 +1,94 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package com.getcapacitor;
+
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.net.Uri;
+import android.util.TypedValue;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+public class AndroidProtocolHandler {
+
+    private Context context;
+
+    public AndroidProtocolHandler(Context context) {
+        this.context = context;
+    }
+
+    public InputStream openAsset(String path) throws IOException {
+        return context.getAssets().open(path, AssetManager.ACCESS_STREAMING);
+    }
+
+    public InputStream openResource(Uri uri) {
+        assert uri.getPath() != null;
+        // The path must be of the form ".../asset_type/asset_name.ext".
+        List<String> pathSegments = uri.getPathSegments();
+        String assetType = pathSegments.get(pathSegments.size() - 2);
+        String assetName = pathSegments.get(pathSegments.size() - 1);
+
+        // Drop the file extension.
+        assetName = assetName.split("\\.")[0];
+        try {
+            // Use the application context for resolving the resource package name so that we do
+            // not use the browser's own resources. Note that if 'context' here belongs to the
+            // test suite, it does not have a separate application context. In that case we use
+            // the original context object directly.
+            if (context.getApplicationContext() != null) {
+                context = context.getApplicationContext();
+            }
+            int fieldId = getFieldId(context, assetType, assetName);
+            int valueType = getValueType(context, fieldId);
+            if (valueType == TypedValue.TYPE_STRING) {
+                return context.getResources().openRawResource(fieldId);
+            } else {
+                Logger.error("Asset not of type string: " + uri);
+            }
+        } catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) {
+            Logger.error("Unable to open resource URL: " + uri, e);
+        }
+        return null;
+    }
+
+    private static int getFieldId(Context context, String assetType, String assetName)
+        throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
+        Class<?> d = context.getClassLoader().loadClass(context.getPackageName() + ".R$" + assetType);
+        java.lang.reflect.Field field = d.getField(assetName);
+        return field.getInt(null);
+    }
+
+    public InputStream openFile(String filePath) throws IOException {
+        String realPath = filePath.replace(Bridge.CAPACITOR_FILE_START, "");
+        File localFile = new File(realPath);
+        return new FileInputStream(localFile);
+    }
+
+    public InputStream openContentUrl(Uri uri) throws IOException {
+        Integer port = uri.getPort();
+        String baseUrl = uri.getScheme() + "://" + uri.getHost();
+        if (port != -1) {
+            baseUrl += ":" + port;
+        }
+        String realPath = uri.toString().replace(baseUrl + Bridge.CAPACITOR_CONTENT_START, "content:/");
+
+        InputStream stream = null;
+        try {
+            stream = context.getContentResolver().openInputStream(Uri.parse(realPath));
+        } catch (SecurityException e) {
+            Logger.error("Unable to open content URL: " + uri, e);
+        }
+        return stream;
+    }
+
+    private static int getValueType(Context context, int fieldId) {
+        TypedValue value = new TypedValue();
+        context.getResources().getValue(fieldId, value, true);
+        return value.type;
+    }
+}

+ 61 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/App.java

@@ -0,0 +1,61 @@
+package com.getcapacitor;
+
+import androidx.annotation.Nullable;
+
+public class App {
+
+    /**
+     * Interface for callbacks when app status changes.
+     */
+    public interface AppStatusChangeListener {
+        void onAppStatusChanged(Boolean isActive);
+    }
+
+    /**
+     * Interface for callbacks when app is restored with pending plugin call.
+     */
+    public interface AppRestoredListener {
+        void onAppRestored(PluginResult result);
+    }
+
+    @Nullable
+    private AppStatusChangeListener statusChangeListener;
+
+    @Nullable
+    private AppRestoredListener appRestoredListener;
+
+    private boolean isActive = false;
+
+    public boolean isActive() {
+        return isActive;
+    }
+
+    /**
+     * Set the object to receive callbacks.
+     * @param listener
+     */
+    public void setStatusChangeListener(@Nullable AppStatusChangeListener listener) {
+        this.statusChangeListener = listener;
+    }
+
+    /**
+     * Set the object to receive callbacks.
+     * @param listener
+     */
+    public void setAppRestoredListener(@Nullable AppRestoredListener listener) {
+        this.appRestoredListener = listener;
+    }
+
+    protected void fireRestoredResult(PluginResult result) {
+        if (appRestoredListener != null) {
+            appRestoredListener.onAppRestored(result);
+        }
+    }
+
+    public void fireStatusChange(boolean isActive) {
+        this.isActive = isActive;
+        if (statusChangeListener != null) {
+            statusChangeListener.onAppStatusChanged(isActive);
+        }
+    }
+}

+ 65 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/AppUUID.java

@@ -0,0 +1,65 @@
+package com.getcapacitor;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import androidx.appcompat.app.AppCompatActivity;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+import java.util.UUID;
+
+public final class AppUUID {
+
+    private static final String KEY = "CapacitorAppUUID";
+
+    public static String getAppUUID(AppCompatActivity activity) throws Exception {
+        assertAppUUID(activity);
+        return readUUID(activity);
+    }
+
+    public static void regenerateAppUUID(AppCompatActivity activity) throws Exception {
+        try {
+            String uuid = generateUUID();
+            writeUUID(activity, uuid);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new Exception("Capacitor App UUID could not be generated.");
+        }
+    }
+
+    private static void assertAppUUID(AppCompatActivity activity) throws Exception {
+        String uuid = readUUID(activity);
+        if (uuid.equals("")) {
+            regenerateAppUUID(activity);
+        }
+    }
+
+    private static String generateUUID() throws NoSuchAlgorithmException {
+        MessageDigest salt = MessageDigest.getInstance("SHA-256");
+        salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
+        return bytesToHex(salt.digest());
+    }
+
+    private static String readUUID(AppCompatActivity activity) {
+        SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
+        return sharedPref.getString(KEY, "");
+    }
+
+    private static void writeUUID(AppCompatActivity activity, String uuid) {
+        SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sharedPref.edit();
+        editor.putString(KEY, uuid);
+        editor.apply();
+    }
+
+    private static String bytesToHex(byte[] bytes) {
+        byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
+        byte[] hexChars = new byte[bytes.length * 2];
+        for (int j = 0; j < bytes.length; j++) {
+            int v = bytes[j] & 0xFF;
+            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
+            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
+        }
+        return new String(hexChars, StandardCharsets.UTF_8);
+    }
+}

+ 1568 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/Bridge.java

@@ -0,0 +1,1568 @@
+package com.getcapacitor;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.webkit.ValueCallback;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContract;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.pm.PackageInfoCompat;
+import androidx.fragment.app.Fragment;
+import com.getcapacitor.android.R;
+import com.getcapacitor.annotation.CapacitorPlugin;
+import com.getcapacitor.annotation.Permission;
+import com.getcapacitor.cordova.MockCordovaInterfaceImpl;
+import com.getcapacitor.cordova.MockCordovaWebViewImpl;
+import com.getcapacitor.util.HostMask;
+import com.getcapacitor.util.InternalUtils;
+import com.getcapacitor.util.PermissionHelper;
+import com.getcapacitor.util.WebColor;
+import java.io.File;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.cordova.ConfigXmlParser;
+import org.apache.cordova.CordovaPreferences;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.PluginEntry;
+import org.apache.cordova.PluginManager;
+import org.json.JSONException;
+
+/**
+ * The Bridge class is the main engine of Capacitor. It manages
+ * loading and communicating with all Plugins,
+ * proxying Native events to Plugins, executing Plugin methods,
+ * communicating with the WebView, and a whole lot more.
+ *
+ * Generally, you'll not use Bridge directly, instead, extend from BridgeActivity
+ * to get a WebView instance and proxy native events automatically.
+ *
+ * If you want to use this Bridge in an existing Android app, please
+ * see the source for BridgeActivity for the methods you'll need to
+ * pass through to Bridge:
+ * <a href="https://github.com/ionic-team/capacitor/blob/HEAD/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java">
+ *   BridgeActivity.java</a>
+ */
+public class Bridge {
+
+    private static final String PREFS_NAME = "CapacitorSettings";
+    private static final String PERMISSION_PREFS_NAME = "PluginPermStates";
+    private static final String BUNDLE_LAST_PLUGIN_ID_KEY = "capacitorLastActivityPluginId";
+    private static final String BUNDLE_LAST_PLUGIN_CALL_METHOD_NAME_KEY = "capacitorLastActivityPluginMethod";
+    private static final String BUNDLE_PLUGIN_CALL_OPTIONS_SAVED_KEY = "capacitorLastPluginCallOptions";
+    private static final String BUNDLE_PLUGIN_CALL_BUNDLE_KEY = "capacitorLastPluginCallBundle";
+    private static final String LAST_BINARY_VERSION_CODE = "lastBinaryVersionCode";
+    private static final String LAST_BINARY_VERSION_NAME = "lastBinaryVersionName";
+    private static final String MINIMUM_ANDROID_WEBVIEW_ERROR = "System WebView is not supported";
+
+    // The name of the directory we use to look for index.html and the rest of our web assets
+    public static final String DEFAULT_WEB_ASSET_DIR = "public";
+    public static final String CAPACITOR_HTTP_SCHEME = "http";
+    public static final String CAPACITOR_HTTPS_SCHEME = "https";
+    public static final String CAPACITOR_FILE_START = "/_capacitor_file_";
+    public static final String CAPACITOR_CONTENT_START = "/_capacitor_content_";
+    public static final String CAPACITOR_HTTP_INTERCEPTOR_START = "/_capacitor_http_interceptor_";
+    public static final String CAPACITOR_HTTPS_INTERCEPTOR_START = "/_capacitor_https_interceptor_";
+
+    public static final int DEFAULT_ANDROID_WEBVIEW_VERSION = 60;
+    public static final int MINIMUM_ANDROID_WEBVIEW_VERSION = 55;
+    public static final int DEFAULT_HUAWEI_WEBVIEW_VERSION = 10;
+    public static final int MINIMUM_HUAWEI_WEBVIEW_VERSION = 10;
+
+    // Loaded Capacitor config
+    private CapConfig config;
+
+    // A reference to the main activity for the app
+    private final AppCompatActivity context;
+    // A reference to the containing Fragment if used
+    private final Fragment fragment;
+    private WebViewLocalServer localServer;
+    private String localUrl;
+    private String appUrl;
+    private String appUrlConfig;
+    private HostMask appAllowNavigationMask;
+    private Set<String> allowedOriginRules = new HashSet<String>();
+    private ArrayList<String> authorities = new ArrayList<>();
+    // A reference to the main WebView for the app
+    private final WebView webView;
+    public final MockCordovaInterfaceImpl cordovaInterface;
+    private CordovaWebView cordovaWebView;
+    private CordovaPreferences preferences;
+    private BridgeWebViewClient webViewClient;
+    private App app;
+
+    // Our MessageHandler for sending and receiving data to the WebView
+    private final MessageHandler msgHandler;
+
+    // The ThreadHandler for executing plugin calls
+    private final HandlerThread handlerThread = new HandlerThread("CapacitorPlugins");
+
+    // Our Handler for posting plugin calls. Created from the ThreadHandler
+    private Handler taskHandler = null;
+
+    private final List<Class<? extends Plugin>> initialPlugins;
+
+    private final List<Plugin> pluginInstances;
+
+    // A map of Plugin Id's to PluginHandle's
+    private Map<String, PluginHandle> plugins = new HashMap<>();
+
+    // Stored plugin calls that we're keeping around to call again someday
+    private Map<String, PluginCall> savedCalls = new HashMap<>();
+
+    // The call IDs of saved plugin calls with associated plugin id for handling permissions
+    private Map<String, LinkedList<String>> savedPermissionCallIds = new HashMap<>();
+
+    // Store a plugin that started a new activity, in case we need to resume
+    // the app and return that data back
+    private PluginCall pluginCallForLastActivity;
+
+    // Any URI that was passed to the app on start
+    private Uri intentUri;
+
+    // A list of listeners that trigger when webView events occur
+    private List<WebViewListener> webViewListeners = new ArrayList<>();
+
+    // An interface to manipulate route resolving
+    private RouteProcessor routeProcessor;
+
+    // A pre-determined path to load the bridge
+    private ServerPath serverPath;
+
+    /**
+     * Create the Bridge with a reference to the main {@link Activity} for the
+     * app, and a reference to the {@link WebView} our app will use.
+     * @param context
+     * @param webView
+     * @deprecated Use {@link Bridge.Builder} to create Bridge instances
+     */
+    @Deprecated
+    public Bridge(
+        AppCompatActivity context,
+        WebView webView,
+        List<Class<? extends Plugin>> initialPlugins,
+        MockCordovaInterfaceImpl cordovaInterface,
+        PluginManager pluginManager,
+        CordovaPreferences preferences,
+        CapConfig config
+    ) {
+        this(context, null, null, webView, initialPlugins, new ArrayList<>(), cordovaInterface, pluginManager, preferences, config);
+    }
+
+    private Bridge(
+        AppCompatActivity context,
+        ServerPath serverPath,
+        Fragment fragment,
+        WebView webView,
+        List<Class<? extends Plugin>> initialPlugins,
+        List<Plugin> pluginInstances,
+        MockCordovaInterfaceImpl cordovaInterface,
+        PluginManager pluginManager,
+        CordovaPreferences preferences,
+        CapConfig config
+    ) {
+        this.app = new App();
+        this.serverPath = serverPath;
+        this.context = context;
+        this.fragment = fragment;
+        this.webView = webView;
+        this.webViewClient = new BridgeWebViewClient(this);
+        this.initialPlugins = initialPlugins;
+        this.pluginInstances = pluginInstances;
+        this.cordovaInterface = cordovaInterface;
+        this.preferences = preferences;
+
+        // Start our plugin execution threads and handlers
+        handlerThread.start();
+        taskHandler = new Handler(handlerThread.getLooper());
+
+        this.config = config != null ? config : CapConfig.loadDefault(getActivity());
+        Logger.init(this.config);
+
+        // Initialize web view and message handler for it
+        this.initWebView();
+        this.setAllowedOriginRules();
+        this.msgHandler = new MessageHandler(this, webView, pluginManager);
+
+        // Grab any intent info that our app was launched with
+        Intent intent = context.getIntent();
+        this.intentUri = intent.getData();
+        // Register our core plugins
+        this.registerAllPlugins();
+
+        this.loadWebView();
+    }
+
+    private void setAllowedOriginRules() {
+        String[] appAllowNavigationConfig = this.config.getAllowNavigation();
+        String authority = this.getHost();
+        String scheme = this.getScheme();
+        allowedOriginRules.add(scheme + "://" + authority);
+        if (this.getServerUrl() != null) {
+            allowedOriginRules.add(this.getServerUrl());
+        }
+        if (appAllowNavigationConfig != null) {
+            for (String allowNavigation : appAllowNavigationConfig) {
+                if (!allowNavigation.startsWith("http")) {
+                    allowedOriginRules.add("https://" + allowNavigation);
+                } else {
+                    allowedOriginRules.add(allowNavigation);
+                }
+            }
+            authorities.addAll(Arrays.asList(appAllowNavigationConfig));
+        }
+        this.appAllowNavigationMask = HostMask.Parser.parse(appAllowNavigationConfig);
+    }
+
+    public App getApp() {
+        return app;
+    }
+
+    private void loadWebView() {
+        final boolean html5mode = this.config.isHTML5Mode();
+
+        // Start the local web server
+        localServer = new WebViewLocalServer(context, this, getJSInjector(), authorities, html5mode);
+        localServer.hostAssets(DEFAULT_WEB_ASSET_DIR);
+
+        Logger.debug("Loading app at " + appUrl);
+
+        webView.setWebChromeClient(new BridgeWebChromeClient(this));
+        webView.setWebViewClient(this.webViewClient);
+
+        if (!isDeployDisabled() && !isNewBinary()) {
+            SharedPreferences prefs = getContext()
+                .getSharedPreferences(com.getcapacitor.plugin.WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
+            String path = prefs.getString(com.getcapacitor.plugin.WebView.CAP_SERVER_PATH, null);
+            if (path != null && !path.isEmpty() && new File(path).exists()) {
+                setServerBasePath(path);
+            }
+        }
+        if (!this.isMinimumWebViewInstalled()) {
+            String errorUrl = this.getErrorUrl();
+            if (errorUrl != null) {
+                webView.loadUrl(errorUrl);
+                return;
+            } else {
+                Logger.error(MINIMUM_ANDROID_WEBVIEW_ERROR);
+            }
+        }
+
+        // If serverPath configured, start server based on provided path
+        if (serverPath != null) {
+            if (serverPath.getType() == ServerPath.PathType.ASSET_PATH) {
+                setServerAssetPath(serverPath.getPath());
+            } else {
+                setServerBasePath(serverPath.getPath());
+            }
+        } else {
+            // Get to work
+            webView.loadUrl(appUrl);
+        }
+    }
+
+    @SuppressLint("WebViewApiAvailability")
+    public boolean isMinimumWebViewInstalled() {
+        PackageManager pm = getContext().getPackageManager();
+
+        // Check getCurrentWebViewPackage() directly if above Android 8
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            PackageInfo info = WebView.getCurrentWebViewPackage();
+            Pattern pattern = Pattern.compile("(\\d+)");
+            Matcher matcher = pattern.matcher(info.versionName);
+            if (matcher.find()) {
+                String majorVersionStr = matcher.group(0);
+                int majorVersion = Integer.parseInt(majorVersionStr);
+                if (info.packageName.equals("com.huawei.webview")) {
+                    return majorVersion >= config.getMinHuaweiWebViewVersion();
+                }
+                return majorVersion >= config.getMinWebViewVersion();
+            } else {
+                return false;
+            }
+        }
+
+        // Otherwise manually check WebView versions
+        try {
+            String webViewPackage = "com.google.android.webview";
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                webViewPackage = "com.android.chrome";
+            }
+            PackageInfo info = InternalUtils.getPackageInfo(pm, webViewPackage);
+            String majorVersionStr = info.versionName.split("\\.")[0];
+            int majorVersion = Integer.parseInt(majorVersionStr);
+            return majorVersion >= config.getMinWebViewVersion();
+        } catch (Exception ex) {
+            Logger.warn("Unable to get package info for 'com.google.android.webview'" + ex.toString());
+        }
+
+        try {
+            PackageInfo info = InternalUtils.getPackageInfo(pm, "com.android.webview");
+            String majorVersionStr = info.versionName.split("\\.")[0];
+            int majorVersion = Integer.parseInt(majorVersionStr);
+            return majorVersion >= config.getMinWebViewVersion();
+        } catch (Exception ex) {
+            Logger.warn("Unable to get package info for 'com.android.webview'" + ex.toString());
+        }
+
+        final int amazonFireMajorWebViewVersion = extractWebViewMajorVersion(pm, "com.amazon.webview.chromium");
+        if (amazonFireMajorWebViewVersion >= config.getMinWebViewVersion()) {
+            return true;
+        }
+
+        // Could not detect any webview, return false
+        return false;
+    }
+
+    private int extractWebViewMajorVersion(final PackageManager pm, final String webViewPackageName) {
+        try {
+            final PackageInfo info = InternalUtils.getPackageInfo(pm, webViewPackageName);
+            final String majorVersionStr = info.versionName.split("\\.")[0];
+            final int majorVersion = Integer.parseInt(majorVersionStr);
+            return majorVersion;
+        } catch (Exception ex) {
+            Logger.warn(String.format("Unable to get package info for '%s' with err '%s'", webViewPackageName, ex));
+        }
+        return 0;
+    }
+
+    public boolean launchIntent(Uri url) {
+        /*
+         * Give plugins the chance to handle the url
+         */
+        for (Map.Entry<String, PluginHandle> entry : plugins.entrySet()) {
+            Plugin plugin = entry.getValue().getInstance();
+            if (plugin != null) {
+                Boolean shouldOverrideLoad = plugin.shouldOverrideLoad(url);
+                if (shouldOverrideLoad != null) {
+                    return shouldOverrideLoad;
+                }
+            }
+        }
+
+        if (url.getScheme().equals("data")) {
+            return false;
+        }
+
+        Uri appUri = Uri.parse(appUrl);
+        if (
+            !(appUri.getHost().equals(url.getHost()) && url.getScheme().equals(appUri.getScheme())) &&
+            !appAllowNavigationMask.matches(url.getHost())
+        ) {
+            try {
+                Intent openIntent = new Intent(Intent.ACTION_VIEW, url);
+                getContext().startActivity(openIntent);
+            } catch (ActivityNotFoundException e) {
+                // TODO - trigger an event
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isNewBinary() {
+        String versionCode = "";
+        String versionName = "";
+        SharedPreferences prefs = getContext()
+            .getSharedPreferences(com.getcapacitor.plugin.WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
+        String lastVersionCode = prefs.getString(LAST_BINARY_VERSION_CODE, null);
+        String lastVersionName = prefs.getString(LAST_BINARY_VERSION_NAME, null);
+
+        try {
+            PackageManager pm = getContext().getPackageManager();
+            PackageInfo pInfo = InternalUtils.getPackageInfo(pm, getContext().getPackageName());
+            versionCode = Integer.toString((int) PackageInfoCompat.getLongVersionCode(pInfo));
+            versionName = pInfo.versionName;
+        } catch (Exception ex) {
+            Logger.error("Unable to get package info", ex);
+        }
+
+        if (!versionCode.equals(lastVersionCode) || !versionName.equals(lastVersionName)) {
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putString(LAST_BINARY_VERSION_CODE, versionCode);
+            editor.putString(LAST_BINARY_VERSION_NAME, versionName);
+            editor.putString(com.getcapacitor.plugin.WebView.CAP_SERVER_PATH, "");
+            editor.apply();
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isDeployDisabled() {
+        return preferences.getBoolean("DisableDeploy", false);
+    }
+
+    public boolean shouldKeepRunning() {
+        return preferences.getBoolean("KeepRunning", true);
+    }
+
+    public void handleAppUrlLoadError(Exception ex) {
+        if (ex instanceof SocketTimeoutException) {
+            Logger.error(
+                "Unable to load app. Ensure the server is running at " +
+                appUrl +
+                ", or modify the " +
+                "appUrl setting in capacitor.config.json (make sure to npx cap copy after to commit changes).",
+                ex
+            );
+        }
+    }
+
+    public boolean isDevMode() {
+        return (getActivity().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+    }
+
+    protected void setCordovaWebView(CordovaWebView cordovaWebView) {
+        this.cordovaWebView = cordovaWebView;
+    }
+
+    /**
+     * Get the Context for the App
+     * @return
+     */
+    public Context getContext() {
+        return this.context;
+    }
+
+    /**
+     * Get the activity for the app
+     * @return
+     */
+    public AppCompatActivity getActivity() {
+        return this.context;
+    }
+
+    /**
+     * Get the fragment for the app, if applicable. This will likely be null unless Capacitor
+     * is being used embedded in a Native Android app.
+     *
+     * @return The fragment containing the Capacitor WebView.
+     */
+    public Fragment getFragment() {
+        return this.fragment;
+    }
+
+    /**
+     * Get the core WebView under Capacitor's control
+     * @return
+     */
+    public WebView getWebView() {
+        return this.webView;
+    }
+
+    /**
+     * Get the URI that was used to launch the app (if any)
+     * @return
+     */
+    public Uri getIntentUri() {
+        return intentUri;
+    }
+
+    /**
+     * Get scheme that is used to serve content
+     * @return
+     */
+    public String getScheme() {
+        return this.config.getAndroidScheme();
+    }
+
+    /**
+     * Get host name that is used to serve content
+     * @return
+     */
+    public String getHost() {
+        return this.config.getHostname();
+    }
+
+    /**
+     * Get the server url that is used to serve content
+     * @return
+     */
+    public String getServerUrl() {
+        return this.config.getServerUrl();
+    }
+
+    public String getErrorUrl() {
+        String errorPath = this.config.getErrorPath();
+
+        if (errorPath != null && !errorPath.trim().isEmpty()) {
+            String authority = this.getHost();
+            String scheme = this.getScheme();
+
+            String localUrl = scheme + "://" + authority;
+
+            return localUrl + "/" + errorPath;
+        }
+
+        return null;
+    }
+
+    public String getAppUrl() {
+        return appUrl;
+    }
+
+    public CapConfig getConfig() {
+        return this.config;
+    }
+
+    public void reset() {
+        savedCalls = new HashMap<>();
+    }
+
+    /**
+     * Initialize the WebView, setting required flags
+     */
+    @SuppressLint("SetJavaScriptEnabled")
+    private void initWebView() {
+        WebSettings settings = webView.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setDomStorageEnabled(true);
+        settings.setGeolocationEnabled(true);
+        settings.setDatabaseEnabled(true);
+        settings.setMediaPlaybackRequiresUserGesture(false);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+        if (this.config.isMixedContentAllowed()) {
+            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+        }
+
+        String appendUserAgent = this.config.getAppendedUserAgentString();
+        if (appendUserAgent != null) {
+            String defaultUserAgent = settings.getUserAgentString();
+            settings.setUserAgentString(defaultUserAgent + " " + appendUserAgent);
+        }
+        String overrideUserAgent = this.config.getOverriddenUserAgentString();
+        if (overrideUserAgent != null) {
+            settings.setUserAgentString(overrideUserAgent);
+        }
+
+        String backgroundColor = this.config.getBackgroundColor();
+        try {
+            if (backgroundColor != null) {
+                webView.setBackgroundColor(WebColor.parseColor(backgroundColor));
+            }
+        } catch (IllegalArgumentException ex) {
+            Logger.debug("WebView background color not applied");
+        }
+
+        if (config.isInitialFocus()) {
+            webView.requestFocusFromTouch();
+        }
+
+        WebView.setWebContentsDebuggingEnabled(this.config.isWebContentsDebuggingEnabled());
+
+        appUrlConfig = this.getServerUrl();
+        String authority = this.getHost();
+        authorities.add(authority);
+        String scheme = this.getScheme();
+
+        localUrl = scheme + "://" + authority;
+
+        if (appUrlConfig != null) {
+            try {
+                URL appUrlObject = new URL(appUrlConfig);
+                authorities.add(appUrlObject.getAuthority());
+            } catch (Exception ex) {
+                Logger.error("Provided server url is invalid: " + ex.getMessage());
+                return;
+            }
+            localUrl = appUrlConfig;
+            appUrl = appUrlConfig;
+        } else {
+            appUrl = localUrl;
+            // custom URL schemes requires path ending with /
+            if (!scheme.equals(Bridge.CAPACITOR_HTTP_SCHEME) && !scheme.equals(CAPACITOR_HTTPS_SCHEME)) {
+                appUrl += "/";
+            }
+        }
+
+        String appUrlPath = this.config.getStartPath();
+        if (appUrlPath != null && !appUrlPath.trim().isEmpty()) {
+            appUrl += appUrlPath;
+        }
+    }
+
+    /**
+     * Register our core Plugin APIs
+     */
+    private void registerAllPlugins() {
+        this.registerPlugin(com.getcapacitor.plugin.CapacitorCookies.class);
+        this.registerPlugin(com.getcapacitor.plugin.WebView.class);
+        this.registerPlugin(com.getcapacitor.plugin.CapacitorHttp.class);
+
+        for (Class<? extends Plugin> pluginClass : this.initialPlugins) {
+            this.registerPlugin(pluginClass);
+        }
+
+        for (Plugin plugin : pluginInstances) {
+            registerPluginInstance(plugin);
+        }
+    }
+
+    /**
+     * Register additional plugins
+     * @param pluginClasses the plugins to register
+     */
+    public void registerPlugins(Class<? extends Plugin>[] pluginClasses) {
+        for (Class<? extends Plugin> plugin : pluginClasses) {
+            this.registerPlugin(plugin);
+        }
+    }
+
+    public void registerPluginInstances(Plugin[] pluginInstances) {
+        for (Plugin plugin : pluginInstances) {
+            this.registerPluginInstance(plugin);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private String getLegacyPluginName(Class<? extends Plugin> pluginClass) {
+        NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class);
+        if (legacyPluginAnnotation == null) {
+            Logger.error("Plugin doesn't have the @CapacitorPlugin annotation. Please add it");
+            return null;
+        }
+
+        return legacyPluginAnnotation.name();
+    }
+
+    /**
+     * Register a plugin class
+     * @param pluginClass a class inheriting from Plugin
+     */
+    public void registerPlugin(Class<? extends Plugin> pluginClass) {
+        String pluginId = pluginId(pluginClass);
+        if (pluginId == null) return;
+
+        try {
+            this.plugins.put(pluginId, new PluginHandle(this, pluginClass));
+        } catch (InvalidPluginException ex) {
+            logInvalidPluginException(pluginClass);
+        } catch (PluginLoadException ex) {
+            logPluginLoadException(pluginClass, ex);
+        }
+    }
+
+    public void registerPluginInstance(Plugin plugin) {
+        Class<? extends Plugin> clazz = plugin.getClass();
+        String pluginId = pluginId(clazz);
+        if (pluginId == null) return;
+
+        try {
+            this.plugins.put(pluginId, new PluginHandle(this, plugin));
+        } catch (InvalidPluginException ex) {
+            logInvalidPluginException(clazz);
+        }
+    }
+
+    private String pluginId(Class<? extends Plugin> clazz) {
+        String pluginName = pluginName(clazz);
+        String pluginId = clazz.getSimpleName();
+        if (pluginName == null) return null;
+
+        if (!pluginName.equals("")) {
+            pluginId = pluginName;
+        }
+        Logger.debug("Registering plugin instance: " + pluginId);
+        return pluginId;
+    }
+
+    private String pluginName(Class<? extends Plugin> clazz) {
+        String pluginName;
+        CapacitorPlugin pluginAnnotation = clazz.getAnnotation(CapacitorPlugin.class);
+        if (pluginAnnotation == null) {
+            pluginName = this.getLegacyPluginName(clazz);
+        } else {
+            pluginName = pluginAnnotation.name();
+        }
+
+        return pluginName;
+    }
+
+    private void logInvalidPluginException(Class<? extends Plugin> clazz) {
+        Logger.error(
+            "NativePlugin " +
+            clazz.getName() +
+            " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" +
+            " the class extends Plugin"
+        );
+    }
+
+    private void logPluginLoadException(Class<? extends Plugin> clazz, Exception ex) {
+        Logger.error("NativePlugin " + clazz.getName() + " failed to load", ex);
+    }
+
+    public PluginHandle getPlugin(String pluginId) {
+        return this.plugins.get(pluginId);
+    }
+
+    /**
+     * Find the plugin handle that responds to the given request code. This will
+     * fire after certain Android OS intent results/permission checks/etc.
+     * @param requestCode
+     * @return
+     */
+    @Deprecated
+    @SuppressWarnings("deprecation")
+    public PluginHandle getPluginWithRequestCode(int requestCode) {
+        for (PluginHandle handle : this.plugins.values()) {
+            int[] requestCodes;
+
+            CapacitorPlugin pluginAnnotation = handle.getPluginAnnotation();
+            if (pluginAnnotation == null) {
+                // Check for legacy plugin annotation, @NativePlugin
+                NativePlugin legacyPluginAnnotation = handle.getLegacyPluginAnnotation();
+                if (legacyPluginAnnotation == null) {
+                    continue;
+                }
+
+                if (legacyPluginAnnotation.permissionRequestCode() == requestCode) {
+                    return handle;
+                }
+
+                requestCodes = legacyPluginAnnotation.requestCodes();
+
+                for (int rc : requestCodes) {
+                    if (rc == requestCode) {
+                        return handle;
+                    }
+                }
+            } else {
+                requestCodes = pluginAnnotation.requestCodes();
+
+                for (int rc : requestCodes) {
+                    if (rc == requestCode) {
+                        return handle;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Call a method on a plugin.
+     * @param pluginId the plugin id to use to lookup the plugin handle
+     * @param methodName the name of the method to call
+     * @param call the call object to pass to the method
+     */
+    public void callPluginMethod(String pluginId, final String methodName, final PluginCall call) {
+        try {
+            final PluginHandle plugin = this.getPlugin(pluginId);
+
+            if (plugin == null) {
+                Logger.error("unable to find plugin : " + pluginId);
+                call.errorCallback("unable to find plugin : " + pluginId);
+                return;
+            }
+
+            if (Logger.shouldLog()) {
+                Logger.verbose(
+                    "callback: " +
+                    call.getCallbackId() +
+                    ", pluginId: " +
+                    plugin.getId() +
+                    ", methodName: " +
+                    methodName +
+                    ", methodData: " +
+                    call.getData().toString()
+                );
+            }
+
+            Runnable currentThreadTask = () -> {
+                try {
+                    plugin.invoke(methodName, call);
+
+                    if (call.isKeptAlive()) {
+                        saveCall(call);
+                    }
+                } catch (PluginLoadException | InvalidPluginMethodException ex) {
+                    Logger.error("Unable to execute plugin method", ex);
+                } catch (Exception ex) {
+                    Logger.error("Serious error executing plugin", ex);
+                    throw new RuntimeException(ex);
+                }
+            };
+
+            taskHandler.post(currentThreadTask);
+        } catch (Exception ex) {
+            Logger.error(Logger.tags("callPluginMethod"), "error : " + ex, null);
+            call.errorCallback(ex.toString());
+        }
+    }
+
+    /**
+     * Evaluate JavaScript in the web view. This method
+     * executes on the main thread automatically.
+     * @param js the JS to execute
+     * @param callback an optional ValueCallback that will synchronously receive a value
+     *                 after calling the JS
+     */
+    public void eval(final String js, final ValueCallback<String> callback) {
+        Handler mainHandler = new Handler(context.getMainLooper());
+        mainHandler.post(() -> webView.evaluateJavascript(js, callback));
+    }
+
+    public void logToJs(final String message, final String level) {
+        eval("window.Capacitor.logJs(\"" + message + "\", \"" + level + "\")", null);
+    }
+
+    public void logToJs(final String message) {
+        logToJs(message, "log");
+    }
+
+    public void triggerJSEvent(final String eventName, final String target) {
+        eval("window.Capacitor.triggerEvent(\"" + eventName + "\", \"" + target + "\")", s -> {});
+    }
+
+    public void triggerJSEvent(final String eventName, final String target, final String data) {
+        eval("window.Capacitor.triggerEvent(\"" + eventName + "\", \"" + target + "\", " + data + ")", s -> {});
+    }
+
+    public void triggerWindowJSEvent(final String eventName) {
+        this.triggerJSEvent(eventName, "window");
+    }
+
+    public void triggerWindowJSEvent(final String eventName, final String data) {
+        this.triggerJSEvent(eventName, "window", data);
+    }
+
+    public void triggerDocumentJSEvent(final String eventName) {
+        this.triggerJSEvent(eventName, "document");
+    }
+
+    public void triggerDocumentJSEvent(final String eventName, final String data) {
+        this.triggerJSEvent(eventName, "document", data);
+    }
+
+    public void execute(Runnable runnable) {
+        taskHandler.post(runnable);
+    }
+
+    public void executeOnMainThread(Runnable runnable) {
+        Handler mainHandler = new Handler(context.getMainLooper());
+
+        mainHandler.post(runnable);
+    }
+
+    /**
+     * Retain a call between plugin invocations
+     * @param call
+     */
+    public void saveCall(PluginCall call) {
+        this.savedCalls.put(call.getCallbackId(), call);
+    }
+
+    /**
+     * Get a retained plugin call
+     * @param callbackId the callbackId to use to lookup the call with
+     * @return the stored call
+     */
+    public PluginCall getSavedCall(String callbackId) {
+        if (callbackId == null) {
+            return null;
+        }
+
+        return this.savedCalls.get(callbackId);
+    }
+
+    PluginCall getPluginCallForLastActivity() {
+        PluginCall pluginCallForLastActivity = this.pluginCallForLastActivity;
+        this.pluginCallForLastActivity = null;
+        return pluginCallForLastActivity;
+    }
+
+    void setPluginCallForLastActivity(PluginCall pluginCallForLastActivity) {
+        this.pluginCallForLastActivity = pluginCallForLastActivity;
+    }
+
+    /**
+     * Release a retained call
+     * @param call a call to release
+     */
+    public void releaseCall(PluginCall call) {
+        releaseCall(call.getCallbackId());
+    }
+
+    /**
+     * Release a retained call by its ID
+     * @param callbackId an ID of a callback to release
+     */
+    public void releaseCall(String callbackId) {
+        this.savedCalls.remove(callbackId);
+    }
+
+    /**
+     * Removes the earliest saved call prior to a permissions request for a given plugin and
+     * returns it.
+     *
+     * @return The saved plugin call
+     */
+    protected PluginCall getPermissionCall(String pluginId) {
+        LinkedList<String> permissionCallIds = this.savedPermissionCallIds.get(pluginId);
+        String savedCallId = null;
+        if (permissionCallIds != null) {
+            savedCallId = permissionCallIds.poll();
+        }
+
+        return getSavedCall(savedCallId);
+    }
+
+    /**
+     * Save a call to be retrieved after requesting permissions. Calls are saved in order.
+     *
+     * @param call The plugin call to save.
+     */
+    protected void savePermissionCall(PluginCall call) {
+        if (call != null) {
+            if (!savedPermissionCallIds.containsKey(call.getPluginId())) {
+                savedPermissionCallIds.put(call.getPluginId(), new LinkedList<>());
+            }
+
+            savedPermissionCallIds.get(call.getPluginId()).add(call.getCallbackId());
+            saveCall(call);
+        }
+    }
+
+    /**
+     * Register an Activity Result Launcher to the containing Fragment or Activity.
+     *
+     * @param contract A contract specifying that an activity can be called with an input of
+     *                 type I and produce an output of type O.
+     * @param callback The callback run on Activity Result.
+     * @return A registered Activity Result Launcher.
+     */
+    public <I, O> ActivityResultLauncher<I> registerForActivityResult(
+        @NonNull final ActivityResultContract<I, O> contract,
+        @NonNull final ActivityResultCallback<O> callback
+    ) {
+        if (fragment != null) {
+            return fragment.registerForActivityResult(contract, callback);
+        } else {
+            return context.registerForActivityResult(contract, callback);
+        }
+    }
+
+    /**
+     * Build the JSInjector that will be used to inject JS into files served to the app,
+     * to ensure that Capacitor's JS and the JS for all the plugins is loaded each time.
+     */
+    private JSInjector getJSInjector() {
+        try {
+            String globalJS = JSExport.getGlobalJS(context, config.isLoggingEnabled(), isDevMode());
+            String bridgeJS = JSExport.getBridgeJS(context);
+            String pluginJS = JSExport.getPluginJS(plugins.values());
+            String cordovaJS = JSExport.getCordovaJS(context);
+            String cordovaPluginsJS = JSExport.getCordovaPluginJS(context);
+            String cordovaPluginsFileJS = JSExport.getCordovaPluginsFileJS(context);
+            String localUrlJS = "window.WEBVIEW_SERVER_URL = '" + localUrl + "';";
+
+            return new JSInjector(globalJS, bridgeJS, pluginJS, cordovaJS, cordovaPluginsJS, cordovaPluginsFileJS, localUrlJS);
+        } catch (Exception ex) {
+            Logger.error("Unable to export Capacitor JS. App will not function!", ex);
+        }
+        return null;
+    }
+
+    /**
+     * Restore any saved bundle state data
+     * @param savedInstanceState
+     */
+    public void restoreInstanceState(Bundle savedInstanceState) {
+        String lastPluginId = savedInstanceState.getString(BUNDLE_LAST_PLUGIN_ID_KEY);
+        String lastPluginCallMethod = savedInstanceState.getString(BUNDLE_LAST_PLUGIN_CALL_METHOD_NAME_KEY);
+        String lastOptionsJson = savedInstanceState.getString(BUNDLE_PLUGIN_CALL_OPTIONS_SAVED_KEY);
+
+        if (lastPluginId != null) {
+            // If we have JSON blob saved, create a new plugin call with the original options
+            if (lastOptionsJson != null) {
+                try {
+                    JSObject options = new JSObject(lastOptionsJson);
+
+                    pluginCallForLastActivity =
+                        new PluginCall(msgHandler, lastPluginId, PluginCall.CALLBACK_ID_DANGLING, lastPluginCallMethod, options);
+                } catch (JSONException ex) {
+                    Logger.error("Unable to restore plugin call, unable to parse persisted JSON object", ex);
+                }
+            }
+
+            // Let the plugin restore any state it needs
+            Bundle bundleData = savedInstanceState.getBundle(BUNDLE_PLUGIN_CALL_BUNDLE_KEY);
+            PluginHandle lastPlugin = getPlugin(lastPluginId);
+            if (bundleData != null && lastPlugin != null) {
+                lastPlugin.getInstance().restoreState(bundleData);
+            } else {
+                Logger.error("Unable to restore last plugin call");
+            }
+        }
+    }
+
+    public void saveInstanceState(Bundle outState) {
+        Logger.debug("Saving instance state!");
+
+        // If there was a last PluginCall for a started activity, we need to
+        // persist it so we can load it again in case our app gets terminated
+        if (pluginCallForLastActivity != null) {
+            PluginCall call = pluginCallForLastActivity;
+            PluginHandle handle = getPlugin(call.getPluginId());
+
+            if (handle != null) {
+                Bundle bundle = handle.getInstance().saveInstanceState();
+                if (bundle != null) {
+                    outState.putString(BUNDLE_LAST_PLUGIN_ID_KEY, call.getPluginId());
+                    outState.putString(BUNDLE_LAST_PLUGIN_CALL_METHOD_NAME_KEY, call.getMethodName());
+                    outState.putString(BUNDLE_PLUGIN_CALL_OPTIONS_SAVED_KEY, call.getData().toString());
+                    outState.putBundle(BUNDLE_PLUGIN_CALL_BUNDLE_KEY, bundle);
+                } else {
+                    Logger.error("Couldn't save last " + call.getPluginId() + "'s Plugin " + call.getMethodName() + " call");
+                }
+            }
+        }
+    }
+
+    @Deprecated
+    @SuppressWarnings("deprecation")
+    public void startActivityForPluginWithResult(PluginCall call, Intent intent, int requestCode) {
+        Logger.debug("Starting activity for result");
+
+        pluginCallForLastActivity = call;
+
+        getActivity().startActivityForResult(intent, requestCode);
+    }
+
+    /**
+     * Check for legacy Capacitor or Cordova plugins that may have registered to handle a permission
+     * request, and handle them if so. If not handled, false is returned.
+     *
+     * @param requestCode the code that was requested
+     * @param permissions the permissions requested
+     * @param grantResults the set of granted/denied permissions
+     * @return true if permission code was handled by a plugin explicitly, false if not
+     */
+    @SuppressWarnings("deprecation")
+    boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+        PluginHandle plugin = getPluginWithRequestCode(requestCode);
+
+        if (plugin == null) {
+            boolean permissionHandled = false;
+            Logger.debug("Unable to find a Capacitor plugin to handle permission requestCode, trying Cordova plugins " + requestCode);
+            try {
+                permissionHandled = cordovaInterface.handlePermissionResult(requestCode, permissions, grantResults);
+            } catch (JSONException e) {
+                Logger.debug("Error on Cordova plugin permissions request " + e.getMessage());
+            }
+            return permissionHandled;
+        }
+
+        // Call deprecated method if using deprecated NativePlugin annotation
+        if (plugin.getPluginAnnotation() == null) {
+            plugin.getInstance().handleRequestPermissionsResult(requestCode, permissions, grantResults);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Saves permission states and rejects if permissions were not correctly defined in
+     * the AndroidManifest.xml file.
+     *
+     * @param plugin
+     * @param savedCall
+     * @param permissions
+     * @return true if permissions were saved and defined correctly, false if not
+     */
+    protected boolean validatePermissions(Plugin plugin, PluginCall savedCall, Map<String, Boolean> permissions) {
+        SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_PREFS_NAME, Activity.MODE_PRIVATE);
+
+        for (Map.Entry<String, Boolean> permission : permissions.entrySet()) {
+            String permString = permission.getKey();
+            boolean isGranted = permission.getValue();
+
+            if (isGranted) {
+                // Permission granted. If previously denied, remove cached state
+                String state = prefs.getString(permString, null);
+
+                if (state != null) {
+                    SharedPreferences.Editor editor = prefs.edit();
+                    editor.remove(permString);
+                    editor.apply();
+                }
+            } else {
+                SharedPreferences.Editor editor = prefs.edit();
+
+                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permString)) {
+                    // Permission denied, can prompt again with rationale
+                    editor.putString(permString, PermissionState.PROMPT_WITH_RATIONALE.toString());
+                } else {
+                    // Permission denied permanently, store this state for future reference
+                    editor.putString(permString, PermissionState.DENIED.toString());
+                }
+
+                editor.apply();
+            }
+        }
+
+        String[] permStrings = permissions.keySet().toArray(new String[0]);
+
+        if (!PermissionHelper.hasDefinedPermissions(getContext(), permStrings)) {
+            StringBuilder builder = new StringBuilder();
+            builder.append("Missing the following permissions in AndroidManifest.xml:\n");
+            String[] missing = PermissionHelper.getUndefinedPermissions(getContext(), permStrings);
+            for (String perm : missing) {
+                builder.append(perm + "\n");
+            }
+            savedCall.reject(builder.toString());
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Helper to check all permissions and see the current states of each permission.
+     *
+     * @since 3.0.0
+     * @return A mapping of permission aliases to the associated granted status.
+     */
+    protected Map<String, PermissionState> getPermissionStates(Plugin plugin) {
+        Map<String, PermissionState> permissionsResults = new HashMap<>();
+        CapacitorPlugin annotation = plugin.getPluginHandle().getPluginAnnotation();
+        for (Permission perm : annotation.permissions()) {
+            // If a permission is defined with no permission constants, return GRANTED for it.
+            // Otherwise, get its true state.
+            if (perm.strings().length == 0 || (perm.strings().length == 1 && perm.strings()[0].isEmpty())) {
+                String key = perm.alias();
+                if (!key.isEmpty()) {
+                    PermissionState existingResult = permissionsResults.get(key);
+
+                    // auto set permission state to GRANTED if the alias is empty.
+                    if (existingResult == null) {
+                        permissionsResults.put(key, PermissionState.GRANTED);
+                    }
+                }
+            } else {
+                for (String permString : perm.strings()) {
+                    String key = perm.alias().isEmpty() ? permString : perm.alias();
+                    PermissionState permissionStatus;
+                    if (ActivityCompat.checkSelfPermission(this.getContext(), permString) == PackageManager.PERMISSION_GRANTED) {
+                        permissionStatus = PermissionState.GRANTED;
+                    } else {
+                        permissionStatus = PermissionState.PROMPT;
+
+                        // Check if there is a cached permission state for the "Never ask again" state
+                        SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_PREFS_NAME, Activity.MODE_PRIVATE);
+                        String state = prefs.getString(permString, null);
+
+                        if (state != null) {
+                            permissionStatus = PermissionState.byState(state);
+                        }
+                    }
+
+                    PermissionState existingResult = permissionsResults.get(key);
+
+                    // multiple permissions with the same alias must all be true, otherwise all false.
+                    if (existingResult == null || existingResult == PermissionState.GRANTED) {
+                        permissionsResults.put(key, permissionStatus);
+                    }
+                }
+            }
+        }
+
+        return permissionsResults;
+    }
+
+    /**
+     * Handle an activity result and pass it to a plugin that has indicated it wants to
+     * handle the result.
+     * @param requestCode
+     * @param resultCode
+     * @param data
+     */
+    @SuppressWarnings("deprecation")
+    boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+        PluginHandle plugin = getPluginWithRequestCode(requestCode);
+
+        if (plugin == null || plugin.getInstance() == null) {
+            Logger.debug("Unable to find a Capacitor plugin to handle requestCode, trying Cordova plugins " + requestCode);
+            return cordovaInterface.onActivityResult(requestCode, resultCode, data);
+        }
+
+        // deprecated, to be removed
+        PluginCall lastCall = plugin.getInstance().getSavedCall();
+
+        // If we don't have a saved last call (because our app was killed and restarted, for example),
+        // Then we should see if we have any saved plugin call information and generate a new,
+        // "dangling" plugin call (a plugin call that doesn't have a corresponding web callback)
+        // and then send that to the plugin
+        if (lastCall == null && pluginCallForLastActivity != null) {
+            plugin.getInstance().saveCall(pluginCallForLastActivity);
+        }
+
+        plugin.getInstance().handleOnActivityResult(requestCode, resultCode, data);
+
+        // Clear the plugin call we may have re-hydrated on app launch
+        pluginCallForLastActivity = null;
+
+        return true;
+    }
+
+    /**
+     * Handle an onNewIntent lifecycle event and notify the plugins
+     * @param intent
+     */
+    public void onNewIntent(Intent intent) {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnNewIntent(intent);
+        }
+
+        if (cordovaWebView != null) {
+            cordovaWebView.onNewIntent(intent);
+        }
+    }
+
+    /**
+     * Handle an onConfigurationChanged event and notify the plugins
+     * @param newConfig
+     */
+    public void onConfigurationChanged(Configuration newConfig) {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnConfigurationChanged(newConfig);
+        }
+    }
+
+    /**
+     * Handle onRestart lifecycle event and notify the plugins
+     */
+    public void onRestart() {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnRestart();
+        }
+    }
+
+    /**
+     * Handle onStart lifecycle event and notify the plugins
+     */
+    public void onStart() {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnStart();
+        }
+
+        if (cordovaWebView != null) {
+            cordovaWebView.handleStart();
+        }
+    }
+
+    /**
+     * Handle onResume lifecycle event and notify the plugins
+     */
+    public void onResume() {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnResume();
+        }
+
+        if (cordovaWebView != null) {
+            cordovaWebView.handleResume(this.shouldKeepRunning());
+        }
+    }
+
+    /**
+     * Handle onPause lifecycle event and notify the plugins
+     */
+    public void onPause() {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnPause();
+        }
+
+        if (cordovaWebView != null) {
+            boolean keepRunning = this.shouldKeepRunning() || cordovaInterface.getActivityResultCallback() != null;
+            cordovaWebView.handlePause(keepRunning);
+        }
+    }
+
+    /**
+     * Handle onStop lifecycle event and notify the plugins
+     */
+    public void onStop() {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnStop();
+        }
+
+        if (cordovaWebView != null) {
+            cordovaWebView.handleStop();
+        }
+    }
+
+    /**
+     * Handle onDestroy lifecycle event and notify the plugins
+     */
+    public void onDestroy() {
+        for (PluginHandle plugin : plugins.values()) {
+            plugin.getInstance().handleOnDestroy();
+        }
+
+        handlerThread.quitSafely();
+
+        if (cordovaWebView != null) {
+            cordovaWebView.handleDestroy();
+        }
+    }
+
+    /**
+     * Handle onDetachedFromWindow lifecycle event
+     */
+    public void onDetachedFromWindow() {
+        webView.removeAllViews();
+        webView.destroy();
+    }
+
+    public String getServerBasePath() {
+        return this.localServer.getBasePath();
+    }
+
+    /**
+     * Tell the local server to load files from the given
+     * file path instead of the assets path.
+     * @param path
+     */
+    public void setServerBasePath(String path) {
+        localServer.hostFiles(path);
+        webView.post(() -> webView.loadUrl(appUrl));
+    }
+
+    /**
+     * Tell the local server to load files from the given
+     * asset path.
+     * @param path
+     */
+    public void setServerAssetPath(String path) {
+        localServer.hostAssets(path);
+        webView.post(() -> webView.loadUrl(appUrl));
+    }
+
+    /**
+     * Reload the WebView
+     */
+    public void reload() {
+        webView.post(() -> webView.loadUrl(appUrl));
+    }
+
+    public String getLocalUrl() {
+        return localUrl;
+    }
+
+    public WebViewLocalServer getLocalServer() {
+        return localServer;
+    }
+
+    public HostMask getAppAllowNavigationMask() {
+        return appAllowNavigationMask;
+    }
+
+    public Set<String> getAllowedOriginRules() {
+        return allowedOriginRules;
+    }
+
+    public BridgeWebViewClient getWebViewClient() {
+        return this.webViewClient;
+    }
+
+    public void setWebViewClient(BridgeWebViewClient client) {
+        this.webViewClient = client;
+        webView.setWebViewClient(client);
+    }
+
+    List<WebViewListener> getWebViewListeners() {
+        return webViewListeners;
+    }
+
+    void setWebViewListeners(List<WebViewListener> webViewListeners) {
+        this.webViewListeners = webViewListeners;
+    }
+
+    RouteProcessor getRouteProcessor() {
+        return routeProcessor;
+    }
+
+    void setRouteProcessor(RouteProcessor routeProcessor) {
+        this.routeProcessor = routeProcessor;
+    }
+
+    ServerPath getServerPath() {
+        return serverPath;
+    }
+
+    /**
+     * Add a listener that the WebViewClient can trigger on certain events.
+     * @param webViewListener A {@link WebViewListener} to add.
+     */
+    public void addWebViewListener(WebViewListener webViewListener) {
+        webViewListeners.add(webViewListener);
+    }
+
+    /**
+     * Remove a listener that the WebViewClient triggers on certain events.
+     * @param webViewListener A {@link WebViewListener} to remove.
+     */
+    public void removeWebViewListener(WebViewListener webViewListener) {
+        webViewListeners.remove(webViewListener);
+    }
+
+    public static class Builder {
+
+        private Bundle instanceState = null;
+        private CapConfig config = null;
+        private List<Class<? extends Plugin>> plugins = new ArrayList<>();
+        private List<Plugin> pluginInstances = new ArrayList<>();
+        private AppCompatActivity activity;
+        private Fragment fragment;
+        private RouteProcessor routeProcessor;
+        private final List<WebViewListener> webViewListeners = new ArrayList<>();
+        private ServerPath serverPath;
+
+        public Builder(AppCompatActivity activity) {
+            this.activity = activity;
+        }
+
+        public Builder(Fragment fragment) {
+            this.activity = (AppCompatActivity) fragment.getActivity();
+            this.fragment = fragment;
+        }
+
+        public Builder setInstanceState(Bundle instanceState) {
+            this.instanceState = instanceState;
+            return this;
+        }
+
+        public Builder setConfig(CapConfig config) {
+            this.config = config;
+            return this;
+        }
+
+        public Builder setPlugins(List<Class<? extends Plugin>> plugins) {
+            this.plugins = plugins;
+            return this;
+        }
+
+        public Builder addPlugin(Class<? extends Plugin> plugin) {
+            this.plugins.add(plugin);
+            return this;
+        }
+
+        public Builder addPlugins(List<Class<? extends Plugin>> plugins) {
+            for (Class<? extends Plugin> cls : plugins) {
+                this.addPlugin(cls);
+            }
+
+            return this;
+        }
+
+        public Builder addPluginInstance(Plugin plugin) {
+            this.pluginInstances.add(plugin);
+            return this;
+        }
+
+        public Builder addPluginInstances(List<Plugin> plugins) {
+            this.pluginInstances.addAll(plugins);
+            return this;
+        }
+
+        public Builder addWebViewListener(WebViewListener webViewListener) {
+            webViewListeners.add(webViewListener);
+            return this;
+        }
+
+        public Builder addWebViewListeners(List<WebViewListener> webViewListeners) {
+            for (WebViewListener listener : webViewListeners) {
+                this.addWebViewListener(listener);
+            }
+
+            return this;
+        }
+
+        public Builder setRouteProcessor(RouteProcessor routeProcessor) {
+            this.routeProcessor = routeProcessor;
+            return this;
+        }
+
+        public Builder setServerPath(ServerPath serverPath) {
+            this.serverPath = serverPath;
+            return this;
+        }
+
+        public Bridge create() {
+            // Cordova initialization
+            ConfigXmlParser parser = new ConfigXmlParser();
+            parser.parse(activity.getApplicationContext());
+            CordovaPreferences preferences = parser.getPreferences();
+            preferences.setPreferencesBundle(activity.getIntent().getExtras());
+            List<PluginEntry> pluginEntries = parser.getPluginEntries();
+
+            MockCordovaInterfaceImpl cordovaInterface = new MockCordovaInterfaceImpl(activity);
+            if (instanceState != null) {
+                cordovaInterface.restoreInstanceState(instanceState);
+            }
+
+            WebView webView = this.fragment != null ? fragment.getView().findViewById(R.id.webview) : activity.findViewById(R.id.webview);
+            MockCordovaWebViewImpl mockWebView = new MockCordovaWebViewImpl(activity.getApplicationContext());
+            mockWebView.init(cordovaInterface, pluginEntries, preferences, webView);
+            PluginManager pluginManager = mockWebView.getPluginManager();
+            cordovaInterface.onCordovaInit(pluginManager);
+
+            // Bridge initialization
+            Bridge bridge = new Bridge(
+                activity,
+                serverPath,
+                fragment,
+                webView,
+                plugins,
+                pluginInstances,
+                cordovaInterface,
+                pluginManager,
+                preferences,
+                config
+            );
+
+            if (webView instanceof CapacitorWebView) {
+                CapacitorWebView capacitorWebView = (CapacitorWebView) webView;
+                capacitorWebView.setBridge(bridge);
+            }
+
+            bridge.setCordovaWebView(mockWebView);
+            bridge.setWebViewListeners(webViewListeners);
+            bridge.setRouteProcessor(routeProcessor);
+
+            if (instanceState != null) {
+                bridge.restoreInstanceState(instanceState);
+            }
+
+            return bridge;
+        }
+    }
+}

+ 197 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java

@@ -0,0 +1,197 @@
+package com.getcapacitor;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import androidx.appcompat.app.AppCompatActivity;
+import com.getcapacitor.android.R;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BridgeActivity extends AppCompatActivity {
+
+    protected Bridge bridge;
+    protected boolean keepRunning = true;
+    protected CapConfig config;
+
+    protected int activityDepth = 0;
+    protected List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
+    protected final Bridge.Builder bridgeBuilder = new Bridge.Builder(this);
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        bridgeBuilder.setInstanceState(savedInstanceState);
+        getApplication().setTheme(R.style.AppTheme_NoActionBar);
+        setTheme(R.style.AppTheme_NoActionBar);
+        setContentView(R.layout.bridge_layout_main);
+        PluginManager loader = new PluginManager(getAssets());
+
+        try {
+            bridgeBuilder.addPlugins(loader.loadPluginClasses());
+        } catch (PluginLoadException ex) {
+            Logger.error("Error loading plugins.", ex);
+        }
+
+        this.load();
+    }
+
+    protected void load() {
+        Logger.debug("Starting BridgeActivity");
+
+        bridge = bridgeBuilder.addPlugins(initialPlugins).setConfig(config).create();
+
+        this.keepRunning = bridge.shouldKeepRunning();
+        this.onNewIntent(getIntent());
+    }
+
+    public void registerPlugin(Class<? extends Plugin> plugin) {
+        bridgeBuilder.addPlugin(plugin);
+    }
+
+    public void registerPlugins(List<Class<? extends Plugin>> plugins) {
+        bridgeBuilder.addPlugins(plugins);
+    }
+
+    public Bridge getBridge() {
+        return this.bridge;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        bridge.saveInstanceState(outState);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        activityDepth++;
+        this.bridge.onStart();
+        Logger.debug("App started");
+    }
+
+    @Override
+    public void onRestart() {
+        super.onRestart();
+        this.bridge.onRestart();
+        Logger.debug("App restarted");
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        bridge.getApp().fireStatusChange(true);
+        this.bridge.onResume();
+        Logger.debug("App resumed");
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        this.bridge.onPause();
+        Logger.debug("App paused");
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+
+        activityDepth = Math.max(0, activityDepth - 1);
+        if (activityDepth == 0) {
+            bridge.getApp().fireStatusChange(false);
+        }
+
+        this.bridge.onStop();
+        Logger.debug("App stopped");
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        this.bridge.onDestroy();
+        Logger.debug("App destroyed");
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        this.bridge.onDetachedFromWindow();
+    }
+
+    /**
+     * Handles permission request results.
+     *
+     * Capacitor is backwards compatible such that plugins using legacy permission request codes
+     * may coexist with plugins using the AndroidX Activity v1.2 permission callback flow introduced
+     * in Capacitor 3.0.
+     *
+     * In this method, plugins are checked first for ownership of the legacy permission request code.
+     * If the {@link Bridge#onRequestPermissionsResult(int, String[], int[])} method indicates it has
+     * handled the permission, then the permission callback will be considered complete. Otherwise,
+     * the permission will be handled using the AndroidX Activity flow.
+     *
+     * @param requestCode the request code associated with the permission request
+     * @param permissions the Android permission strings requested
+     * @param grantResults the status result of the permission request
+     */
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+        if (this.bridge == null) {
+            return;
+        }
+
+        if (!bridge.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
+            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        }
+    }
+
+    /**
+     * Handles activity results.
+     *
+     * Capacitor is backwards compatible such that plugins using legacy activity result codes
+     * may coexist with plugins using the AndroidX Activity v1.2 activity callback flow introduced
+     * in Capacitor 3.0.
+     *
+     * In this method, plugins are checked first for ownership of the legacy request code. If the
+     * {@link Bridge#onActivityResult(int, int, Intent)} method indicates it has handled the activity
+     * result, then the callback will be considered complete. Otherwise, the result will be handled
+     * using the AndroidX Activiy flow.
+     *
+     * @param requestCode the request code associated with the activity result
+     * @param resultCode the result code
+     * @param data any data included with the activity result
+     */
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (this.bridge == null) {
+            return;
+        }
+
+        if (!bridge.onActivityResult(requestCode, resultCode, data)) {
+            super.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+
+        if (this.bridge == null || intent == null) {
+            return;
+        }
+
+        this.bridge.onNewIntent(intent);
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        if (this.bridge == null) {
+            return;
+        }
+
+        this.bridge.onConfigurationChanged(newConfig);
+    }
+}

+ 134 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeFragment.java

@@ -0,0 +1,134 @@
+package com.getcapacitor;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+import com.getcapacitor.android.R;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A simple {@link Fragment} subclass.
+ * Use the {@link BridgeFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class BridgeFragment extends Fragment {
+
+    private static final String ARG_START_DIR = "startDir";
+
+    protected Bridge bridge;
+    protected boolean keepRunning = true;
+
+    private final List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
+    private CapConfig config = null;
+
+    private final List<WebViewListener> webViewListeners = new ArrayList<>();
+
+    public BridgeFragment() {
+        // Required empty public constructor
+    }
+
+    /**
+     * Use this factory method to create a new instance of
+     * this fragment using the provided parameters.
+     *
+     * @param startDir the directory to serve content from
+     * @return A new instance of fragment BridgeFragment.
+     */
+    public static BridgeFragment newInstance(String startDir) {
+        BridgeFragment fragment = new BridgeFragment();
+        Bundle args = new Bundle();
+        args.putString(ARG_START_DIR, startDir);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public void addPlugin(Class<? extends Plugin> plugin) {
+        this.initialPlugins.add(plugin);
+    }
+
+    public void setConfig(CapConfig config) {
+        this.config = config;
+    }
+
+    public Bridge getBridge() {
+        return bridge;
+    }
+
+    public void addWebViewListener(WebViewListener webViewListener) {
+        webViewListeners.add(webViewListener);
+    }
+
+    /**
+     * Load the WebView and create the Bridge
+     */
+    protected void load(Bundle savedInstanceState) {
+        Logger.debug("Loading Bridge with BridgeFragment");
+
+        Bundle args = getArguments();
+        String startDir = null;
+
+        if (args != null) {
+            startDir = getArguments().getString(ARG_START_DIR);
+        }
+
+        bridge =
+            new Bridge.Builder(this)
+                .setInstanceState(savedInstanceState)
+                .setPlugins(initialPlugins)
+                .setConfig(config)
+                .addWebViewListeners(webViewListeners)
+                .create();
+
+        if (startDir != null) {
+            bridge.setServerAssetPath(startDir);
+        }
+
+        this.keepRunning = bridge.shouldKeepRunning();
+    }
+
+    @Override
+    public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
+        super.onInflate(context, attrs, savedInstanceState);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.bridge_fragment);
+        CharSequence c = a.getString(R.styleable.bridge_fragment_start_dir);
+
+        if (c != null) {
+            String startDir = c.toString();
+            Bundle args = new Bundle();
+            args.putString(ARG_START_DIR, startDir);
+            setArguments(args);
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        return inflater.inflate(R.layout.fragment_bridge, container, false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        this.load(savedInstanceState);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (this.bridge != null) {
+            this.bridge.onDestroy();
+        }
+    }
+}

+ 510 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java

@@ -0,0 +1,510 @@
+package com.getcapacitor;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.view.View;
+import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.MimeTypeMap;
+import android.webkit.PermissionRequest;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.widget.EditText;
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.core.content.FileProvider;
+import com.getcapacitor.util.PermissionHelper;
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * Custom WebChromeClient handler, required for showing dialogs, confirms, etc. in our
+ * WebView instance.
+ */
+public class BridgeWebChromeClient extends WebChromeClient {
+
+    private interface PermissionListener {
+        void onPermissionSelect(Boolean isGranted);
+    }
+
+    private interface ActivityResultListener {
+        void onActivityResult(ActivityResult result);
+    }
+
+    private ActivityResultLauncher permissionLauncher;
+    private ActivityResultLauncher activityLauncher;
+    private PermissionListener permissionListener;
+    private ActivityResultListener activityListener;
+
+    private Bridge bridge;
+
+    public BridgeWebChromeClient(Bridge bridge) {
+        this.bridge = bridge;
+
+        ActivityResultCallback<Map<String, Boolean>> permissionCallback = (Map<String, Boolean> isGranted) -> {
+            if (permissionListener != null) {
+                boolean granted = true;
+                for (Map.Entry<String, Boolean> permission : isGranted.entrySet()) {
+                    if (!permission.getValue()) granted = false;
+                }
+                permissionListener.onPermissionSelect(granted);
+            }
+        };
+
+        permissionLauncher = bridge.registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), permissionCallback);
+        activityLauncher =
+            bridge.registerForActivityResult(
+                new ActivityResultContracts.StartActivityForResult(),
+                result -> {
+                    if (activityListener != null) {
+                        activityListener.onActivityResult(result);
+                    }
+                }
+            );
+    }
+
+    /**
+     * Render web content in `view`.
+     *
+     * Both this method and {@link #onHideCustomView()} are required for
+     * rendering web content in full screen.
+     *
+     * @see <a href="https://developer.android.com/reference/android/webkit/WebChromeClient#onShowCustomView(android.view.View,%20android.webkit.WebChromeClient.CustomViewCallback)">onShowCustomView() docs</a>
+     */
+    @Override
+    public void onShowCustomView(View view, CustomViewCallback callback) {
+        callback.onCustomViewHidden();
+        super.onShowCustomView(view, callback);
+    }
+
+    /**
+     * Render web content in the original Web View again.
+     *
+     * Do not remove this method--@see #onShowCustomView(View, CustomViewCallback).
+     */
+    @Override
+    public void onHideCustomView() {
+        super.onHideCustomView();
+    }
+
+    @Override
+    public void onPermissionRequest(final PermissionRequest request) {
+        boolean isRequestPermissionRequired = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M;
+
+        List<String> permissionList = new ArrayList<>();
+        if (Arrays.asList(request.getResources()).contains("android.webkit.resource.VIDEO_CAPTURE")) {
+            permissionList.add(Manifest.permission.CAMERA);
+        }
+        if (Arrays.asList(request.getResources()).contains("android.webkit.resource.AUDIO_CAPTURE")) {
+            permissionList.add(Manifest.permission.MODIFY_AUDIO_SETTINGS);
+            permissionList.add(Manifest.permission.RECORD_AUDIO);
+        }
+        if (!permissionList.isEmpty() && isRequestPermissionRequired) {
+            String[] permissions = permissionList.toArray(new String[0]);
+            permissionListener =
+                isGranted -> {
+                    if (isGranted) {
+                        request.grant(request.getResources());
+                    } else {
+                        request.deny();
+                    }
+                };
+            permissionLauncher.launch(permissions);
+        } else {
+            request.grant(request.getResources());
+        }
+    }
+
+    /**
+     * Show the browser alert modal
+     * @param view
+     * @param url
+     * @param message
+     * @param result
+     * @return
+     */
+    @Override
+    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
+        if (bridge.getActivity().isFinishing()) {
+            return true;
+        }
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
+        builder
+            .setMessage(message)
+            .setPositiveButton(
+                "OK",
+                (dialog, buttonIndex) -> {
+                    dialog.dismiss();
+                    result.confirm();
+                }
+            )
+            .setOnCancelListener(
+                dialog -> {
+                    dialog.dismiss();
+                    result.cancel();
+                }
+            );
+
+        AlertDialog dialog = builder.create();
+
+        dialog.show();
+
+        return true;
+    }
+
+    /**
+     * Show the browser confirm modal
+     * @param view
+     * @param url
+     * @param message
+     * @param result
+     * @return
+     */
+    @Override
+    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
+        if (bridge.getActivity().isFinishing()) {
+            return true;
+        }
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
+
+        builder
+            .setMessage(message)
+            .setPositiveButton(
+                "OK",
+                (dialog, buttonIndex) -> {
+                    dialog.dismiss();
+                    result.confirm();
+                }
+            )
+            .setNegativeButton(
+                "Cancel",
+                (dialog, buttonIndex) -> {
+                    dialog.dismiss();
+                    result.cancel();
+                }
+            )
+            .setOnCancelListener(
+                dialog -> {
+                    dialog.dismiss();
+                    result.cancel();
+                }
+            );
+
+        AlertDialog dialog = builder.create();
+
+        dialog.show();
+
+        return true;
+    }
+
+    /**
+     * Show the browser prompt modal
+     * @param view
+     * @param url
+     * @param message
+     * @param defaultValue
+     * @param result
+     * @return
+     */
+    @Override
+    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {
+        if (bridge.getActivity().isFinishing()) {
+            return true;
+        }
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
+        final EditText input = new EditText(view.getContext());
+
+        builder
+            .setMessage(message)
+            .setView(input)
+            .setPositiveButton(
+                "OK",
+                (dialog, buttonIndex) -> {
+                    dialog.dismiss();
+
+                    String inputText1 = input.getText().toString().trim();
+                    result.confirm(inputText1);
+                }
+            )
+            .setNegativeButton(
+                "Cancel",
+                (dialog, buttonIndex) -> {
+                    dialog.dismiss();
+                    result.cancel();
+                }
+            )
+            .setOnCancelListener(
+                dialog -> {
+                    dialog.dismiss();
+                    result.cancel();
+                }
+            );
+
+        AlertDialog dialog = builder.create();
+
+        dialog.show();
+
+        return true;
+    }
+
+    /**
+     * Handle the browser geolocation permission prompt
+     * @param origin
+     * @param callback
+     */
+    @Override
+    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
+        super.onGeolocationPermissionsShowPrompt(origin, callback);
+        Logger.debug("onGeolocationPermissionsShowPrompt: DOING IT HERE FOR ORIGIN: " + origin);
+        final String[] geoPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION };
+
+        if (!PermissionHelper.hasPermissions(bridge.getContext(), geoPermissions)) {
+            permissionListener =
+                isGranted -> {
+                    if (isGranted) {
+                        callback.invoke(origin, true, false);
+                    } else {
+                        final String[] coarsePermission = { Manifest.permission.ACCESS_COARSE_LOCATION };
+                        if (
+                            Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
+                            PermissionHelper.hasPermissions(bridge.getContext(), coarsePermission)
+                        ) {
+                            callback.invoke(origin, true, false);
+                        } else {
+                            callback.invoke(origin, false, false);
+                        }
+                    }
+                };
+            permissionLauncher.launch(geoPermissions);
+        } else {
+            // permission is already granted
+            callback.invoke(origin, true, false);
+            Logger.debug("onGeolocationPermissionsShowPrompt: has required permission");
+        }
+    }
+
+    @Override
+    public boolean onShowFileChooser(
+        WebView webView,
+        final ValueCallback<Uri[]> filePathCallback,
+        final FileChooserParams fileChooserParams
+    ) {
+        List<String> acceptTypes = Arrays.asList(fileChooserParams.getAcceptTypes());
+        boolean captureEnabled = fileChooserParams.isCaptureEnabled();
+        boolean capturePhoto = captureEnabled && acceptTypes.contains("image/*");
+        final boolean captureVideo = captureEnabled && acceptTypes.contains("video/*");
+        if ((capturePhoto || captureVideo)) {
+            if (isMediaCaptureSupported()) {
+                showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo);
+            } else {
+                permissionListener =
+                    isGranted -> {
+                        if (isGranted) {
+                            showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo);
+                        } else {
+                            Logger.warn(Logger.tags("FileChooser"), "Camera permission not granted");
+                            filePathCallback.onReceiveValue(null);
+                        }
+                    };
+                final String[] camPermission = { Manifest.permission.CAMERA };
+                permissionLauncher.launch(camPermission);
+            }
+        } else {
+            showFilePicker(filePathCallback, fileChooserParams);
+        }
+
+        return true;
+    }
+
+    private boolean isMediaCaptureSupported() {
+        String[] permissions = { Manifest.permission.CAMERA };
+        return (
+            PermissionHelper.hasPermissions(bridge.getContext(), permissions) ||
+            !PermissionHelper.hasDefinedPermission(bridge.getContext(), Manifest.permission.CAMERA)
+        );
+    }
+
+    private void showMediaCaptureOrFilePicker(ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams, boolean isVideo) {
+        // TODO: add support for video capture on Android M and older
+        // On Android M and lower the VIDEO_CAPTURE_INTENT (e.g.: intent.getData())
+        // returns a file:// URI instead of the expected content:// URI.
+        // So we disable it for now because it requires a bit more work
+        boolean isVideoCaptureSupported = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N;
+        boolean shown = false;
+        if (isVideo && isVideoCaptureSupported) {
+            shown = showVideoCapturePicker(filePathCallback);
+        } else {
+            shown = showImageCapturePicker(filePathCallback);
+        }
+        if (!shown) {
+            Logger.warn(Logger.tags("FileChooser"), "Media capture intent could not be launched. Falling back to default file picker.");
+            showFilePicker(filePathCallback, fileChooserParams);
+        }
+    }
+
+    @SuppressLint("QueryPermissionsNeeded")
+    private boolean showImageCapturePicker(final ValueCallback<Uri[]> filePathCallback) {
+        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+        if (takePictureIntent.resolveActivity(bridge.getActivity().getPackageManager()) == null) {
+            return false;
+        }
+
+        final Uri imageFileUri;
+        try {
+            imageFileUri = createImageFileUri();
+        } catch (Exception ex) {
+            Logger.error("Unable to create temporary media capture file: " + ex.getMessage());
+            return false;
+        }
+        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
+        activityListener =
+            activityResult -> {
+                Uri[] result = null;
+                if (activityResult.getResultCode() == Activity.RESULT_OK) {
+                    result = new Uri[] { imageFileUri };
+                }
+                filePathCallback.onReceiveValue(result);
+            };
+        activityLauncher.launch(takePictureIntent);
+
+        return true;
+    }
+
+    @SuppressLint("QueryPermissionsNeeded")
+    private boolean showVideoCapturePicker(final ValueCallback<Uri[]> filePathCallback) {
+        Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+        if (takeVideoIntent.resolveActivity(bridge.getActivity().getPackageManager()) == null) {
+            return false;
+        }
+
+        activityListener =
+            activityResult -> {
+                Uri[] result = null;
+                if (activityResult.getResultCode() == Activity.RESULT_OK) {
+                    result = new Uri[] { activityResult.getData().getData() };
+                }
+                filePathCallback.onReceiveValue(result);
+            };
+        activityLauncher.launch(takeVideoIntent);
+
+        return true;
+    }
+
+    private void showFilePicker(final ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
+        Intent intent = fileChooserParams.createIntent();
+        if (fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE) {
+            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+        }
+        if (fileChooserParams.getAcceptTypes().length > 1 || intent.getType().startsWith(".")) {
+            String[] validTypes = getValidTypes(fileChooserParams.getAcceptTypes());
+            intent.putExtra(Intent.EXTRA_MIME_TYPES, validTypes);
+            if (intent.getType().startsWith(".")) {
+                intent.setType(validTypes[0]);
+            }
+        }
+        try {
+            activityListener =
+                activityResult -> {
+                    Uri[] result;
+                    Intent resultIntent = activityResult.getData();
+                    if (activityResult.getResultCode() == Activity.RESULT_OK && resultIntent.getClipData() != null) {
+                        final int numFiles = resultIntent.getClipData().getItemCount();
+                        result = new Uri[numFiles];
+                        for (int i = 0; i < numFiles; i++) {
+                            result[i] = resultIntent.getClipData().getItemAt(i).getUri();
+                        }
+                    } else {
+                        result = WebChromeClient.FileChooserParams.parseResult(activityResult.getResultCode(), resultIntent);
+                    }
+                    filePathCallback.onReceiveValue(result);
+                };
+            activityLauncher.launch(intent);
+        } catch (ActivityNotFoundException e) {
+            filePathCallback.onReceiveValue(null);
+        }
+    }
+
+    private String[] getValidTypes(String[] currentTypes) {
+        List<String> validTypes = new ArrayList<>();
+        MimeTypeMap mtm = MimeTypeMap.getSingleton();
+        for (String mime : currentTypes) {
+            if (mime.startsWith(".")) {
+                String extension = mime.substring(1);
+                String extensionMime = mtm.getMimeTypeFromExtension(extension);
+                if (extensionMime != null && !validTypes.contains(extensionMime)) {
+                    validTypes.add(extensionMime);
+                }
+            } else if (!validTypes.contains(mime)) {
+                validTypes.add(mime);
+            }
+        }
+        Object[] validObj = validTypes.toArray();
+        return Arrays.copyOf(validObj, validObj.length, String[].class);
+    }
+
+    @Override
+    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+        String tag = Logger.tags("Console");
+        if (consoleMessage.message() != null && isValidMsg(consoleMessage.message())) {
+            String msg = String.format(
+                "File: %s - Line %d - Msg: %s",
+                consoleMessage.sourceId(),
+                consoleMessage.lineNumber(),
+                consoleMessage.message()
+            );
+            String level = consoleMessage.messageLevel().name();
+            if ("ERROR".equalsIgnoreCase(level)) {
+                Logger.error(tag, msg, null);
+            } else if ("WARNING".equalsIgnoreCase(level)) {
+                Logger.warn(tag, msg);
+            } else if ("TIP".equalsIgnoreCase(level)) {
+                Logger.debug(tag, msg);
+            } else {
+                Logger.info(tag, msg);
+            }
+        }
+        return true;
+    }
+
+    public boolean isValidMsg(String msg) {
+        return !(
+            msg.contains("%cresult %c") ||
+            (msg.contains("%cnative %c")) ||
+            msg.equalsIgnoreCase("[object Object]") ||
+            msg.equalsIgnoreCase("console.groupEnd")
+        );
+    }
+
+    private Uri createImageFileUri() throws IOException {
+        Activity activity = bridge.getActivity();
+        File photoFile = createImageFile(activity);
+        return FileProvider.getUriForFile(activity, bridge.getContext().getPackageName() + ".fileprovider", photoFile);
+    }
+
+    private File createImageFile(Activity activity) throws IOException {
+        // Create an image file name
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        String imageFileName = "JPEG_" + timeStamp + "_";
+        File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
+
+        return File.createTempFile(imageFileName, ".jpg", storageDir);
+    }
+}

+ 111 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/BridgeWebViewClient.java

@@ -0,0 +1,111 @@
+package com.getcapacitor;
+
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.webkit.RenderProcessGoneDetail;
+import android.webkit.WebResourceError;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import java.util.List;
+
+public class BridgeWebViewClient extends WebViewClient {
+
+    private Bridge bridge;
+
+    public BridgeWebViewClient(Bridge bridge) {
+        this.bridge = bridge;
+    }
+
+    @Override
+    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
+        return bridge.getLocalServer().shouldInterceptRequest(request);
+    }
+
+    @Override
+    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+        Uri url = request.getUrl();
+        return bridge.launchIntent(url);
+    }
+
+    @Deprecated
+    @Override
+    public boolean shouldOverrideUrlLoading(WebView view, String url) {
+        return bridge.launchIntent(Uri.parse(url));
+    }
+
+    @Override
+    public void onPageFinished(WebView view, String url) {
+        super.onPageFinished(view, url);
+        List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
+
+        if (webViewListeners != null && view.getProgress() == 100) {
+            for (WebViewListener listener : bridge.getWebViewListeners()) {
+                listener.onPageLoaded(view);
+            }
+        }
+    }
+
+    @Override
+    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
+        super.onReceivedError(view, request, error);
+
+        List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
+        if (webViewListeners != null) {
+            for (WebViewListener listener : bridge.getWebViewListeners()) {
+                listener.onReceivedError(view);
+            }
+        }
+
+        String errorPath = bridge.getErrorUrl();
+        if (errorPath != null && request.isForMainFrame()) {
+            view.loadUrl(errorPath);
+        }
+    }
+
+    @Override
+    public void onPageStarted(WebView view, String url, Bitmap favicon) {
+        super.onPageStarted(view, url, favicon);
+        bridge.reset();
+        List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
+
+        if (webViewListeners != null) {
+            for (WebViewListener listener : bridge.getWebViewListeners()) {
+                listener.onPageStarted(view);
+            }
+        }
+    }
+
+    @Override
+    public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
+        super.onReceivedHttpError(view, request, errorResponse);
+
+        List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
+        if (webViewListeners != null) {
+            for (WebViewListener listener : bridge.getWebViewListeners()) {
+                listener.onReceivedHttpError(view);
+            }
+        }
+
+        String errorPath = bridge.getErrorUrl();
+        if (errorPath != null && request.isForMainFrame()) {
+            view.loadUrl(errorPath);
+        }
+    }
+
+    @Override
+    public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
+        super.onRenderProcessGone(view, detail);
+        boolean result = false;
+
+        List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
+        if (webViewListeners != null) {
+            for (WebViewListener listener : bridge.getWebViewListeners()) {
+                result = listener.onRenderProcessGone(view, detail) || result;
+            }
+        }
+
+        return result;
+    }
+}

+ 670 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/CapConfig.java

@@ -0,0 +1,670 @@
+package com.getcapacitor;
+
+import static com.getcapacitor.Bridge.CAPACITOR_HTTP_SCHEME;
+import static com.getcapacitor.Bridge.DEFAULT_ANDROID_WEBVIEW_VERSION;
+import static com.getcapacitor.Bridge.DEFAULT_HUAWEI_WEBVIEW_VERSION;
+import static com.getcapacitor.Bridge.MINIMUM_ANDROID_WEBVIEW_VERSION;
+import static com.getcapacitor.Bridge.MINIMUM_HUAWEI_WEBVIEW_VERSION;
+import static com.getcapacitor.FileUtils.readFileFromAssets;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.AssetManager;
+import androidx.annotation.Nullable;
+import com.getcapacitor.util.JSONUtils;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Represents the configuration options for Capacitor
+ */
+public class CapConfig {
+
+    private static final String LOG_BEHAVIOR_NONE = "none";
+    private static final String LOG_BEHAVIOR_DEBUG = "debug";
+    private static final String LOG_BEHAVIOR_PRODUCTION = "production";
+
+    // Server Config
+    private boolean html5mode = true;
+    private String serverUrl;
+    private String hostname = "localhost";
+    private String androidScheme = CAPACITOR_HTTP_SCHEME;
+    private String[] allowNavigation;
+
+    // Android Config
+    private String overriddenUserAgentString;
+    private String appendedUserAgentString;
+    private String backgroundColor;
+    private boolean allowMixedContent = false;
+    private boolean captureInput = false;
+    private boolean webContentsDebuggingEnabled = false;
+    private boolean loggingEnabled = true;
+    private boolean initialFocus = true;
+    private boolean useLegacyBridge = false;
+    private int minWebViewVersion = DEFAULT_ANDROID_WEBVIEW_VERSION;
+    private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
+    private String errorPath;
+
+    // Embedded
+    private String startPath;
+
+    // Plugins
+    private Map<String, PluginConfig> pluginsConfiguration = null;
+
+    // Config Object JSON (legacy)
+    private JSONObject configJSON = new JSONObject();
+
+    /**
+     * Constructs an empty config file.
+     */
+    private CapConfig() {}
+
+    /**
+     * Get an instance of the Config file object.
+     * @deprecated use {@link #loadDefault(Context)} to load an instance of the Config object
+     * from the capacitor.config.json file, or use the {@link CapConfig.Builder} to construct
+     * a CapConfig for embedded use.
+     *
+     * @param assetManager The AssetManager used to load the config file
+     * @param config JSON describing a configuration to use
+     */
+    @Deprecated
+    public CapConfig(AssetManager assetManager, JSONObject config) {
+        if (config != null) {
+            this.configJSON = config;
+        } else {
+            // Load the capacitor.config.json
+            loadConfigFromAssets(assetManager, null);
+        }
+
+        deserializeConfig(null);
+    }
+
+    /**
+     * Constructs a Capacitor Configuration from config.json file.
+     *
+     * @param context The context.
+     * @return A loaded config file, if successful.
+     */
+    public static CapConfig loadDefault(Context context) {
+        CapConfig config = new CapConfig();
+
+        if (context == null) {
+            Logger.error("Capacitor Config could not be created from file. Context must not be null.");
+            return config;
+        }
+
+        config.loadConfigFromAssets(context.getAssets(), null);
+        config.deserializeConfig(context);
+        return config;
+    }
+
+    /**
+     * Constructs a Capacitor Configuration from config.json file within the app assets.
+     *
+     * @param context The context.
+     * @param path A path relative to the root assets directory.
+     * @return A loaded config file, if successful.
+     */
+    public static CapConfig loadFromAssets(Context context, String path) {
+        CapConfig config = new CapConfig();
+
+        if (context == null) {
+            Logger.error("Capacitor Config could not be created from file. Context must not be null.");
+            return config;
+        }
+
+        config.loadConfigFromAssets(context.getAssets(), path);
+        config.deserializeConfig(context);
+        return config;
+    }
+
+    /**
+     * Constructs a Capacitor Configuration from config.json file within the app file-space.
+     *
+     * @param context The context.
+     * @param path A path relative to the root of the app file-space.
+     * @return A loaded config file, if successful.
+     */
+    public static CapConfig loadFromFile(Context context, String path) {
+        CapConfig config = new CapConfig();
+
+        if (context == null) {
+            Logger.error("Capacitor Config could not be created from file. Context must not be null.");
+            return config;
+        }
+
+        config.loadConfigFromFile(path);
+        config.deserializeConfig(context);
+        return config;
+    }
+
+    /**
+     * Constructs a Capacitor Configuration using ConfigBuilder.
+     *
+     * @param builder A config builder initialized with values
+     */
+    private CapConfig(Builder builder) {
+        // Server Config
+        this.html5mode = builder.html5mode;
+        this.serverUrl = builder.serverUrl;
+        this.hostname = builder.hostname;
+
+        if (this.validateScheme(builder.androidScheme)) {
+            this.androidScheme = builder.androidScheme;
+        }
+
+        this.allowNavigation = builder.allowNavigation;
+
+        // Android Config
+        this.overriddenUserAgentString = builder.overriddenUserAgentString;
+        this.appendedUserAgentString = builder.appendedUserAgentString;
+        this.backgroundColor = builder.backgroundColor;
+        this.allowMixedContent = builder.allowMixedContent;
+        this.captureInput = builder.captureInput;
+        this.webContentsDebuggingEnabled = builder.webContentsDebuggingEnabled;
+        this.loggingEnabled = builder.loggingEnabled;
+        this.initialFocus = builder.initialFocus;
+        this.useLegacyBridge = builder.useLegacyBridge;
+        this.minWebViewVersion = builder.minWebViewVersion;
+        this.minHuaweiWebViewVersion = builder.minHuaweiWebViewVersion;
+        this.errorPath = builder.errorPath;
+
+        // Embedded
+        this.startPath = builder.startPath;
+
+        // Plugins Config
+        this.pluginsConfiguration = builder.pluginsConfiguration;
+    }
+
+    /**
+     * Loads a Capacitor Configuration JSON file into a Capacitor Configuration object.
+     * An optional path string can be provided to look for the config in a subdirectory path.
+     */
+    private void loadConfigFromAssets(AssetManager assetManager, String path) {
+        if (path == null) {
+            path = "";
+        } else {
+            // Add slash at the end to form a proper file path if going deeper in assets dir
+            if (path.charAt(path.length() - 1) != '/') {
+                path = path + "/";
+            }
+        }
+
+        try {
+            String jsonString = readFileFromAssets(assetManager, path + "capacitor.config.json");
+            configJSON = new JSONObject(jsonString);
+        } catch (IOException ex) {
+            Logger.error("Unable to load capacitor.config.json. Run npx cap copy first", ex);
+        } catch (JSONException ex) {
+            Logger.error("Unable to parse capacitor.config.json. Make sure it's valid json", ex);
+        }
+    }
+
+    /**
+     * Loads a Capacitor Configuration JSON file into a Capacitor Configuration object.
+     * An optional path string can be provided to look for the config in a subdirectory path.
+     */
+    private void loadConfigFromFile(String path) {
+        if (path == null) {
+            path = "";
+        } else {
+            // Add slash at the end to form a proper file path if going deeper in assets dir
+            if (path.charAt(path.length() - 1) != '/') {
+                path = path + "/";
+            }
+        }
+
+        try {
+            File configFile = new File(path + "capacitor.config.json");
+            String jsonString = FileUtils.readFileFromDisk(configFile);
+            configJSON = new JSONObject(jsonString);
+        } catch (JSONException ex) {
+            Logger.error("Unable to parse capacitor.config.json. Make sure it's valid json", ex);
+        } catch (IOException ex) {
+            Logger.error("Unable to load capacitor.config.json.", ex);
+        }
+    }
+
+    /**
+     * Deserializes the config from JSON into a Capacitor Configuration object.
+     */
+    private void deserializeConfig(@Nullable Context context) {
+        boolean isDebug = context != null && (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+
+        // Server
+        html5mode = JSONUtils.getBoolean(configJSON, "server.html5mode", html5mode);
+        serverUrl = JSONUtils.getString(configJSON, "server.url", null);
+        hostname = JSONUtils.getString(configJSON, "server.hostname", hostname);
+        errorPath = JSONUtils.getString(configJSON, "server.errorPath", null);
+
+        String configSchema = JSONUtils.getString(configJSON, "server.androidScheme", androidScheme);
+        if (this.validateScheme(configSchema)) {
+            androidScheme = configSchema;
+        }
+
+        allowNavigation = JSONUtils.getArray(configJSON, "server.allowNavigation", null);
+
+        // Android
+        overriddenUserAgentString =
+            JSONUtils.getString(configJSON, "android.overrideUserAgent", JSONUtils.getString(configJSON, "overrideUserAgent", null));
+        appendedUserAgentString =
+            JSONUtils.getString(configJSON, "android.appendUserAgent", JSONUtils.getString(configJSON, "appendUserAgent", null));
+        backgroundColor =
+            JSONUtils.getString(configJSON, "android.backgroundColor", JSONUtils.getString(configJSON, "backgroundColor", null));
+        allowMixedContent =
+            JSONUtils.getBoolean(
+                configJSON,
+                "android.allowMixedContent",
+                JSONUtils.getBoolean(configJSON, "allowMixedContent", allowMixedContent)
+            );
+        minWebViewVersion = JSONUtils.getInt(configJSON, "android.minWebViewVersion", DEFAULT_ANDROID_WEBVIEW_VERSION);
+        minHuaweiWebViewVersion = JSONUtils.getInt(configJSON, "android.minHuaweiWebViewVersion", DEFAULT_HUAWEI_WEBVIEW_VERSION);
+        captureInput = JSONUtils.getBoolean(configJSON, "android.captureInput", captureInput);
+        useLegacyBridge = JSONUtils.getBoolean(configJSON, "android.useLegacyBridge", useLegacyBridge);
+        webContentsDebuggingEnabled = JSONUtils.getBoolean(configJSON, "android.webContentsDebuggingEnabled", isDebug);
+
+        String logBehavior = JSONUtils.getString(
+            configJSON,
+            "android.loggingBehavior",
+            JSONUtils.getString(configJSON, "loggingBehavior", LOG_BEHAVIOR_DEBUG)
+        );
+        switch (logBehavior.toLowerCase(Locale.ROOT)) {
+            case LOG_BEHAVIOR_PRODUCTION:
+                loggingEnabled = true;
+                break;
+            case LOG_BEHAVIOR_NONE:
+                loggingEnabled = false;
+                break;
+            default: // LOG_BEHAVIOR_DEBUG
+                loggingEnabled = isDebug;
+        }
+
+        initialFocus = JSONUtils.getBoolean(configJSON, "android.initialFocus", initialFocus);
+
+        // Plugins
+        pluginsConfiguration = deserializePluginsConfig(JSONUtils.getObject(configJSON, "plugins"));
+    }
+
+    private boolean validateScheme(String scheme) {
+        List<String> invalidSchemes = Arrays.asList("file", "ftp", "ftps", "ws", "wss", "about", "blob", "data");
+        if (invalidSchemes.contains(scheme)) {
+            Logger.warn(scheme + " is not an allowed scheme.  Defaulting to http.");
+            return false;
+        }
+
+        // Non-http(s) schemes are not allowed to modify the URL path as of Android Webview 117
+        if (!scheme.equals("http") && !scheme.equals("https")) {
+            Logger.warn(
+                "Using a non-standard scheme: " + scheme + " for Android. This is known to cause issues as of Android Webview 117."
+            );
+        }
+
+        return true;
+    }
+
+    public boolean isHTML5Mode() {
+        return html5mode;
+    }
+
+    public String getServerUrl() {
+        return serverUrl;
+    }
+
+    public String getErrorPath() {
+        return errorPath;
+    }
+
+    public String getHostname() {
+        return hostname;
+    }
+
+    public String getStartPath() {
+        return startPath;
+    }
+
+    public String getAndroidScheme() {
+        return androidScheme;
+    }
+
+    public String[] getAllowNavigation() {
+        return allowNavigation;
+    }
+
+    public String getOverriddenUserAgentString() {
+        return overriddenUserAgentString;
+    }
+
+    public String getAppendedUserAgentString() {
+        return appendedUserAgentString;
+    }
+
+    public String getBackgroundColor() {
+        return backgroundColor;
+    }
+
+    public boolean isMixedContentAllowed() {
+        return allowMixedContent;
+    }
+
+    public boolean isInputCaptured() {
+        return captureInput;
+    }
+
+    public boolean isWebContentsDebuggingEnabled() {
+        return webContentsDebuggingEnabled;
+    }
+
+    public boolean isLoggingEnabled() {
+        return loggingEnabled;
+    }
+
+    public boolean isInitialFocus() {
+        return initialFocus;
+    }
+
+    public boolean isUsingLegacyBridge() {
+        return useLegacyBridge;
+    }
+
+    public int getMinWebViewVersion() {
+        if (minWebViewVersion < MINIMUM_ANDROID_WEBVIEW_VERSION) {
+            Logger.warn("Specified minimum webview version is too low, defaulting to " + MINIMUM_ANDROID_WEBVIEW_VERSION);
+            return MINIMUM_ANDROID_WEBVIEW_VERSION;
+        }
+
+        return minWebViewVersion;
+    }
+
+    public int getMinHuaweiWebViewVersion() {
+        if (minHuaweiWebViewVersion < MINIMUM_HUAWEI_WEBVIEW_VERSION) {
+            Logger.warn("Specified minimum Huawei webview version is too low, defaulting to " + MINIMUM_HUAWEI_WEBVIEW_VERSION);
+            return MINIMUM_HUAWEI_WEBVIEW_VERSION;
+        }
+
+        return minHuaweiWebViewVersion;
+    }
+
+    public PluginConfig getPluginConfiguration(String pluginId) {
+        PluginConfig pluginConfig = pluginsConfiguration.get(pluginId);
+        if (pluginConfig == null) {
+            pluginConfig = new PluginConfig(new JSONObject());
+        }
+
+        return pluginConfig;
+    }
+
+    /**
+     * Get a JSON object value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getObject(String)}  to access plugin config values.
+     * For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @return The value from the config, if exists. Null if not
+     */
+    @Deprecated
+    public JSONObject getObject(String key) {
+        try {
+            return configJSON.getJSONObject(key);
+        } catch (Exception ex) {}
+        return null;
+    }
+
+    /**
+     * Get a string value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getString(String, String)} to access plugin config
+     * values. For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @return The value from the config, if exists. Null if not
+     */
+    @Deprecated
+    public String getString(String key) {
+        return JSONUtils.getString(configJSON, key, null);
+    }
+
+    /**
+     * Get a string value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getString(String, String)} to access plugin config
+     * values. For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    @Deprecated
+    public String getString(String key, String defaultValue) {
+        return JSONUtils.getString(configJSON, key, defaultValue);
+    }
+
+    /**
+     * Get a boolean value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getBoolean(String, boolean)} to access plugin config
+     * values. For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    @Deprecated
+    public boolean getBoolean(String key, boolean defaultValue) {
+        return JSONUtils.getBoolean(configJSON, key, defaultValue);
+    }
+
+    /**
+     * Get an integer value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getInt(String, int)}  to access the plugin config
+     * values. For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    @Deprecated
+    public int getInt(String key, int defaultValue) {
+        return JSONUtils.getInt(configJSON, key, defaultValue);
+    }
+
+    /**
+     * Get a string array value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getArray(String)}  to access the plugin config
+     * values. For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @return The value from the config, if exists. Null if not
+     */
+    @Deprecated
+    public String[] getArray(String key) {
+        return JSONUtils.getArray(configJSON, key, null);
+    }
+
+    /**
+     * Get a string array value from the Capacitor config.
+     * @deprecated use {@link PluginConfig#getArray(String, String[])}  to access the plugin
+     * config values. For main Capacitor config values, use the appropriate getter.
+     *
+     * @param key A key to fetch from the config
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    @Deprecated
+    public String[] getArray(String key, String[] defaultValue) {
+        return JSONUtils.getArray(configJSON, key, defaultValue);
+    }
+
+    private static Map<String, PluginConfig> deserializePluginsConfig(JSONObject pluginsConfig) {
+        Map<String, PluginConfig> pluginsMap = new HashMap<>();
+
+        // return an empty map if there is no pluginsConfig json
+        if (pluginsConfig == null) {
+            return pluginsMap;
+        }
+
+        Iterator<String> pluginIds = pluginsConfig.keys();
+
+        while (pluginIds.hasNext()) {
+            String pluginId = pluginIds.next();
+            JSONObject value = null;
+
+            try {
+                value = pluginsConfig.getJSONObject(pluginId);
+                PluginConfig pluginConfig = new PluginConfig(value);
+                pluginsMap.put(pluginId, pluginConfig);
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return pluginsMap;
+    }
+
+    /**
+     * Builds a Capacitor Configuration in code
+     */
+    public static class Builder {
+
+        private Context context;
+
+        // Server Config Values
+        private boolean html5mode = true;
+        private String serverUrl;
+        private String errorPath;
+        private String hostname = "localhost";
+        private String androidScheme = CAPACITOR_HTTP_SCHEME;
+        private String[] allowNavigation;
+
+        // Android Config Values
+        private String overriddenUserAgentString;
+        private String appendedUserAgentString;
+        private String backgroundColor;
+        private boolean allowMixedContent = false;
+        private boolean captureInput = false;
+        private Boolean webContentsDebuggingEnabled = null;
+        private boolean loggingEnabled = true;
+        private boolean initialFocus = false;
+        private boolean useLegacyBridge = false;
+        private int minWebViewVersion = DEFAULT_ANDROID_WEBVIEW_VERSION;
+        private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
+
+        // Embedded
+        private String startPath = null;
+
+        // Plugins Config Object
+        private Map<String, PluginConfig> pluginsConfiguration = new HashMap<>();
+
+        /**
+         * Constructs a new CapConfig Builder.
+         *
+         * @param context The context
+         */
+        public Builder(Context context) {
+            this.context = context;
+        }
+
+        /**
+         * Builds a Capacitor Config from the builder.
+         *
+         * @return A new Capacitor Config
+         */
+        public CapConfig create() {
+            if (webContentsDebuggingEnabled == null) {
+                webContentsDebuggingEnabled = (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+            }
+
+            return new CapConfig(this);
+        }
+
+        public Builder setPluginsConfiguration(JSONObject pluginsConfiguration) {
+            this.pluginsConfiguration = deserializePluginsConfig(pluginsConfiguration);
+            return this;
+        }
+
+        public Builder setHTML5mode(boolean html5mode) {
+            this.html5mode = html5mode;
+            return this;
+        }
+
+        public Builder setServerUrl(String serverUrl) {
+            this.serverUrl = serverUrl;
+            return this;
+        }
+
+        public Builder setErrorPath(String errorPath) {
+            this.errorPath = errorPath;
+            return this;
+        }
+
+        public Builder setHostname(String hostname) {
+            this.hostname = hostname;
+            return this;
+        }
+
+        public Builder setStartPath(String path) {
+            this.startPath = path;
+            return this;
+        }
+
+        public Builder setAndroidScheme(String androidScheme) {
+            this.androidScheme = androidScheme;
+            return this;
+        }
+
+        public Builder setAllowNavigation(String[] allowNavigation) {
+            this.allowNavigation = allowNavigation;
+            return this;
+        }
+
+        public Builder setOverriddenUserAgentString(String overriddenUserAgentString) {
+            this.overriddenUserAgentString = overriddenUserAgentString;
+            return this;
+        }
+
+        public Builder setAppendedUserAgentString(String appendedUserAgentString) {
+            this.appendedUserAgentString = appendedUserAgentString;
+            return this;
+        }
+
+        public Builder setBackgroundColor(String backgroundColor) {
+            this.backgroundColor = backgroundColor;
+            return this;
+        }
+
+        public Builder setAllowMixedContent(boolean allowMixedContent) {
+            this.allowMixedContent = allowMixedContent;
+            return this;
+        }
+
+        public Builder setCaptureInput(boolean captureInput) {
+            this.captureInput = captureInput;
+            return this;
+        }
+
+        public Builder setUseLegacyBridge(boolean useLegacyBridge) {
+            this.useLegacyBridge = useLegacyBridge;
+            return this;
+        }
+
+        public Builder setWebContentsDebuggingEnabled(boolean webContentsDebuggingEnabled) {
+            this.webContentsDebuggingEnabled = webContentsDebuggingEnabled;
+            return this;
+        }
+
+        public Builder setLoggingEnabled(boolean enabled) {
+            this.loggingEnabled = enabled;
+            return this;
+        }
+
+        public Builder setInitialFocus(boolean focus) {
+            this.initialFocus = focus;
+            return this;
+        }
+    }
+}

+ 52 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java

@@ -0,0 +1,52 @@
+package com.getcapacitor;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.webkit.WebView;
+
+public class CapacitorWebView extends WebView {
+
+    private BaseInputConnection capInputConnection;
+    private Bridge bridge;
+
+    public CapacitorWebView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setBridge(Bridge bridge) {
+        this.bridge = bridge;
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        CapConfig config;
+        if (bridge != null) {
+            config = bridge.getConfig();
+        } else {
+            config = CapConfig.loadDefault(getContext());
+        }
+
+        boolean captureInput = config.isInputCaptured();
+        if (captureInput) {
+            if (capInputConnection == null) {
+                capInputConnection = new BaseInputConnection(this, false);
+            }
+            return capInputConnection;
+        }
+        return super.onCreateInputConnection(outAttrs);
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
+            evaluateJavascript("document.activeElement.value = document.activeElement.value + '" + event.getCharacters() + "';", null);
+            return false;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+}

+ 292 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java

@@ -0,0 +1,292 @@
+/**
+ * Portions adopted from react-native-image-crop-picker
+ *
+ * MIT License
+
+ * Copyright (c) 2017 Ivan Pusic
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.getcapacitor;
+
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * Common File utilities, such as resolve content URIs and
+ * creating portable web paths from low-level files
+ */
+public class FileUtils {
+
+    private static String CapacitorFileScheme = Bridge.CAPACITOR_FILE_START;
+
+    public enum Type {
+        IMAGE("image");
+
+        private String type;
+
+        Type(String type) {
+            this.type = type;
+        }
+    }
+
+    public static String getPortablePath(Context c, String host, Uri u) {
+        String path = getFileUrlForUri(c, u);
+        if (path.startsWith("file://")) {
+            path = path.replace("file://", "");
+        }
+        return host + Bridge.CAPACITOR_FILE_START + path;
+    }
+
+    public static String getFileUrlForUri(final Context context, final Uri uri) {
+        // DocumentProvider
+        if (DocumentsContract.isDocumentUri(context, uri)) {
+            // ExternalStorageProvider
+            if (isExternalStorageDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                if ("primary".equalsIgnoreCase(type)) {
+                    return legacyPrimaryPath(split[1]);
+                } else {
+                    final int splitIndex = docId.indexOf(':', 1);
+                    final String tag = docId.substring(0, splitIndex);
+                    final String path = docId.substring(splitIndex + 1);
+
+                    String nonPrimaryVolume = getPathToNonPrimaryVolume(context, tag);
+                    if (nonPrimaryVolume != null) {
+                        String result = nonPrimaryVolume + "/" + path;
+                        File file = new File(result);
+                        if (file.exists() && file.canRead()) {
+                            return result;
+                        }
+                        return null;
+                    }
+                }
+            }
+            // DownloadsProvider
+            else if (isDownloadsDocument(uri)) {
+                final String id = DocumentsContract.getDocumentId(uri);
+                final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+                return getDataColumn(context, contentUri, null, null);
+            }
+            // MediaProvider
+            else if (isMediaDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                Uri contentUri = null;
+                if ("image".equals(type)) {
+                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+
+                final String selection = "_id=?";
+                final String[] selectionArgs = new String[] { split[1] };
+
+                return getDataColumn(context, contentUri, selection, selectionArgs);
+            }
+        }
+        // MediaStore (and general)
+        else if ("content".equalsIgnoreCase(uri.getScheme())) {
+            // Return the remote address
+            if (isGooglePhotosUri(uri)) return uri.getLastPathSegment();
+            return getDataColumn(context, uri, null, null);
+        }
+        // File
+        else if ("file".equalsIgnoreCase(uri.getScheme())) {
+            return uri.getPath();
+        }
+
+        return null;
+    }
+
+    @SuppressWarnings("deprecation")
+    private static String legacyPrimaryPath(String pathPart) {
+        return Environment.getExternalStorageDirectory() + "/" + pathPart;
+    }
+
+    /**
+     * Read a plaintext file from the assets directory.
+     *
+     * @param assetManager Used to open the file.
+     * @param fileName The path of the file to read.
+     * @return The contents of the file path.
+     * @throws IOException Thrown if any issues reading the provided file path.
+     */
+    static String readFileFromAssets(AssetManager assetManager, String fileName) throws IOException {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(assetManager.open(fileName)))) {
+            StringBuilder buffer = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                buffer.append(line).append("\n");
+            }
+
+            return buffer.toString();
+        }
+    }
+
+    /**
+     * Read a plaintext file from within the app disk space.
+     *
+     * @param file The file to read.
+     * @return The contents of the file path.
+     * @throws IOException Thrown if any issues reading the provided file path.
+     */
+    static String readFileFromDisk(File file) throws IOException {
+        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            StringBuilder buffer = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                buffer.append(line).append("\n");
+            }
+
+            return buffer.toString();
+        }
+    }
+
+    /**
+     * Get the value of the data column for this Uri. This is useful for
+     * MediaStore Uris, and other file-based ContentProviders.
+     *
+     * @param context The context.
+     * @param uri The Uri to query.
+     * @param selection (Optional) Filter used in the query.
+     * @param selectionArgs (Optional) Selection arguments used in the query.
+     * @return The value of the _data column, which is typically a file path.
+     */
+    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+        String path = null;
+        Cursor cursor = null;
+        final String column = "_data";
+        final String[] projection = { column };
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
+            if (cursor != null && cursor.moveToFirst()) {
+                final int index = cursor.getColumnIndexOrThrow(column);
+                path = cursor.getString(index);
+            }
+        } catch (IllegalArgumentException ex) {
+            return getCopyFilePath(uri, context);
+        } finally {
+            if (cursor != null) cursor.close();
+        }
+        if (path == null) {
+            return getCopyFilePath(uri, context);
+        }
+        return path;
+    }
+
+    private static String getCopyFilePath(Uri uri, Context context) {
+        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
+        int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+        cursor.moveToFirst();
+        String name = (cursor.getString(nameIndex));
+        File file = new File(context.getFilesDir(), name);
+        try {
+            InputStream inputStream = context.getContentResolver().openInputStream(uri);
+            FileOutputStream outputStream = new FileOutputStream(file);
+            int read = 0;
+            int maxBufferSize = 1024 * 1024;
+            int bufferSize = Math.min(inputStream.available(), maxBufferSize);
+            final byte[] buffers = new byte[bufferSize];
+            while ((read = inputStream.read(buffers)) != -1) {
+                outputStream.write(buffers, 0, read);
+            }
+            inputStream.close();
+            outputStream.close();
+        } catch (Exception e) {
+            return null;
+        } finally {
+            if (cursor != null) cursor.close();
+        }
+        return file.getPath();
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is ExternalStorageProvider.
+     */
+    private static boolean isExternalStorageDocument(Uri uri) {
+        return "com.android.externalstorage.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is DownloadsProvider.
+     */
+    private static boolean isDownloadsDocument(Uri uri) {
+        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is MediaProvider.
+     */
+    private static boolean isMediaDocument(Uri uri) {
+        return "com.android.providers.media.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is Google Photos.
+     */
+    private static boolean isGooglePhotosUri(Uri uri) {
+        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
+    }
+
+    private static String getPathToNonPrimaryVolume(Context context, String tag) {
+        File[] volumes = context.getExternalCacheDirs();
+        if (volumes != null) {
+            for (File volume : volumes) {
+                if (volume != null) {
+                    String path = volume.getAbsolutePath();
+                    if (path != null) {
+                        int index = path.indexOf(tag);
+                        if (index != -1) {
+                            return path.substring(0, index) + tag;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}

+ 8 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/InvalidPluginException.java

@@ -0,0 +1,8 @@
+package com.getcapacitor;
+
+class InvalidPluginException extends Exception {
+
+    public InvalidPluginException(String s) {
+        super(s);
+    }
+}

+ 16 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/InvalidPluginMethodException.java

@@ -0,0 +1,16 @@
+package com.getcapacitor;
+
+class InvalidPluginMethodException extends Exception {
+
+    public InvalidPluginMethodException(String s) {
+        super(s);
+    }
+
+    public InvalidPluginMethodException(Throwable t) {
+        super(t);
+    }
+
+    public InvalidPluginMethodException(String s, Throwable t) {
+        super(s, t);
+    }
+}

+ 51 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSArray.java

@@ -0,0 +1,51 @@
+package com.getcapacitor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+public class JSArray extends JSONArray {
+
+    public JSArray() {
+        super();
+    }
+
+    public JSArray(String json) throws JSONException {
+        super(json);
+    }
+
+    public JSArray(Collection copyFrom) {
+        super(copyFrom);
+    }
+
+    public JSArray(Object array) throws JSONException {
+        super(array);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <E> List<E> toList() throws JSONException {
+        List<E> items = new ArrayList<>();
+        Object o = null;
+        for (int i = 0; i < this.length(); i++) {
+            o = this.get(i);
+            try {
+                items.add((E) this.get(i));
+            } catch (Exception ex) {
+                throw new JSONException("Not all items are instances of the given type");
+            }
+        }
+        return items;
+    }
+
+    /**
+     * Create a new JSArray without throwing a error
+     */
+    public static JSArray from(Object array) {
+        try {
+            return new JSArray(array);
+        } catch (JSONException ex) {}
+        return null;
+    }
+}

+ 193 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSExport.java

@@ -0,0 +1,193 @@
+package com.getcapacitor;
+
+import static com.getcapacitor.FileUtils.readFileFromAssets;
+
+import android.content.Context;
+import android.text.TextUtils;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class JSExport {
+
+    private static String CATCHALL_OPTIONS_PARAM = "_options";
+    private static String CALLBACK_PARAM = "_callback";
+
+    public static String getGlobalJS(Context context, boolean loggingEnabled, boolean isDebug) {
+        return "window.Capacitor = { DEBUG: " + isDebug + ", isLoggingEnabled: " + loggingEnabled + ", Plugins: {} };";
+    }
+
+    public static String getCordovaJS(Context context) {
+        String fileContent = "";
+        try {
+            fileContent = readFileFromAssets(context.getAssets(), "public/cordova.js");
+        } catch (IOException ex) {
+            Logger.error("Unable to read public/cordova.js file, Cordova plugins will not work");
+        }
+        return fileContent;
+    }
+
+    public static String getCordovaPluginsFileJS(Context context) {
+        String fileContent = "";
+        try {
+            fileContent = readFileFromAssets(context.getAssets(), "public/cordova_plugins.js");
+        } catch (IOException ex) {
+            Logger.error("Unable to read public/cordova_plugins.js file, Cordova plugins will not work");
+        }
+        return fileContent;
+    }
+
+    public static String getPluginJS(Collection<PluginHandle> plugins) {
+        List<String> lines = new ArrayList<>();
+        JSONArray pluginArray = new JSONArray();
+
+        lines.add("// Begin: Capacitor Plugin JS");
+        for (PluginHandle plugin : plugins) {
+            lines.add(
+                "(function(w) {\n" +
+                "var a = (w.Capacitor = w.Capacitor || {});\n" +
+                "var p = (a.Plugins = a.Plugins || {});\n" +
+                "var t = (p['" +
+                plugin.getId() +
+                "'] = {});\n" +
+                "t.addListener = function(eventName, callback) {\n" +
+                "  return w.Capacitor.addListener('" +
+                plugin.getId() +
+                "', eventName, callback);\n" +
+                "}"
+            );
+            Collection<PluginMethodHandle> methods = plugin.getMethods();
+            for (PluginMethodHandle method : methods) {
+                if (method.getName().equals("addListener") || method.getName().equals("removeListener")) {
+                    // Don't export add/remove listener, we do that automatically above as they are "special snowflakes"
+                    continue;
+                }
+                lines.add(generateMethodJS(plugin, method));
+            }
+
+            lines.add("})(window);\n");
+            pluginArray.put(createPluginHeader(plugin));
+        }
+
+        return TextUtils.join("\n", lines) + "\nwindow.Capacitor.PluginHeaders = " + pluginArray.toString() + ";";
+    }
+
+    public static String getCordovaPluginJS(Context context) {
+        return getFilesContent(context, "public/plugins");
+    }
+
+    public static String getFilesContent(Context context, String path) {
+        StringBuilder builder = new StringBuilder();
+        try {
+            String[] content = context.getAssets().list(path);
+            if (content.length > 0) {
+                for (String file : content) {
+                    if (!file.endsWith(".map")) {
+                        builder.append(getFilesContent(context, path + "/" + file));
+                    }
+                }
+            } else {
+                return readFileFromAssets(context.getAssets(), path);
+            }
+        } catch (IOException ex) {
+            Logger.warn("Unable to read file at path " + path);
+        }
+        return builder.toString();
+    }
+
+    private static JSONObject createPluginHeader(PluginHandle plugin) {
+        JSONObject pluginObj = new JSONObject();
+        Collection<PluginMethodHandle> methods = plugin.getMethods();
+        try {
+            String id = plugin.getId();
+            JSONArray methodArray = new JSONArray();
+            pluginObj.put("name", id);
+
+            for (PluginMethodHandle method : methods) {
+                methodArray.put(createPluginMethodHeader(method));
+            }
+
+            pluginObj.put("methods", methodArray);
+        } catch (JSONException e) {
+            // ignore
+        }
+        return pluginObj;
+    }
+
+    private static JSONObject createPluginMethodHeader(PluginMethodHandle method) {
+        JSONObject methodObj = new JSONObject();
+
+        try {
+            methodObj.put("name", method.getName());
+            if (!method.getReturnType().equals(PluginMethod.RETURN_NONE)) {
+                methodObj.put("rtype", method.getReturnType());
+            }
+        } catch (JSONException e) {
+            // ignore
+        }
+
+        return methodObj;
+    }
+
+    public static String getBridgeJS(Context context) throws JSExportException {
+        return getFilesContent(context, "native-bridge.js");
+    }
+
+    private static String generateMethodJS(PluginHandle plugin, PluginMethodHandle method) {
+        List<String> lines = new ArrayList<>();
+
+        List<String> args = new ArrayList<>();
+        // Add the catch all param that will take a full javascript object to pass to the plugin
+        args.add(CATCHALL_OPTIONS_PARAM);
+
+        String returnType = method.getReturnType();
+        if (returnType.equals(PluginMethod.RETURN_CALLBACK)) {
+            args.add(CALLBACK_PARAM);
+        }
+
+        // Create the method function declaration
+        lines.add("t['" + method.getName() + "'] = function(" + TextUtils.join(", ", args) + ") {");
+
+        switch (returnType) {
+            case PluginMethod.RETURN_NONE:
+                lines.add(
+                    "return w.Capacitor.nativeCallback('" +
+                    plugin.getId() +
+                    "', '" +
+                    method.getName() +
+                    "', " +
+                    CATCHALL_OPTIONS_PARAM +
+                    ")"
+                );
+                break;
+            case PluginMethod.RETURN_PROMISE:
+                lines.add(
+                    "return w.Capacitor.nativePromise('" + plugin.getId() + "', '" + method.getName() + "', " + CATCHALL_OPTIONS_PARAM + ")"
+                );
+                break;
+            case PluginMethod.RETURN_CALLBACK:
+                lines.add(
+                    "return w.Capacitor.nativeCallback('" +
+                    plugin.getId() +
+                    "', '" +
+                    method.getName() +
+                    "', " +
+                    CATCHALL_OPTIONS_PARAM +
+                    ", " +
+                    CALLBACK_PARAM +
+                    ")"
+                );
+                break;
+            default:
+            // TODO: Do something here?
+        }
+
+        lines.add("}");
+
+        return TextUtils.join("\n", lines);
+    }
+}

+ 16 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSExportException.java

@@ -0,0 +1,16 @@
+package com.getcapacitor;
+
+public class JSExportException extends Exception {
+
+    public JSExportException(String s) {
+        super(s);
+    }
+
+    public JSExportException(Throwable t) {
+        super(t);
+    }
+
+    public JSExportException(String s, Throwable t) {
+        super(s, t);
+    }
+}

+ 107 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSInjector.java

@@ -0,0 +1,107 @@
+package com.getcapacitor;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * JSInject is responsible for returning Capacitor's core
+ * runtime JS and any plugin JS back into HTML page responses
+ * to the client.
+ */
+class JSInjector {
+
+    private String globalJS;
+    private String bridgeJS;
+    private String pluginJS;
+    private String cordovaJS;
+    private String cordovaPluginsJS;
+    private String cordovaPluginsFileJS;
+    private String localUrlJS;
+
+    public JSInjector(
+        String globalJS,
+        String bridgeJS,
+        String pluginJS,
+        String cordovaJS,
+        String cordovaPluginsJS,
+        String cordovaPluginsFileJS,
+        String localUrlJS
+    ) {
+        this.globalJS = globalJS;
+        this.bridgeJS = bridgeJS;
+        this.pluginJS = pluginJS;
+        this.cordovaJS = cordovaJS;
+        this.cordovaPluginsJS = cordovaPluginsJS;
+        this.cordovaPluginsFileJS = cordovaPluginsFileJS;
+        this.localUrlJS = localUrlJS;
+    }
+
+    /**
+     * Generates injectable JS content.
+     * This may be used in other forms of injecting that aren't using an InputStream.
+     * @return
+     */
+    public String getScriptString() {
+        return (
+            globalJS +
+            "\n\n" +
+            localUrlJS +
+            "\n\n" +
+            bridgeJS +
+            "\n\n" +
+            pluginJS +
+            "\n\n" +
+            cordovaJS +
+            "\n\n" +
+            cordovaPluginsFileJS +
+            "\n\n" +
+            cordovaPluginsJS
+        );
+    }
+
+    /**
+     * Given an InputStream from the web server, prepend it with
+     * our JS stream
+     * @param responseStream
+     * @return
+     */
+    public InputStream getInjectedStream(InputStream responseStream) {
+        String js = "<script type=\"text/javascript\">" + getScriptString() + "</script>";
+        String html = this.readAssetStream(responseStream);
+
+        // Insert the js string at the position after <head> or before </head> using StringBuilder
+        StringBuilder modifiedHtml = new StringBuilder(html);
+        if (html.contains("<head>")) {
+            modifiedHtml.insert(html.indexOf("<head>") + "<head>".length(), "\n" + js + "\n");
+            html = modifiedHtml.toString();
+        } else if (html.contains("</head>")) {
+            modifiedHtml.insert(html.indexOf("</head>"), "\n" + js + "\n");
+            html = modifiedHtml.toString();
+        } else {
+            Logger.error("Unable to inject Capacitor, Plugins won't work");
+        }
+        return new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8));
+    }
+
+    private String readAssetStream(InputStream stream) {
+        try {
+            final int bufferSize = 1024;
+            final char[] buffer = new char[bufferSize];
+            final StringBuilder out = new StringBuilder();
+            Reader in = new InputStreamReader(stream, StandardCharsets.UTF_8);
+            for (;;) {
+                int rsz = in.read(buffer, 0, buffer.length);
+                if (rsz < 0) break;
+                out.append(buffer, 0, rsz);
+            }
+            return out.toString();
+        } catch (Exception e) {
+            Logger.error("Unable to process HTML asset file. This is a fatal error", e);
+        }
+
+        return "";
+    }
+}

+ 164 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSObject.java

@@ -0,0 +1,164 @@
+package com.getcapacitor;
+
+import androidx.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * A wrapper around JSONObject that isn't afraid to do simple
+ * JSON put operations without having to throw an exception
+ * for every little thing jeez
+ */
+public class JSObject extends JSONObject {
+
+    public JSObject() {
+        super();
+    }
+
+    public JSObject(String json) throws JSONException {
+        super(json);
+    }
+
+    public JSObject(JSONObject obj, String[] names) throws JSONException {
+        super(obj, names);
+    }
+
+    /**
+     * Convert a pathetic JSONObject into a JSObject
+     * @param obj
+     */
+    public static JSObject fromJSONObject(JSONObject obj) throws JSONException {
+        Iterator<String> keysIter = obj.keys();
+        List<String> keys = new ArrayList<>();
+        while (keysIter.hasNext()) {
+            keys.add(keysIter.next());
+        }
+
+        return new JSObject(obj, keys.toArray(new String[keys.size()]));
+    }
+
+    @Override
+    @Nullable
+    public String getString(String key) {
+        return getString(key, null);
+    }
+
+    @Nullable
+    public String getString(String key, @Nullable String defaultValue) {
+        try {
+            String value = super.getString(key);
+            if (!super.isNull(key)) {
+                return value;
+            }
+        } catch (JSONException ex) {}
+        return defaultValue;
+    }
+
+    @Nullable
+    public Integer getInteger(String key) {
+        return getInteger(key, null);
+    }
+
+    @Nullable
+    public Integer getInteger(String key, @Nullable Integer defaultValue) {
+        try {
+            return super.getInt(key);
+        } catch (JSONException e) {}
+        return defaultValue;
+    }
+
+    @Nullable
+    public Boolean getBoolean(String key, @Nullable Boolean defaultValue) {
+        try {
+            return super.getBoolean(key);
+        } catch (JSONException e) {}
+        return defaultValue;
+    }
+
+    /**
+     * Fetch boolean from jsonObject
+     */
+    @Nullable
+    public Boolean getBool(String key) {
+        return getBoolean(key, null);
+    }
+
+    @Nullable
+    public JSObject getJSObject(String name) {
+        try {
+            return getJSObject(name, null);
+        } catch (JSONException e) {}
+        return null;
+    }
+
+    @Nullable
+    public JSObject getJSObject(String name, @Nullable JSObject defaultValue) throws JSONException {
+        try {
+            Object obj = get(name);
+            if (obj instanceof JSONObject) {
+                Iterator<String> keysIter = ((JSONObject) obj).keys();
+                List<String> keys = new ArrayList<>();
+                while (keysIter.hasNext()) {
+                    keys.add(keysIter.next());
+                }
+
+                return new JSObject((JSONObject) obj, keys.toArray(new String[keys.size()]));
+            }
+        } catch (JSONException ex) {}
+        return defaultValue;
+    }
+
+    @Override
+    public JSObject put(String key, boolean value) {
+        try {
+            super.put(key, value);
+        } catch (JSONException ex) {}
+        return this;
+    }
+
+    @Override
+    public JSObject put(String key, int value) {
+        try {
+            super.put(key, value);
+        } catch (JSONException ex) {}
+        return this;
+    }
+
+    @Override
+    public JSObject put(String key, long value) {
+        try {
+            super.put(key, value);
+        } catch (JSONException ex) {}
+        return this;
+    }
+
+    @Override
+    public JSObject put(String key, double value) {
+        try {
+            super.put(key, value);
+        } catch (JSONException ex) {}
+        return this;
+    }
+
+    @Override
+    public JSObject put(String key, Object value) {
+        try {
+            super.put(key, value);
+        } catch (JSONException ex) {}
+        return this;
+    }
+
+    public JSObject put(String key, String value) {
+        try {
+            super.put(key, value);
+        } catch (JSONException ex) {}
+        return this;
+    }
+
+    public JSObject putSafe(String key, Object value) throws JSONException {
+        return (JSObject) super.put(key, value);
+    }
+}

+ 65 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/JSValue.java

@@ -0,0 +1,65 @@
+package com.getcapacitor;
+
+import org.json.JSONException;
+
+/**
+ * Represents a single user-data value of any type on the capacitor PluginCall object.
+ */
+public class JSValue {
+
+    private final Object value;
+
+    /**
+     * @param call The capacitor plugin call, used for accessing the value safely.
+     * @param name The name of the property to access.
+     */
+    public JSValue(PluginCall call, String name) {
+        this.value = this.toValue(call, name);
+    }
+
+    /**
+     * Returns the coerced but uncasted underlying value.
+     */
+    public Object getValue() {
+        return this.value;
+    }
+
+    @Override
+    public String toString() {
+        return this.getValue().toString();
+    }
+
+    /**
+     * Returns the underlying value as a JSObject, or throwing if it cannot.
+     *
+     * @throws JSONException If the underlying value is not a JSObject.
+     */
+    public JSObject toJSObject() throws JSONException {
+        if (this.value instanceof JSObject) return (JSObject) this.value;
+        throw new JSONException("JSValue could not be coerced to JSObject.");
+    }
+
+    /**
+     * Returns the underlying value as a JSArray, or throwing if it cannot.
+     *
+     * @throws JSONException If the underlying value is not a JSArray.
+     */
+    public JSArray toJSArray() throws JSONException {
+        if (this.value instanceof JSArray) return (JSArray) this.value;
+        throw new JSONException("JSValue could not be coerced to JSArray.");
+    }
+
+    /**
+     * Returns the underlying value this object represents, coercing it into a capacitor-friendly object if supported.
+     */
+    private Object toValue(PluginCall call, String name) {
+        Object value = null;
+        value = call.getArray(name, null);
+        if (value != null) return value;
+        value = call.getObject(name, null);
+        if (value != null) return value;
+        value = call.getString(name, null);
+        if (value != null) return value;
+        return call.getData().opt(name);
+    }
+}

+ 103 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/Logger.java

@@ -0,0 +1,103 @@
+package com.getcapacitor;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+public class Logger {
+
+    public static final String LOG_TAG_CORE = "Capacitor";
+    public static CapConfig config;
+
+    private static Logger instance;
+
+    private static Logger getInstance() {
+        if (instance == null) {
+            instance = new Logger();
+        }
+        return instance;
+    }
+
+    public static void init(CapConfig config) {
+        Logger.getInstance().loadConfig(config);
+    }
+
+    private void loadConfig(CapConfig config) {
+        Logger.config = config;
+    }
+
+    public static String tags(String... subtags) {
+        if (subtags != null && subtags.length > 0) {
+            return LOG_TAG_CORE + "/" + TextUtils.join("/", subtags);
+        }
+
+        return LOG_TAG_CORE;
+    }
+
+    public static void verbose(String message) {
+        verbose(LOG_TAG_CORE, message);
+    }
+
+    public static void verbose(String tag, String message) {
+        if (!shouldLog()) {
+            return;
+        }
+
+        Log.v(tag, message);
+    }
+
+    public static void debug(String message) {
+        debug(LOG_TAG_CORE, message);
+    }
+
+    public static void debug(String tag, String message) {
+        if (!shouldLog()) {
+            return;
+        }
+
+        Log.d(tag, message);
+    }
+
+    public static void info(String message) {
+        info(LOG_TAG_CORE, message);
+    }
+
+    public static void info(String tag, String message) {
+        if (!shouldLog()) {
+            return;
+        }
+
+        Log.i(tag, message);
+    }
+
+    public static void warn(String message) {
+        warn(LOG_TAG_CORE, message);
+    }
+
+    public static void warn(String tag, String message) {
+        if (!shouldLog()) {
+            return;
+        }
+
+        Log.w(tag, message);
+    }
+
+    public static void error(String message) {
+        error(LOG_TAG_CORE, message, null);
+    }
+
+    public static void error(String message, Throwable e) {
+        error(LOG_TAG_CORE, message, e);
+    }
+
+    public static void error(String tag, String message, Throwable e) {
+        if (!shouldLog()) {
+            return;
+        }
+
+        Log.e(tag, message, e);
+    }
+
+    public static boolean shouldLog() {
+        return config == null || config.isLoggingEnabled();
+    }
+}

+ 159 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/MessageHandler.java

@@ -0,0 +1,159 @@
+package com.getcapacitor;
+
+import android.webkit.JavascriptInterface;
+import android.webkit.WebView;
+import androidx.webkit.JavaScriptReplyProxy;
+import androidx.webkit.WebViewCompat;
+import androidx.webkit.WebViewFeature;
+import org.apache.cordova.PluginManager;
+
+/**
+ * MessageHandler handles messages from the WebView, dispatching them
+ * to plugins.
+ */
+public class MessageHandler {
+
+    private Bridge bridge;
+    private WebView webView;
+    private PluginManager cordovaPluginManager;
+    private JavaScriptReplyProxy javaScriptReplyProxy;
+
+    public MessageHandler(Bridge bridge, WebView webView, PluginManager cordovaPluginManager) {
+        this.bridge = bridge;
+        this.webView = webView;
+        this.cordovaPluginManager = cordovaPluginManager;
+
+        if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER) && !bridge.getConfig().isUsingLegacyBridge()) {
+            WebViewCompat.WebMessageListener capListener = (view, message, sourceOrigin, isMainFrame, replyProxy) -> {
+                if (isMainFrame) {
+                    postMessage(message.getData());
+                    javaScriptReplyProxy = replyProxy;
+                } else {
+                    Logger.warn("Plugin execution is allowed in Main Frame only");
+                }
+            };
+            try {
+                WebViewCompat.addWebMessageListener(webView, "androidBridge", bridge.getAllowedOriginRules(), capListener);
+            } catch (Exception ex) {
+                webView.addJavascriptInterface(this, "androidBridge");
+            }
+        } else {
+            webView.addJavascriptInterface(this, "androidBridge");
+        }
+    }
+
+    /**
+     * The main message handler that will be called from JavaScript
+     * to send a message to the native bridge.
+     * @param jsonStr
+     */
+    @JavascriptInterface
+    @SuppressWarnings("unused")
+    public void postMessage(String jsonStr) {
+        try {
+            JSObject postData = new JSObject(jsonStr);
+
+            String type = postData.getString("type");
+
+            boolean typeIsNotNull = type != null;
+            boolean isCordovaPlugin = typeIsNotNull && type.equals("cordova");
+            boolean isJavaScriptError = typeIsNotNull && type.equals("js.error");
+
+            String callbackId = postData.getString("callbackId");
+
+            if (isCordovaPlugin) {
+                String service = postData.getString("service");
+                String action = postData.getString("action");
+                String actionArgs = postData.getString("actionArgs");
+
+                Logger.verbose(
+                    Logger.tags("Plugin"),
+                    "To native (Cordova plugin): callbackId: " +
+                    callbackId +
+                    ", service: " +
+                    service +
+                    ", action: " +
+                    action +
+                    ", actionArgs: " +
+                    actionArgs
+                );
+
+                this.callCordovaPluginMethod(callbackId, service, action, actionArgs);
+            } else if (isJavaScriptError) {
+                Logger.error("JavaScript Error: " + jsonStr);
+            } else {
+                String pluginId = postData.getString("pluginId");
+                String methodName = postData.getString("methodName");
+                JSObject methodData = postData.getJSObject("options", new JSObject());
+
+                Logger.verbose(
+                    Logger.tags("Plugin"),
+                    "To native (Capacitor plugin): callbackId: " + callbackId + ", pluginId: " + pluginId + ", methodName: " + methodName
+                );
+
+                this.callPluginMethod(callbackId, pluginId, methodName, methodData);
+            }
+        } catch (Exception ex) {
+            Logger.error("Post message error:", ex);
+        }
+    }
+
+    public void sendResponseMessage(PluginCall call, PluginResult successResult, PluginResult errorResult) {
+        try {
+            PluginResult data = new PluginResult();
+            data.put("save", call.isKeptAlive());
+            data.put("callbackId", call.getCallbackId());
+            data.put("pluginId", call.getPluginId());
+            data.put("methodName", call.getMethodName());
+
+            boolean pluginResultInError = errorResult != null;
+            if (pluginResultInError) {
+                data.put("success", false);
+                data.put("error", errorResult);
+                Logger.debug("Sending plugin error: " + data.toString());
+            } else {
+                data.put("success", true);
+                if (successResult != null) {
+                    data.put("data", successResult);
+                }
+            }
+
+            boolean isValidCallbackId = !call.getCallbackId().equals(PluginCall.CALLBACK_ID_DANGLING);
+            if (isValidCallbackId) {
+                if (bridge.getConfig().isUsingLegacyBridge()) {
+                    legacySendResponseMessage(data);
+                } else if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER) && javaScriptReplyProxy != null) {
+                    javaScriptReplyProxy.postMessage(data.toString());
+                } else {
+                    legacySendResponseMessage(data);
+                }
+            } else {
+                bridge.getApp().fireRestoredResult(data);
+            }
+        } catch (Exception ex) {
+            Logger.error("sendResponseMessage: error: " + ex);
+        }
+        if (!call.isKeptAlive()) {
+            call.release(bridge);
+        }
+    }
+
+    private void legacySendResponseMessage(PluginResult data) {
+        final String runScript = "window.Capacitor.fromNative(" + data.toString() + ")";
+        final WebView webView = this.webView;
+        webView.post(() -> webView.evaluateJavascript(runScript, null));
+    }
+
+    private void callPluginMethod(String callbackId, String pluginId, String methodName, JSObject methodData) {
+        PluginCall call = new PluginCall(this, pluginId, callbackId, methodName, methodData);
+        bridge.callPluginMethod(pluginId, methodName, call);
+    }
+
+    private void callCordovaPluginMethod(String callbackId, String service, String action, String actionArgs) {
+        bridge.execute(
+            () -> {
+                cordovaPluginManager.exec(service, action, callbackId, actionArgs);
+            }
+        );
+    }
+}

+ 37 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/NativePlugin.java

@@ -0,0 +1,37 @@
+package com.getcapacitor;
+
+import com.getcapacitor.annotation.CapacitorPlugin;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base annotation for all Plugins
+ * @deprecated
+ * <p> Use {@link CapacitorPlugin} instead
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Deprecated
+public @interface NativePlugin {
+    /**
+     * Request codes this plugin uses and responds to, in order to tie
+     * Android events back the plugin to handle
+     */
+    int[] requestCodes() default {};
+
+    /**
+     * Permissions this plugin needs, in order to make permission requests
+     * easy if the plugin only needs basic permission prompting
+     */
+    String[] permissions() default {};
+
+    /**
+     * The request code to use when automatically requesting permissions
+     */
+    int permissionRequestCode() default 9000;
+
+    /**
+     * A custom name for the plugin, otherwise uses the
+     * simple class name.
+     */
+    String name() default "";
+}

+ 31 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PermissionState.java

@@ -0,0 +1,31 @@
+package com.getcapacitor;
+
+import java.util.Locale;
+
+/**
+ * Represents the state of a permission
+ *
+ * @since 3.0.0
+ */
+public enum PermissionState {
+    GRANTED("granted"),
+    DENIED("denied"),
+    PROMPT("prompt"),
+    PROMPT_WITH_RATIONALE("prompt-with-rationale");
+
+    private String state;
+
+    PermissionState(String state) {
+        this.state = state;
+    }
+
+    @Override
+    public String toString() {
+        return state;
+    }
+
+    public static PermissionState byState(String state) {
+        state = state.toUpperCase(Locale.ROOT).replace('-', '_');
+        return valueOf(state);
+    }
+}

+ 1046 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/Plugin.java

@@ -0,0 +1,1046 @@
+package com.getcapacitor;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Bundle;
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import com.getcapacitor.annotation.ActivityCallback;
+import com.getcapacitor.annotation.CapacitorPlugin;
+import com.getcapacitor.annotation.Permission;
+import com.getcapacitor.annotation.PermissionCallback;
+import com.getcapacitor.util.PermissionHelper;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.json.JSONException;
+
+/**
+ * Plugin is the base class for all plugins, containing a number of
+ * convenient features for interacting with the {@link Bridge}, managing
+ * plugin permissions, tracking lifecycle events, and more.
+ *
+ * You should inherit from this class when creating new plugins, along with
+ * adding the {@link CapacitorPlugin} annotation to add additional required
+ * metadata about the Plugin
+ */
+public class Plugin {
+
+    // The key we will use inside of a persisted Bundle for the JSON blob
+    // for a plugin call options.
+    private static final String BUNDLE_PERSISTED_OPTIONS_JSON_KEY = "_json";
+
+    // Reference to the Bridge
+    protected Bridge bridge;
+
+    // Reference to the PluginHandle wrapper for this Plugin
+    protected PluginHandle handle;
+
+    /**
+     * A way for plugins to quickly save a call that they will need to reference
+     * between activity/permissions starts/requests
+     *
+     * @deprecated store calls on the bridge using the methods
+     * {@link com.getcapacitor.Bridge#saveCall(PluginCall)},
+     * {@link com.getcapacitor.Bridge#getSavedCall(String)} and
+     * {@link com.getcapacitor.Bridge#releaseCall(PluginCall)}
+     */
+    @Deprecated
+    protected PluginCall savedLastCall;
+
+    // Stored event listeners
+    private final Map<String, List<PluginCall>> eventListeners;
+
+    /**
+     * Launchers used by the plugin to handle activity results
+     */
+    private final Map<String, ActivityResultLauncher<Intent>> activityLaunchers = new HashMap<>();
+
+    /**
+     * Launchers used by the plugin to handle permission results
+     */
+    private final Map<String, ActivityResultLauncher<String[]>> permissionLaunchers = new HashMap<>();
+
+    private String lastPluginCallId;
+
+    // Stored results of an event if an event was fired and
+    // no listeners were attached yet. Only stores the last value.
+    private final Map<String, List<JSObject>> retainedEventArguments;
+
+    public Plugin() {
+        eventListeners = new HashMap<>();
+        retainedEventArguments = new HashMap<>();
+    }
+
+    /**
+     * Called when the plugin has been connected to the bridge
+     * and is ready to start initializing.
+     */
+    public void load() {}
+
+    /**
+     * Registers activity result launchers defined on plugins, used for permission requests and
+     * activities started for result.
+     */
+    void initializeActivityLaunchers() {
+        List<Method> pluginClassMethods = new ArrayList<>();
+        for (
+            Class<?> pluginCursor = getClass();
+            !pluginCursor.getName().equals(Object.class.getName());
+            pluginCursor = pluginCursor.getSuperclass()
+        ) {
+            pluginClassMethods.addAll(Arrays.asList(pluginCursor.getDeclaredMethods()));
+        }
+
+        for (final Method method : pluginClassMethods) {
+            if (method.isAnnotationPresent(ActivityCallback.class)) {
+                // register callbacks annotated with ActivityCallback for activity results
+                ActivityResultLauncher<Intent> launcher = bridge.registerForActivityResult(
+                    new ActivityResultContracts.StartActivityForResult(),
+                    result -> triggerActivityCallback(method, result)
+                );
+
+                activityLaunchers.put(method.getName(), launcher);
+            } else if (method.isAnnotationPresent(PermissionCallback.class)) {
+                // register callbacks annotated with PermissionCallback for permission results
+                ActivityResultLauncher<String[]> launcher = bridge.registerForActivityResult(
+                    new ActivityResultContracts.RequestMultiplePermissions(),
+                    permissions -> triggerPermissionCallback(method, permissions)
+                );
+
+                permissionLaunchers.put(method.getName(), launcher);
+            }
+        }
+    }
+
+    private void triggerPermissionCallback(Method method, Map<String, Boolean> permissionResultMap) {
+        PluginCall savedCall = bridge.getPermissionCall(handle.getId());
+
+        // validate permissions and invoke the permission result callback
+        if (bridge.validatePermissions(this, savedCall, permissionResultMap)) {
+            try {
+                method.setAccessible(true);
+                method.invoke(this, savedCall);
+            } catch (IllegalAccessException | InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void triggerActivityCallback(Method method, ActivityResult result) {
+        PluginCall savedCall = bridge.getSavedCall(lastPluginCallId);
+        if (savedCall == null) {
+            savedCall = bridge.getPluginCallForLastActivity();
+        }
+        // invoke the activity result callback
+        try {
+            method.setAccessible(true);
+            method.invoke(this, savedCall, result);
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Start activity for result with the provided Intent and resolve with the provided callback method name.
+     * <p>
+     * If there is no registered activity callback for the method name passed in, the call will
+     * be rejected. Make sure a valid activity result callback method is registered using the
+     * {@link ActivityCallback} annotation.
+     *
+     * @param call the plugin call
+     * @param intent the intent used to start an activity
+     * @param callbackName the name of the callback to run when the launched activity is finished
+     * @since 3.0.0
+     */
+    public void startActivityForResult(PluginCall call, Intent intent, String callbackName) {
+        ActivityResultLauncher<Intent> activityResultLauncher = getActivityLauncherOrReject(call, callbackName);
+        if (activityResultLauncher == null) {
+            // return when null since call was rejected in getLauncherOrReject
+            return;
+        }
+        bridge.setPluginCallForLastActivity(call);
+        lastPluginCallId = call.getCallbackId();
+        bridge.saveCall(call);
+        activityResultLauncher.launch(intent);
+    }
+
+    private void permissionActivityResult(PluginCall call, String[] permissionStrings, String callbackName) {
+        ActivityResultLauncher<String[]> permissionResultLauncher = getPermissionLauncherOrReject(call, callbackName);
+        if (permissionResultLauncher == null) {
+            // return when null since call was rejected in getLauncherOrReject
+            return;
+        }
+
+        bridge.savePermissionCall(call);
+        permissionResultLauncher.launch(permissionStrings);
+    }
+
+    /**
+     * Get the main {@link Context} for the current Activity (your app)
+     * @return the Context for the current activity
+     */
+    public Context getContext() {
+        return this.bridge.getContext();
+    }
+
+    /**
+     * Get the main {@link Activity} for the app
+     * @return the Activity for the current app
+     */
+    public AppCompatActivity getActivity() {
+        return this.bridge.getActivity();
+    }
+
+    /**
+     * Set the Bridge instance for this plugin
+     * @param bridge
+     */
+    public void setBridge(Bridge bridge) {
+        this.bridge = bridge;
+    }
+
+    /**
+     * Get the Bridge instance for this plugin
+     */
+    public Bridge getBridge() {
+        return this.bridge;
+    }
+
+    /**
+     * Set the wrapper {@link PluginHandle} instance for this plugin that
+     * contains additional metadata about the Plugin instance (such
+     * as indexed methods for reflection, and {@link CapacitorPlugin} annotation data).
+     * @param pluginHandle
+     */
+    public void setPluginHandle(PluginHandle pluginHandle) {
+        this.handle = pluginHandle;
+    }
+
+    /**
+     * Return the wrapper {@link PluginHandle} for this plugin.
+     *
+     * This wrapper contains additional metadata about the plugin instance,
+     * such as indexed methods for reflection, and {@link CapacitorPlugin} annotation data).
+     * @return
+     */
+    public PluginHandle getPluginHandle() {
+        return this.handle;
+    }
+
+    /**
+     * Get the root App ID
+     * @return
+     */
+    public String getAppId() {
+        return getContext().getPackageName();
+    }
+
+    /**
+     * Called to save a {@link PluginCall} in order to reference it
+     * later, such as in an activity or permissions result handler
+     * @deprecated use {@link Bridge#saveCall(PluginCall)}
+     *
+     * @param lastCall
+     */
+    @Deprecated
+    public void saveCall(PluginCall lastCall) {
+        this.savedLastCall = lastCall;
+    }
+
+    /**
+     * Set the last saved call to null to free memory
+     * @deprecated use {@link PluginCall#release(Bridge)}
+     */
+    @Deprecated
+    public void freeSavedCall() {
+        this.savedLastCall.release(bridge);
+        this.savedLastCall = null;
+    }
+
+    /**
+     * Get the last saved call, if any
+     * @deprecated use {@link Bridge#getSavedCall(String)}
+     *
+     * @return
+     */
+    @Deprecated
+    public PluginCall getSavedCall() {
+        return this.savedLastCall;
+    }
+
+    /**
+     * Get the config options for this plugin.
+     *
+     * @return a config object representing the plugin config options, or an empty config
+     * if none exists
+     */
+    public PluginConfig getConfig() {
+        return bridge.getConfig().getPluginConfiguration(handle.getId());
+    }
+
+    /**
+     * Get the value for a key on the config for this plugin.
+     * @deprecated use {@link #getConfig()} and access config values using the methods available
+     * depending on the type.
+     *
+     * @param key the key for the config value
+     * @return some object containing the value from the config
+     */
+    @Deprecated
+    public Object getConfigValue(String key) {
+        try {
+            PluginConfig pluginConfig = getConfig();
+            return pluginConfig.getConfigJSON().get(key);
+        } catch (JSONException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Check whether any of the given permissions has been defined in the AndroidManifest.xml
+     * @deprecated use {@link #isPermissionDeclared(String)}
+     *
+     * @param permissions
+     * @return
+     */
+    @Deprecated
+    public boolean hasDefinedPermissions(String[] permissions) {
+        for (String permission : permissions) {
+            if (!PermissionHelper.hasDefinedPermission(getContext(), permission)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Check if all annotated permissions have been defined in the AndroidManifest.xml
+     * @deprecated use {@link #isPermissionDeclared(String)}
+     *
+     * @return true if permissions are all defined in the Manifest
+     */
+    @Deprecated
+    public boolean hasDefinedRequiredPermissions() {
+        CapacitorPlugin annotation = handle.getPluginAnnotation();
+        if (annotation == null) {
+            // Check for legacy plugin annotation, @NativePlugin
+            NativePlugin legacyAnnotation = handle.getLegacyPluginAnnotation();
+            return hasDefinedPermissions(legacyAnnotation.permissions());
+        } else {
+            for (Permission perm : annotation.permissions()) {
+                for (String permString : perm.strings()) {
+                    if (!PermissionHelper.hasDefinedPermission(getContext(), permString)) {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Checks if the given permission alias is correctly declared in AndroidManifest.xml
+     * @param alias a permission alias defined on the plugin
+     * @return true only if all permissions associated with the given alias are declared in the manifest
+     */
+    public boolean isPermissionDeclared(String alias) {
+        CapacitorPlugin annotation = handle.getPluginAnnotation();
+        if (annotation != null) {
+            for (Permission perm : annotation.permissions()) {
+                if (alias.equalsIgnoreCase(perm.alias())) {
+                    boolean result = true;
+                    for (String permString : perm.strings()) {
+                        result = result && PermissionHelper.hasDefinedPermission(getContext(), permString);
+                    }
+
+                    return result;
+                }
+            }
+        }
+
+        Logger.error(String.format("isPermissionDeclared: No alias defined for %s " + "or missing @CapacitorPlugin annotation.", alias));
+        return false;
+    }
+
+    /**
+     * Check whether the given permission has been granted by the user
+     * @deprecated use {@link #getPermissionState(String)} and {@link #getPermissionStates()} to get
+     * the states of permissions defined on the Plugin in conjunction with the @CapacitorPlugin
+     * annotation. Use the Android API {@link ActivityCompat#checkSelfPermission(Context, String)}
+     * methods to check permissions with Android permission strings
+     *
+     * @param permission
+     * @return
+     */
+    @Deprecated
+    public boolean hasPermission(String permission) {
+        return ActivityCompat.checkSelfPermission(this.getContext(), permission) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
+     * If the plugin annotation specified a set of permissions, this method checks if each is
+     * granted
+     * @deprecated use {@link #getPermissionState(String)} or {@link #getPermissionStates()} to
+     * check whether permissions are granted or not
+     *
+     * @return
+     */
+    @Deprecated
+    public boolean hasRequiredPermissions() {
+        CapacitorPlugin annotation = handle.getPluginAnnotation();
+        if (annotation == null) {
+            // Check for legacy plugin annotation, @NativePlugin
+            NativePlugin legacyAnnotation = handle.getLegacyPluginAnnotation();
+            for (String perm : legacyAnnotation.permissions()) {
+                if (ActivityCompat.checkSelfPermission(this.getContext(), perm) != PackageManager.PERMISSION_GRANTED) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        for (Permission perm : annotation.permissions()) {
+            for (String permString : perm.strings()) {
+                if (ActivityCompat.checkSelfPermission(this.getContext(), permString) != PackageManager.PERMISSION_GRANTED) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Request all of the specified permissions in the CapacitorPlugin annotation (if any)
+     *
+     * If there is no registered permission callback for the PluginCall passed in, the call will
+     * be rejected. Make sure a valid permission callback method is registered using the
+     * {@link PermissionCallback} annotation.
+     *
+     * @since 3.0.0
+     * @param call the plugin call
+     * @param callbackName the name of the callback to run when the permission request is complete
+     */
+    protected void requestAllPermissions(@NonNull PluginCall call, @NonNull String callbackName) {
+        CapacitorPlugin annotation = handle.getPluginAnnotation();
+        if (annotation != null) {
+            HashSet<String> perms = new HashSet<>();
+            for (Permission perm : annotation.permissions()) {
+                perms.addAll(Arrays.asList(perm.strings()));
+            }
+
+            permissionActivityResult(call, perms.toArray(new String[0]), callbackName);
+        }
+    }
+
+    /**
+     * Request permissions using an alias defined on the plugin.
+     *
+     * If there is no registered permission callback for the PluginCall passed in, the call will
+     * be rejected. Make sure a valid permission callback method is registered using the
+     * {@link PermissionCallback} annotation.
+     *
+     * @param alias an alias defined on the plugin
+     * @param call  the plugin call involved in originating the request
+     * @param callbackName the name of the callback to run when the permission request is complete
+     */
+    protected void requestPermissionForAlias(@NonNull String alias, @NonNull PluginCall call, @NonNull String callbackName) {
+        requestPermissionForAliases(new String[] { alias }, call, callbackName);
+    }
+
+    /**
+     * Request permissions using aliases defined on the plugin.
+     *
+     * If there is no registered permission callback for the PluginCall passed in, the call will
+     * be rejected. Make sure a valid permission callback method is registered using the
+     * {@link PermissionCallback} annotation.
+     *
+     * @param aliases a set of aliases defined on the plugin
+     * @param call    the plugin call involved in originating the request
+     * @param callbackName the name of the callback to run when the permission request is complete
+     */
+    protected void requestPermissionForAliases(@NonNull String[] aliases, @NonNull PluginCall call, @NonNull String callbackName) {
+        if (aliases.length == 0) {
+            Logger.error("No permission alias was provided");
+            return;
+        }
+
+        String[] permissions = getPermissionStringsForAliases(aliases);
+
+        if (permissions.length > 0) {
+            permissionActivityResult(call, permissions, callbackName);
+        }
+    }
+
+    /**
+     * Gets the Android permission strings defined on the {@link CapacitorPlugin} annotation with
+     * the provided aliases.
+     *
+     * @param aliases aliases for permissions defined on the plugin
+     * @return Android permission strings associated with the provided aliases, if exists
+     */
+    private String[] getPermissionStringsForAliases(@NonNull String[] aliases) {
+        CapacitorPlugin annotation = handle.getPluginAnnotation();
+        HashSet<String> perms = new HashSet<>();
+        for (Permission perm : annotation.permissions()) {
+            if (Arrays.asList(aliases).contains(perm.alias())) {
+                perms.addAll(Arrays.asList(perm.strings()));
+            }
+        }
+
+        return perms.toArray(new String[0]);
+    }
+
+    /**
+     * Gets the activity launcher associated with the calling methodName, or rejects the call if
+     * no registered launcher exists
+     *
+     * @param call       the plugin call
+     * @param methodName the name of the activity callback method
+     * @return a launcher, or null if none found
+     */
+    private @Nullable ActivityResultLauncher<Intent> getActivityLauncherOrReject(PluginCall call, String methodName) {
+        ActivityResultLauncher<Intent> activityLauncher = activityLaunchers.get(methodName);
+
+        // if there is no registered launcher, reject the call with an error and return null
+        if (activityLauncher == null) {
+            String registerError =
+                "There is no ActivityCallback method registered for the name: %s. " +
+                "Please define a callback method annotated with @ActivityCallback " +
+                "that receives arguments: (PluginCall, ActivityResult)";
+            registerError = String.format(Locale.US, registerError, methodName);
+            Logger.error(registerError);
+            call.reject(registerError);
+            return null;
+        }
+
+        return activityLauncher;
+    }
+
+    /**
+     * Gets the permission launcher associated with the calling methodName, or rejects the call if
+     * no registered launcher exists
+     *
+     * @param call       the plugin call
+     * @param methodName the name of the permission callback method
+     * @return a launcher, or null if none found
+     */
+    private @Nullable ActivityResultLauncher<String[]> getPermissionLauncherOrReject(PluginCall call, String methodName) {
+        ActivityResultLauncher<String[]> permissionLauncher = permissionLaunchers.get(methodName);
+
+        // if there is no registered launcher, reject the call with an error and return null
+        if (permissionLauncher == null) {
+            String registerError =
+                "There is no PermissionCallback method registered for the name: %s. " +
+                "Please define a callback method annotated with @PermissionCallback " +
+                "that receives arguments: (PluginCall)";
+            registerError = String.format(Locale.US, registerError, methodName);
+            Logger.error(registerError);
+            call.reject(registerError);
+            return null;
+        }
+
+        return permissionLauncher;
+    }
+
+    /**
+     * Request all of the specified permissions in the CapacitorPlugin annotation (if any)
+     *
+     * @deprecated use {@link #requestAllPermissions(PluginCall, String)} in conjunction with @CapacitorPlugin
+     */
+    @Deprecated
+    public void pluginRequestAllPermissions() {
+        NativePlugin legacyAnnotation = handle.getLegacyPluginAnnotation();
+        ActivityCompat.requestPermissions(getActivity(), legacyAnnotation.permissions(), legacyAnnotation.permissionRequestCode());
+    }
+
+    /**
+     * Helper for requesting a specific permission
+     *
+     * @param permission  the permission to request
+     * @param requestCode the requestCode to use to associate the result with the plugin
+     * @deprecated use {@link #requestPermissionForAlias(String, PluginCall, String)} in conjunction with @CapacitorPlugin
+     */
+    @Deprecated
+    public void pluginRequestPermission(String permission, int requestCode) {
+        ActivityCompat.requestPermissions(getActivity(), new String[] { permission }, requestCode);
+    }
+
+    /**
+     * Helper for requesting specific permissions
+     * @deprecated use {@link #requestPermissionForAliases(String[], PluginCall, String)} in conjunction
+     * with @CapacitorPlugin
+     *
+     * @param permissions the set of permissions to request
+     * @param requestCode the requestCode to use to associate the result with the plugin
+     */
+    @Deprecated
+    public void pluginRequestPermissions(String[] permissions, int requestCode) {
+        ActivityCompat.requestPermissions(getActivity(), permissions, requestCode);
+    }
+
+    /**
+     * Get the permission state for the provided permission alias.
+     *
+     * @param alias the permission alias to get
+     * @return the state of the provided permission alias or null
+     */
+    public PermissionState getPermissionState(String alias) {
+        return getPermissionStates().get(alias);
+    }
+
+    /**
+     * Helper to check all permissions defined on a plugin and see the state of each.
+     *
+     * @since 3.0.0
+     * @return A mapping of permission aliases to the associated granted status.
+     */
+    public Map<String, PermissionState> getPermissionStates() {
+        return bridge.getPermissionStates(this);
+    }
+
+    /**
+     * Add a listener for the given event
+     * @param eventName
+     * @param call
+     */
+    private void addEventListener(String eventName, PluginCall call) {
+        List<PluginCall> listeners = eventListeners.get(eventName);
+        if (listeners == null || listeners.isEmpty()) {
+            listeners = new ArrayList<>();
+            eventListeners.put(eventName, listeners);
+
+            // Must add the call before sending retained arguments
+            listeners.add(call);
+
+            sendRetainedArgumentsForEvent(eventName);
+        } else {
+            listeners.add(call);
+        }
+    }
+
+    /**
+     * Remove a listener from the given event
+     * @param eventName
+     * @param call
+     */
+    private void removeEventListener(String eventName, PluginCall call) {
+        List<PluginCall> listeners = eventListeners.get(eventName);
+        if (listeners == null) {
+            return;
+        }
+
+        listeners.remove(call);
+    }
+
+    /**
+     * Notify all listeners that an event occurred
+     * @param eventName
+     * @param data
+     */
+    protected void notifyListeners(String eventName, JSObject data, boolean retainUntilConsumed) {
+        Logger.verbose(getLogTag(), "Notifying listeners for event " + eventName);
+        List<PluginCall> listeners = eventListeners.get(eventName);
+        if (listeners == null || listeners.isEmpty()) {
+            Logger.debug(getLogTag(), "No listeners found for event " + eventName);
+            if (retainUntilConsumed) {
+                List<JSObject> argList = retainedEventArguments.get(eventName);
+
+                if (argList == null) {
+                    argList = new ArrayList<JSObject>();
+                }
+
+                argList.add(data);
+                retainedEventArguments.put(eventName, argList);
+            }
+            return;
+        }
+
+        CopyOnWriteArrayList<PluginCall> listenersCopy = new CopyOnWriteArrayList(listeners);
+        for (PluginCall call : listenersCopy) {
+            call.resolve(data);
+        }
+    }
+
+    /**
+     * Notify all listeners that an event occurred
+     * This calls {@link Plugin#notifyListeners(String, JSObject, boolean)}
+     * with retainUntilConsumed set to false
+     * @param eventName
+     * @param data
+     */
+    protected void notifyListeners(String eventName, JSObject data) {
+        notifyListeners(eventName, data, false);
+    }
+
+    /**
+     * Check if there are any listeners for the given event
+     */
+    protected boolean hasListeners(String eventName) {
+        List<PluginCall> listeners = eventListeners.get(eventName);
+        if (listeners == null) {
+            return false;
+        }
+        return !listeners.isEmpty();
+    }
+
+    /**
+     * Send retained arguments (if any) for this event. This
+     * is called only when the first listener for an event is added
+     * @param eventName
+     */
+    private void sendRetainedArgumentsForEvent(String eventName) {
+        // copy retained args and null source to prevent potential race conditions
+        List<JSObject> retainedArgs = retainedEventArguments.get(eventName);
+        if (retainedArgs == null) {
+            return;
+        }
+
+        retainedEventArguments.remove(eventName);
+
+        for (JSObject retained : retainedArgs) {
+            notifyListeners(eventName, retained);
+        }
+    }
+
+    /**
+     * Exported plugin call for adding a listener to this plugin
+     * @param call
+     */
+    @SuppressWarnings("unused")
+    @PluginMethod(returnType = PluginMethod.RETURN_NONE)
+    public void addListener(PluginCall call) {
+        String eventName = call.getString("eventName");
+        call.setKeepAlive(true);
+        addEventListener(eventName, call);
+    }
+
+    /**
+     * Exported plugin call to remove a listener from this plugin
+     * @param call
+     */
+    @SuppressWarnings("unused")
+    @PluginMethod(returnType = PluginMethod.RETURN_NONE)
+    public void removeListener(PluginCall call) {
+        String eventName = call.getString("eventName");
+        String callbackId = call.getString("callbackId");
+        PluginCall savedCall = bridge.getSavedCall(callbackId);
+        if (savedCall != null) {
+            removeEventListener(eventName, savedCall);
+            bridge.releaseCall(savedCall);
+        }
+    }
+
+    /**
+     * Exported plugin call to remove all listeners from this plugin
+     * @param call
+     */
+    @SuppressWarnings("unused")
+    @PluginMethod(returnType = PluginMethod.RETURN_PROMISE)
+    public void removeAllListeners(PluginCall call) {
+        eventListeners.clear();
+        call.resolve();
+    }
+
+    /**
+     * Exported plugin call for checking the granted status for each permission
+     * declared on the plugin. This plugin call responds with a mapping of permissions to
+     * the associated granted status.
+     *
+     * @since 3.0.0
+     */
+    @PluginMethod
+    @PermissionCallback
+    public void checkPermissions(PluginCall pluginCall) {
+        Map<String, PermissionState> permissionsResult = getPermissionStates();
+
+        if (permissionsResult.size() == 0) {
+            // if no permissions are defined on the plugin, resolve undefined
+            pluginCall.resolve();
+        } else {
+            JSObject permissionsResultJSON = new JSObject();
+            for (Map.Entry<String, PermissionState> entry : permissionsResult.entrySet()) {
+                permissionsResultJSON.put(entry.getKey(), entry.getValue());
+            }
+
+            pluginCall.resolve(permissionsResultJSON);
+        }
+    }
+
+    /**
+     * Exported plugin call to request all permissions for this plugin.
+     * To manually request permissions within a plugin use:
+     * {@link #requestAllPermissions(PluginCall, String)}, or
+     * {@link #requestPermissionForAlias(String, PluginCall, String)}, or
+     * {@link #requestPermissionForAliases(String[], PluginCall, String)}
+     *
+     * @param call the plugin call
+     */
+    @PluginMethod
+    public void requestPermissions(PluginCall call) {
+        CapacitorPlugin annotation = handle.getPluginAnnotation();
+        if (annotation == null) {
+            handleLegacyPermission(call);
+        } else {
+            // handle permission requests for plugins defined with @CapacitorPlugin (since 3.0.0)
+            String[] permAliases = null;
+            Set<String> autoGrantPerms = new HashSet<>();
+
+            // If call was made with a list of specific permission aliases to request, save them
+            // to be requested
+            JSArray providedPerms = call.getArray("permissions");
+            List<String> providedPermsList = null;
+
+            if (providedPerms != null) {
+                try {
+                    providedPermsList = providedPerms.toList();
+                } catch (JSONException ignore) {
+                    // do nothing
+                }
+            }
+
+            // If call was made without any custom permissions, request all from plugin annotation
+            Set<String> aliasSet = new HashSet<>();
+            if (providedPermsList == null || providedPermsList.isEmpty()) {
+                for (Permission perm : annotation.permissions()) {
+                    // If a permission is defined with no permission strings, separate it for auto-granting.
+                    // Otherwise, the alias is added to the list to be requested.
+                    if (perm.strings().length == 0 || (perm.strings().length == 1 && perm.strings()[0].isEmpty())) {
+                        if (!perm.alias().isEmpty()) {
+                            autoGrantPerms.add(perm.alias());
+                        }
+                    } else {
+                        aliasSet.add(perm.alias());
+                    }
+                }
+
+                permAliases = aliasSet.toArray(new String[0]);
+            } else {
+                for (Permission perm : annotation.permissions()) {
+                    if (providedPermsList.contains(perm.alias())) {
+                        aliasSet.add(perm.alias());
+                    }
+                }
+
+                if (aliasSet.isEmpty()) {
+                    call.reject("No valid permission alias was requested of this plugin.");
+                } else {
+                    permAliases = aliasSet.toArray(new String[0]);
+                }
+            }
+
+            if (permAliases != null && permAliases.length > 0) {
+                // request permissions using provided aliases or all defined on the plugin
+                requestPermissionForAliases(permAliases, call, "checkPermissions");
+            } else if (!autoGrantPerms.isEmpty()) {
+                // if the plugin only has auto-grant permissions, return all as GRANTED
+                JSObject permissionsResults = new JSObject();
+
+                for (String perm : autoGrantPerms) {
+                    permissionsResults.put(perm, PermissionState.GRANTED.toString());
+                }
+
+                call.resolve(permissionsResults);
+            } else {
+                // no permissions are defined on the plugin, resolve undefined
+                call.resolve();
+            }
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void handleLegacyPermission(PluginCall call) {
+        // handle permission requests for plugins defined with @NativePlugin (prior to 3.0.0)
+        NativePlugin legacyAnnotation = this.handle.getLegacyPluginAnnotation();
+        String[] perms = legacyAnnotation.permissions();
+        if (perms.length > 0) {
+            saveCall(call);
+            pluginRequestPermissions(perms, legacyAnnotation.permissionRequestCode());
+        } else {
+            call.resolve();
+        }
+    }
+
+    /**
+     * Handle request permissions result. A plugin using the deprecated {@link NativePlugin}
+     * should override this to handle the result, or this method will handle the result
+     * for our convenient requestPermissions call.
+     * @deprecated in favor of using callbacks in conjunction with {@link CapacitorPlugin}
+     *
+     * @param requestCode
+     * @param permissions
+     * @param grantResults
+     */
+    @Deprecated
+    protected void handleRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+        if (!hasDefinedPermissions(permissions)) {
+            StringBuilder builder = new StringBuilder();
+            builder.append("Missing the following permissions in AndroidManifest.xml:\n");
+            String[] missing = PermissionHelper.getUndefinedPermissions(getContext(), permissions);
+            for (String perm : missing) {
+                builder.append(perm + "\n");
+            }
+            savedLastCall.reject(builder.toString());
+            savedLastCall = null;
+        }
+    }
+
+    /**
+     * Called before the app is destroyed to give a plugin the chance to
+     * save the last call options for a saved plugin. By default, this
+     * method saves the full JSON blob of the options call. Since Bundle sizes
+     * may be limited, plugins that expect to be called with large data
+     * objects (such as a file), should override this method and selectively
+     * store option values in a {@link Bundle} to avoid exceeding limits.
+     * @return a new {@link Bundle} with fields set from the options of the last saved {@link PluginCall}
+     */
+    protected Bundle saveInstanceState() {
+        PluginCall savedCall = bridge.getSavedCall(lastPluginCallId);
+
+        if (savedCall == null) {
+            return null;
+        }
+
+        Bundle ret = new Bundle();
+        JSObject callData = savedCall.getData();
+
+        if (callData != null) {
+            ret.putString(BUNDLE_PERSISTED_OPTIONS_JSON_KEY, callData.toString());
+        }
+
+        return ret;
+    }
+
+    /**
+     * Called when the app is opened with a previously un-handled
+     * activity response. If the plugin that started the activity
+     * stored data in {@link Plugin#saveInstanceState()} then this
+     * method will be called to allow the plugin to restore from that.
+     * @param state
+     */
+    protected void restoreState(Bundle state) {}
+
+    /**
+     * Handle activity result, should be overridden by each plugin
+     *
+     * @deprecated provide a callback method using the {@link ActivityCallback} annotation and use
+     * the {@link #startActivityForResult(PluginCall, Intent, String)} method
+     *
+     * @param requestCode
+     * @param resultCode
+     * @param data
+     */
+    @Deprecated
+    protected void handleOnActivityResult(int requestCode, int resultCode, Intent data) {}
+
+    /**
+     * Handle onNewIntent
+     * @param intent
+     */
+    protected void handleOnNewIntent(Intent intent) {}
+
+    /**
+     * Handle onConfigurationChanged
+     * @param newConfig
+     */
+    protected void handleOnConfigurationChanged(Configuration newConfig) {}
+
+    /**
+     * Handle onStart
+     */
+    protected void handleOnStart() {}
+
+    /**
+     * Handle onRestart
+     */
+    protected void handleOnRestart() {}
+
+    /**
+     * Handle onResume
+     */
+    protected void handleOnResume() {}
+
+    /**
+     * Handle onPause
+     */
+    protected void handleOnPause() {}
+
+    /**
+     * Handle onStop
+     */
+    protected void handleOnStop() {}
+
+    /**
+     * Handle onDestroy
+     */
+    protected void handleOnDestroy() {}
+
+    /**
+     * Give the plugins a chance to take control when a URL is about to be loaded in the WebView.
+     * Returning true causes the WebView to abort loading the URL.
+     * Returning false causes the WebView to continue loading the URL.
+     * Returning null will defer to the default Capacitor policy
+     */
+    @SuppressWarnings("unused")
+    public Boolean shouldOverrideLoad(Uri url) {
+        return null;
+    }
+
+    /**
+     * Start a new Activity.
+     *
+     * Note: This method must be used by all plugins instead of calling
+     * {@link Activity#startActivityForResult} as it associates the plugin with
+     * any resulting data from the new Activity even if this app
+     * is destroyed by the OS (to free up memory, for example).
+     * @param intent
+     * @param resultCode
+     */
+    @Deprecated
+    protected void startActivityForResult(PluginCall call, Intent intent, int resultCode) {
+        bridge.startActivityForPluginWithResult(call, intent, resultCode);
+    }
+
+    /**
+     * Execute the given runnable on the Bridge's task handler
+     * @param runnable
+     */
+    public void execute(Runnable runnable) {
+        bridge.execute(runnable);
+    }
+
+    /**
+     * Shortcut for getting the plugin log tag
+     * @param subTags
+     */
+    protected String getLogTag(String... subTags) {
+        return Logger.tags(subTags);
+    }
+
+    /**
+     * Gets a plugin log tag with the child's class name as subTag.
+     */
+    protected String getLogTag() {
+        return Logger.tags(this.getClass().getSimpleName());
+    }
+}

+ 440 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginCall.java

@@ -0,0 +1,440 @@
+package com.getcapacitor;
+
+import androidx.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Wraps a call from the web layer to native
+ */
+public class PluginCall {
+
+    /**
+     * A special callback id that indicates there is no matching callback
+     * on the client to associate any PluginCall results back to. This is used
+     * in the case of an app resuming with saved instance data, for example.
+     */
+    public static final String CALLBACK_ID_DANGLING = "-1";
+
+    private final MessageHandler msgHandler;
+    private final String pluginId;
+    private final String callbackId;
+    private final String methodName;
+    private final JSObject data;
+
+    private boolean keepAlive = false;
+
+    /**
+     * Indicates that this PluginCall was released, and should no longer be used
+     */
+    @Deprecated
+    private boolean isReleased = false;
+
+    public PluginCall(MessageHandler msgHandler, String pluginId, String callbackId, String methodName, JSObject data) {
+        this.msgHandler = msgHandler;
+        this.pluginId = pluginId;
+        this.callbackId = callbackId;
+        this.methodName = methodName;
+        this.data = data;
+    }
+
+    public void successCallback(PluginResult successResult) {
+        if (CALLBACK_ID_DANGLING.equals(this.callbackId)) {
+            // don't send back response if the callbackId was "-1"
+            return;
+        }
+
+        this.msgHandler.sendResponseMessage(this, successResult, null);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link #resolve(JSObject data)}
+     */
+    @Deprecated
+    public void success(JSObject data) {
+        PluginResult result = new PluginResult(data);
+        this.msgHandler.sendResponseMessage(this, result, null);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link #resolve()}
+     */
+    @Deprecated
+    public void success() {
+        this.resolve(new JSObject());
+    }
+
+    public void resolve(JSObject data) {
+        PluginResult result = new PluginResult(data);
+        this.msgHandler.sendResponseMessage(this, result, null);
+    }
+
+    public void resolve() {
+        this.msgHandler.sendResponseMessage(this, null, null);
+    }
+
+    public void errorCallback(String msg) {
+        PluginResult errorResult = new PluginResult();
+
+        try {
+            errorResult.put("message", msg);
+        } catch (Exception jsonEx) {
+            Logger.error(Logger.tags("Plugin"), jsonEx.toString(), null);
+        }
+
+        this.msgHandler.sendResponseMessage(this, null, errorResult);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link #reject(String msg, Exception ex)}
+     */
+    @Deprecated
+    public void error(String msg, Exception ex) {
+        reject(msg, ex);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link #reject(String msg, String code, Exception ex)}
+     */
+    @Deprecated
+    public void error(String msg, String code, Exception ex) {
+        reject(msg, code, ex);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link #reject(String msg)}
+     */
+    @Deprecated
+    public void error(String msg) {
+        reject(msg);
+    }
+
+    public void reject(String msg, String code, Exception ex, JSObject data) {
+        PluginResult errorResult = new PluginResult();
+
+        if (ex != null) {
+            Logger.error(Logger.tags("Plugin"), msg, ex);
+        }
+
+        try {
+            errorResult.put("message", msg);
+            errorResult.put("code", code);
+            if (null != data) {
+                errorResult.put("data", data);
+            }
+        } catch (Exception jsonEx) {
+            Logger.error(Logger.tags("Plugin"), jsonEx.getMessage(), jsonEx);
+        }
+
+        this.msgHandler.sendResponseMessage(this, null, errorResult);
+    }
+
+    public void reject(String msg, Exception ex, JSObject data) {
+        reject(msg, null, ex, data);
+    }
+
+    public void reject(String msg, String code, JSObject data) {
+        reject(msg, code, null, data);
+    }
+
+    public void reject(String msg, String code, Exception ex) {
+        reject(msg, code, ex, null);
+    }
+
+    public void reject(String msg, JSObject data) {
+        reject(msg, null, null, data);
+    }
+
+    public void reject(String msg, Exception ex) {
+        reject(msg, null, ex, null);
+    }
+
+    public void reject(String msg, String code) {
+        reject(msg, code, null, null);
+    }
+
+    public void reject(String msg) {
+        reject(msg, null, null, null);
+    }
+
+    public void unimplemented() {
+        unimplemented("not implemented");
+    }
+
+    public void unimplemented(String msg) {
+        reject(msg, "UNIMPLEMENTED", null, null);
+    }
+
+    public void unavailable() {
+        unavailable("not available");
+    }
+
+    public void unavailable(String msg) {
+        reject(msg, "UNAVAILABLE", null, null);
+    }
+
+    public String getPluginId() {
+        return this.pluginId;
+    }
+
+    public String getCallbackId() {
+        return this.callbackId;
+    }
+
+    public String getMethodName() {
+        return this.methodName;
+    }
+
+    public JSObject getData() {
+        return this.data;
+    }
+
+    @Nullable
+    public String getString(String name) {
+        return this.getString(name, null);
+    }
+
+    @Nullable
+    public String getString(String name, @Nullable String defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof String) {
+            return (String) value;
+        }
+        return defaultValue;
+    }
+
+    @Nullable
+    public Integer getInt(String name) {
+        return this.getInt(name, null);
+    }
+
+    @Nullable
+    public Integer getInt(String name, @Nullable Integer defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof Integer) {
+            return (Integer) value;
+        }
+        return defaultValue;
+    }
+
+    @Nullable
+    public Long getLong(String name) {
+        return this.getLong(name, null);
+    }
+
+    @Nullable
+    public Long getLong(String name, @Nullable Long defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof Long) {
+            return (Long) value;
+        }
+        return defaultValue;
+    }
+
+    @Nullable
+    public Float getFloat(String name) {
+        return this.getFloat(name, null);
+    }
+
+    @Nullable
+    public Float getFloat(String name, @Nullable Float defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof Float) {
+            return (Float) value;
+        }
+        if (value instanceof Double) {
+            return ((Double) value).floatValue();
+        }
+        if (value instanceof Integer) {
+            return ((Integer) value).floatValue();
+        }
+        return defaultValue;
+    }
+
+    @Nullable
+    public Double getDouble(String name) {
+        return this.getDouble(name, null);
+    }
+
+    @Nullable
+    public Double getDouble(String name, @Nullable Double defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof Double) {
+            return (Double) value;
+        }
+        if (value instanceof Float) {
+            return ((Float) value).doubleValue();
+        }
+        if (value instanceof Integer) {
+            return ((Integer) value).doubleValue();
+        }
+        return defaultValue;
+    }
+
+    @Nullable
+    public Boolean getBoolean(String name) {
+        return this.getBoolean(name, null);
+    }
+
+    @Nullable
+    public Boolean getBoolean(String name, @Nullable Boolean defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof Boolean) {
+            return (Boolean) value;
+        }
+        return defaultValue;
+    }
+
+    public JSObject getObject(String name) {
+        return this.getObject(name, null);
+    }
+
+    @Nullable
+    public JSObject getObject(String name, JSObject defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof JSONObject) {
+            try {
+                return JSObject.fromJSONObject((JSONObject) value);
+            } catch (JSONException ex) {
+                return defaultValue;
+            }
+        }
+        return defaultValue;
+    }
+
+    public JSArray getArray(String name) {
+        return this.getArray(name, null);
+    }
+
+    /**
+     * Get a JSONArray and turn it into a JSArray
+     * @param name
+     * @param defaultValue
+     * @return
+     */
+    @Nullable
+    public JSArray getArray(String name, JSArray defaultValue) {
+        Object value = this.data.opt(name);
+        if (value == null) {
+            return defaultValue;
+        }
+
+        if (value instanceof JSONArray) {
+            try {
+                JSONArray valueArray = (JSONArray) value;
+                List<Object> items = new ArrayList<>();
+                for (int i = 0; i < valueArray.length(); i++) {
+                    items.add(valueArray.get(i));
+                }
+                return new JSArray(items.toArray());
+            } catch (JSONException ex) {
+                return defaultValue;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * @param name of the option to check
+     * @return boolean indicating if the plugin call has an option for the provided name.
+     * @deprecated Presence of a key should not be considered significant.
+     * Use typed accessors to check the value instead.
+     */
+    @Deprecated
+    public boolean hasOption(String name) {
+        return this.data.has(name);
+    }
+
+    /**
+     * Indicate that the Bridge should cache this call in order to call
+     * it again later. For example, the addListener system uses this to
+     * continuously call the call's callback (😆).
+     * @deprecated use {@link #setKeepAlive(Boolean)} instead
+     */
+    @Deprecated
+    public void save() {
+        setKeepAlive(true);
+    }
+
+    /**
+     * Indicate that the Bridge should cache this call in order to call
+     * it again later. For example, the addListener system uses this to
+     * continuously call the call's callback.
+     *
+     * @param keepAlive whether to keep the callback saved
+     */
+    public void setKeepAlive(Boolean keepAlive) {
+        this.keepAlive = keepAlive;
+    }
+
+    public void release(Bridge bridge) {
+        this.keepAlive = false;
+        bridge.releaseCall(this);
+        this.isReleased = true;
+    }
+
+    /**
+     * @deprecated use {@link #isKeptAlive()}
+     * @return true if the plugin call is kept alive
+     */
+    @Deprecated
+    public boolean isSaved() {
+        return isKeptAlive();
+    }
+
+    /**
+     * Gets the keepAlive value of the plugin call
+     * @return true if the plugin call is kept alive
+     */
+    public boolean isKeptAlive() {
+        return keepAlive;
+    }
+
+    @Deprecated
+    public boolean isReleased() {
+        return isReleased;
+    }
+
+    class PluginCallDataTypeException extends Exception {
+
+        PluginCallDataTypeException(String m) {
+            super(m);
+        }
+    }
+}

+ 116 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginConfig.java

@@ -0,0 +1,116 @@
+package com.getcapacitor;
+
+import com.getcapacitor.util.JSONUtils;
+import org.json.JSONObject;
+
+/**
+ * Represents the configuration options for plugins used by Capacitor
+ */
+public class PluginConfig {
+
+    /**
+     * The object containing plugin config values.
+     */
+    private final JSONObject config;
+
+    /**
+     * Constructs a PluginsConfig with the provided JSONObject value.
+     *
+     * @param config A plugin configuration expressed as a JSON Object
+     */
+    PluginConfig(JSONObject config) {
+        this.config = config;
+    }
+
+    /**
+     * Get a string value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @return The value from the config, if exists. Null if not
+     */
+    public String getString(String configKey) {
+        return getString(configKey, null);
+    }
+
+    /**
+     * Get a string value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    public String getString(String configKey, String defaultValue) {
+        return JSONUtils.getString(config, configKey, defaultValue);
+    }
+
+    /**
+     * Get a boolean value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    public boolean getBoolean(String configKey, boolean defaultValue) {
+        return JSONUtils.getBoolean(config, configKey, defaultValue);
+    }
+
+    /**
+     * Get an integer value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    public int getInt(String configKey, int defaultValue) {
+        return JSONUtils.getInt(config, configKey, defaultValue);
+    }
+
+    /**
+     * Get a string array value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @return The value from the config, if exists. Null if not
+     */
+    public String[] getArray(String configKey) {
+        return getArray(configKey, null);
+    }
+
+    /**
+     * Get a string array value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @param defaultValue A default value to return if the key does not exist in the config
+     * @return The value from the config, if key exists. Default value returned if not
+     */
+    public String[] getArray(String configKey, String[] defaultValue) {
+        return JSONUtils.getArray(config, configKey, defaultValue);
+    }
+
+    /**
+     * Get a JSON object value for a plugin in the Capacitor config.
+     *
+     * @param configKey The key of the value to retrieve
+     * @return The value from the config, if exists. Null if not
+     */
+    public JSONObject getObject(String configKey) {
+        return JSONUtils.getObject(config, configKey);
+    }
+
+    /**
+     * Check if the PluginConfig is empty.
+     *
+     * @return true if the plugin config has no entries
+     */
+    public boolean isEmpty() {
+        return config.length() == 0;
+    }
+
+    /**
+     * Gets the JSON Object containing the config of the the provided plugin ID.
+     *
+     * @return The config for that plugin
+     */
+    public JSONObject getConfigJSON() {
+        return config;
+    }
+}

+ 160 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginHandle.java

@@ -0,0 +1,160 @@
+package com.getcapacitor;
+
+import com.getcapacitor.annotation.CapacitorPlugin;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * PluginHandle is an instance of a plugin that has been registered
+ * and indexed. Think of it as a Plugin instance with extra metadata goodies
+ */
+public class PluginHandle {
+
+    private final Bridge bridge;
+    private final Class<? extends Plugin> pluginClass;
+
+    private final Map<String, PluginMethodHandle> pluginMethods = new HashMap<>();
+
+    private final String pluginId;
+
+    @SuppressWarnings("deprecation")
+    private NativePlugin legacyPluginAnnotation;
+
+    private CapacitorPlugin pluginAnnotation;
+
+    private Plugin instance;
+
+    @SuppressWarnings("deprecation")
+    private PluginHandle(Class<? extends Plugin> clazz, Bridge bridge) throws InvalidPluginException {
+        this.bridge = bridge;
+        this.pluginClass = clazz;
+
+        CapacitorPlugin pluginAnnotation = pluginClass.getAnnotation(CapacitorPlugin.class);
+        if (pluginAnnotation == null) {
+            // Check for legacy plugin annotation, @NativePlugin
+            NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class);
+            if (legacyPluginAnnotation == null) {
+                throw new InvalidPluginException("No @CapacitorPlugin annotation found for plugin " + pluginClass.getName());
+            }
+
+            if (!legacyPluginAnnotation.name().equals("")) {
+                this.pluginId = legacyPluginAnnotation.name();
+            } else {
+                this.pluginId = pluginClass.getSimpleName();
+            }
+
+            this.legacyPluginAnnotation = legacyPluginAnnotation;
+        } else {
+            if (!pluginAnnotation.name().equals("")) {
+                this.pluginId = pluginAnnotation.name();
+            } else {
+                this.pluginId = pluginClass.getSimpleName();
+            }
+
+            this.pluginAnnotation = pluginAnnotation;
+        }
+
+        this.indexMethods(clazz);
+    }
+
+    public PluginHandle(Bridge bridge, Class<? extends Plugin> pluginClass) throws InvalidPluginException, PluginLoadException {
+        this(pluginClass, bridge);
+        this.load();
+    }
+
+    public PluginHandle(Bridge bridge, Plugin plugin) throws InvalidPluginException {
+        this(plugin.getClass(), bridge);
+        this.loadInstance(plugin);
+    }
+
+    public Class<? extends Plugin> getPluginClass() {
+        return pluginClass;
+    }
+
+    public String getId() {
+        return this.pluginId;
+    }
+
+    @SuppressWarnings("deprecation")
+    public NativePlugin getLegacyPluginAnnotation() {
+        return this.legacyPluginAnnotation;
+    }
+
+    public CapacitorPlugin getPluginAnnotation() {
+        return this.pluginAnnotation;
+    }
+
+    public Plugin getInstance() {
+        return this.instance;
+    }
+
+    public Collection<PluginMethodHandle> getMethods() {
+        return this.pluginMethods.values();
+    }
+
+    public Plugin load() throws PluginLoadException {
+        if (this.instance != null) {
+            return this.instance;
+        }
+
+        try {
+            this.instance = this.pluginClass.newInstance();
+            return this.loadInstance(instance);
+        } catch (InstantiationException | IllegalAccessException ex) {
+            throw new PluginLoadException("Unable to load plugin instance. Ensure plugin is publicly accessible");
+        }
+    }
+
+    public Plugin loadInstance(Plugin plugin) {
+        this.instance = plugin;
+        this.instance.setPluginHandle(this);
+        this.instance.setBridge(this.bridge);
+        this.instance.load();
+        this.instance.initializeActivityLaunchers();
+        return this.instance;
+    }
+
+    /**
+     * Call a method on a plugin.
+     * @param methodName the name of the method to call
+     * @param call the constructed PluginCall with parameters from the caller
+     * @throws InvalidPluginMethodException if no method was found on that plugin
+     */
+    public void invoke(String methodName, PluginCall call)
+        throws PluginLoadException, InvalidPluginMethodException, InvocationTargetException, IllegalAccessException {
+        if (this.instance == null) {
+            // Can throw PluginLoadException
+            this.load();
+        }
+
+        PluginMethodHandle methodMeta = pluginMethods.get(methodName);
+        if (methodMeta == null) {
+            throw new InvalidPluginMethodException("No method " + methodName + " found for plugin " + pluginClass.getName());
+        }
+
+        methodMeta.getMethod().invoke(this.instance, call);
+    }
+
+    /**
+     * Index all the known callable methods for a plugin for faster
+     * invocation later
+     */
+    private void indexMethods(Class<? extends Plugin> plugin) {
+        //Method[] methods = pluginClass.getDeclaredMethods();
+        Method[] methods = pluginClass.getMethods();
+
+        for (Method methodReflect : methods) {
+            PluginMethod method = methodReflect.getAnnotation(PluginMethod.class);
+
+            if (method == null) {
+                continue;
+            }
+
+            PluginMethodHandle methodMeta = new PluginMethodHandle(methodReflect, method);
+            pluginMethods.put(methodReflect.getName(), methodMeta);
+        }
+    }
+}

+ 16 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginInvocationException.java

@@ -0,0 +1,16 @@
+package com.getcapacitor;
+
+class PluginInvocationException extends Exception {
+
+    public PluginInvocationException(String s) {
+        super(s);
+    }
+
+    public PluginInvocationException(Throwable t) {
+        super(t);
+    }
+
+    public PluginInvocationException(String s, Throwable t) {
+        super(s, t);
+    }
+}

+ 19 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginLoadException.java

@@ -0,0 +1,19 @@
+package com.getcapacitor;
+
+/**
+ * Thrown when a plugin fails to instantiate
+ */
+public class PluginLoadException extends Exception {
+
+    public PluginLoadException(String s) {
+        super(s);
+    }
+
+    public PluginLoadException(Throwable t) {
+        super(t);
+    }
+
+    public PluginLoadException(String s, Throwable t) {
+        super(s, t);
+    }
+}

+ 56 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginManager.java

@@ -0,0 +1,56 @@
+package com.getcapacitor;
+
+import android.content.res.AssetManager;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class PluginManager {
+
+    private final AssetManager assetManager;
+
+    public PluginManager(AssetManager assetManager) {
+        this.assetManager = assetManager;
+    }
+
+    public List<Class<? extends Plugin>> loadPluginClasses() throws PluginLoadException {
+        JSONArray pluginsJSON = parsePluginsJSON();
+        ArrayList<Class<? extends Plugin>> pluginList = new ArrayList<>();
+
+        try {
+            for (int i = 0, size = pluginsJSON.length(); i < size; i++) {
+                JSONObject pluginJSON = pluginsJSON.getJSONObject(i);
+                String classPath = pluginJSON.getString("classpath");
+                Class<?> c = Class.forName(classPath);
+                pluginList.add(c.asSubclass(Plugin.class));
+            }
+        } catch (JSONException e) {
+            throw new PluginLoadException("Could not parse capacitor.plugins.json as JSON");
+        } catch (ClassNotFoundException e) {
+            throw new PluginLoadException("Could not find class by class path: " + e.getMessage());
+        }
+
+        return pluginList;
+    }
+
+    private JSONArray parsePluginsJSON() throws PluginLoadException {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(assetManager.open("capacitor.plugins.json")))) {
+            StringBuilder builder = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                builder.append(line);
+            }
+            String jsonString = builder.toString();
+            return new JSONArray(jsonString);
+        } catch (IOException e) {
+            throw new PluginLoadException("Could not load capacitor.plugins.json");
+        } catch (JSONException e) {
+            throw new PluginLoadException("Could not parse capacitor.plugins.json as JSON");
+        }
+    }
+}

+ 15 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginMethod.java

@@ -0,0 +1,15 @@
+package com.getcapacitor;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PluginMethod {
+    String RETURN_PROMISE = "promise";
+
+    String RETURN_CALLBACK = "callback";
+
+    String RETURN_NONE = "none";
+
+    String returnType() default RETURN_PROMISE;
+}

+ 33 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginMethodHandle.java

@@ -0,0 +1,33 @@
+package com.getcapacitor;
+
+import java.lang.reflect.Method;
+
+public class PluginMethodHandle {
+
+    // The reflect method reference
+    private final Method method;
+    // The name of the method
+    private final String name;
+    // The return type of the method (see PluginMethod for constants)
+    private final String returnType;
+
+    public PluginMethodHandle(Method method, PluginMethod methodDecorator) {
+        this.method = method;
+
+        this.name = method.getName();
+
+        this.returnType = methodDecorator.returnType();
+    }
+
+    public String getReturnType() {
+        return returnType;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+}

+ 84 - 0
app-angular/.angular/node_modules/.store/@capacitor+android@5.7.2/node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/PluginResult.java

@@ -0,0 +1,84 @@
+package com.getcapacitor;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Wraps a result for web from calling a native plugin.
+ */
+public class PluginResult {
+
+    private final JSObject json;
+
+    public PluginResult() {
+        this(new JSObject());
+    }
+
+    public PluginResult(JSObject json) {
+        this.json = json;
+    }
+
+    public PluginResult put(String name, boolean value) {
+        return this.jsonPut(name, value);
+    }
+
+    public PluginResult put(String name, double value) {
+        return this.jsonPut(name, value);
+    }
+
+    public PluginResult put(String name, int value) {
+        return this.jsonPut(name, value);
+    }
+
+    public PluginResult put(String name, long value) {
+        return this.jsonPut(name, value);
+    }
+
+    /**
+     * Format a date as an ISO string
+     */
+    public PluginResult put(String name, Date value) {
+        TimeZone tz = TimeZone.getTimeZone("UTC");
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+        df.setTimeZone(tz);
+        return this.jsonPut(name, df.format(value));
+    }
+
+    public PluginResult put(String name, Object value) {
+        return this.jsonPut(name, value);
+    }
+
+    public PluginResult put(String name, PluginResult value) {
+        return this.jsonPut(name, value.json);
+    }
+
+    PluginResult jsonPut(String name, Object value) {
+        try {
+            this.json.put(name, value);
+        } catch (Exception ex) {
+            Logger.error(Logger.tags("Plugin"), "", ex);
+        }
+        return this;
+    }
+
+    public String toString() {
+        return this.json.toString();
+    }
+
+    /**
+     * Return plugin metadata and information about the result, if it succeeded the data, or error information if it didn't.
+     * This is used for appRestoredResult, as it's technically a raw data response from a plugin.
+     * @return the raw data response from the plugin.
+     */
+    public JSObject getWrappedResult() {
+        JSObject ret = new JSObject();
+        ret.put("pluginId", this.json.getString("pluginId"));
+        ret.put("methodName", this.json.getString("methodName"));
+        ret.put("success", this.json.getBoolean("success", false));
+        ret.put("data", this.json.getJSObject("data"));
+        ret.put("error", this.json.getJSObject("error"));
+        return ret;
+    }
+}

Some files were not shown because too many files changed in this diff