Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
seanwu1105 committed Dec 8, 2020
2 parents c5971dd + 983a1a2 commit 05a262c
Show file tree
Hide file tree
Showing 93 changed files with 1,624 additions and 1,377 deletions.
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.10.0 - 2020-12-08

### Added

- Add transaction-details page. #286
- Display different status badge to distinguish different "In Progress" activity. #199

### Changed

#### Code Quality

- Rewrite the tests of `NotificationService` with `MockLocalNotificationsPlugin`.
- Rewrite tests for `PreferenceManager` service by mocking Capacitor `Storage` plugin.
- Rewrite the interface of `ConfirmAlert` with tests.
- Add tests for `LanguageService`.
- Change the pre-release branch to master.
- Rename `NumbersStorageBackend` with `DiaBackend`.
- Implement `NotificationService.notifyOnGoing` method. Close #254.
- Apply on-going notification to `CollectorService.runAndStore` method.
- Apply on-going notification to `DiaBackendAssetRepository.add` method.
- Reimplement simplified `IgnoredTransactionRepository`.
- Extract `/api/**/transactions` endpoints to standalone service.
- Extract `/api/**/assets` endpoints to standalone service.
- Extract `/auth` endpoints to standalone service with tests.
- Add readonly modifier to most dictionary interface.
- Improve the import location for `secret.ts` from set-secret preconfig.

### Fixed

- Fix white margin on iOS 13.7 iPhone 6s Plus. #289
- Fix background color of the PostCapture image. #285
- Fix unified font size on Capture tab. #284
- Fix cannot scroll on asset page. #282

## 0.9.4 - 2020-12-04

### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Run `npm i` to update `package-lock.json`.

Write the changelog in `CHANGELOG.md`.

When push to the `develop` branch with new version in the `package.json` file, GitHub Action would automatically do the following jobs:
When push to the `master` branch with new version in the `package.json` file, GitHub Action would automatically do the following jobs:

1. Create release GitHub page with debug APK.
1. Publish the app to Play Console on alpha track.
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ android {
applicationId "io.numbersprotocol.capturelite"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 47
versionName "0.9.4"
versionCode 48
versionName "0.10.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand Down
4 changes: 1 addition & 3 deletions e2e/src/app.po.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// tslint:disable-next-line: no-implicit-dependencies
// tslint:disable: no-implicit-dependencies prefer-function-over-method
import { browser, by, element } from 'protractor';

export class AppPage {
// tslint:disable-next-line: prefer-function-over-method
async navigateTo() {
return browser.get('/');
}

// tslint:disable-next-line: prefer-function-over-method
async getParagraphText() {
return element(by.deepCss('app-root ion-content')).getText();
}
Expand Down
2 changes: 1 addition & 1 deletion 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.9.4",
"version": "0.10.0",
"author": "numbersprotocol",
"homepage": "https://numbersprotocol.io/",
"scripts": {
Expand Down
10 changes: 3 additions & 7 deletions set-secret.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
const fs = require('fs');

// Configure Angular `secret.ts` file path
const targetPath = './src/environments/secret.ts';
const targetPath = './src/app/services/dia-backend/secret.ts';

// `secret.ts` file structure
const envConfigFile = `export const secret = {
numbersStorageBaseUrl: '${process.env.NUMBERS_STORAGE_BASE_URL}'
};
const envConfigFile = `export const BASE_URL = '${process.env.NUMBERS_STORAGE_BASE_URL}';
`;
fs.writeFile(targetPath, envConfigFile, err => {
if (err) {
throw console.error(err);
} else {
console.log(
`Angular secrets.ts file generated correctly at ${targetPath} \n`
);
console.log(`A secret file has generated successfully at ${targetPath} \n`);
}
});
48 changes: 19 additions & 29 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { Plugins } from '@capacitor/core';
import { Platform } from '@ionic/angular';
import { TranslocoService } from '@ngneat/transloco';
import { UntilDestroy } from '@ngneat/until-destroy';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { defer } from 'rxjs';
import { concatMap, first } from 'rxjs/operators';
import { CollectorService } from './services/collector/collector.service';
import { CapacitorFactsProvider } from './services/collector/facts/capacitor-facts-provider/capacitor-facts-provider.service';
import { WebCryptoApiSignatureProvider } from './services/collector/signature/web-crypto-api-signature-provider/web-crypto-api-signature-provider.service';
import { DiaBackendAssetRepository } from './services/dia-backend/asset/dia-backend-asset-repository.service';
import { LanguageService } from './services/language/language.service';
import { NotificationService } from './services/notification/notification.service';
import { NumbersStorageApi } from './services/publisher/numbers-storage/numbers-storage-api.service';
import { NumbersStoragePublisher } from './services/publisher/numbers-storage/numbers-storage-publisher';
import { AssetRepository } from './services/publisher/numbers-storage/repositories/asset/asset-repository.service';
import { PublishersAlert } from './services/publisher/publishers-alert/publishers-alert.service';
import { restoreKilledCapture } from './utils/camera';

const { SplashScreen } = Plugins;
Expand All @@ -28,32 +26,35 @@ export class AppComponent {
constructor(
private readonly platform: Platform,
private readonly collectorService: CollectorService,
private readonly publishersAlert: PublishersAlert,
private readonly translocoService: TranslocoService,
private readonly notificationService: NotificationService,
private readonly numbersStorageApi: NumbersStorageApi,
private readonly assetRepository: AssetRepository,
private readonly iconRegistry: MatIconRegistry,
private readonly sanitizer: DomSanitizer,
private readonly capacitorFactsProvider: CapacitorFactsProvider,
private readonly webCryptoApiSignatureProvider: WebCryptoApiSignatureProvider,
private readonly diaBackendAssetRepository: DiaBackendAssetRepository,
notificationService: NotificationService,
langaugeService: LanguageService
) {
notificationService.requestPermission();
langaugeService.initialize();
this.restoreAppStatus();
this.initializeApp();
this.initializeCollector();
this.initializePublisher();
this.registerIcon();
}

async restoreAppStatus() {
const photo = await restoreKilledCapture();
const proof = await this.collectorService.runAndStore({
[photo.base64]: { mimeType: photo.mimeType },
});
return this.publishersAlert.presentOrPublish(proof);
restoreAppStatus() {
return defer(restoreKilledCapture)
.pipe(
concatMap(photo =>
this.collectorService.runAndStore({
[photo.base64]: { mimeType: photo.mimeType },
})
),
concatMap(proof => this.diaBackendAssetRepository.add(proof)),
first(),
untilDestroyed(this)
)
.subscribe();
}

async initializeApp() {
Expand All @@ -69,17 +70,6 @@ export class AppComponent {
);
}

initializePublisher() {
this.publishersAlert.addPublisher(
new NumbersStoragePublisher(
this.translocoService,
this.notificationService,
this.numbersStorageApi,
this.assetRepository
)
);
}

registerIcon() {
this.iconRegistry.addSvgIcon(
'media-id',
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { FormlyModule } from '@ngx-formly/core';
import { FormlyMaterialModule } from '@ngx-formly/material';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { TranslocoRootModule } from './services/transloco/transloco-root.module';
import { TranslocoRootModule } from './services/language/transloco/transloco-root.module';
import { SharedModule } from './shared/shared.module';

@NgModule({
Expand Down
27 changes: 9 additions & 18 deletions src/app/guards/auth/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,25 @@ import {
RouterStateSnapshot,
UrlTree,
} from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { NumbersStorageApi } from '../../services/publisher/numbers-storage/numbers-storage-api.service';
import { DiaBackendAuthService } from '../../services/dia-backend/auth/dia-backend-auth.service';

@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(
private readonly router: Router,
private readonly numbersStorageApi: NumbersStorageApi
private readonly diaBackendAuthService: DiaBackendAuthService
) {}

canActivate(
async canActivate(
_route: ActivatedRouteSnapshot,
_state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
return this.numbersStorageApi.isEnabled$().pipe(
map(isEnabled => {
if (isEnabled) {
return true;
}
return this.router.parseUrl('/login');
})
);
): Promise<boolean | UrlTree> {
const hasLoggedIn = await this.diaBackendAuthService.hasLoggedIn();
if (!hasLoggedIn) {
return this.router.parseUrl('/login');
}
return hasLoggedIn;
}
}
7 changes: 7 additions & 0 deletions src/app/pages/home/activity/activity-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ const routes: Routes = [
path: '',
component: ActivityPage,
},
{
path: 'transaction-details',
loadChildren: () =>
import('./transaction-details/transaction-details.module').then(
m => m.TransactionDetailsPageModule
),
},
];

@NgModule({
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/home/activity/activity.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<ng-container
*ngFor="let activity of activitiesWithStatus$ | async; last as isLast"
>
<mat-list-item>
<mat-list-item routerLink="transaction-details" [state]="activity">
<img matListAvatar [src]="activity.asset.asset_file_thumbnail" />
<div mat-line>{{ activity.asset.id }}</div>
<div mat-line>{{ activity.created_at | date: 'short' }}</div>
Expand Down
6 changes: 6 additions & 0 deletions src/app/pages/home/activity/activity.page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ mat-toolbar {
border-color: deepskyblue;
}

button.waitingToBeAccepted {
color: white;
border-color: deepskyblue;
background-color: deepskyblue;
}

button.returned {
color: white;
border-color: var(--ion-color-danger);
Expand Down
70 changes: 33 additions & 37 deletions src/app/pages/home/activity/activity.page.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Component } from '@angular/core';
import { UntilDestroy } from '@ngneat/until-destroy';
import { of, zip } from 'rxjs';
import { concatMap, first, map, pluck } from 'rxjs/operators';
import { concatMap, pluck } from 'rxjs/operators';
import { DiaBackendAuthService } from '../../../services/dia-backend/auth/dia-backend-auth.service';
import {
NumbersStorageApi,
Transaction,
} from '../../../services/publisher/numbers-storage/numbers-storage-api.service';
import { forkJoinWithDefault } from '../../../utils/rx-operators';
DiaBackendTransaction,
DiaBackendTransactionRepository,
} from '../../../services/dia-backend/transaction/dia-backend-transaction-repository.service';

@UntilDestroy({ checkProperties: true })
@Component({
Expand All @@ -16,48 +15,45 @@ import { forkJoinWithDefault } from '../../../utils/rx-operators';
})
export class ActivityPage {
readonly status = Status;
readonly activitiesWithStatus$ = this.numbersStorageApi
.listTransactions$()
readonly activitiesWithStatus$ = this.diaBackendTransactionRepository
.getAll$()
.pipe(
pluck('results'),
concatMap(activities =>
zip(
of(activities),
forkJoinWithDefault(
activities.map(activity => this.getStatus$(activity))
)
Promise.all(
activities.map(async activity => ({
...activity,
status: await this.getStatus(activity),
}))
)
),
map(([activities, statusList]) =>
activities.map((activity, index) => ({
...activity,
status: statusList[index],
}))
)
);

constructor(private readonly numbersStorageApi: NumbersStorageApi) {}
constructor(
private readonly diaBackendAuthService: DiaBackendAuthService,
private readonly diaBackendTransactionRepository: DiaBackendTransactionRepository
) {}

private getStatus$(activity: Transaction) {
return this.numbersStorageApi.getEmail$().pipe(
map(email => {
if (activity.expired) {
return Status.Returned;
}
if (!activity.fulfilled_at) {
return Status.InProgress;
}
if (activity.sender === email) {
return Status.Delivered;
}
return Status.Accepted;
}),
first()
);
private async getStatus(activity: DiaBackendTransaction) {
const email = await this.diaBackendAuthService.getEmail();
if (activity.expired) {
return Status.Returned;
}
if (!activity.fulfilled_at) {
if (activity.receiver_email === email) {
return Status.InProgress;
}
return Status.waitingToBeAccepted;
}
if (activity.sender === email) {
return Status.Delivered;
}
return Status.Accepted;
}
}

enum Status {
export enum Status {
waitingToBeAccepted = 'waitingToBeAccepted',
InProgress = 'inProgress',
Returned = 'returned',
Delivered = 'delivered',
Expand Down
Loading

0 comments on commit 05a262c

Please sign in to comment.