diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 6bfddddf9..a446272ef 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; + 775D86C92BEA01B700806515 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 775D86C82BEA01B700806515 /* PrivacyInfo.xcprivacy */; }; A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; }; DE095D00277AF00900242276 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DE095CFF277AF00900242276 /* GoogleService-Info.plist */; }; DE28999027B790A900F6581C /* public in Resources */ = {isa = PBXBuildFile; fileRef = DE28998F27B790A900F6581C /* public */; }; @@ -30,6 +31,7 @@ 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 775D86C82BEA01B700806515 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; DE095CFF277AF00900242276 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -65,6 +67,7 @@ 504EC2FB1FED79650016851F = { isa = PBXGroup; children = ( + 775D86C82BEA01B700806515 /* PrivacyInfo.xcprivacy */, DE2706742854C3960046512E /* Configuration.storekit */, 504EC3061FED79650016851F /* App */, 504EC3051FED79650016851F /* Products */, @@ -175,6 +178,7 @@ 504EC30D1FED79650016851F /* Main.storyboard in Resources */, 2FAD9763203C412B000D30F8 /* config.xml in Resources */, DE095D00277AF00900242276 /* GoogleService-Info.plist in Resources */, + 775D86C92BEA01B700806515 /* PrivacyInfo.xcprivacy in Resources */, DE28999027B790A900F6581C /* public in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index 4a76e5872..e3e0ae263 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -5,7 +5,7 @@ PODS: - AppsFlyerFramework (6.12.1): - AppsFlyerFramework/Main (= 6.12.1) - AppsFlyerFramework/Main (6.12.1) - - Capacitor (5.0.5): + - Capacitor (5.7.5): - CapacitorCordova - CapacitorApp (5.0.3): - Capacitor @@ -26,7 +26,7 @@ PODS: - Capacitor - CapacitorCommunityWifi (0.0.1): - Capacitor - - CapacitorCordova (5.0.5) + - CapacitorCordova (5.7.5) - CapacitorDevice (5.0.4): - Capacitor - CapacitorFilesystem (5.0.4): @@ -47,7 +47,7 @@ PODS: - Capacitor - CapacitorStorage (1.2.4): - Capacitor - - CordovaPlugins (5.0.5): + - CordovaPlugins (5.7.5): - CapacitorCordova - Firebase/CoreOnly (10.14.0): - FirebaseCore (= 10.14.0) @@ -212,7 +212,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: AppsflyerCapacitorPlugin: 0094cd9f754091410f30237ab7f21b2604db12f5 AppsFlyerFramework: e29b63fc5441400a38a31c5501c1da500b9d53d0 - Capacitor: b1248915663add1bd6567e2b67c1c1fa3abcf5e8 + Capacitor: 7d42085cb786b2d3ea9ac8a17ebd7e3305be7b72 CapacitorApp: 7a5dec8b33573707164b293475d5c89ba684364a CapacitorBlobWriter: 110eeaf80611f19bf01a8a05ff3672149ed0baad CapacitorBrowser: 2688852d02f1e89560a31b70521c71a5e7348860 @@ -222,7 +222,7 @@ SPEC CHECKSUMS: CapacitorCommunityBluetoothLe: 7de4f21022a05b15195abfb002872884d00715fc CapacitorCommunityHttp: 7be90668527ef14ee10d08135b0e00fac9cf8247 CapacitorCommunityWifi: 47188c74f2c6bcaefb619380863be8c67b1917c8 - CapacitorCordova: f8c06b897c74ee8f7701fe10e6443b40822bc83a + CapacitorCordova: c946a6052b547e1e185fc46862003f7b9130ead1 CapacitorDevice: eb4b5e3b42ac35d2527f20aad296b59e0785dc8d CapacitorFilesystem: e1bdfab09b95b181c844c16abcfda45ec8e8ed6b CapacitorGeolocation: 33015be1ef496585a60da9efa1c5642ff8624db3 @@ -233,7 +233,7 @@ SPEC CHECKSUMS: CapacitorShare: 427bba238a1e3f116b2b349019aec6ea7f42cebd CapacitorSplashScreen: 93a389d4f7673c08214ae25bb6f21d867d5305c5 CapacitorStorage: 8ec2cf8fec179d829288b16c6fba6c3c43d2bdc9 - CordovaPlugins: c905b3b4dfc87d2a11bdbdaf396289c4a22c39dd + CordovaPlugins: 99eaff153de2b294dcca53aa61ca5b9eb3b31043 Firebase: 6c1bf3f534bc422d52af2e41fe0d50bf08b6b773 FirebaseCore: 6fc17ac9f03509d51c131298aacb3ee5698b4f02 FirebaseCoreInternal: d558159ee6cc4b823c2296ecc193de9f6d9a5bb3 diff --git a/ios/App/PrivacyInfo.xcprivacy b/ios/App/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..fe840a043 --- /dev/null +++ b/ios/App/PrivacyInfo.xcprivacy @@ -0,0 +1,17 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + + diff --git a/package-lock.json b/package-lock.json index c7b92cddc..1080f93b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,16 +23,16 @@ "@capacitor-community/bluetooth-le": "^2.2.3", "@capacitor-community/http": "github:numbersprotocol/http#fix-catch-disabled-Local-Network-case-on-iOS", "@capacitor-community/wifi": "github:numbersprotocol/community-capacitor-wifi#capacitor3", - "@capacitor/android": "^5.0.5", + "@capacitor/android": "5.7.5", "@capacitor/app": "^5.0.3", "@capacitor/browser": "^5.0.3", "@capacitor/camera": "^5.0.4", "@capacitor/clipboard": "^5.0.4", - "@capacitor/core": "^5.0.5", + "@capacitor/core": "5.7.5", "@capacitor/device": "^5.0.4", - "@capacitor/filesystem": "^5.0.4", + "@capacitor/filesystem": "5.1.1", "@capacitor/geolocation": "^5.0.4", - "@capacitor/ios": "^5.0.5", + "@capacitor/ios": "5.7.5", "@capacitor/local-notifications": "^5.0.6", "@capacitor/network": "^5.0.4", "@capacitor/push-notifications": "^5.0.6", @@ -67,6 +67,7 @@ "immutable": "^4.0.0-rc.14", "lodash-es": "^4.17.21", "material-design-icons-iconfont": "^6.1.0", + "mime-types": "2.1.35", "ng-circle-progress": "^1.6.0", "ngx-joyride": "^2.5.0", "ngx-long-press2": "^2.0.0", @@ -92,12 +93,13 @@ "@angular/compiler": "^14.2.0", "@angular/compiler-cli": "^14.2.0", "@angular/language-service": "^14.2.0", - "@capacitor/cli": "^5.0.5", + "@capacitor/cli": "5.7.5", "@ionic/angular-toolkit": "^4.0.0", "@types/hammerjs": "^2.0.41", "@types/jasmine": "^3.8.2", "@types/jasminewd2": "^2.0.10", "@types/lodash-es": "^4.17.4", + "@types/mime-types": "2.1.4", "@types/node": "^16.7.10", "@typescript-eslint/eslint-plugin": "^5.29.0", "@typescript-eslint/parser": "^5.36.2", @@ -3207,11 +3209,11 @@ } }, "node_modules/@capacitor/android": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-5.0.5.tgz", - "integrity": "sha512-vH5Qoy+p2Egsu1GtPtOsihHcEI2fCGCIHwlUGPaXXGysudzpzWtJZ5JZNlycJyfRdjECrjkutgbNaHLog+YlXQ==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-5.7.5.tgz", + "integrity": "sha512-VKb9VarGA2hJ8PuLk4EhSq4jvgM+V8JOoNw00WdD6Q4rbgDKSa7WIKTw75sFrNRGiwHSZ99FPvmisJfr1Spk+Q==", "peerDependencies": { - "@capacitor/core": "^5.0.0" + "@capacitor/core": "^5.7.0" } }, "node_modules/@capacitor/app": { @@ -3239,9 +3241,9 @@ } }, "node_modules/@capacitor/cli": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-5.0.5.tgz", - "integrity": "sha512-Mf+lr2L98NfDZki3e5jdG176LUH0rf+OFoMa/oFf6dp4iHwQjS1HiHN5iaGcfJ5RWt432SMEB0dOgicXPb4KCQ==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-5.7.5.tgz", + "integrity": "sha512-CEgCXq3NNacS+9EptJXM+Cm915oB8eNPhiTP7ylKsQchrY0CGbeyO5y4A/oYnB/h4f+UiaX3ShlIOljx3+agqw==", "dev": true, "dependencies": { "@ionic/cli-framework-output": "^2.2.5", @@ -3252,7 +3254,7 @@ "debug": "^4.3.4", "env-paths": "^2.2.0", "kleur": "^4.1.4", - "native-run": "^1.7.2", + "native-run": "^2.0.0", "open": "^8.4.0", "plist": "^3.0.5", "prompts": "^2.4.2", @@ -3379,9 +3381,9 @@ } }, "node_modules/@capacitor/core": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.0.5.tgz", - "integrity": "sha512-sulwWXEhYI6cBIj1WnH9k+a8z1f4XTRDtdh3YfXNdeV36UT7T55GCeGrPoQMm7ww6iWyGuv1VEzVIuZFga8rtw==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.5.tgz", + "integrity": "sha512-babBo26lgIyKkAOr/AbPq5wwi9I4uHDP0lBteJq7p4xZElA6tAA8mD3xRH1/4EKmZ4+acYpKmmyegX3zsVh37A==", "dependencies": { "tslib": "^2.1.0" } @@ -3395,11 +3397,11 @@ } }, "node_modules/@capacitor/filesystem": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-5.0.4.tgz", - "integrity": "sha512-dsmy8Hz19+SMI5hwTzHto3TXT3ckbgCJ5kfI4oel73yyn3G7zjdKZuHoZRINoX1BbFNSZryzpbMQ69lSOLCpnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-5.1.1.tgz", + "integrity": "sha512-wq55joyYocsYI0f0UNoDE9TPxI0n4fx+PmejGR5JOYFzrnU8DqcSJ9EREAYAkkoOrmQHrB1vuN9F79XC0PuADw==", "peerDependencies": { - "@capacitor/core": "^5.0.0" + "@capacitor/core": "^5.1.1" } }, "node_modules/@capacitor/geolocation": { @@ -3411,11 +3413,11 @@ } }, "node_modules/@capacitor/ios": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-5.0.5.tgz", - "integrity": "sha512-U72TPbKN1HlUqEGCOPsCBp6j93Qu1TazWUuA8Q1yfcGDfSOE0zMDNl3eU7XO5OyzpV7z9lf8NJdehimezVl7sA==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-5.7.5.tgz", + "integrity": "sha512-mREcvv4XC9USSAbYmf/2Lmbr52eZjMDpKYwxwi2CKLJXGXNjYfJaHm6jnPordAl6kZdm3Bm/tnx+rYpb9KptGA==", "peerDependencies": { - "@capacitor/core": "^5.0.0" + "@capacitor/core": "^5.7.0" } }, "node_modules/@capacitor/local-notifications": { @@ -5621,6 +5623,12 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", "dev": true }, + "node_modules/@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", @@ -6355,6 +6363,15 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -7148,9 +7165,9 @@ } }, "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "dev": true, "engines": { "node": ">=0.6" @@ -15509,37 +15526,164 @@ } }, "node_modules/native-run": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/native-run/-/native-run-1.7.2.tgz", - "integrity": "sha512-2aahC8iXIO8BcvEukVMrYwL5sXurkuIGyQgfSGBto832W6ejV+cB5Ww+2/CRxmyozhbxARJ2OMpEGPV8sTqsrQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.1.tgz", + "integrity": "sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==", "dev": true, "dependencies": { - "@ionic/utils-fs": "^3.1.6", - "@ionic/utils-terminal": "^2.3.3", + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", "bplist-parser": "^0.3.2", "debug": "^4.3.4", "elementtree": "^0.1.7", - "ini": "^3.0.1", - "plist": "^3.0.6", - "split2": "^4.1.0", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", "through2": "^4.0.2", - "tslib": "^2.4.0", + "tslib": "^2.6.2", "yauzl": "^2.10.0" }, "bin": { "native-run": "bin/native-run" }, "engines": { - "node": ">=12.13.0" + "node": ">=16.0.0" + } + }, + "node_modules/native-run/node_modules/@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/native-run/node_modules/@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "dev": true, + "dependencies": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/native-run/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/native-run/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/native-run/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/native-run/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, "node_modules/native-run/node_modules/ini": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", - "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/native-run/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/native-run/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/native-run/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/native-run/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" } }, "node_modules/natural-compare": { @@ -17337,16 +17481,17 @@ } }, "node_modules/plist": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz", - "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "dependencies": { + "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" }, "engines": { - "node": ">=6" + "node": ">=10.4.0" } }, "node_modules/pngjs": { @@ -26288,9 +26433,9 @@ } }, "@capacitor/android": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-5.0.5.tgz", - "integrity": "sha512-vH5Qoy+p2Egsu1GtPtOsihHcEI2fCGCIHwlUGPaXXGysudzpzWtJZ5JZNlycJyfRdjECrjkutgbNaHLog+YlXQ==" + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-5.7.5.tgz", + "integrity": "sha512-VKb9VarGA2hJ8PuLk4EhSq4jvgM+V8JOoNw00WdD6Q4rbgDKSa7WIKTw75sFrNRGiwHSZ99FPvmisJfr1Spk+Q==" }, "@capacitor/app": { "version": "5.0.3", @@ -26308,9 +26453,9 @@ "integrity": "sha512-Sl4PpoRv/FahCTugjyCZQ8MMH9Tgh5ySr8ZqY59mFKReoCu7xKnp9Ue8D8mzR9nE08gRiUBMqtl5FJbJR2f+Yg==" }, "@capacitor/cli": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-5.0.5.tgz", - "integrity": "sha512-Mf+lr2L98NfDZki3e5jdG176LUH0rf+OFoMa/oFf6dp4iHwQjS1HiHN5iaGcfJ5RWt432SMEB0dOgicXPb4KCQ==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/cli/-/cli-5.7.5.tgz", + "integrity": "sha512-CEgCXq3NNacS+9EptJXM+Cm915oB8eNPhiTP7ylKsQchrY0CGbeyO5y4A/oYnB/h4f+UiaX3ShlIOljx3+agqw==", "dev": true, "requires": { "@ionic/cli-framework-output": "^2.2.5", @@ -26321,7 +26466,7 @@ "debug": "^4.3.4", "env-paths": "^2.2.0", "kleur": "^4.1.4", - "native-run": "^1.7.2", + "native-run": "^2.0.0", "open": "^8.4.0", "plist": "^3.0.5", "prompts": "^2.4.2", @@ -26407,9 +26552,9 @@ "integrity": "sha512-x15Vdq8h5eh6iSYzrdwQXjtlbRe8kNWDOG9HtGGa8xlKoqDECYS7VqFhrZUXJpJpjWDUDqIwF9JpcSoLRHiHbg==" }, "@capacitor/core": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.0.5.tgz", - "integrity": "sha512-sulwWXEhYI6cBIj1WnH9k+a8z1f4XTRDtdh3YfXNdeV36UT7T55GCeGrPoQMm7ww6iWyGuv1VEzVIuZFga8rtw==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.5.tgz", + "integrity": "sha512-babBo26lgIyKkAOr/AbPq5wwi9I4uHDP0lBteJq7p4xZElA6tAA8mD3xRH1/4EKmZ4+acYpKmmyegX3zsVh37A==", "requires": { "tslib": "^2.1.0" } @@ -26420,9 +26565,9 @@ "integrity": "sha512-Zt2eCPfT4oh/VYWURhixj/cRjgpEFD+HgPoldzL9N88ugraqq13p/RKEhUGJ6/tCFVwflVRC5984NsAotm25Jw==" }, "@capacitor/filesystem": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-5.0.4.tgz", - "integrity": "sha512-dsmy8Hz19+SMI5hwTzHto3TXT3ckbgCJ5kfI4oel73yyn3G7zjdKZuHoZRINoX1BbFNSZryzpbMQ69lSOLCpnQ==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-5.1.1.tgz", + "integrity": "sha512-wq55joyYocsYI0f0UNoDE9TPxI0n4fx+PmejGR5JOYFzrnU8DqcSJ9EREAYAkkoOrmQHrB1vuN9F79XC0PuADw==" }, "@capacitor/geolocation": { "version": "5.0.4", @@ -26430,9 +26575,9 @@ "integrity": "sha512-/WXiLBY4hxigWMQp/i/BcFLwGSGVNcnPX4M0tNI11bfUsO6DJ0/dMsSw2xn8a7QxEsKmVUYE5UeOOZNLeUiLHg==" }, "@capacitor/ios": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-5.0.5.tgz", - "integrity": "sha512-U72TPbKN1HlUqEGCOPsCBp6j93Qu1TazWUuA8Q1yfcGDfSOE0zMDNl3eU7XO5OyzpV7z9lf8NJdehimezVl7sA==" + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-5.7.5.tgz", + "integrity": "sha512-mREcvv4XC9USSAbYmf/2Lmbr52eZjMDpKYwxwi2CKLJXGXNjYfJaHm6jnPordAl6kZdm3Bm/tnx+rYpb9KptGA==" }, "@capacitor/local-notifications": { "version": "5.0.6", @@ -27992,6 +28137,12 @@ "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", "dev": true }, + "@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", + "dev": true + }, "@types/minimist": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", @@ -28534,6 +28685,12 @@ "@xtuc/long": "4.2.2" } }, + "@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -29135,9 +29292,9 @@ } }, "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "dev": true }, "big.js": { @@ -35456,28 +35613,126 @@ "dev": true }, "native-run": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/native-run/-/native-run-1.7.2.tgz", - "integrity": "sha512-2aahC8iXIO8BcvEukVMrYwL5sXurkuIGyQgfSGBto832W6ejV+cB5Ww+2/CRxmyozhbxARJ2OMpEGPV8sTqsrQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.1.tgz", + "integrity": "sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==", "dev": true, "requires": { - "@ionic/utils-fs": "^3.1.6", - "@ionic/utils-terminal": "^2.3.3", + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", "bplist-parser": "^0.3.2", "debug": "^4.3.4", "elementtree": "^0.1.7", - "ini": "^3.0.1", - "plist": "^3.0.6", - "split2": "^4.1.0", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", "through2": "^4.0.2", - "tslib": "^2.4.0", + "tslib": "^2.6.2", "yauzl": "^2.10.0" }, "dependencies": { + "@ionic/utils-fs": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-3.1.7.tgz", + "integrity": "sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA==", + "dev": true, + "requires": { + "@types/fs-extra": "^8.0.0", + "debug": "^4.0.0", + "fs-extra": "^9.0.0", + "tslib": "^2.0.1" + } + }, + "@ionic/utils-terminal": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz", + "integrity": "sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A==", + "dev": true, + "requires": { + "@types/slice-ansi": "^4.0.0", + "debug": "^4.0.0", + "signal-exit": "^3.0.3", + "slice-ansi": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "tslib": "^2.0.1", + "untildify": "^4.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "ini": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", - "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true } } @@ -36708,11 +36963,12 @@ } }, "plist": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz", - "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "requires": { + "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } diff --git a/package.json b/package.json index 539683683..79602780a 100644 --- a/package.json +++ b/package.json @@ -34,16 +34,16 @@ "@capacitor-community/bluetooth-le": "^2.2.3", "@capacitor-community/http": "github:numbersprotocol/http#fix-catch-disabled-Local-Network-case-on-iOS", "@capacitor-community/wifi": "github:numbersprotocol/community-capacitor-wifi#capacitor3", - "@capacitor/android": "^5.0.5", + "@capacitor/android": "5.7.5", "@capacitor/app": "^5.0.3", "@capacitor/browser": "^5.0.3", "@capacitor/camera": "^5.0.4", "@capacitor/clipboard": "^5.0.4", - "@capacitor/core": "^5.0.5", + "@capacitor/core": "5.7.5", "@capacitor/device": "^5.0.4", - "@capacitor/filesystem": "^5.0.4", + "@capacitor/filesystem": "5.1.1", "@capacitor/geolocation": "^5.0.4", - "@capacitor/ios": "^5.0.5", + "@capacitor/ios": "5.7.5", "@capacitor/local-notifications": "^5.0.6", "@capacitor/network": "^5.0.4", "@capacitor/push-notifications": "^5.0.6", @@ -78,6 +78,7 @@ "immutable": "^4.0.0-rc.14", "lodash-es": "^4.17.21", "material-design-icons-iconfont": "^6.1.0", + "mime-types": "2.1.35", "ng-circle-progress": "^1.6.0", "ngx-joyride": "^2.5.0", "ngx-long-press2": "^2.0.0", @@ -104,12 +105,13 @@ "@angular/compiler": "^14.2.0", "@angular/compiler-cli": "^14.2.0", "@angular/language-service": "^14.2.0", - "@capacitor/cli": "^5.0.5", + "@capacitor/cli": "5.7.5", "@ionic/angular-toolkit": "^4.0.0", "@types/hammerjs": "^2.0.41", "@types/jasmine": "^3.8.2", "@types/jasminewd2": "^2.0.10", "@types/lodash-es": "^4.17.4", + "@types/mime-types": "2.1.4", "@types/node": "^16.7.10", "@typescript-eslint/eslint-plugin": "^5.29.0", "@typescript-eslint/parser": "^5.36.2", @@ -148,6 +150,7 @@ "os": false, "http": false, "https": false, + "path": false, "stream": false } } diff --git a/src/app/features/home/details/details.page.ts b/src/app/features/home/details/details.page.ts index 6fac0f2f9..9bf08afe7 100644 --- a/src/app/features/home/details/details.page.ts +++ b/src/app/features/home/details/details.page.ts @@ -6,11 +6,21 @@ import { DomSanitizer } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; import { Browser } from '@capacitor/browser'; import { Clipboard } from '@capacitor/clipboard'; +import { Directory, Filesystem } from '@capacitor/filesystem'; import { ActionSheetController, AlertController } from '@ionic/angular'; import { ActionSheetButton } from '@ionic/core'; import { TranslocoService } from '@ngneat/transloco'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; -import { EMPTY, Observable, ReplaySubject, combineLatest, defer } from 'rxjs'; +import { extension } from 'mime-types'; +import { + EMPTY, + Observable, + ReplaySubject, + Subject, + combineLatest, + defer, + of, +} from 'rxjs'; import { catchError, concatMap, @@ -20,6 +30,7 @@ import { map, pluck, switchMap, + takeUntil, tap, } from 'rxjs/operators'; import SwiperCore, { Swiper, Virtual } from 'swiper'; @@ -27,7 +38,10 @@ import { BlockingActionService } from '../../../shared/blocking-action/blocking- import { CaptureAppWebCryptoApiSignatureProvider } from '../../../shared/collector/signature/capture-app-web-crypto-api-signature-provider/capture-app-web-crypto-api-signature-provider.service'; import { ConfirmAlert } from '../../../shared/confirm-alert/confirm-alert.service'; import { ContactSelectionDialogComponent } from '../../../shared/contact-selection-dialog/contact-selection-dialog.component'; -import { DiaBackendAssetRepository } from '../../../shared/dia-backend/asset/dia-backend-asset-repository.service'; +import { + DiaBackendAsset, + DiaBackendAssetRepository, +} from '../../../shared/dia-backend/asset/dia-backend-asset-repository.service'; import { DiaBackendAuthService } from '../../../shared/dia-backend/auth/dia-backend-auth.service'; import { BUBBLE_IFRAME_URL } from '../../../shared/dia-backend/secret'; import { DiaBackendStoreService } from '../../../shared/dia-backend/store/dia-backend-store.service'; @@ -39,11 +53,13 @@ import { NetworkService } from '../../../shared/network/network.service'; import { ProofRepository } from '../../../shared/repositories/proof/proof-repository.service'; import { ShareService } from '../../../shared/share/share.service'; import { UserGuideService } from '../../../shared/user-guide/user-guide.service'; +import { MimeType } from '../../../utils/mime-type'; import { VOID$, isNonNullable, switchTap, } from '../../../utils/rx-operators/rx-operators'; +import { getAssetProfileForNSE } from '../../../utils/url'; import { DetailedCapture, InformationSessionService, @@ -174,6 +190,8 @@ export class DetailsPage { 1 ); + private readonly shareMenuDismissed$ = new Subject(); + readonly activeDetailedCapture$ = this._activeDetailedCapture$.pipe( distinctUntilChanged(), tap( @@ -248,6 +266,31 @@ export class DetailsPage { .subscribe(); } + private static isSupportC2paDownloadFormat(mimeType: MimeType) { + // https://github.com/contentauth/c2patool?tab=readme-ov-file#supported-file-formats + return [ + 'video/msvideo', + 'video/avi', + 'application-msvideo', // avi + 'image/avif', // avif + 'application/x-c2pa-manifest-store', // c2pa + 'image/x-adobe-dng', // dng + 'image/heic', // heic + 'image/heif', // heif + 'image/jpeg', // jpg, jpeg + 'audio/mp4', // m4a + 'audio/mpeg', // mp3 + 'video/mp4', + 'application/mp4', // mp4 + 'video/quicktime', // mov + 'image/png', // png + 'image/svg+xml', // svg + 'image/tiff', // tif, tiff + 'audio/x-wav', // wav + 'image/webp', // webp + ].includes(mimeType); + } + iframeUrlFor(detailedCapture: any) { return this.sanitizer.bypassSecurityTrustResourceUrl( `${BUBBLE_IFRAME_URL}/asset_page?nid=${detailedCapture.id}` @@ -313,8 +356,10 @@ export class DetailsPage { this.activeDetailedCapture$.pipe(switchMap(c => c.diaBackendAsset$)), this.capAppWebCryptoApiSignatureProvider.publicKey$, this.translocoService.selectTranslateObject({ - 'message.copyIpfsAddress': null, - 'message.shareAssetProfile': null, + 'details.shares.downloadC2pa': null, + 'details.shares.viewBlockchainProof': null, + 'details.shares.shareBlockchainProof': null, + 'details.shares.copyNid': null, }), ]) .pipe( @@ -323,23 +368,46 @@ export class DetailsPage { ([ diaBackendAsset, publicKey, - [messageCopyIpfsAddress, messageShareAssetProfile], + [downloadC2paText, viewProofText, shareProofText, copyNidText], ]) => new Promise(resolve => { const buttons: ActionSheetButton[] = []; + if ( + diaBackendAsset && + DetailsPage.isSupportC2paDownloadFormat( + diaBackendAsset.asset_file_mime_type + ) + ) { + buttons.push({ + text: downloadC2paText, + handler: async () => { + await this.handleDownloadC2paAction(diaBackendAsset); + resolve(); + }, + }); + } if ( diaBackendAsset?.owner_addresses.asset_wallet_address === publicKey ) { buttons.push({ - text: messageShareAssetProfile, + text: viewProofText, handler: async () => { - const result = await this.confirmAlert.present({ - message: - this.translocoService.translate( - 'message.assetBecomePublicAfterSharing' - ) + '!', - }); + await this.handleOpenProofAction(diaBackendAsset.id); + resolve(); + }, + }); + buttons.push({ + text: shareProofText, + handler: async () => { + const result = + diaBackendAsset.public_access || + (await this.confirmAlert.present({ + message: + this.translocoService.translate( + 'message.assetBecomePublicAfterSharing' + ) + '!', + })); if (result) { this.share(); } @@ -350,18 +418,20 @@ export class DetailsPage { if (diaBackendAsset?.cid) { buttons.push({ - text: messageCopyIpfsAddress, + text: copyNidText, handler: () => { - const ipfsAddress = `https://ipfs-pin.numbersprotocol.io/ipfs/${diaBackendAsset.cid}`; - this.copyToClipboard(ipfsAddress); + this.copyToClipboard(diaBackendAsset.cid); resolve(); }, }); } - this.actionSheetController - .create({ buttons }) - .then(sheet => sheet.present()); + this.actionSheetController.create({ buttons }).then(sheet => { + sheet.present(); + sheet.onDidDismiss().then(() => { + this.shareMenuDismissed$.next(); + }); + }); }) ), untilDestroyed(this) @@ -454,6 +524,65 @@ export class DetailsPage { .subscribe(); } + private async handleDownloadC2paAction(diaBackendAsset: DiaBackendAsset) { + const filePath = await this.diaBackendAssetRepository + .downloadC2pa$(diaBackendAsset.id) + .pipe( + catchError((err: unknown) => { + if (err instanceof HttpErrorResponse) { + const errorMessage = err.error?.error?.message; + if (errorMessage) { + return this.errorService.toastError$(errorMessage); + } + } + return this.errorService.toastError$(err); + }), + switchMap(c2paResult => + defer(() => { + let filePath = c2paResult.cid; + const ext = extension(diaBackendAsset.asset_file_mime_type); + if (ext) { + filePath += `.${ext}`; + } + return Filesystem.downloadFile({ + url: c2paResult.url, + path: filePath, + directory: Directory.Cache, + }); + }) + ), + catchError((err: unknown) => this.errorService.toastError$(err)), + switchMap(downloadResult => { + if (!downloadResult.path) { + return this.errorService.toastError$( + this.translocoService.translate('error.unknownError') + ); + } + return of(downloadResult.path); + }), + untilDestroyed(this), + takeUntil(this.shareMenuDismissed$) + ) + .toPromise(); + + if (!filePath || !(await ShareService.canShare())) { + // Failed or web no navigator share + return; + } + + let fileUrl = filePath; + if (!fileUrl.startsWith('file://')) { + fileUrl = `file://${fileUrl}`; + } + await ShareService.shareFile(fileUrl) + .catch(async reason => { + if (reason?.message !== 'Share canceled') { + await this.errorService.toastError$(reason).toPromise(); + } + }) + .finally(() => Filesystem.deleteFile({ path: filePath })); + } + private handleEditAction() { combineLatest([ this.showCaptureDetailsInIframe$, @@ -520,6 +649,17 @@ export class DetailsPage { .subscribe(); } + private async handleOpenProofAction(id: string) { + await defer(() => + Browser.open({ + url: getAssetProfileForNSE(id), + toolbarColor: '#564dfc', + }) + ) + .pipe(untilDestroyed(this), takeUntil(this.shareMenuDismissed$)) + .toPromise(); + } + private async handleUnpublishAction() { const unpublishAction$ = this.activeDetailedCapture$.pipe( first(), @@ -683,7 +823,13 @@ export class DetailsPage { activeDetailedCapture => activeDetailedCapture.diaBackendAsset$ ), isNonNullable(), - concatMap(diaBackendAsset => this.shareService.share(diaBackendAsset)), + concatMap(diaBackendAsset => + this.shareService.share(diaBackendAsset).catch(reason => { + if (reason?.message !== 'Share canceled') { + throw reason; + } + }) + ), catchError((err: unknown) => this.errorService.toastError$(err)), untilDestroyed(this) ) diff --git a/src/app/shared/capacitor-plugins/mock-filesystem-plugin.ts b/src/app/shared/capacitor-plugins/mock-filesystem-plugin.ts index fd4d51d33..0d6970f3b 100644 --- a/src/app/shared/capacitor-plugins/mock-filesystem-plugin.ts +++ b/src/app/shared/capacitor-plugins/mock-filesystem-plugin.ts @@ -2,26 +2,29 @@ /* eslint-disable class-methods-use-this, @typescript-eslint/require-await */ import { PluginListenerHandle } from '@capacitor/core'; import { - AppendFileOptions as FileAppendOptions, CopyOptions, CopyResult, + DownloadFileOptions, + DownloadFileResult, + AppendFileOptions as FileAppendOptions, DeleteFileOptions as FileDeleteOptions, FileInfo, + ReadFileOptions as FileReadOptions, + ReadFileResult as FileReadResult, + WriteFileOptions as FileWriteOptions, + WriteFileResult as FileWriteResult, FilesystemPlugin, GetUriOptions, GetUriResult, MkdirOptions, PermissionStatus, + ProgressListener, ReaddirOptions, ReaddirResult, - ReadFileOptions as FileReadOptions, - ReadFileResult as FileReadResult, RenameOptions, RmdirOptions, StatOptions, StatResult, - WriteFileOptions as FileWriteOptions, - WriteFileResult as FileWriteResult, } from '@capacitor/filesystem'; import { groupBy } from 'lodash-es'; import { base64ToString, stringToBase64 } from '../../utils/encoding/encoding'; @@ -116,10 +119,14 @@ export class MockFilesystemPlugin implements FilesystemPlugin { throw new Error('Method not implemented.'); } + async downloadFile(_: DownloadFileOptions): Promise { + throw new Error('Method not implemented.'); + } + addListener( _eventName: string, - _listenerFunc: () => any - ): PluginListenerHandle { + _listenerFunc: ProgressListener + ): Promise & PluginListenerHandle { throw new Error('Method not implemented.'); } } diff --git a/src/app/shared/dia-backend/asset/dia-backend-asset-repository.service.ts b/src/app/shared/dia-backend/asset/dia-backend-asset-repository.service.ts index 21b303b63..d54d83896 100644 --- a/src/app/shared/dia-backend/asset/dia-backend-asset-repository.service.ts +++ b/src/app/shared/dia-backend/asset/dia-backend-asset-repository.service.ts @@ -201,6 +201,18 @@ export class DiaBackendAssetRepository { ); } + downloadC2pa$(id: string) { + return defer(() => this.authService.getAuthHeaders()).pipe( + concatMap(headers => + this.httpClient.post( + `${BASE_URL}/api/v3/assets/${id}/c2pa/`, + {}, + { headers } + ) + ) + ); + } + downloadFile$({ id, field }: { id: string; field: AssetDownloadField }) { const formData = new FormData(); formData.append('field', field); @@ -342,6 +354,7 @@ export interface DiaBackendAsset extends Tuple { readonly post_creation_workflow_id: string; readonly mint_workflow_id: string; readonly uploaded_at: string; + readonly public_access: boolean; } export interface OwnerAddresses extends Tuple { @@ -360,6 +373,11 @@ type UpdateAssetResponse = DiaBackendAsset; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface DeleteAssetResponse {} +interface DownloadC2paResponse { + url: string; + cid: string; +} + async function buildFormDataToCreateAsset(proof: Proof) { const formData = new FormData(); diff --git a/src/app/shared/share/share.service.ts b/src/app/shared/share/share.service.ts index f591c9e14..4c89d5456 100644 --- a/src/app/shared/share/share.service.ts +++ b/src/app/shared/share/share.service.ts @@ -22,6 +22,14 @@ export class ShareService { private readonly translocoService: TranslocoService ) {} + static async canShare() { + return (await Share.canShare()).value; + } + + static async shareFile(url: string) { + return Share.share({ url: url }); + } + async share(asset: DiaBackendAsset) { return Share.share({ text: this.defaultShareText, @@ -30,12 +38,14 @@ export class ShareService { } private async setPublicAndGetLink(asset: DiaBackendAsset) { - const formData = new FormData(); - formData.append('public_access', 'true'); - await this.diaBackendAssetRepository - .updateCapture$(asset.id, formData) - .pipe(catchError((err: unknown) => this.errorService.toastError$(err))) - .toPromise(); + if (!asset.public_access) { + const formData = new FormData(); + formData.append('public_access', 'true'); + await this.diaBackendAssetRepository + .updateCapture$(asset.id, formData) + .pipe(catchError((err: unknown) => this.errorService.toastError$(err))) + .toPromise(); + } return getAssetProfileForNSE(asset.id); } diff --git a/src/assets/i18n/en-us.json b/src/assets/i18n/en-us.json index 239aa9c2a..9ae60e9a8 100644 --- a/src/assets/i18n/en-us.json +++ b/src/assets/i18n/en-us.json @@ -188,8 +188,6 @@ "videoLimitation": "Capture App DOES NOT support video recording longer than 10 secs. Recording longer than 10 secs will not be saved.", "yesIUnderstand": "Yes, I understand", "verificationSuccess": "Success", - "copyIpfsAddress": "Copy IPFS address", - "shareAssetProfile": "Share Asset Profile", "assetBecomePublicAfterSharing": "This asset will become public after sharing", "assetBecomePublicFor24Hours": "Anyone with the link will be able to access the asset in the next 24 hours", "mintNft": "Mint NFT", @@ -297,6 +295,12 @@ "networkActions": "Network Actions", "remove": "Remove" }, + "shares": { + "copyNid": "Copy Nid", + "downloadC2pa": "Download C2PA", + "shareBlockchainProof": "Share Blockchain Proof", + "viewBlockchainProof": "View Blockchain Proof" + }, "error": { "canNotPerfomEditAction": "Temporarily unable to edit. Retry with stable connection or post-asset registration.", "canNotPerformMintAndShareAction": "This asset is minted so that can not perform Mint & Share action", diff --git a/src/assets/i18n/zh-tw.json b/src/assets/i18n/zh-tw.json index be6e7aaab..930b35e5f 100644 --- a/src/assets/i18n/zh-tw.json +++ b/src/assets/i18n/zh-tw.json @@ -188,8 +188,6 @@ "videoLimitation": "錄製的影片長度需小於 10 秒鐘。", "yesIUnderstand": "我了解", "verificationSuccess": "驗證成功", - "copyIpfsAddress": "複製 IPFS 位址", - "shareAssetProfile": "分享資產檔案", "assetBecomePublicAfterSharing": "該資產將在分享後公開", "assetBecomePublicFor24Hours": "其他用戶在接下來的 24 小時將可透過此連結存取影像", "mintNft": "鑄造 NFT", @@ -297,6 +295,12 @@ "networkActions": "網絡動作", "remove": "移除" }, + "shares": { + "copyNid": "複製 Nid", + "downloadC2pa": "下載 C2PA", + "shareBlockchainProof": "分享區塊鏈證明", + "viewBlockchainProof": "檢視區塊鏈證明" + }, "error": { "canNotPerfomEditAction": "暫時無法編輯。請確認連線穩定,或在資產註冊完成後再重試。", "canNotPerformMintAndShareAction": "該資產已鑄造完成,無法再次鑄造與分享",