Skip to content

Commit

Permalink
Merge pull request #3173 from numbersprotocol/v240104-capture-cam-ion…
Browse files Browse the repository at this point in the history
…ic-launch
  • Loading branch information
shc261392 authored Jan 11, 2024
2 parents 6fb9378 + 5922db2 commit 5576880
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 35 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.88.6] - 2024-01-11

### Added

Feature update the NSE domain (#3161)
Feat confirm dialog on pull to refresh (#3171)
Feat sort assets in VERIFIED tab by uploaded_at (#3158)

### Fixed

Fix excessive api call (#3157)

## [0.87.1] - 2023-12-04

### Fixed
Expand Down Expand Up @@ -2226,7 +2238,8 @@ This is the first release! _Capture Lite_ is a cross-platform app adapted from [
- Web - see the demo [here](https://github.com/numbersprotocol/capture-lite#demo-app)
- Android - the APK file `app-debug.apk` is attached to this release

[unreleased]: https://github.com/numbersprotocol/capture-lite/compare/0.87.1...HEAD
[unreleased]: https://github.com/numbersprotocol/capture-lite/compare/0.88.6...HEAD
[0.88.6]: https://github.com/numbersprotocol/capture-lite/compare/0.87.1...0.88.6
[0.87.1]: https://github.com/numbersprotocol/capture-lite/compare/0.87.0...0.87.1
[0.87.0]: https://github.com/numbersprotocol/capture-lite/compare/0.86.4...0.87.0
[0.86.4]: https://github.com/numbersprotocol/capture-lite/compare/0.83.2...0.86.4
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "io.numbersprotocol.capturelite"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 871
versionName "0.87.1"
versionCode 886
versionName "0.88.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
Expand Down
8 changes: 4 additions & 4 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,13 @@
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 871;
CURRENT_PROJECT_VERSION = 886;
DEVELOPMENT_TEAM = G7NB5YCKAP;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = G7NB5YCKAP;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.87.1;
MARKETING_VERSION = 0.88.6;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = io.numbersprotocol.capturelite;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -395,13 +395,13 @@
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 871;
CURRENT_PROJECT_VERSION = 886;
DEVELOPMENT_TEAM = G7NB5YCKAP;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = G7NB5YCKAP;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.87.1;
MARKETING_VERSION = 0.88.6;
PRODUCT_BUNDLE_IDENTIFIER = io.numbersprotocol.capturelite;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = NumbersAppDistributionV4;
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "capture-lite",
"version": "0.87.1",
"version": "0.88.6",
"author": "numbersprotocol",
"homepage": "https://numbersprotocol.io/",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ export class CaptureItemComponent {
)
);

readonly hasCaption$ = this.proof$.pipe(
switchMap(proof => this.diaBackendAssetRepository.fetchByProof$(proof)),
map(asset => asset.caption !== '')
);
readonly hasCaption$ = this.proof$.pipe(map(proof => proof.caption !== ''));

readonly isVideo$ = this.proof$.pipe(
concatMap(proof => proof.getFirstAssetMeta()),
Expand Down
45 changes: 31 additions & 14 deletions src/app/features/home/capture-tab/capture-tab.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { formatDate, KeyValue } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
import {
ActionSheetButton,
Expand All @@ -15,7 +16,6 @@ import {
catchError,
concatMap,
concatMapTo,
finalize,
map,
pluck,
shareReplay,
Expand Down Expand Up @@ -45,6 +45,7 @@ import { getOldProof } from '../../../shared/repositories/proof/old-proof-adapte
import { Proof } from '../../../shared/repositories/proof/proof';
import { ProofRepository } from '../../../shared/repositories/proof/proof-repository.service';
import { reloadApp } from '../../../utils/miscellaneous';
import { PrefetchingDialogComponent } from '../onboarding/prefetching-dialog/prefetching-dialog.component';

@UntilDestroy({ checkProperties: true })
@Component({
Expand Down Expand Up @@ -94,7 +95,9 @@ export class CaptureTabComponent implements OnInit {
);

readonly captures$ = this.proofs$.pipe(
map(proofs => proofs.sort((a, b) => b.timestamp - a.timestamp))
map(proofs =>
proofs.sort((a, b) => b.uploadedAtOrTimestamp - a.uploadedAtOrTimestamp)
)
);

readonly networkConnected$ = this.networkService.connected$;
Expand Down Expand Up @@ -158,6 +161,8 @@ export class CaptureTabComponent implements OnInit {
private readonly mediaStore: MediaStore,
private readonly database: Database,
private readonly confirmAlert: ConfirmAlert,
private readonly dialog: MatDialog,

private readonly preferenceManager: PreferenceManager,
private readonly changeDetectorRef: ChangeDetectorRef,
private readonly proofRepository: ProofRepository,
Expand Down Expand Up @@ -334,17 +339,29 @@ export class CaptureTabComponent implements OnInit {
return item.id;
}

refreshCaptures(event: Event) {
this.diaBackendAssetRefreshingService
.refresh()
.pipe(
finalize(() => {
this.capturedTabPageIndex$.next(0);
this.collectedTabPageIndex$.next(0);
this.draftTabPageIndex$.next(0);
return (<CustomEvent>event).detail.complete();
})
)
.subscribe();
async refreshCaptures(event: Event) {
(<CustomEvent>event).detail.complete();

const confirmRefresh = await this.showRefreshAlert();
if (confirmRefresh) {
this.capturedTabPageIndex$.next(0);
this.collectedTabPageIndex$.next(0);
this.draftTabPageIndex$.next(0);

return this.dialog.open(PrefetchingDialogComponent, {
disableClose: true,
});
}
}

private async showRefreshAlert() {
return this.confirmAlert.present({
header: this.translocoService.translate('syncAndRestore'),
message: this.translocoService.translate('message.confirmSyncAndRestore'),
confirmButtonText: this.translocoService.translate(
'confirmSyncAndRestore'
),
cancelButtonText: this.translocoService.translate('cancelSyncAndRestore'),
});
}
}
45 changes: 40 additions & 5 deletions src/app/features/home/details/edit-caption/edit-caption.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@ import { DomSanitizer } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router';
import { NavController } from '@ionic/angular';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { combineLatest, fromEvent } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { combineLatest, fromEvent, of } from 'rxjs';
import {
concatMap,
finalize,
first,
map,
tap as switchTap,
} from 'rxjs/operators';
import { DiaBackendAuthService } from '../../../../shared/dia-backend/auth/dia-backend-auth.service';
import { BUBBLE_IFRAME_URL } from '../../../../shared/dia-backend/secret';
import { BubbleToIonicPostMessage } from '../../../../shared/iframe/iframe';
import { IframeService } from '../../../../shared/iframe/iframe.service';
import { getOldProof } from '../../../../shared/repositories/proof/old-proof-adapter';
import { ProofRepository } from '../../../../shared/repositories/proof/proof-repository.service';
import { isNonNullable } from '../../../../utils/rx-operators/rx-operators';
import { InformationSessionService } from '../information/session/information-session.service';

@UntilDestroy()
@Component({
Expand Down Expand Up @@ -43,15 +52,17 @@ export class EditCaptionPage {
private readonly sanitizer: DomSanitizer,
private readonly navController: NavController,
private readonly iframeService: IframeService,
private readonly diaBackendAuthService: DiaBackendAuthService
private readonly diaBackendAuthService: DiaBackendAuthService,
private readonly informationSessionService: InformationSessionService,
private readonly proofRepository: ProofRepository
) {
this.processIframeEvents();
}

processIframeEvents() {
fromEvent(window, 'message')
.pipe(
tap(event => {
switchTap(event => {
const postMessageEvent = event as MessageEvent;
const data = postMessageEvent.data as BubbleToIonicPostMessage;
switch (data) {
Expand All @@ -60,12 +71,36 @@ export class EditCaptionPage {
break;
case BubbleToIonicPostMessage.EDIT_CAPTION_SAVE:
this.iframeService.refreshDetailsPageIframe();
this.navController.back();
this.syncCaptionAndNavigateBack();
break;
}
}),
untilDestroyed(this)
)
.subscribe();
}

syncCaptionAndNavigateBack() {
if (this.informationSessionService.activatedDetailedCapture) {
combineLatest([
this.informationSessionService.activatedDetailedCapture.proof$,
this.informationSessionService.activatedDetailedCapture.caption$,
])
.pipe(
first(),
concatMap(([proof, latestCaptionFromBackend]) => {
if (proof) {
proof.caption = latestCaptionFromBackend;
return this.proofRepository.update(
[proof],
(x, y) => getOldProof(x).hash === getOldProof(y).hash
);
}
return of(null);
}),
finalize(() => this.navController.back())
)
.subscribe();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ export interface DiaBackendAsset extends Tuple {
readonly caption: string;
readonly post_creation_workflow_id: string;
readonly mint_workflow_id: string;
readonly uploaded_at: string;
}

export interface OwnerAddresses extends Tuple {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ export class DiaBackendAssetDownloadingService {
},
});
proof.diaBackendAssetId = diaBackendAsset.id;
proof.caption = diaBackendAsset.caption;
proof.uploadedAt = diaBackendAsset.uploaded_at;
if (diaBackendAsset.signed_metadata) proof.setSignatureVersion();
return this.proofRepository.add(proof, OnConflictStrategy.REPLACE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export class DiaBackendAssetUploadingService {
}),
map(diaBackendAsset => {
proof.diaBackendAssetId = diaBackendAsset.id;
proof.uploadedAt = diaBackendAsset.uploaded_at;
return proof;
}),
retryWhen(err$ =>
Expand Down
37 changes: 37 additions & 0 deletions src/app/shared/repositories/proof/proof.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,43 @@ describe('Proof utils', () => {
const expected = `{\n "asset_mime_type": "${ASSET1_MIMETYPE}",\n "caption": "",\n "created_at": ${TIMESTAMP},\n "device_name": "${DEVICE_NAME_VALUE1}",\n "information": {\n "device.device_name": "${DEVICE_NAME_VALUE2}",\n "device.humidity": 0.8,\n "geolocation.geolocation_latitude": ${GEOLOCATION_LATITUDE2},\n "geolocation.geolocation_longitude": ${GEOLOCATION_LONGITUDE2}\n },\n "location_latitude": ${GEOLOCATION_LATITUDE1},\n "location_longitude": ${GEOLOCATION_LONGITUDE1},\n "proof_hash": "${ASSET1_SHA256SUM}",\n "recorder": "Capture",\n "spec_version": "2.0.0"\n}`;
expect(getSerializedSortedProofMetadata(ProofMetadata)).toEqual(expected);
});

describe('uploadedAtOrTimestamp', () => {
it('should return timestamp in milliseconds when uploadedAt is undefined', async () => {
proof = await Proof.from(mediaStore, ASSETS, TRUTH, SIGNATURES_VALID);
expect(proof.uploadedAtOrTimestamp).toEqual(TRUTH.timestamp);
});

it('should return uploadedAt in milliseconds when uploadedAt is defined', async () => {
const date = '2023-12-21T01:15:17Z'; // sample returned by API
const dateInMilliseconds = Date.parse(date);

proof = await Proof.from(mediaStore, ASSETS, TRUTH, SIGNATURES_VALID);
proof.uploadedAt = date;

expect(proof.uploadedAtOrTimestamp).toEqual(dateInMilliseconds);
});

it('should return timestamp in milliseconds when uploadedAt is not a valid date', async () => {
proof = await Proof.from(mediaStore, ASSETS, TRUTH, SIGNATURES_VALID);
proof.uploadedAt = 'invalid date';
expect(proof.uploadedAtOrTimestamp).toEqual(TRUTH.timestamp);
});

it('should return timestamp in milliseconds when its in seconds', async () => {
const timestamp = 1627545600; // 29th July 2021 12:00:00 GMT
const timestampInMilliseconds = timestamp * 1000;

proof = await Proof.from(
mediaStore,
ASSETS,
{ ...TRUTH, timestamp },
SIGNATURES_VALID
);

expect(proof.uploadedAtOrTimestamp).toEqual(timestampInMilliseconds);
});
});
});

const ASSET1_MIMETYPE: MimeType = 'image/png';
Expand Down
Loading

0 comments on commit 5576880

Please sign in to comment.