Skip to content

Commit

Permalink
Fix #202, #201 and #198 (#204)
Browse files Browse the repository at this point in the history
* Rename app name to Capture and proof detials to capture details. #201 #202

* Show sender on app-post-capture-card. #198

This is implemented with a BAD architecture. The PostCapture wall only display contents from the server,
and the app does NOT save any cache of PostCaptures. The performance will deteriorate for the huge
ovehead from the Internet. This architecture should be redesign with the new (reliable) storage
implementation and the new data model for the exchange between server and app.

* Fix tests.
  • Loading branch information
seanwu1105 authored Nov 16, 2020
1 parent c14a7bb commit 34eaaf8
Show file tree
Hide file tree
Showing 14 changed files with 57 additions and 81 deletions.
2 changes: 1 addition & 1 deletion android/app/src/main/assets/capacitor.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"appId": "io.numbersprotocol.capturelite",
"appName": "Capture Lite",
"appName": "Capture",
"bundledWebRuntime": false,
"npmClient": "npm",
"webDir": "www",
Expand Down
4 changes: 2 additions & 2 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="app_name">Capture Lite</string>
<string name="title_activity_main">Capture Lite</string>
<string name="app_name">Capture</string>
<string name="title_activity_main">Capture</string>
<string name="package_name">io.numbersprotocol.capturelite</string>
<string name="custom_url_scheme">io.numbersprotocol.capturelite</string>
</resources>
2 changes: 1 addition & 1 deletion capacitor.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"appId": "io.numbersprotocol.capturelite",
"appName": "Capture Lite",
"appName": "Capture",
"bundledWebRuntime": false,
"npmClient": "npm",
"webDir": "www",
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/home/asset/asset.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<button routerLink=".." routerDirection="back" mat-icon-button>
<mat-icon>arrow_back</mat-icon>
</button>
<span>{{ t('proofDetails') }}</span>
<span>{{ t('captureDetails') }}</span>
<button (click)="openContactSelectionDialog()" mat-icon-button>
<mat-icon>send</mat-icon>
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
<!-- preview -->

<ng-container *ngIf="isPreview">
<app-post-capture-card [userName]="userName$ | async" [asset]="asset$ | async" [imageSrc]="base64Src$ | async">
<app-post-capture-card [transaction]="{ sender: (asset$ | async).owner, asset: { caption: previewCaption }}"
[asset]="asset$ | async">
</app-post-capture-card>

