diff --git a/openvidu-ionic/android/app/capacitor.build.gradle b/openvidu-ionic/android/app/capacitor.build.gradle index 1c2a7a88..e552d498 100644 --- a/openvidu-ionic/android/app/capacitor.build.gradle +++ b/openvidu-ionic/android/app/capacitor.build.gradle @@ -9,10 +9,7 @@ android { apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" dependencies { - implementation project(':capacitor-app') - implementation project(':capacitor-haptics') - implementation project(':capacitor-keyboard') - implementation project(':capacitor-status-bar') + implementation project(':jcesarmobile-ssl-skip') } diff --git a/openvidu-ionic/android/app/src/main/AndroidManifest.xml.orig b/openvidu-ionic/android/app/src/main/AndroidManifest.xml.orig deleted file mode 100644 index 99bdcb3f..00000000 --- a/openvidu-ionic/android/app/src/main/AndroidManifest.xml.orig +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/openvidu-ionic/android/capacitor.settings.gradle b/openvidu-ionic/android/capacitor.settings.gradle index bd358734..87763e6a 100644 --- a/openvidu-ionic/android/capacitor.settings.gradle +++ b/openvidu-ionic/android/capacitor.settings.gradle @@ -2,14 +2,5 @@ include ':capacitor-android' project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor') -include ':capacitor-app' -project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android') - -include ':capacitor-haptics' -project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android') - -include ':capacitor-keyboard' -project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android') - -include ':capacitor-status-bar' -project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') +include ':jcesarmobile-ssl-skip' +project(':jcesarmobile-ssl-skip').projectDir = new File('../node_modules/@jcesarmobile/ssl-skip/android') diff --git a/openvidu-ionic/capacitor.config.ts b/openvidu-ionic/capacitor.config.ts index 27adcfeb..ba3c9e5c 100644 --- a/openvidu-ionic/capacitor.config.ts +++ b/openvidu-ionic/capacitor.config.ts @@ -1,12 +1,31 @@ import { CapacitorConfig } from '@capacitor/cli'; +import {environment} from './src/environments/environment'; const config: CapacitorConfig = { appId: 'io.ionic.starter', appName: 'openvidu-ionic', webDir: 'www', server: { - androidScheme: 'https' + androidScheme: 'http', + iosScheme: 'http', } }; +if (environment.externalIp) { + config.server = config.server || {}; + // config.server.hostname = 'localhost'; + config.server.cleartext = true; + config.includePlugins = config.includePlugins || []; + // '@jcesarmobile/ssl-skip' plugin is needed to allow serve the app over HTTPS + // with a self-signed certificate without installing the certificate in the device + config.includePlugins.push('@jcesarmobile/ssl-skip', 'cordova-plugin-android-permissions'); + + // Android configuration + config.android = config.android || {}; + config.android.allowMixedContent = true; + + // iOS configuration + +} + export default config; diff --git a/openvidu-ionic/package-lock.json b/openvidu-ionic/package-lock.json index 21458724..cff2e536 100644 --- a/openvidu-ionic/package-lock.json +++ b/openvidu-ionic/package-lock.json @@ -16,6 +16,8 @@ "@angular/platform-browser": "^16.0.0", "@angular/platform-browser-dynamic": "^16.0.0", "@angular/router": "^16.0.0", + "@awesome-cordova-plugins/android-permissions": "6.4.0", + "@awesome-cordova-plugins/core": "6.4.0", "@capacitor/android": "5.5.0", "@capacitor/app": "5.0.6", "@capacitor/core": "5.5.0", @@ -23,6 +25,7 @@ "@capacitor/keyboard": "5.0.6", "@capacitor/status-bar": "5.0.6", "@ionic/angular": "^7.0.0", + "cordova-plugin-android-permissions": "^1.1.5", "ionicons": "^7.0.0", "livekit-client": "^1.14.4", "rxjs": "~7.8.0", @@ -41,6 +44,7 @@ "@angular/language-service": "^16.0.0", "@capacitor/cli": "5.5.0", "@ionic/angular-toolkit": "^9.0.0", + "@jcesarmobile/ssl-skip": "^0.2.0", "@types/jasmine": "~4.3.0", "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "5.3.0", @@ -84,12 +88,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1602.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.9.tgz", - "integrity": "sha512-U3vfb/e2sFfg0D9FyyRBXRPP7g4FBFtGK8Q3JPmvAVsHHwi5AUFRNR7YBChB/T5TMNY077HcTyEirVh2FeUpdA==", + "version": "0.1602.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.10.tgz", + "integrity": "sha512-FwemQXh3edqA/S6zPpsqKei5v7gt0R0WpjJoAJaz+FOpfDwij1fwnKr88XINY8xcefTcQaTDQxJZheJShA/hHw==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.9", + "@angular-devkit/core": "16.2.10", "rxjs": "7.8.1" }, "engines": { @@ -99,15 +103,15 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.9.tgz", - "integrity": "sha512-S1C4UYxRVyNt3C0wCxbT2jZ1dN5i37kS0mol3PQjbR8gQ0GQzHmzhjTBl1oImo8aouET9yhrk9etk65oat4mBQ==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.10.tgz", + "integrity": "sha512-msB/qjIsAOySDxdU5DpcX2sWGUEJOFIO03O9+HbtLwf3NDfe74mFfejxuKlHJXIJdgpM2Zc948M6+618QKpUYA==", "dev": true, "dependencies": { "@ampproject/remapping": "2.2.1", - "@angular-devkit/architect": "0.1602.9", - "@angular-devkit/build-webpack": "0.1602.9", - "@angular-devkit/core": "16.2.9", + "@angular-devkit/architect": "0.1602.10", + "@angular-devkit/build-webpack": "0.1602.10", + "@angular-devkit/core": "16.2.10", "@babel/core": "7.22.9", "@babel/generator": "7.22.9", "@babel/helper-annotate-as-pure": "7.22.5", @@ -119,7 +123,7 @@ "@babel/runtime": "7.22.6", "@babel/template": "7.22.5", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "16.2.9", + "@ngtools/webpack": "16.2.10", "@vitejs/plugin-basic-ssl": "1.0.1", "ansi-colors": "4.1.3", "autoprefixer": "10.4.14", @@ -305,12 +309,12 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1602.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.9.tgz", - "integrity": "sha512-+3IxovfBPR2Vy730mGa0SVKkd5LQVom85gjXOs7WcnnnZmfc1q/BtFlqTgW1UWvTxP8IQdm7UYWVclQfL/WExw==", + "version": "0.1602.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.10.tgz", + "integrity": "sha512-H7HiFKbZl/xVxpr1RH05SGawTpA1417wvr2nFGRu2OiePd0lPr6pIhcq8F8gt7JcA8yZKKaqjn2gU+6um2MFLg==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1602.9", + "@angular-devkit/architect": "0.1602.10", "rxjs": "7.8.1" }, "engines": { @@ -324,9 +328,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.9.tgz", - "integrity": "sha512-dcHWjHBNGm3yCeNz19y8A1At4KgyC6XHNnbFL0y+nnZYiaESXjUoXJYKASedI6A+Bpl0HNq2URhH6bL6Af3+4w==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.10.tgz", + "integrity": "sha512-eo7suLDjyu5bSlEr4TluYkFm4v2PVLSAPgnau8XHHlN5Yg4P/BZ00ve7LA7C9S1gzRSCrxQhK5ki4rnoFTo5zg==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -351,12 +355,12 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.9.tgz", - "integrity": "sha512-lB51CGCILpcSI37CwKUAGDLxMqh7zmuRbiPo9s9mSkCM4ccqxFlaL+VFTq2/laneARD6aikpOHnkVm5myNzQPw==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.10.tgz", + "integrity": "sha512-UCfPJKVNekb21bWRbzyx81tfHN3x8vU4ZMX/VA6xALg//QalMB7NOkkXBAssthnLastkyzkUtlvApTp2+R+EkQ==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.9", + "@angular-devkit/core": "16.2.10", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -369,9 +373,9 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.2.0.tgz", - "integrity": "sha512-SZjXOi3YIjuX2CocuRsR2QH6k1ca9lRO6IMm0YIYMmBPFCRP2KFHkL6aQnXM6DSaymQNN2TXfpuvUd45NxhU1w==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.3.1.tgz", + "integrity": "sha512-PmIOnRwqdOW1bvZtpTGBTDcOq/Czm3D+IPC/k90yIMs1VsAtcxqUmUtELje+ylJeb2LPeEZavekSnEpcatM4HQ==", "dev": true, "dependencies": { "@nx/devkit": "16.5.1", @@ -383,18 +387,18 @@ } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.2.0.tgz", - "integrity": "sha512-ct9orDYxkMl2+uvM7UBfgV28Dq57V4dEs+Drh7cD673JIMa6sXbgmd0QEtm8W3cmyK/jcTzmuoufxbH7hOxd6g==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.3.1.tgz", + "integrity": "sha512-m4WP1xwS9XLcC/3n6lIcG5HZoai/5eb5W3xm48GVcv//0qE2p7S96RSgKPgGHvif5pF8O9xAqEWs3gDEG45+7A==", "dev": true }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.2.0.tgz", - "integrity": "sha512-zdiAIox1T+B71HL+A8m+1jWdU34nvPGLhCRw/uZNwHzknsF4tYzNQ9W7T/SC/g/2s1yT2yNosEVNJSGSFvunJg==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.3.1.tgz", + "integrity": "sha512-kSc8ESfoy8TUSthbq0Lpq9e17I+3Smy4rHoNpKCFEGuJgPs0+OssZMxB6a5EawGbv2EKTPEtrxzFm1WsLR0U9Q==", "dev": true, "dependencies": { - "@angular-eslint/utils": "16.2.0", + "@angular-eslint/utils": "16.3.1", "@typescript-eslint/utils": "5.62.0" }, "peerDependencies": { @@ -403,17 +407,17 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.2.0.tgz", - "integrity": "sha512-YFdQ6hHX6NlQj0lfogZwfyKjU8pqkJU+Zsk0ehjlXP8VfKFVmDeQT5/Xr6Df9C8pveC3hvq6Jgd8vo67S9Enxg==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.3.1.tgz", + "integrity": "sha512-+RcFEWqNiRt3+5jXvmlIDlXtP9+vjdmgmVL6tt8yDbqdjBOewtyMu4pE4YaR4sFboyxgME9PbO2WrOyPXh6xjg==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "16.2.0", - "@angular-eslint/utils": "16.2.0", + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "@angular-eslint/utils": "16.3.1", "@typescript-eslint/type-utils": "5.62.0", "@typescript-eslint/utils": "5.62.0", "aria-query": "5.3.0", - "axobject-query": "3.2.1" + "axobject-query": "4.0.0" }, "peerDependencies": { "eslint": "^7.20.0 || ^8.0.0", @@ -421,13 +425,13 @@ } }, "node_modules/@angular-eslint/schematics": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.2.0.tgz", - "integrity": "sha512-2JUVR7hAKx37mgWeDjvyWEMH5uSeeksYuaQT5wwlgIzgrO4BNFuqs6Rgyp2jiYa7BFMX/qHULSa+bSq5J5ceEA==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.3.1.tgz", + "integrity": "sha512-cqrdobdtRY2XjLa6PhuGOQ7UhTRk2AvWS01sKeGjZ94nQJm5NUtEUyf6u3deIPYllW7gSAWjYzKUObKcTW/R+g==", "dev": true, "dependencies": { - "@angular-eslint/eslint-plugin": "16.2.0", - "@angular-eslint/eslint-plugin-template": "16.2.0", + "@angular-eslint/eslint-plugin": "16.3.1", + "@angular-eslint/eslint-plugin-template": "16.3.1", "@nx/devkit": "16.5.1", "ignore": "5.2.4", "nx": "16.5.1", @@ -439,12 +443,12 @@ } }, "node_modules/@angular-eslint/template-parser": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.2.0.tgz", - "integrity": "sha512-v2jVKTy2wN7iM9nHpBkxLn2wfL8jSl4IlPrXThIqj8No2VHtpLQZPKuXbGPUXQX05VS2Mj5feScQ36ZVGS8Rbw==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.3.1.tgz", + "integrity": "sha512-9+SxUtxB2iOnm0ldS2ow0stMxe02rB/TxeMIe8fxsLFHZdw8RQvs/p3HLvVHXzv6gUblMHebIb/ubUmwEVb2SA==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "16.2.0", + "@angular-eslint/bundled-angular-compiler": "16.3.1", "eslint-scope": "^7.0.0" }, "peerDependencies": { @@ -453,12 +457,12 @@ } }, "node_modules/@angular-eslint/utils": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.2.0.tgz", - "integrity": "sha512-NxMRwnlIgzmbJQfWkfd9y3Sz0hzjFdK5LH44i+3D5NhpPdZ6SzwHAjMYWoYsmmNQX5tlDXoicYF9Mz9Wz8DJ/A==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.3.1.tgz", + "integrity": "sha512-tEBcce0rG+DmcPO8jhRffUFDioGw3G4cUAE15XlRctY1J3QzOBH9HdUOTDt0mMjBgpWCzh0YVT1Moh2bPXU9Xg==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "16.2.0", + "@angular-eslint/bundled-angular-compiler": "16.3.1", "@typescript-eslint/utils": "5.62.0" }, "peerDependencies": { @@ -481,15 +485,15 @@ } }, "node_modules/@angular/cli": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.9.tgz", - "integrity": "sha512-wkpV/Ni26LUeDmhee2TPXXEq3feEdZMSG8+nkfUK9kqIcxm0IjI1GLPeiVOX7aQobuKNe2cCAFNwsrXWjj+2og==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.10.tgz", + "integrity": "sha512-zDqlD+rXFuYZP169c2v35HkMbkchVCft5sS+VpoCCgYTk2rwxpeYkjJ8DQZztZJZRXQ+EMpkv/TubswmDro2zA==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1602.9", - "@angular-devkit/core": "16.2.9", - "@angular-devkit/schematics": "16.2.9", - "@schematics/angular": "16.2.9", + "@angular-devkit/architect": "0.1602.10", + "@angular-devkit/core": "16.2.10", + "@angular-devkit/schematics": "16.2.10", + "@schematics/angular": "16.2.10", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -752,6 +756,29 @@ "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "node_modules/@awesome-cordova-plugins/android-permissions": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/android-permissions/-/android-permissions-6.4.0.tgz", + "integrity": "sha512-JmJW/WMM9yOeYl3G9C5OIucpgp7E+71qhN1aHPZQSIKivHGRFhZrX/K4lBjKqrIra4dVIV5swCqfQNwCHglLww==", + "dependencies": { + "@types/cordova": "latest" + }, + "peerDependencies": { + "@awesome-cordova-plugins/core": "^6.0.1", + "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0" + } + }, + "node_modules/@awesome-cordova-plugins/core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/core/-/core-6.4.0.tgz", + "integrity": "sha512-06I5JdTgAgKTby+VG+3sQF5+z4RNCEyVl6y7tz2rICx8MURL1biuh3oGGN1rCQQjsuMZcX5siMBr0NF/OHqxLQ==", + "dependencies": { + "@types/cordova": "latest" + }, + "peerDependencies": { + "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -3134,11 +3161,11 @@ "dev": true }, "node_modules/@ionic/angular": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.5.3.tgz", - "integrity": "sha512-LgTF8nNFj0B71E98gPEAP4cbSAnNfpDG82l/FGtozG83nto60wp13rWPtVuqG+xLSZqHgV6vN6d9W+2NfE46SQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.5.4.tgz", + "integrity": "sha512-TmySfb2HgFoZZaIvIyRKXhH68rHg8TMcrtVP/cTPv3NJiGDH3TGvbIdQmUtdjQ+WUqlgwCsuk7rNgSHtrC5F0w==", "dependencies": { - "@ionic/core": "7.5.3", + "@ionic/core": "7.5.4", "ionicons": "^7.0.0", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -3267,11 +3294,11 @@ } }, "node_modules/@ionic/core": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.3.tgz", - "integrity": "sha512-nd4NV6gSgohLvKHGmf+jAcgzI1387eKq3enjBfE574FK/ikl5CeIltv0MBVJr9lz0pNSL/y9m1tdaFg+syASuA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.4.tgz", + "integrity": "sha512-rZbKlcVucRTDOK2Woh4CWPePlsXiUt3G9dCUniduKD7WeiuAk0GzfmoM3WXBvcUpkVTUIOrvKHaqd3JJSWEIzg==", "dependencies": { - "@stencil/core": "^4.6.0", + "@stencil/core": "^4.7.1", "ionicons": "^7.2.1", "tslib": "^2.1.0" } @@ -3348,9 +3375,9 @@ } }, "node_modules/@ionic/utils-subprocess": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.13.tgz", - "integrity": "sha512-wguf0zfmca1UA1uF2kmbr/4jukrizlYlpIdtG1FdEaGrof8d5djdwg+g3jHe5dTR88urUQ3Gw68Yhs242dgGrg==", + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz", + "integrity": "sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==", "dev": true, "dependencies": { "@ionic/utils-array": "2.1.6", @@ -3507,6 +3534,12 @@ "node": ">=8" } }, + "node_modules/@jcesarmobile/ssl-skip": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@jcesarmobile/ssl-skip/-/ssl-skip-0.2.0.tgz", + "integrity": "sha512-hkhOM5+qPm5xzOYcbUODzYTZKyATEM3qixzUL1gJsJckZ5wAUQxyZJFM3hcUANv8fV8cONfX7A+d/DJpzVvM+Q==", + "dev": true + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -3572,9 +3605,9 @@ "dev": true }, "node_modules/@ngtools/webpack": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.9.tgz", - "integrity": "sha512-rOclD7FfT4OSwVA0nDnULbJS6TORJ0+sQiuT2ebaNFErYr3LOm6Zut05tnmzFw8q1cePrILbG+xpnbggNr9Pyw==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.10.tgz", + "integrity": "sha512-XAVn59zP3ztuKDtw92Xc9+64RK4u4c9g8y5GgtjIWeOwgNXl8bYhAo3uTZzrSrOu96DFZGjsmghFab/7/C2pDg==", "dev": true, "engines": { "node": "^16.14.0 || >=18.10.0", @@ -4061,13 +4094,13 @@ } }, "node_modules/@schematics/angular": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.9.tgz", - "integrity": "sha512-uiU2YbZRVHgk1N1DDsek/5CKhfpZ8myJYNJk8eHV5LswnXOP3aqvH23VhneaAgOYwK5fISC7eMG0pLVKMvFfZQ==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.10.tgz", + "integrity": "sha512-PXmoswvN7qknTsXDmEvhZ9UG+awwWnQ/1Jd/eqqQx08iAaAT81OsXj1bN7eSs6tEGBKGjPb6q2xzuiECAdymzg==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.9", - "@angular-devkit/schematics": "16.2.9", + "@angular-devkit/core": "16.2.10", + "@angular-devkit/schematics": "16.2.10", "jsonc-parser": "3.2.0" }, "engines": { @@ -4325,6 +4358,11 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", "dev": true }, + "node_modules/@types/cordova": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-11.0.3.tgz", + "integrity": "sha512-kyuRQ40/NWQVhqGIHq78Ehu2Bf9Mlg0LhmSmis6ZFJK7z933FRfYi8tHe/k/0fB+PGfCf95rJC6TO7dopaFvAg==" + }, "node_modules/@types/cors": { "version": "2.8.16", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", @@ -5656,9 +5694,9 @@ } }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -5681,9 +5719,9 @@ } }, "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", "dev": true, "dependencies": { "dequal": "^2.0.3" @@ -6631,6 +6669,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cordova-plugin-android-permissions": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/cordova-plugin-android-permissions/-/cordova-plugin-android-permissions-1.1.5.tgz", + "integrity": "sha512-oTTV9cCMBqXTCmU+nYRebsP2IQfrtdvl2vYXHjoJgv5NHCIDgY4KFg6kJTcwXQOiymeGXuw0+MTvJJOueAdleA==", + "engines": [ + { + "name": "cordova", + "version": ">=5.0.0" + } + ] + }, "node_modules/core-js-compat": { "version": "3.33.2", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", @@ -10171,9 +10220,9 @@ } }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.1.tgz", - "integrity": "sha512-opCrKqbthmq3SKZ10mFMQG9dk3fTa3quaOLD35kJa5ejwZHd9xAr+kLuziiZz2cG32s4lMZxNdmdcEQnTDP4+g==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" @@ -17326,25 +17375,25 @@ } }, "@angular-devkit/architect": { - "version": "0.1602.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.9.tgz", - "integrity": "sha512-U3vfb/e2sFfg0D9FyyRBXRPP7g4FBFtGK8Q3JPmvAVsHHwi5AUFRNR7YBChB/T5TMNY077HcTyEirVh2FeUpdA==", + "version": "0.1602.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.10.tgz", + "integrity": "sha512-FwemQXh3edqA/S6zPpsqKei5v7gt0R0WpjJoAJaz+FOpfDwij1fwnKr88XINY8xcefTcQaTDQxJZheJShA/hHw==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.9", + "@angular-devkit/core": "16.2.10", "rxjs": "7.8.1" } }, "@angular-devkit/build-angular": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.9.tgz", - "integrity": "sha512-S1C4UYxRVyNt3C0wCxbT2jZ1dN5i37kS0mol3PQjbR8gQ0GQzHmzhjTBl1oImo8aouET9yhrk9etk65oat4mBQ==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.10.tgz", + "integrity": "sha512-msB/qjIsAOySDxdU5DpcX2sWGUEJOFIO03O9+HbtLwf3NDfe74mFfejxuKlHJXIJdgpM2Zc948M6+618QKpUYA==", "dev": true, "requires": { "@ampproject/remapping": "2.2.1", - "@angular-devkit/architect": "0.1602.9", - "@angular-devkit/build-webpack": "0.1602.9", - "@angular-devkit/core": "16.2.9", + "@angular-devkit/architect": "0.1602.10", + "@angular-devkit/build-webpack": "0.1602.10", + "@angular-devkit/core": "16.2.10", "@babel/core": "7.22.9", "@babel/generator": "7.22.9", "@babel/helper-annotate-as-pure": "7.22.5", @@ -17356,7 +17405,7 @@ "@babel/runtime": "7.22.6", "@babel/template": "7.22.5", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "16.2.9", + "@ngtools/webpack": "16.2.10", "@vitejs/plugin-basic-ssl": "1.0.1", "ansi-colors": "4.1.3", "autoprefixer": "10.4.14", @@ -17447,19 +17496,19 @@ } }, "@angular-devkit/build-webpack": { - "version": "0.1602.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.9.tgz", - "integrity": "sha512-+3IxovfBPR2Vy730mGa0SVKkd5LQVom85gjXOs7WcnnnZmfc1q/BtFlqTgW1UWvTxP8IQdm7UYWVclQfL/WExw==", + "version": "0.1602.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.10.tgz", + "integrity": "sha512-H7HiFKbZl/xVxpr1RH05SGawTpA1417wvr2nFGRu2OiePd0lPr6pIhcq8F8gt7JcA8yZKKaqjn2gU+6um2MFLg==", "dev": true, "requires": { - "@angular-devkit/architect": "0.1602.9", + "@angular-devkit/architect": "0.1602.10", "rxjs": "7.8.1" } }, "@angular-devkit/core": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.9.tgz", - "integrity": "sha512-dcHWjHBNGm3yCeNz19y8A1At4KgyC6XHNnbFL0y+nnZYiaESXjUoXJYKASedI6A+Bpl0HNq2URhH6bL6Af3+4w==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.10.tgz", + "integrity": "sha512-eo7suLDjyu5bSlEr4TluYkFm4v2PVLSAPgnau8XHHlN5Yg4P/BZ00ve7LA7C9S1gzRSCrxQhK5ki4rnoFTo5zg==", "dev": true, "requires": { "ajv": "8.12.0", @@ -17471,12 +17520,12 @@ } }, "@angular-devkit/schematics": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.9.tgz", - "integrity": "sha512-lB51CGCILpcSI37CwKUAGDLxMqh7zmuRbiPo9s9mSkCM4ccqxFlaL+VFTq2/laneARD6aikpOHnkVm5myNzQPw==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.10.tgz", + "integrity": "sha512-UCfPJKVNekb21bWRbzyx81tfHN3x8vU4ZMX/VA6xALg//QalMB7NOkkXBAssthnLastkyzkUtlvApTp2+R+EkQ==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.9", + "@angular-devkit/core": "16.2.10", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -17484,9 +17533,9 @@ } }, "@angular-eslint/builder": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.2.0.tgz", - "integrity": "sha512-SZjXOi3YIjuX2CocuRsR2QH6k1ca9lRO6IMm0YIYMmBPFCRP2KFHkL6aQnXM6DSaymQNN2TXfpuvUd45NxhU1w==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.3.1.tgz", + "integrity": "sha512-PmIOnRwqdOW1bvZtpTGBTDcOq/Czm3D+IPC/k90yIMs1VsAtcxqUmUtELje+ylJeb2LPeEZavekSnEpcatM4HQ==", "dev": true, "requires": { "@nx/devkit": "16.5.1", @@ -17494,43 +17543,43 @@ } }, "@angular-eslint/bundled-angular-compiler": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.2.0.tgz", - "integrity": "sha512-ct9orDYxkMl2+uvM7UBfgV28Dq57V4dEs+Drh7cD673JIMa6sXbgmd0QEtm8W3cmyK/jcTzmuoufxbH7hOxd6g==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.3.1.tgz", + "integrity": "sha512-m4WP1xwS9XLcC/3n6lIcG5HZoai/5eb5W3xm48GVcv//0qE2p7S96RSgKPgGHvif5pF8O9xAqEWs3gDEG45+7A==", "dev": true }, "@angular-eslint/eslint-plugin": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.2.0.tgz", - "integrity": "sha512-zdiAIox1T+B71HL+A8m+1jWdU34nvPGLhCRw/uZNwHzknsF4tYzNQ9W7T/SC/g/2s1yT2yNosEVNJSGSFvunJg==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.3.1.tgz", + "integrity": "sha512-kSc8ESfoy8TUSthbq0Lpq9e17I+3Smy4rHoNpKCFEGuJgPs0+OssZMxB6a5EawGbv2EKTPEtrxzFm1WsLR0U9Q==", "dev": true, "requires": { - "@angular-eslint/utils": "16.2.0", + "@angular-eslint/utils": "16.3.1", "@typescript-eslint/utils": "5.62.0" } }, "@angular-eslint/eslint-plugin-template": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.2.0.tgz", - "integrity": "sha512-YFdQ6hHX6NlQj0lfogZwfyKjU8pqkJU+Zsk0ehjlXP8VfKFVmDeQT5/Xr6Df9C8pveC3hvq6Jgd8vo67S9Enxg==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.3.1.tgz", + "integrity": "sha512-+RcFEWqNiRt3+5jXvmlIDlXtP9+vjdmgmVL6tt8yDbqdjBOewtyMu4pE4YaR4sFboyxgME9PbO2WrOyPXh6xjg==", "dev": true, "requires": { - "@angular-eslint/bundled-angular-compiler": "16.2.0", - "@angular-eslint/utils": "16.2.0", + "@angular-eslint/bundled-angular-compiler": "16.3.1", + "@angular-eslint/utils": "16.3.1", "@typescript-eslint/type-utils": "5.62.0", "@typescript-eslint/utils": "5.62.0", "aria-query": "5.3.0", - "axobject-query": "3.2.1" + "axobject-query": "4.0.0" } }, "@angular-eslint/schematics": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.2.0.tgz", - "integrity": "sha512-2JUVR7hAKx37mgWeDjvyWEMH5uSeeksYuaQT5wwlgIzgrO4BNFuqs6Rgyp2jiYa7BFMX/qHULSa+bSq5J5ceEA==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.3.1.tgz", + "integrity": "sha512-cqrdobdtRY2XjLa6PhuGOQ7UhTRk2AvWS01sKeGjZ94nQJm5NUtEUyf6u3deIPYllW7gSAWjYzKUObKcTW/R+g==", "dev": true, "requires": { - "@angular-eslint/eslint-plugin": "16.2.0", - "@angular-eslint/eslint-plugin-template": "16.2.0", + "@angular-eslint/eslint-plugin": "16.3.1", + "@angular-eslint/eslint-plugin-template": "16.3.1", "@nx/devkit": "16.5.1", "ignore": "5.2.4", "nx": "16.5.1", @@ -17539,22 +17588,22 @@ } }, "@angular-eslint/template-parser": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.2.0.tgz", - "integrity": "sha512-v2jVKTy2wN7iM9nHpBkxLn2wfL8jSl4IlPrXThIqj8No2VHtpLQZPKuXbGPUXQX05VS2Mj5feScQ36ZVGS8Rbw==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.3.1.tgz", + "integrity": "sha512-9+SxUtxB2iOnm0ldS2ow0stMxe02rB/TxeMIe8fxsLFHZdw8RQvs/p3HLvVHXzv6gUblMHebIb/ubUmwEVb2SA==", "dev": true, "requires": { - "@angular-eslint/bundled-angular-compiler": "16.2.0", + "@angular-eslint/bundled-angular-compiler": "16.3.1", "eslint-scope": "^7.0.0" } }, "@angular-eslint/utils": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.2.0.tgz", - "integrity": "sha512-NxMRwnlIgzmbJQfWkfd9y3Sz0hzjFdK5LH44i+3D5NhpPdZ6SzwHAjMYWoYsmmNQX5tlDXoicYF9Mz9Wz8DJ/A==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.3.1.tgz", + "integrity": "sha512-tEBcce0rG+DmcPO8jhRffUFDioGw3G4cUAE15XlRctY1J3QzOBH9HdUOTDt0mMjBgpWCzh0YVT1Moh2bPXU9Xg==", "dev": true, "requires": { - "@angular-eslint/bundled-angular-compiler": "16.2.0", + "@angular-eslint/bundled-angular-compiler": "16.3.1", "@typescript-eslint/utils": "5.62.0" } }, @@ -17567,15 +17616,15 @@ } }, "@angular/cli": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.9.tgz", - "integrity": "sha512-wkpV/Ni26LUeDmhee2TPXXEq3feEdZMSG8+nkfUK9kqIcxm0IjI1GLPeiVOX7aQobuKNe2cCAFNwsrXWjj+2og==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.10.tgz", + "integrity": "sha512-zDqlD+rXFuYZP169c2v35HkMbkchVCft5sS+VpoCCgYTk2rwxpeYkjJ8DQZztZJZRXQ+EMpkv/TubswmDro2zA==", "dev": true, "requires": { - "@angular-devkit/architect": "0.1602.9", - "@angular-devkit/core": "16.2.9", - "@angular-devkit/schematics": "16.2.9", - "@schematics/angular": "16.2.9", + "@angular-devkit/architect": "0.1602.10", + "@angular-devkit/core": "16.2.10", + "@angular-devkit/schematics": "16.2.10", + "@schematics/angular": "16.2.10", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -17738,6 +17787,22 @@ "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "@awesome-cordova-plugins/android-permissions": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/android-permissions/-/android-permissions-6.4.0.tgz", + "integrity": "sha512-JmJW/WMM9yOeYl3G9C5OIucpgp7E+71qhN1aHPZQSIKivHGRFhZrX/K4lBjKqrIra4dVIV5swCqfQNwCHglLww==", + "requires": { + "@types/cordova": "latest" + } + }, + "@awesome-cordova-plugins/core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/core/-/core-6.4.0.tgz", + "integrity": "sha512-06I5JdTgAgKTby+VG+3sQF5+z4RNCEyVl6y7tz2rICx8MURL1biuh3oGGN1rCQQjsuMZcX5siMBr0NF/OHqxLQ==", + "requires": { + "@types/cordova": "latest" + } + }, "@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -19330,11 +19395,11 @@ "dev": true }, "@ionic/angular": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.5.3.tgz", - "integrity": "sha512-LgTF8nNFj0B71E98gPEAP4cbSAnNfpDG82l/FGtozG83nto60wp13rWPtVuqG+xLSZqHgV6vN6d9W+2NfE46SQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.5.4.tgz", + "integrity": "sha512-TmySfb2HgFoZZaIvIyRKXhH68rHg8TMcrtVP/cTPv3NJiGDH3TGvbIdQmUtdjQ+WUqlgwCsuk7rNgSHtrC5F0w==", "requires": { - "@ionic/core": "7.5.3", + "@ionic/core": "7.5.4", "ionicons": "^7.0.0", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -19426,11 +19491,11 @@ } }, "@ionic/core": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.3.tgz", - "integrity": "sha512-nd4NV6gSgohLvKHGmf+jAcgzI1387eKq3enjBfE574FK/ikl5CeIltv0MBVJr9lz0pNSL/y9m1tdaFg+syASuA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.5.4.tgz", + "integrity": "sha512-rZbKlcVucRTDOK2Woh4CWPePlsXiUt3G9dCUniduKD7WeiuAk0GzfmoM3WXBvcUpkVTUIOrvKHaqd3JJSWEIzg==", "requires": { - "@stencil/core": "^4.6.0", + "@stencil/core": "^4.7.1", "ionicons": "^7.2.1", "tslib": "^2.1.0" } @@ -19492,9 +19557,9 @@ } }, "@ionic/utils-subprocess": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.13.tgz", - "integrity": "sha512-wguf0zfmca1UA1uF2kmbr/4jukrizlYlpIdtG1FdEaGrof8d5djdwg+g3jHe5dTR88urUQ3Gw68Yhs242dgGrg==", + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz", + "integrity": "sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg==", "dev": true, "requires": { "@ionic/utils-array": "2.1.6", @@ -19608,6 +19673,12 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@jcesarmobile/ssl-skip": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@jcesarmobile/ssl-skip/-/ssl-skip-0.2.0.tgz", + "integrity": "sha512-hkhOM5+qPm5xzOYcbUODzYTZKyATEM3qixzUL1gJsJckZ5wAUQxyZJFM3hcUANv8fV8cONfX7A+d/DJpzVvM+Q==", + "dev": true + }, "@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -19664,9 +19735,9 @@ "dev": true }, "@ngtools/webpack": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.9.tgz", - "integrity": "sha512-rOclD7FfT4OSwVA0nDnULbJS6TORJ0+sQiuT2ebaNFErYr3LOm6Zut05tnmzFw8q1cePrILbG+xpnbggNr9Pyw==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.10.tgz", + "integrity": "sha512-XAVn59zP3ztuKDtw92Xc9+64RK4u4c9g8y5GgtjIWeOwgNXl8bYhAo3uTZzrSrOu96DFZGjsmghFab/7/C2pDg==", "dev": true, "requires": {} }, @@ -19971,13 +20042,13 @@ "optional": true }, "@schematics/angular": { - "version": "16.2.9", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.9.tgz", - "integrity": "sha512-uiU2YbZRVHgk1N1DDsek/5CKhfpZ8myJYNJk8eHV5LswnXOP3aqvH23VhneaAgOYwK5fISC7eMG0pLVKMvFfZQ==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.10.tgz", + "integrity": "sha512-PXmoswvN7qknTsXDmEvhZ9UG+awwWnQ/1Jd/eqqQx08iAaAT81OsXj1bN7eSs6tEGBKGjPb6q2xzuiECAdymzg==", "dev": true, "requires": { - "@angular-devkit/core": "16.2.9", - "@angular-devkit/schematics": "16.2.9", + "@angular-devkit/core": "16.2.10", + "@angular-devkit/schematics": "16.2.10", "jsonc-parser": "3.2.0" } }, @@ -20182,6 +20253,11 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", "dev": true }, + "@types/cordova": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-11.0.3.tgz", + "integrity": "sha512-kyuRQ40/NWQVhqGIHq78Ehu2Bf9Mlg0LhmSmis6ZFJK7z933FRfYi8tHe/k/0fB+PGfCf95rJC6TO7dopaFvAg==" + }, "@types/cors": { "version": "2.8.16", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.16.tgz", @@ -21188,9 +21264,9 @@ "dev": true }, "axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", "dev": true, "requires": { "follow-redirects": "^1.15.0", @@ -21212,9 +21288,9 @@ } }, "axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", "dev": true, "requires": { "dequal": "^2.0.3" @@ -21918,6 +21994,11 @@ } } }, + "cordova-plugin-android-permissions": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/cordova-plugin-android-permissions/-/cordova-plugin-android-permissions-1.1.5.tgz", + "integrity": "sha512-oTTV9cCMBqXTCmU+nYRebsP2IQfrtdvl2vYXHjoJgv5NHCIDgY4KFg6kJTcwXQOiymeGXuw0+MTvJJOueAdleA==" + }, "core-js-compat": { "version": "3.33.2", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", @@ -24580,9 +24661,9 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.1.tgz", - "integrity": "sha512-opCrKqbthmq3SKZ10mFMQG9dk3fTa3quaOLD35kJa5ejwZHd9xAr+kLuziiZz2cG32s4lMZxNdmdcEQnTDP4+g==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true }, "istanbul-lib-instrument": { diff --git a/openvidu-ionic/package.json b/openvidu-ionic/package.json index 65136ec6..93beb762 100644 --- a/openvidu-ionic/package.json +++ b/openvidu-ionic/package.json @@ -4,8 +4,7 @@ "author": "Ionic Framework", "homepage": "https://ionicframework.com/", "scripts": { - "ng": "ng", - "start": "ng serve", + "start": "ionic serve", "build": "ng build", "watch": "ng build --watch --configuration development", "android": "npx ionic capacitor run android", @@ -14,7 +13,8 @@ "build:full": "npm run trapeze && npx ionic capacitor sync", "build:android": "npm run build:full && npx ionic capacitor build android --no-open && cd android && ./gradlew assembleDebug && ./gradlew assembleRelease", "copy:android": "cp ./android/app/build/outputs/apk/debug/app-debug.apk /opt/openvidu/android/openvidu-ionic.apk", - "dev:mobile": "npx ionic cap run android -l --external" + "dev:android": "./scripts/mobile_run.sh android", + "dev:ios": "./scripts/mobile_run.sh ios" }, "private": true, "dependencies": { @@ -26,13 +26,16 @@ "@angular/platform-browser": "^16.0.0", "@angular/platform-browser-dynamic": "^16.0.0", "@angular/router": "^16.0.0", - "@capacitor/android": "5.5.0", + "@awesome-cordova-plugins/android-permissions": "6.4.0", + "@awesome-cordova-plugins/core": "6.4.0", + "@capacitor/android": "5.5.1", "@capacitor/app": "5.0.6", "@capacitor/core": "5.5.0", "@capacitor/haptics": "5.0.6", "@capacitor/keyboard": "5.0.6", "@capacitor/status-bar": "5.0.6", "@ionic/angular": "^7.0.0", + "cordova-plugin-android-permissions": "^1.1.5", "ionicons": "^7.0.0", "livekit-client": "^1.14.4", "rxjs": "~7.8.0", @@ -51,6 +54,7 @@ "@angular/language-service": "^16.0.0", "@capacitor/cli": "5.5.0", "@ionic/angular-toolkit": "^9.0.0", + "@jcesarmobile/ssl-skip": "^0.2.0", "@types/jasmine": "~4.3.0", "@types/node": "^12.11.1", "@typescript-eslint/eslint-plugin": "5.3.0", diff --git a/openvidu-ionic/scripts/mobile_run.sh b/openvidu-ionic/scripts/mobile_run.sh new file mode 100755 index 00000000..f664487f --- /dev/null +++ b/openvidu-ionic/scripts/mobile_run.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Check if an argument is provided +if [ -z "$1" ]; then + echo "Please provide the PLATFORM name." + echo "Example: ./android_run.sh " + exit 1 +fi + +PLATFORM=$1 + +# Getting the operating system +os_name=$(uname) + +case "$os_name" in + "Linux") + # Commands for Linux + LOCAL_IP=$(hostname -I | awk '{print $1}') + ;; + "Darwin") + # Commands for macOS + LOCAL_IP=$(ifconfig | grep "inet " | grep -Fv) + ;; + CYGWIN*|"MINGW32_NT"|"MINGW64_NT") + # Commands for Windows (Cygwin or MinGW) + LOCAL_IP=$(ipconfig | grep "IPv4 Address" | awk '{print $NF}') + ;; + *) + # Unsupported/Unknown OS + echo "Unsupported operating system: $os_name" + exit 1 + ;; +esac + +if [ -z "$LOCAL_IP" ]; then + echo "Cannot get your local IP address." + exit 1 +fi + +echo "Your local ip is $LOCAL_IP" +echo "Setting up your movile environment for developing OpenVidu..." + +# Set environment variables +sed -i "s/\(externalIp:\s*'\)[^']*/\1$LOCAL_IP/" src/environments/environment.ts + +npx ionic cap run $PLATFORM -l --external --disable-host-check --public-host=$LOCAL_IP --ssl + + + diff --git a/openvidu-ionic/src/app/components/ov-video.component.ts b/openvidu-ionic/src/app/components/ov-video.component.ts index ed329ddd..95082cb1 100644 --- a/openvidu-ionic/src/app/components/ov-video.component.ts +++ b/openvidu-ionic/src/app/components/ov-video.component.ts @@ -9,10 +9,10 @@ import { LocalVideoTrack, RemoteVideoTrack } from 'livekit-client'; @Component({ selector: 'ov-video', - template: '', + template: '', }) export class OpenViduVideoComponent implements AfterViewInit { - @ViewChild('videoElement') elementRef!: ElementRef; + @ViewChild('videoElement') elementRef!: ElementRef; _track!: LocalVideoTrack | RemoteVideoTrack; diff --git a/openvidu-ionic/src/app/home/home.module.ts b/openvidu-ionic/src/app/home/home.module.ts index e1de79ed..9788f3a8 100644 --- a/openvidu-ionic/src/app/home/home.module.ts +++ b/openvidu-ionic/src/app/home/home.module.ts @@ -8,6 +8,7 @@ import { HomePageRoutingModule } from './home-routing.module'; import { HttpClientModule } from '@angular/common/http'; import { OpenViduVideoComponent } from '../components/ov-video.component'; import { OpenViduAudioComponent } from '../components/ov-audio.component'; +import { AndroidPermissions } from '@awesome-cordova-plugins/android-permissions/ngx'; @NgModule({ @@ -19,5 +20,8 @@ import { OpenViduAudioComponent } from '../components/ov-audio.component'; HttpClientModule, ], declarations: [HomePage, OpenViduVideoComponent, OpenViduAudioComponent], + providers: [ + AndroidPermissions, + ], }) export class HomePageModule {} diff --git a/openvidu-ionic/src/app/home/home.page.html b/openvidu-ionic/src/app/home/home.page.html index 4022d4f9..10b0d150 100644 --- a/openvidu-ionic/src/app/home/home.page.html +++ b/openvidu-ionic/src/app/home/home.page.html @@ -59,37 +59,46 @@ - -
-
-

