diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 65d484520..f9d5d9474 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -12,6 +12,7 @@ import { PriceService } from './services/price.service'; import { EnterpriseService } from './services/enterprise.service'; import { WebsocketService } from './services/websocket.service'; import { AudioService } from './services/audio.service'; +import { PreloadService } from './services/preload.service'; import { SeoService } from './services/seo.service'; import { OpenGraphService } from './services/opengraph.service'; import { ZoneService } from './services/zone-shim.service'; @@ -46,6 +47,7 @@ const providers = [ CapAddressPipe, AppPreloadingStrategy, ServicesApiServices, + PreloadService, { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true }, { provide: ZONE_SERVICE, useClass: ZoneService }, ]; diff --git a/frontend/src/app/components/block/block-transactions.component.ts b/frontend/src/app/components/block/block-transactions.component.ts index 29e825ac1..08a2298dd 100644 --- a/frontend/src/app/components/block/block-transactions.component.ts +++ b/frontend/src/app/components/block/block-transactions.component.ts @@ -4,6 +4,7 @@ import { Transaction, Vout } from '../../interfaces/electrs.interface'; import { Observable, Subscription, catchError, combineLatest, map, of, startWith, switchMap, tap } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { ElectrsApiService } from '../../services/electrs-api.service'; +import { PreloadService } from '../../services/preload.service'; @Component({ selector: 'app-block-transactions', @@ -11,14 +12,13 @@ import { ElectrsApiService } from '../../services/electrs-api.service'; styleUrl: './block-transactions.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class BlockTransactionsComponent implements OnInit, OnDestroy { +export class BlockTransactionsComponent implements OnInit { @Input() txCount: number; @Input() timestamp: number; @Input() blockHash: string; @Input() previousBlockHash: string; @Input() block$: Observable; @Input() paginationMaxSize: number; - @Output() blockReward = new EventEmitter(); itemsPerPage = this.stateService.env.ITEMS_PER_PAGE; page = 1; @@ -50,20 +50,6 @@ export class BlockTransactionsComponent implements OnInit, OnDestroy { return of([]); })) ), - ) - .pipe( - tap((transactions: Transaction[]) => { - if (transactions && transactions[0] && transactions[0].vin[0].is_coinbase) { - const blockReward = transactions[0].vout.reduce((acc: number, curr: Vout) => acc + curr.value, 0) / 100000000; - this.blockReward.emit(blockReward); - } - this.unsubscribeNextBlockSubscriptions(); - if (this.previousBlockHash) { - setTimeout(() => { - this.nextBlockTxListSubscription = this.electrsApiService.getBlockTransactions$(this.previousBlockHash).subscribe(); - }, 100); - } - }) ); this.txsLoadingStatus$ = this.route.paramMap @@ -77,14 +63,4 @@ export class BlockTransactionsComponent implements OnInit, OnDestroy { target.scrollIntoView(); // works for chrome this.router.navigate([], { queryParams: { page: page }, queryParamsHandling: 'merge' }); } - - unsubscribeNextBlockSubscriptions(): void { - if (this.nextBlockTxListSubscription !== undefined) { - this.nextBlockTxListSubscription.unsubscribe(); - } - } - - ngOnDestroy(): void { - this.unsubscribeNextBlockSubscriptions(); - } } diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html index c83459375..c4975e686 100644 --- a/frontend/src/app/components/block/block.component.html +++ b/frontend/src/app/components/block/block.component.html @@ -326,7 +326,7 @@ @defer (on viewport) { - + } @placeholder {
diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index d1e175e91..d18a634b6 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -16,6 +16,7 @@ import { seoDescriptionNetwork } from '../../shared/common.utils'; import { PriceService, Price } from '../../services/price.service'; import { CacheService } from '../../services/cache.service'; import { ServicesApiServices } from '../../services/services-api.service'; +import { PreloadService } from '../../services/preload.service'; @Component({ selector: 'app-block', @@ -67,14 +68,11 @@ export class BlockComponent implements OnInit, OnDestroy { mode: 'projected' | 'actual' = 'projected'; overviewSubscription: Subscription; - auditSubscription: Subscription; keyNavigationSubscription: Subscription; blocksSubscription: Subscription; cacheBlocksSubscription: Subscription; networkChangedSubscription: Subscription; queryParamsSubscription: Subscription; - nextBlockSubscription: Subscription = undefined; - nextBlockSummarySubscription: Subscription = undefined; timeLtrSubscription: Subscription; timeLtr: boolean; childChangeSubscription: Subscription; @@ -101,6 +99,7 @@ export class BlockComponent implements OnInit, OnDestroy { private cacheService: CacheService, private servicesApiService: ServicesApiServices, private cd: ChangeDetectorRef, + private preloadService: PreloadService, ) { this.webGlEnabled = this.stateService.isBrowser && detectWebGL(); } @@ -159,7 +158,6 @@ export class BlockComponent implements OnInit, OnDestroy { switchMap((params: ParamMap) => { const blockHash: string = params.get('id') || ''; this.block = undefined; - // this.page = 1; this.error = undefined; this.fees = undefined; this.oobFees = 0; @@ -237,15 +235,11 @@ export class BlockComponent implements OnInit, OnDestroy { } }), tap((block: BlockExtended) => { - if (block.height > 0) { - // Preload previous block summary (execute the http query so the response will be cached) - this.unsubscribeNextBlockSubscriptions(); - setTimeout(() => { - this.nextBlockSubscription = this.apiService.getBlock$(block.previousblockhash).subscribe(); - if (this.auditSupported) { - this.apiService.getBlockAudit$(block.previousblockhash); - } - }, 100); + if (block.previousblockhash) { + this.preloadService.block$.next(block.previousblockhash); + if (this.auditSupported) { + this.preloadService.blockAudit$.next(block.previousblockhash); + } } this.updateAuditAvailableFromBlockHeight(block.height); this.block = block; @@ -536,29 +530,17 @@ export class BlockComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.stateService.markBlock$.next({}); this.overviewSubscription?.unsubscribe(); - this.auditSubscription?.unsubscribe(); this.keyNavigationSubscription?.unsubscribe(); this.blocksSubscription?.unsubscribe(); this.cacheBlocksSubscription?.unsubscribe(); this.networkChangedSubscription?.unsubscribe(); this.queryParamsSubscription?.unsubscribe(); this.timeLtrSubscription?.unsubscribe(); - this.auditSubscription?.unsubscribe(); - this.unsubscribeNextBlockSubscriptions(); this.childChangeSubscription?.unsubscribe(); this.priceSubscription?.unsubscribe(); this.oobSubscription?.unsubscribe(); } - unsubscribeNextBlockSubscriptions(): void { - if (this.nextBlockSubscription !== undefined) { - this.nextBlockSubscription.unsubscribe(); - } - if (this.nextBlockSummarySubscription !== undefined) { - this.nextBlockSummarySubscription.unsubscribe(); - } - } - // TODO - Refactor this.fees/this.reward for liquid because it is not // used anymore on Bitcoin networks (we use block.extras directly) setBlockSubsidy(): void { @@ -773,10 +755,4 @@ export class BlockComponent implements OnInit, OnDestroy { this.block.canonical = block.id; } } - - updateBlockReward(blockReward: number): void { - if (this.fees === undefined) { - this.fees = blockReward; - } - } } \ No newline at end of file diff --git a/frontend/src/app/services/preload.service.ts b/frontend/src/app/services/preload.service.ts new file mode 100644 index 000000000..386d4deb4 --- /dev/null +++ b/frontend/src/app/services/preload.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import { ElectrsApiService } from '../services/electrs-api.service'; +import { Subject, debounceTime, switchMap } from 'rxjs'; +import { ApiService } from './api.service'; + +@Injectable({ + providedIn: 'root' +}) +export class PreloadService { + block$ = new Subject; + blockAudit$ = new Subject; + debounceTime = 250; + + constructor( + private electrsApiService: ElectrsApiService, + private apiService: ApiService, + ) { + this.block$ + .pipe( + debounceTime(this.debounceTime), + switchMap((blockHash) => this.electrsApiService.getBlockTransactions$(blockHash)) + ) + .subscribe(); + + this.blockAudit$ + .pipe( + debounceTime(this.debounceTime), + switchMap((blockHash) => this.apiService.getBlockAudit$(blockHash)) + ) + .subscribe(); + } + +}