<button (click)="send(previewCaption)" class="send-button" mat-raised-button color="primary">
Expand Down
9 changes: 3 additions & 6 deletions src/app/pages/home/home.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,9 @@
</mat-tab>
<mat-tab label="PostCapture">
<div class="tab-content">
<ng-container *ngFor="let assetsWithRaw of postCapturesWithRawByDate$ | async">
<div class="mat-title">{{ assetsWithRaw[0].date }}</div>
<app-post-capture-card *ngFor="let assetWithRaw of assetsWithRaw" userName="User Name"
[asset]="assetWithRaw.asset" [imageSrc]="'data:image/png;base64,' + assetWithRaw.rawBase64">
</app-post-capture-card>
</ng-container>
<app-post-capture-card *ngFor="let postCapture of postCaptures$ | async"
[transaction]="postCapture.transaction" [asset]="postCapture.asset">
</app-post-capture-card>
</div>
</mat-tab>
</mat-tab-group>
Expand Down
35 changes: 21 additions & 14 deletions src/app/pages/home/home.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,8 @@ export class HomePage {
private readonly captures$ = this.assets$.pipe(
map(assets => assets.filter(asset => asset.is_original_owner))
);
private readonly postCaptures$ = this.assets$.pipe(
map(assets => assets.filter(asset => !asset.is_original_owner))
);
postCaptures$ = this.getPostCaptures();
readonly capturesWithRawByDate$ = this.captures$.pipe(this.appendAssetsRawAndGroupedByDate$());
readonly postCapturesWithRawByDate$ = this.postCaptures$.pipe(this.appendAssetsRawAndGroupedByDate$());

readonly userName$ = this.numbersStorageApi.getUserName$();
captureButtonShow = true;
Expand All @@ -42,6 +39,22 @@ export class HomePage {
private readonly numbersStorageApi: NumbersStorageApi
) { }

private getPostCaptures() {
return zip(this.numbersStorageApi.listTransactions$(), this.numbersStorageApi.getEmail$()).pipe(
map(([transactionListResponse, email]) => transactionListResponse.results.filter(
transaction => transaction.sender !== email && !transaction.expired && transaction.fulfilled_at
)),
concatMap(transactions => zip(
of(transactions),
forkJoinWithDefault(transactions.map(transaction => this.numbersStorageApi.readAsset$(transaction.asset.id)))
)),
map(([transactions, assets]) => transactions.map((transaction, index) => ({
transaction,
asset: assets[index]
})))
);
}

capture() {
this.cameraService.capture$().pipe(
map(cameraPhoto => this.collectorService.storeAndCollect(
Expand All @@ -58,7 +71,6 @@ export class HomePage {
isNonNullable(),
first()
)))),
// tslint:disable-next-line: no-non-null-assertion
concatMap(proofs => forkJoinWithDefault(proofs.map(proof => this.proofRepository.getThumbnail$(proof)))),
concatMap(base64Strings => zip(assets$, of(base64Strings))),
map(([assets, base64Strings]) => assets.map((asset, index) => ({
Expand All @@ -71,16 +83,10 @@ export class HomePage {
)),
map(assetsWithRawBase64 => assetsWithRawBase64.reduce((groupedAssetsWithRawBase64, assetWithRawBase64) => {
const index = groupedAssetsWithRawBase64.findIndex(
processingAssetsWithRawBase64 =>
processingAssetsWithRawBase64[0].date
=== assetWithRawBase64.date
processingAssetsWithRawBase64 => processingAssetsWithRawBase64[0].date === assetWithRawBase64.date
);
if (index === -1) {
groupedAssetsWithRawBase64.push([assetWithRawBase64]);
}
else {
groupedAssetsWithRawBase64[index].push(assetWithRawBase64);
}
if (index === -1) { groupedAssetsWithRawBase64.push([assetWithRawBase64]); }
else { groupedAssetsWithRawBase64[index].push(assetWithRawBase64); }
return groupedAssetsWithRawBase64;
}, [] as { asset: Asset, rawBase64: string, date: string; }[][])
)
Expand All @@ -89,5 +95,6 @@ export class HomePage {

onTapChanged(event: MatTabChangeEvent) {
this.captureButtonShow = event.index === 0;
if (event.index === 1) { this.postCaptures$ = this.getPostCaptures(); }
}
}
3 changes: 0 additions & 3 deletions src/app/pages/home/inbox/inbox.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { of, zip } from 'rxjs';
import { concatMap, map, pluck, tap } from 'rxjs/operators';
import { BlockingActionService } from 'src/app/services/blocking-action/blocking-action.service';
import { AssetRepository } from 'src/app/services/publisher/numbers-storage/data/asset/asset-repository.service';
import { IgnoredTransactionRepository } from 'src/app/services/publisher/numbers-storage/data/ignored-transaction/ignored-transaction-repository.service';
import { NumbersStorageApi } from 'src/app/services/publisher/numbers-storage/numbers-storage-api.service';

Expand All @@ -19,7 +18,6 @@ export class InboxPage {

constructor(
private readonly numbersStorageApi: NumbersStorageApi,
private readonly assetRepository: AssetRepository,
private readonly ignoredTransactionRepository: IgnoredTransactionRepository,
private readonly blockingActionService: BlockingActionService
) { }
Expand All @@ -38,7 +36,6 @@ export class InboxPage {

accept(id: string) {
const action$ = this.numbersStorageApi.acceptTransaction$(id).pipe(
concatMap(asset => this.assetRepository.addFromNumbersStorage$(asset)),
tap(_ => this.refresh())
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { of, zip } from 'rxjs';
import { concatMap, concatMapTo, first, map, pluck } from 'rxjs/operators';
import { concatMap, concatMapTo, first, map, pluck, tap } from 'rxjs/operators';
import { dataUrlWithBase64ToBlob$ } from 'src/app/utils/encoding/encoding';
import { PreferenceManager } from 'src/app/utils/preferences/preference-manager';
import { secret } from '../../../../environments/secret';
Expand Down Expand Up @@ -96,7 +96,8 @@ export class NumbersStorageApi {

readAsset$(id: string) {
return this.getHttpHeadersWithAuthToken$().pipe(
concatMap(headers => this.httpClient.get<Asset>(`${baseUrl}/api/v2/assets/${id}/`, { headers }))
concatMap(headers => this.httpClient.get<Asset>(`${baseUrl}/api/v2/assets/${id}/`, { headers })),
tap(v => console.log(v))
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<mat-card *transloco="let t">
<mat-card-header>
<div mat-card-avatar class="post-capture-avatar"></div>
<mat-card-title>{{ asset.owner }}</mat-card-title>
<mat-card-title>{{ transaction.sender }}</mat-card-title>
<mat-card-subtitle>{{ asset.uploaded_at | date: 'short' }}</mat-card-subtitle>
<span class="toolbar-spacer"></span>
</mat-card-header>
<img [src]="imageSrc" mat-card-image>
<img [src]="asset.asset_file" mat-card-image>
<mat-card-content>
<mat-list dense class="info-list" [class.info-list-show]="openMore">
<mat-list-item>
Expand All @@ -19,18 +19,18 @@
<mat-icon mat-list-icon>access_time</mat-icon>
<div mat-line>
<span>{{ t('timestamp') }}</span>
<span class="info-list-content">{{ (proof$ | async)?.timestamp | date:'medium' }}</span>
<span class="info-list-content">{{ asset.uploaded_at | date:'medium' }}</span>
</div>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>place</mat-icon>
<div mat-line>
<span>{{ t('location') }}</span>
<div mat-line>{{ (latitude$ | async) + ', ' + (longitude$ | async) }}</div>
<span class="info-list-content" mat-line>{{ latitude + ', ' + longitude }}</span>
</div>
</mat-list-item>
</mat-list>
<p class="caption-ellipsis mat-body" [class.caption-full]="openMore">{{ (caption$ | async)?.text }}</p>
<p class="caption-ellipsis mat-body" [class.caption-full]="openMore">{{ transaction.asset.caption }}</p>
</mat-card-content>
<mat-card-actions [align]="'end'">
<button (click)="openMore = !openMore" mat-button>{{ t('viewAll') + '...' }}</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MatIconTestingModule } from '@angular/material/icon/testing';
import { MatListModule } from '@angular/material/list';
import { IonicModule } from '@ionic/angular';
import { Asset } from 'src/app/services/publisher/numbers-storage/data/asset/asset';
import { Transaction } from 'src/app/services/publisher/numbers-storage/numbers-storage-api.service';
import { getTranslocoModule } from 'src/app/transloco/transloco-root.module.spec';
import { PostCaptureCardComponent } from './post-capture-card.component';

Expand All @@ -25,7 +26,14 @@ describe('PostCaptureCardComponent', () => {
uploaded_at: '',
is_original_owner: true
};
const expectedImageSrc = 'https://picsum.photos/200/300';
const expectedTranasction: Transaction = {
id: '',
sender: '',
asset: expectedAsset,
created_at: '',
expired: false,
fulfilled_at: ''
};

beforeEach(async(() => {
TestBed.configureTestingModule({
Expand All @@ -45,7 +53,7 @@ describe('PostCaptureCardComponent', () => {
fixture = TestBed.createComponent(PostCaptureCardComponent);
component = fixture.componentInstance;
component.asset = expectedAsset;
component.imageSrc = expectedImageSrc;
component.transaction = expectedTranasction;
fixture.detectChanges();
}));

Expand Down
47 changes: 6 additions & 41 deletions src/app/shared/post-capture-card/post-capture-card.component.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { Component, Input, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { concatMap, map, pluck, switchMap } from 'rxjs/operators';
import { CapacitorProvider } from 'src/app/services/collector/information/capacitor-provider/capacitor-provider';
import { Caption } from 'src/app/services/data/caption/caption';
import { CaptionRepository } from 'src/app/services/data/caption/caption-repository.service';
import { InformationRepository } from 'src/app/services/data/information/information-repository.service';
import { Proof } from 'src/app/services/data/proof/proof';
import { ProofRepository } from 'src/app/services/data/proof/proof-repository.service';
import { Asset } from 'src/app/services/publisher/numbers-storage/data/asset/asset';
import { isNonNullable } from 'src/app/utils/rx-operators';
import { Transaction } from 'src/app/services/publisher/numbers-storage/numbers-storage-api.service';

@Component({
selector: 'app-post-capture-card',
Expand All @@ -17,43 +9,16 @@ import { isNonNullable } from 'src/app/utils/rx-operators';
})
export class PostCaptureCardComponent implements OnInit {

@Input() userName!: string;
@Input() transaction!: Transaction;
@Input() asset!: Asset;
@Input() imageSrc!: string;

proof$!: Observable<Proof>;
caption$!: Observable<Caption>;
latitude$!: Observable<string>;
longitude$!: Observable<string>;
latitude!: string;
longitude!: string;

openMore = false;

constructor(
private readonly proofRepository: ProofRepository,
private readonly informationRepository: InformationRepository,
private readonly captionRepository: CaptionRepository
) { }

ngOnInit() {
this.proof$ = this.proofRepository.getByHash$(this.asset.proof_hash).pipe(
isNonNullable()
);
this.caption$ = this.proof$.pipe(
isNonNullable(),
concatMap(proof => this.captionRepository.getByProof$(proof)),
isNonNullable()
);
this.latitude$ = this.proof$.pipe(
switchMap(proof => this.informationRepository.getByProof$(proof)),
map(informationList => informationList.find(information => information.provider === CapacitorProvider.ID && information.name === 'Current GPS Latitude')),
isNonNullable(),
pluck('value')
);
this.longitude$ = this.proof$.pipe(
switchMap(proof => this.informationRepository.getByProof$(proof)),
map(informationList => informationList.find(information => information.provider === CapacitorProvider.ID && information.name === 'Current GPS Longitude')),
isNonNullable(),
pluck('value')
);
this.latitude = this.asset.information.information.find(info => info.name === 'Current GPS Latitude')?.value || 'unknown';
this.longitude = this.asset.information.information.find(info => info.name === 'Current GPS Longitude')?.value || 'unknown';
}
}
2 changes: 1 addition & 1 deletion src/assets/i18n/en-us.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"profile": "Profile",
"settings": "Settings",
"privacy": "Privacy",
"proofDetails": "Proof Details",
"captureDetails": "Capture Details",
"informationDetails": "Information Details",
"caption": "Caption",
"hash": "Hash",
Expand Down
2 changes: 1 addition & 1 deletion src/assets/i18n/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"profile": "個人資料",
"settings": "設定",
"privacy": "隱私",
"proofDetails": "拍攝資訊",
"captureDetails": "拍攝資訊",
"informationDetails": "詳細資訊",
"caption": "標題",
"hash": "雜湊",
Expand Down

0 comments on commit 34eaaf8

Please sign in to comment.