From df0ecdf713b3642011dab97fbc85024af5ce9feb Mon Sep 17 00:00:00 2001 From: Olga Shen Date: Wed, 29 May 2024 14:09:13 +0800 Subject: [PATCH] feat(features/home/details): improve C2PA flow Improve the C2PA download flow by using a browser-based method instead of the sharing method. The sharing method is typical for iOS, but many apps, such as social media or photo apps, may strip out C2PA information. --- ios/App/Podfile.lock | 4 +- package-lock.json | 14 ---- package.json | 2 - src/app/features/home/details/details.page.ts | 81 ++++++++----------- 4 files changed, 37 insertions(+), 64 deletions(-) diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index e3e0ae263..4e29a8b82 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -29,7 +29,7 @@ PODS: - CapacitorCordova (5.7.5) - CapacitorDevice (5.0.4): - Capacitor - - CapacitorFilesystem (5.0.4): + - CapacitorFilesystem (5.1.1): - Capacitor - CapacitorGeolocation (5.0.4): - Capacitor @@ -224,7 +224,7 @@ SPEC CHECKSUMS: CapacitorCommunityWifi: 47188c74f2c6bcaefb619380863be8c67b1917c8 CapacitorCordova: c946a6052b547e1e185fc46862003f7b9130ead1 CapacitorDevice: eb4b5e3b42ac35d2527f20aad296b59e0785dc8d - CapacitorFilesystem: e1bdfab09b95b181c844c16abcfda45ec8e8ed6b + CapacitorFilesystem: 38e85e56818420bed3f0aa1b77128f503a960821 CapacitorGeolocation: 33015be1ef496585a60da9efa1c5642ff8624db3 CapacitorLocalNotifications: c2d8b14794064fd4814b1d6c4ddbac8029afa295 CapacitorNativeSettings: b6f40955945bc659f966a43fa54fc6be192d8f9b diff --git a/package-lock.json b/package-lock.json index aaae1f22d..7aca40411 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,7 +67,6 @@ "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", @@ -99,7 +98,6 @@ "@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", @@ -5623,12 +5621,6 @@ "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", @@ -28137,12 +28129,6 @@ "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", diff --git a/package.json b/package.json index d9ee08677..b81e6ca04 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,6 @@ "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", @@ -111,7 +110,6 @@ "@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", diff --git a/src/app/features/home/details/details.page.ts b/src/app/features/home/details/details.page.ts index 9bf08afe7..1e4ee8cf0 100644 --- a/src/app/features/home/details/details.page.ts +++ b/src/app/features/home/details/details.page.ts @@ -6,12 +6,10 @@ 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 { extension } from 'mime-types'; import { EMPTY, Observable, @@ -19,13 +17,13 @@ import { Subject, combineLatest, defer, - of, } from 'rxjs'; import { catchError, concatMap, concatMapTo, distinctUntilChanged, + finalize, first, map, pluck, @@ -525,9 +523,36 @@ export class DetailsPage { } private async handleDownloadC2paAction(diaBackendAsset: DiaBackendAsset) { - const filePath = await this.diaBackendAssetRepository - .downloadC2pa$(diaBackendAsset.id) + let fileUrl: string | undefined = undefined; + const downloadC2paDismissed$ = new Subject(); + const alert = await this.alertController.create({ + header: this.translocoService.translate('details.shares.downloadC2pa'), + message: `
${this.translocoService.translate( + 'message.pleaseWait' + )}`, + backdropDismiss: false, + buttons: [ + { text: this.translocoService.translate('cancel'), role: 'cancel' }, + ], + }); + + alert.onDidDismiss().then(async () => { + downloadC2paDismissed$.next(); + if (fileUrl) { + const link = document.createElement('a'); + link.href = `${BUBBLE_IFRAME_URL}/download?url=${fileUrl}`; + link.hidden = true; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + }); + + defer(() => alert.present()) .pipe( + switchMap(() => + this.diaBackendAssetRepository.downloadC2pa$(diaBackendAsset.id) + ), catchError((err: unknown) => { if (err instanceof HttpErrorResponse) { const errorMessage = err.error?.error?.message; @@ -537,50 +562,14 @@ export class DetailsPage { } 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); + map(c2paResult => { + fileUrl = c2paResult.url; }), + finalize(() => alert.dismiss()), untilDestroyed(this), - takeUntil(this.shareMenuDismissed$) + takeUntil(downloadC2paDismissed$) ) - .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 })); + .subscribe(); } private handleEditAction() {