- {{ getParticipantName(localPublication.trackSid) }} -

- -
- -
-

- {{ getParticipantName(publication.trackSid) }} -

- - -
+ +
+

{{ myRoomName }}

+ + + +
+

+ {{ getParticipantName(localPublication.trackSid) }} +

+ +
+
+ + +

+ {{ getParticipantName(publication.trackSid) }} +

+ + +
+
+
+ p { background-color: #d8ffbd; } +::ng-deep video { + width: 100%; + height: 100%; + object-fit: cover; +} + .hidden { display: none; } + + +/* Hide the default video controls */ +::ng-deep video::-webkit-media-controls { + display: none; /* For Safari and Chrome */ +} + +::ng-deep video::-webkit-media-controls-panel { + display: none; /* For newer versions of Safari */ +} + +::ng-deep video::-webkit-media-controls-play-button { + display: none; /* For Safari Play button */ +} + +::ng-deep video::-webkit-media-controls-start-playback-button { + display: none; /* For Safari Start Playback button */ +} diff --git a/openvidu-ionic/src/app/home/home.page.ts b/openvidu-ionic/src/app/home/home.page.ts index 8a411fc1..c1616e37 100644 --- a/openvidu-ionic/src/app/home/home.page.ts +++ b/openvidu-ionic/src/app/home/home.page.ts @@ -6,10 +6,13 @@ import { RemoteTrackPublication, Room, RoomEvent, + TrackPublishOptions, } from 'livekit-client'; import { HttpClient } from '@angular/common/http'; import { AlertController, Platform } from '@ionic/angular'; import { lastValueFrom, take } from 'rxjs'; +import { AndroidPermissions } from '@awesome-cordova-plugins/android-permissions/ngx'; +import { environment } from 'src/environments/environment'; @Component({ selector: 'app-home', @@ -36,25 +39,32 @@ export class HomePage { private cameraSelected!: MediaDeviceInfo; private isFrontCamera: boolean = false; + ANDROID_PERMISSIONS = [ + this.androidPermissions.PERMISSION.CAMERA, + this.androidPermissions.PERMISSION.RECORD_AUDIO, + this.androidPermissions.PERMISSION.MODIFY_AUDIO_SETTINGS, + ]; + constructor( private httpClient: HttpClient, private alertController: AlertController, - private platform: Platform + private platform: Platform, + private androidPermissions: AndroidPermissions ) { this.generateParticipantInfo(); - // WARNING!! To make easier first steps with mobile devices, this code allows - // using the demos OpenVidu deployment when no custom deployment is provided - // if ( - // this.platform.is('hybrid') && - // this.APPLICATION_SERVER_URL === 'http://localhost:5000/' - // ) { - // /** - // * WARNING: this APPLICATION_SERVER_URL is not secure and is only meant for a first quick test. - // * Anyone could access your video rooms. You should modify the APPLICATION_SERVER_URL to a custom private one. - // */ - // this.APPLICATION_SERVER_URL = 'https://call.next.openvidu.io/'; - // } + // WARNING!! To make the mobile development easier, this code allows + // using your local IP address for communicating with the backend. + // For production uses, the server should be accessible from the Internet + if (this.platform.is('hybrid')) { + if (environment.externalIp) { + console.warn('Your local IP address: ', environment.externalIp); + this.APPLICATION_SERVER_URL = this.APPLICATION_SERVER_URL.replace( + 'localhost', + environment.externalIp + ); + } + } } @HostListener('window:beforeunload') @@ -103,17 +113,29 @@ export class HomePage { this.myRoomName, this.myParticipantName ); - const livekitUrl = this.getLivekitUrlFromMetadata(token); + + let livekitUrl = this.getLivekitUrlFromMetadata(token); + + if (environment.externalIp) { + // WARNING!! To make the mobile development easier, this code allows + // using your local IP address for communicating with the backend. + // For production uses, the server should be accessible from the Internet + livekitUrl = livekitUrl.replace('localhost', environment.externalIp); + } + // First param is the LiveKit server URL. Second param is the access token await this.room.connect(livekitUrl, token); // --- 5) Requesting and Checking Android Permissions if (this.platform.is('hybrid') && this.platform.is('android')) { - console.log('Ionic Android platform'); await this.checkAndroidPermissions(); } + const publishOptions: TrackPublishOptions = { + stream: 'test', + }; + const [audioPublication, videoPublication] = await Promise.all([ this.room.localParticipant.setMicrophoneEnabled(true), this.room.localParticipant.setCameraEnabled(true), @@ -121,6 +143,7 @@ export class HomePage { // Set the main video in the page to display our webcam and store our localPublication this.localPublication = videoPublication; + this.refreshVideos(); await this.initDevices(); } catch (error: any) { console.log( @@ -185,7 +208,13 @@ export class HomePage { async toggleCamera() { if (this.room) { const enabled = !this.room.localParticipant.isCameraEnabled; + // const options: VideoCaptureOptions = {}; + // const publishOptions: TrackPublishOptions = { + // stream: 'test', + // }; + await this.room.localParticipant.setCameraEnabled(enabled); + this.refreshVideos(); this.cameraIcon = enabled ? 'videocam' : 'eye-off'; } } @@ -193,7 +222,14 @@ export class HomePage { async toggleMicrophone() { if (this.room) { const enabled = !this.room.localParticipant.isMicrophoneEnabled; - await this.room.localParticipant.setMicrophoneEnabled(enabled); + const publishOptions: TrackPublishOptions = { + stream: 'test', + }; + await this.room.localParticipant.setMicrophoneEnabled( + enabled, + undefined, + publishOptions + ); this.microphoneIcon = enabled ? 'mic' : 'mic-off'; } } @@ -207,6 +243,8 @@ export class HomePage { if (newCamera && this.room) { await this.room.switchActiveDevice('videoinput', newCamera.deviceId); this.cameraSelected = newCamera; + + this.refreshVideos(); } } catch (error) { console.error(error); @@ -245,9 +283,43 @@ export class HomePage { await alert.present(); } + private refreshVideos() { + // setTimeout(() => { + // console.warn('track restarted: UPDATED DOM'); + // const refreshedElement = document.getElementById('refreshed-workaround'); + // if (refreshedElement) { + // refreshedElement.remove(); + // } else { + // const p = document.createElement('p'); + // p.id = 'refreshed-workaround'; + // document.getElementById('room')?.appendChild(p); + // } + // }, 200); + } + private async checkAndroidPermissions(): Promise { await this.platform.ready(); - //TODO: Implement Android permissions + try { + await this.androidPermissions.requestPermissions( + this.ANDROID_PERMISSIONS + ); + const promisesArray: Promise[] = []; + this.ANDROID_PERMISSIONS.forEach((permission) => { + console.log('Checking ', permission); + promisesArray.push(this.androidPermissions.checkPermission(permission)); + }); + const responses = await Promise.all(promisesArray); + let allHasPermissions = true; + responses.forEach((response, i) => { + allHasPermissions = response.hasPermission; + if (!allHasPermissions) { + throw new Error('Permissions denied: ' + this.ANDROID_PERMISSIONS[i]); + } + }); + } catch (error) { + console.error('Error requesting or checking permissions: ', error); + throw error; + } } private async initDevices() { diff --git a/openvidu-ionic/src/assets/images/video-poster.png b/openvidu-ionic/src/assets/images/video-poster.png new file mode 100644 index 00000000..60de08e4 Binary files /dev/null and b/openvidu-ionic/src/assets/images/video-poster.png differ diff --git a/openvidu-ionic/src/environments/environment.prod.ts b/openvidu-ionic/src/environments/environment.prod.ts index 3612073b..ebf651ab 100644 --- a/openvidu-ionic/src/environments/environment.prod.ts +++ b/openvidu-ionic/src/environments/environment.prod.ts @@ -1,3 +1,5 @@ export const environment = { - production: true + production: true, + // Only for local development with a real device. This will be filled automatically running 'npm dev:android' or 'npm dev:ios' + externalIp: '' }; diff --git a/openvidu-ionic/src/environments/environment.ts b/openvidu-ionic/src/environments/environment.ts index f56ff470..bcdf903c 100644 --- a/openvidu-ionic/src/environments/environment.ts +++ b/openvidu-ionic/src/environments/environment.ts @@ -3,14 +3,7 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, + // Only for local development with a real device. This will be filled automatically running 'npm dev:android' or 'npm dev:ios' + externalIp: '192.168.1.46' }; - -/* - * For easier debugging in development mode, you can import the following file - * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. - * - * This import should be commented out in production mode because it will have a negative impact - * on performance if an error is thrown. - */ -// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.