diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts
index 320ac6a9d..4e327eced 100644
--- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts
+++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts
@@ -1,27 +1,32 @@
-import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
-import { Subscription, pipe } from 'rxjs';
+import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
+import { Subscription, Observable, fromEvent, merge, of } from 'rxjs';
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
import { StateService } from 'src/app/services/state.service';
import { Router } from '@angular/router';
-import { take, map } from 'rxjs/operators';
+import { take, map, switchMap } from 'rxjs/operators';
import { feeLevels, mempoolFeeColors } from 'src/app/app.constants';
@Component({
selector: 'app-mempool-blocks',
templateUrl: './mempool-blocks.component.html',
styleUrls: ['./mempool-blocks.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MempoolBlocksComponent implements OnInit, OnDestroy {
mempoolBlocks: MempoolBlock[];
+ mempoolBlocks$: Observable;
+
mempoolBlocksFull: MempoolBlock[];
mempoolBlockStyles = [];
- mempoolBlocksSubscription: Subscription;
+ markBlocksSubscription: Subscription;
+ blockSubscription: Subscription;
+ networkSubscription: Subscription;
network = '';
blockWidth = 125;
blockPadding = 30;
arrowVisible = false;
- tabHidden = true;
+ tabHidden = false;
rightPosition = 0;
transition = '2s';
@@ -36,21 +41,25 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
constructor(
private router: Router,
private stateService: StateService,
+ private cd: ChangeDetectorRef,
) { }
ngOnInit() {
this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden);
- this.mempoolBlocksSubscription = this.stateService.mempoolBlocks$
- .pipe(
- map((blocks) => {
- if (!blocks.length) {
- return [{ index: 0, blockSize: 0, blockVSize: 0, feeRange: [0, 0], medianFee: 0, nTx: 0, totalFees: 0 }];
- }
- return blocks;
- }),
- )
- .subscribe((blocks) => {
+ this.mempoolBlocks$ = merge(
+ of(true),
+ fromEvent(window, 'resize')
+ )
+ .pipe(
+ switchMap(() => this.stateService.mempoolBlocks$),
+ map((blocks) => {
+ if (!blocks.length) {
+ return [{ index: 0, blockSize: 0, blockVSize: 0, feeRange: [0, 0], medianFee: 0, nTx: 0, totalFees: 0 }];
+ }
+ return blocks;
+ }),
+ map((blocks) => {
blocks.forEach((block, i) => {
block.index = this.blockIndex + i;
});
@@ -59,9 +68,11 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(JSON.parse(stringifiedBlocks));
this.updateMempoolBlockStyles();
this.calculateTransactionPosition();
- });
+ return this.mempoolBlocks;
+ })
+ );
- this.stateService.markBlock$
+ this.markBlocksSubscription = this.stateService.markBlock$
.subscribe((state) => {
this.markIndex = undefined;
this.txFeePerVSize = undefined;
@@ -72,16 +83,17 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
this.txFeePerVSize = state.txFeePerVSize;
}
this.calculateTransactionPosition();
+ this.cd.markForCheck();
});
- this.stateService.blocks$
+ this.blockSubscription = this.stateService.blocks$
.subscribe(([block]) => {
if (block.matchRate >= 66 && !this.tabHidden) {
this.blockIndex++;
}
});
- this.stateService.networkChanged$
+ this.networkSubscription = this.stateService.networkChanged$
.subscribe((network) => this.network = network);
this.stateService.keyNavigation$.subscribe((event) => {
@@ -109,15 +121,11 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
});
}
- @HostListener('window:resize', ['$event'])
- onResize() {
- if (this.mempoolBlocks && this.mempoolBlocks.length) {
- this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(JSON.parse(JSON.stringify(this.mempoolBlocksFull)));
- }
- }
-
ngOnDestroy() {
- this.mempoolBlocksSubscription.unsubscribe();
+ this.markBlocksSubscription.unsubscribe();
+ this.blockSubscription.unsubscribe();
+ this.networkSubscription.unsubscribe();
+ clearTimeout(this.resetTransitionTimeout);
}
trackByFn(index: number, block: MempoolBlock) {
@@ -192,7 +200,11 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
this.transition = 'inherit';
this.rightPosition = this.markIndex * (this.blockWidth + this.blockPadding) + 0.5 * this.blockWidth;
this.arrowVisible = true;
- this.resetTransitionTimeout = window.setTimeout(() => this.transition = '2s', 100);
+
+ this.resetTransitionTimeout = window.setTimeout(() => {
+ this.transition = '2s';
+ this.cd.markForCheck();
+ }, 100);
return;
}
diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts
index 259a003c5..1fe8ddf9b 100644
--- a/frontend/src/app/components/transaction/transaction.component.ts
+++ b/frontend/src/app/components/transaction/transaction.component.ts
@@ -1,7 +1,7 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ElectrsApiService } from '../../services/electrs-api.service';
import { ActivatedRoute, ParamMap } from '@angular/router';
-import { switchMap, filter, take, catchError, flatMap } from 'rxjs/operators';
+import { switchMap, filter, catchError } from 'rxjs/operators';
import { Transaction, Block } from '../../interfaces/electrs.interface';
import { of, merge, Subscription, Observable } from 'rxjs';
import { StateService } from '../../services/state.service';
@@ -9,7 +9,6 @@ import { WebsocketService } from '../../services/websocket.service';
import { AudioService } from 'src/app/services/audio.service';
import { ApiService } from 'src/app/services/api.service';
import { SeoService } from 'src/app/services/seo.service';
-import { BisqTransaction } from 'src/app/bisq/bisq.interfaces';
@Component({
selector: 'app-transaction',
diff --git a/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts
index 32ca9b258..639822dda 100644
--- a/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts
+++ b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts
@@ -1,15 +1,19 @@
-import { Component, ChangeDetectionStrategy, OnChanges, Input, OnInit, ChangeDetectorRef } from '@angular/core';
+import { Component, ChangeDetectionStrategy, OnChanges, Input, OnInit, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { Transaction, Block } from 'src/app/interfaces/electrs.interface';
import { StateService } from 'src/app/services/state.service';
+import { Subscription } from 'rxjs';
@Component({
selector: 'app-tx-fee-rating',
templateUrl: './tx-fee-rating.component.html',
styleUrls: ['./tx-fee-rating.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class TxFeeRatingComponent implements OnInit, OnChanges {
+export class TxFeeRatingComponent implements OnInit, OnChanges, OnDestroy {
@Input() tx: Transaction;
+ blocksSubscription: Subscription;
+
medianFeeNeeded: number;
overpaidTimes: number;
feeRating: number;
@@ -18,13 +22,15 @@ export class TxFeeRatingComponent implements OnInit, OnChanges {
constructor(
private stateService: StateService,
+ private cd: ChangeDetectorRef,
) { }
ngOnInit() {
- this.stateService.blocks$.subscribe(([block]) => {
+ this.blocksSubscription = this.stateService.blocks$.subscribe(([block]) => {
this.blocks.push(block);
if (this.tx.status.confirmed && this.tx.status.block_height === block.height) {
this.calculateRatings(block);
+ this.cd.markForCheck();
}
});
}
@@ -41,6 +47,10 @@ export class TxFeeRatingComponent implements OnInit, OnChanges {
}
}
+ ngOnDestroy() {
+ this.blocksSubscription.unsubscribe();
+ }
+
calculateRatings(block: Block) {
const feePervByte = this.tx.fee / (this.tx.weight / 4);
this.medianFeeNeeded = Math.round(block.feeRange[Math.round(block.feeRange.length * 0.5)]);