Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Duplicate] V240104 capture cam ionic launch #3173

Merged
merged 23 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a09e1e8
feat(capture-tab): show confirm dialog before refresh
sultanmyrza Dec 14, 2023
1ec67a1
fix(zh-tw): syncAndRestore
sultanmyrza Dec 14, 2023
9e8956f
fix(en-us): confirmSyncAndRestore
sultanmyrza Dec 14, 2023
c57a1eb
WIP: add caption field to Proof, IndexedProofView
sultanmyrza Dec 19, 2023
585cb4e
WIP: sync Proof.caption with diaBackendAsset on edit
sultanmyrza Dec 19, 2023
b5b43a9
WIP: sync Proof.caption with diaBackendAsset on edit
sultanmyrza Dec 19, 2023
a60ee61
WIP: retrieve hasCaption from Proof object instead of API call
sultanmyrza Dec 19, 2023
fcc0568
WIP: set proof.caption in storeIndexedProof
sultanmyrza Dec 19, 2023
6496bd4
WIP: add uploadedAt to Proof, IndexedProofView
sultanmyrza Dec 21, 2023
3e6adaf
WIP: add uploaded_at to DiaBackendAsset
sultanmyrza Dec 20, 2023
41f9cd4
WIP: set proof.uploadedDate after successful upload
sultanmyrza Dec 21, 2023
0e26e4b
WIP: set proof.uploadedDate during storeRemoteCapture
sultanmyrza Dec 21, 2023
a2d591b
WIP: sort verified tabs by uploadedAt or timestamp
sultanmyrza Dec 20, 2023
c4a0040
refactor(capture-item): remove unnecessary .trim() on caption
sultanmyrza Jan 2, 2024
dbd0354
refactor(proof.ts): remove unused try catch block
sultanmyrza Jan 2, 2024
b0b3349
feat(urls.ts): redirect nftsearch.site to verify.numbersprotocol.io
sultanmyrza Jan 2, 2024
49e3a13
fix(urls.ts): change query param to cid from nid as requested
sultanmyrza Jan 5, 2024
c892830
Merge pull request #3161 from numbersprotocol/feature-update-the-NSE-…
sultanmyrza Jan 11, 2024
064e7cf
Merge pull request #3171 from numbersprotocol/feat-confirm-dialog-on-…
sultanmyrza Jan 11, 2024
d9b5652
Merge pull request #3157 from numbersprotocol/fix-excessive-api-call
sultanmyrza Jan 11, 2024
d09dc29
Merge branch 'feat-sort-assets-in-VERIFIED-tab-by-uploaded_at' into v…
sultanmyrza Jan 11, 2024
b12b5f5
chore: bump app version to 0.88.6
sultanmyrza Jan 11, 2024
5922db2
chore: update CHANGELOG.md for 0.88.6
sultanmyrza Jan 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading