diff --git a/src/app/components/add-address/add-address.component.html b/src/app/components/add-address/add-address.component.html new file mode 100644 index 00000000..3f4f4f01 --- /dev/null +++ b/src/app/components/add-address/add-address.component.html @@ -0,0 +1,15 @@ + +
+

This address is not in your address book:

+
+ + {{ address }} +
+

Do you want to add it?

+
+ No + Yes +
+ No, disable address book feature +
+
\ No newline at end of file diff --git a/src/app/components/add-address/add-address.component.scss b/src/app/components/add-address/add-address.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/add-address/add-address.component.spec.ts b/src/app/components/add-address/add-address.component.spec.ts new file mode 100644 index 00000000..c773c3d2 --- /dev/null +++ b/src/app/components/add-address/add-address.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { AddAddressComponent } from './add-address.component'; + +describe('AddAddressComponent', () => { + let component: AddAddressComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ AddAddressComponent ], + imports: [IonicModule.forRoot()] + }).compileComponents(); + + fixture = TestBed.createComponent(AddAddressComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/add-address/add-address.component.ts b/src/app/components/add-address/add-address.component.ts new file mode 100644 index 00000000..6e86802f --- /dev/null +++ b/src/app/components/add-address/add-address.component.ts @@ -0,0 +1,78 @@ +import { IAirGapTransaction } from '@airgap/coinlib-core/interfaces/IAirGapTransaction'; +import { Component, Input, OnInit } from '@angular/core'; +import { AddType, ContactsService } from 'src/app/services/contacts/contacts.service'; +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service'; +import { NavigationService } from 'src/app/services/navigation/navigation.service'; + +@Component({ + selector: 'airgap-add-address', + templateUrl: './add-address.component.html', + styleUrls: ['./add-address.component.scss'], +}) +export class AddAddressComponent implements OnInit { + public addressesNotOnContactBook: string[] = [] + @Input() private airGapTxs: IAirGapTransaction[] = [] + // selectTransactionsDetails + // this.transactionsDetails$ = this.store.select(fromDeserializedDetail.selectTransactionsDetails) + + constructor(private readonly navigationService: NavigationService, private readonly contactsService: ContactsService) { } + + async ngOnInit() { + await this.checkAdressesNames() + } + + public async checkAdressesNames() { + // Check for addresses in contact book + if (this.airGapTxs && this.airGapTxs.length > 0) { + const isBookenabled = await this.contactsService.isBookEnabled() + if (isBookenabled) { + this.addressesNotOnContactBook = [] + for (let i = 0; i < this.airGapTxs.length; i++) { + this.airGapTxs[i].extra = { names: {} } + const transaction = this.airGapTxs[i] + const toAddresses = transaction.to + for (let j = 0; j < toAddresses.length; j++) { + const toAddress = toAddresses[j] + const hasContactBookAddress = await this.contactsService.isAddressInContacts(toAddress) + if (!hasContactBookAddress) this.addressesNotOnContactBook.push(toAddress) + else { + const name = await this.contactsService.getContactName(toAddress) + if (name) this.airGapTxs[i].extra.names[toAddress] = name + } + } + const fromAddresses = transaction.from + for (let j = 0; j < fromAddresses.length; j++) { + const fromAddress = fromAddresses[j] + const hasContactBookAddress = await this.contactsService.isAddressInContacts(fromAddress) + if (!hasContactBookAddress && !this.addressesNotOnContactBook.includes(fromAddress)) + this.addressesNotOnContactBook.push(fromAddress) + else { + const name = await this.contactsService.getContactName(fromAddress) + if (name) this.airGapTxs[i].extra.names[fromAddress] = name + } + } + } + } + } + } + + async onClickDontAddContact(address: string) { + await this.contactsService.addSuggestion(address) + const index = this.addressesNotOnContactBook.findIndex((address) => address === address) + if (index >= 0) { + this.addressesNotOnContactBook.splice(index, 1) + } + } + + async onClickAddContact(address: string) { + this.navigationService + .routeWithState('/contact-book-contacts-detail', { isNew: true, address, addType: AddType.SIGNING }) + .catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + async onClickDisableContact() { + await this.contactsService.setBookEnable(false) + this.addressesNotOnContactBook = [] + } + +} diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index 8bae9cbb..f1e3188d 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -27,6 +27,7 @@ import { VerifyKeyComponent } from './verify-key/verify-key.component' import { InteractionSelectionComponent } from './interaction-selection/interaction-selection.component' import { MnemonicKeyboardComponent } from './mnemonic-keyboard/mnemonic-keyboard.component' import { ProgressIndicatorComponent } from './progress-indicator/progress-indicator.component' +import { AddAddressComponent } from './add-address/add-address.component' @NgModule({ declarations: [ @@ -47,7 +48,8 @@ import { ProgressIndicatorComponent } from './progress-indicator/progress-indica KeyboardPopoverComponent, InteractionSelectionComponent, MnemonicKeyboardComponent, - ProgressIndicatorComponent + ProgressIndicatorComponent, + AddAddressComponent ], imports: [ IonicModule, @@ -78,7 +80,8 @@ import { ProgressIndicatorComponent } from './progress-indicator/progress-indica KeyboardPopoverComponent, InteractionSelectionComponent, MnemonicKeyboardComponent, - ProgressIndicatorComponent + ProgressIndicatorComponent, + AddAddressComponent ] }) export class ComponentsModule {} diff --git a/src/app/pages/interaction-selection/interaction-selection.module.ts b/src/app/pages/interaction-selection/interaction-selection.module.ts index b082a76a..5950be53 100644 --- a/src/app/pages/interaction-selection/interaction-selection.module.ts +++ b/src/app/pages/interaction-selection/interaction-selection.module.ts @@ -5,6 +5,8 @@ import { RouterModule, Routes } from '@angular/router' import { IonicModule } from '@ionic/angular' import { TranslateModule } from '@ngx-translate/core' +import { ComponentsModule } from '../../components/components.module' + import { InteractionSelectionPage } from './interaction-selection.page' const routes: Routes = [ @@ -15,7 +17,7 @@ const routes: Routes = [ ] @NgModule({ - imports: [CommonModule, FormsModule, IonicModule, RouterModule.forChild(routes), TranslateModule], + imports: [CommonModule, FormsModule, IonicModule, RouterModule.forChild(routes), TranslateModule, ComponentsModule], declarations: [InteractionSelectionPage] }) export class InteractionSelectionPageModule {} diff --git a/src/app/pages/interaction-selection/interaction-selection.page.html b/src/app/pages/interaction-selection/interaction-selection.page.html index c642b6aa..6f9c9698 100644 --- a/src/app/pages/interaction-selection/interaction-selection.page.html +++ b/src/app/pages/interaction-selection/interaction-selection.page.html @@ -29,4 +29,6 @@

diff --git a/src/app/pages/interaction-selection/interaction-selection.page.ts b/src/app/pages/interaction-selection/interaction-selection.page.ts index c1ae0344..cc34a043 100644 --- a/src/app/pages/interaction-selection/interaction-selection.page.ts +++ b/src/app/pages/interaction-selection/interaction-selection.page.ts @@ -4,6 +4,9 @@ import { InteractionType, VaultStorageKey, VaultStorageService } from 'src/app/s import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/error-handler.service' import { IInteractionOptions, InteractionCommunicationType, InteractionService } from '../../services/interaction/interaction.service' import { NavigationService } from '../../services/navigation/navigation.service' +import { Store } from '@ngrx/store' +import { selectTransactionsDetails } from '../deserialized-detail/deserialized-detail.reducer' +import * as fromDeserializedDetail from '../deserialized-detail/deserialized-detail.reducer' @Component({ selector: 'airgap-interaction-selection', @@ -12,11 +15,13 @@ import { NavigationService } from '../../services/navigation/navigation.service' }) export class InteractionSelectionPage { private interactionOptions: IInteractionOptions + transactionsDetails$ = this.store.select(selectTransactionsDetails) constructor( private readonly navigationService: NavigationService, private readonly storageService: VaultStorageService, - private readonly interactionService: InteractionService + private readonly interactionService: InteractionService, + private store: Store ) {} public ionViewDidEnter(): void {