diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html index 5a73a48cf..552e64d1e 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html @@ -1,147 +1,133 @@ -
+
@if (error) { - - } @else { +
+ +
+ } - @if (step === 'completed') { -
-
-
-
-
Transaction is now being accelerated!
-
-
-
+ @else if (step === 'cta') { + +
+
+

Accelerate your Bitcoin transaction?

- } +
- @else if (step === 'cta') { - -
+
+
-

Accelerate your Bitcoin transaction?

-
-
- - -
-
-
- - -
-
-
-
-
-
- - -
-
-
-
-
- -
-
-
- } - - @else if (step === 'checkout') { - -
-
-

Confirm your payment

-
-
- -
-
-
- Payment to mempool.space for acceleration of txid {{ txid.substr(0, 10) }}..{{ txid.substr(-10) }} -
-
-
- - @if (!loadingCashapp) { -
-
-
- Total additional cost
- - Pay - - with - +
+ +
-
-
- } - -
-
-
-
- @if (loadingCashapp) { -
- Loading payment method... -
-
- } +
- -
-
-
- Changed your mind? - -
-
- } - - @else if (step === 'processing') { -
+
-

Confirm your payment

+
+ + +
+
+
+ +
+
+ + } + + @else if (step === 'checkout') { + +
+
+

Confirm your payment

+
+
- -
+
+
+
+ Payment to mempool.space for acceleration of txid {{ txid.substr(0, 10) }}..{{ txid.substr(-10) }} +
+
+
+ @if (!loadingCashapp) {
-
- We are processing your payment... -
-
+ Total additional cost
+ + Pay + + with + +
} - +
+
+
+
+ @if (loadingCashapp) { +
+ Loading payment method... +
+
+ } +
+
+
+ +
+
+
+ Changed your mind? + +
+
+ } + + @else if (step === 'processing') { +
+
+

Confirm your payment

+
+
+ +
+
+
+ +
+
+ We are processing your payment... +
+
+
+
+
}
diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts index dc2d03d02..249568efa 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts @@ -1,6 +1,5 @@ -import { Component, OnInit, OnDestroy, Output, EventEmitter, Input, ChangeDetectorRef } from '@angular/core'; +import { Component, OnInit, OnDestroy, Output, EventEmitter, Input, ChangeDetectorRef, SimpleChanges } from '@angular/core'; import { Subscription, tap, of, catchError } from 'rxjs'; -import { WebsocketService } from '../../services/websocket.service'; import { ServicesApiServices } from '../../services/services-api.service'; import { nextRoundNumber } from '../../shared/common.utils'; import { StateService } from '../../services/state.service'; @@ -14,6 +13,7 @@ import { AudioService } from '../../services/audio.service'; export class AccelerateCheckout implements OnInit, OnDestroy { @Input() eta: number = Date.now() + 123456789; @Input() txid: string = '70c18d76cdb285a1b5bd87fdaae165880afa189809c30b4083ff7c0e69ee09ad'; + @Input() scrollEvent: boolean; @Output() close = new EventEmitter(); calculating = true; @@ -34,10 +34,9 @@ export class AccelerateCheckout implements OnInit, OnDestroy { cashAppPay: any; cashAppSubscription: Subscription; conversionsSubscription: Subscription; - step: 'cta' | 'checkout' | 'processing' | 'completed' = 'cta'; + step: 'cta' | 'checkout' | 'processing' = 'cta'; constructor( - private websocketService: WebsocketService, private servicesApiService: ServicesApiServices, private stateService: StateService, private audioService: AudioService, @@ -63,7 +62,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy { this.estimate(); } }); - } ngOnDestroy() { @@ -72,6 +70,32 @@ export class AccelerateCheckout implements OnInit, OnDestroy { } } + ngOnChanges(changes: SimpleChanges): void { + if (changes.scrollEvent) { + this.scrollToPreview('acceleratePreviewAnchor', 'start'); + } + } + + /** + * Scroll to element id with or without setTimeout + */ + scrollToPreviewWithTimeout(id: string, position: ScrollLogicalPosition) { + setTimeout(() => { + this.scrollToPreview(id, position); + }, 1000); + } + scrollToPreview(id: string, position: ScrollLogicalPosition) { + const acceleratePreviewAnchor = document.getElementById(id); + if (acceleratePreviewAnchor) { + this.cd.markForCheck(); + acceleratePreviewAnchor.scrollIntoView({ + behavior: 'smooth', + inline: position, + block: position, + }); + } + } + /** * Accelerator */ @@ -148,8 +172,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { this.payments = window.Square.payments(this.square.appId, this.square.locationId) await this.requestCashAppPayment(); } catch (e) { - console.error(e); - this.error = 'Error loading Square Payments'; + console.debug('Error loading Square Payments', e); return; } } @@ -164,7 +187,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { this.conversionsSubscription = this.stateService.conversions$.subscribe( async (conversions) => { if (this.cashAppPay) { - await this.cashAppPay.destroy(); + this.cashAppPay.destroy(); } const redirectHostname = document.location.hostname === 'localhost' ? `http://localhost:4200`: `https://${document.location.hostname}`; @@ -206,16 +229,27 @@ export class AccelerateCheckout implements OnInit, OnDestroy { ).subscribe({ next: () => { that.audioService.playSound('ascend-chime-cartoon'); - that.step = 'completed'; + if (that.cashAppPay) { + that.cashAppPay.destroy(); + } setTimeout(() => { that.closeModal(); - }, 10000); + if (window.history.replaceState) { + const urlParams = new URLSearchParams(window.location.search); + window.history.replaceState(null, null, window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, '')); + } + }, 1000); }, error: (response) => { if (response.status === 403 && response.error === 'not_available') { that.error = 'waitlisted'; } else { that.error = response.error; + setTimeout(() => { + // Reset everything by reloading the page :D, can be improved + const urlParams = new URLSearchParams(window.location.search); + window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``)); + }, 3000); } } }); @@ -236,19 +270,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy { } selectedOptionChanged(event) { this.choosenOption = event.target.id; - if (this.choosenOption === 'wait') { - this.restart(); - this.closeModal(); - } - } - restart() { - this.step = 'cta'; - this.choosenOption = 'wait'; } closeModal(): void { - if (this.cashAppPay) { - this.cashAppPay.destroy(); - } this.close.emit(); } } diff --git a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts index eaa995683..76833bb1a 100644 --- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts +++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges, HostListener, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core'; +import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges, HostListener, ChangeDetectorRef } from '@angular/core'; import { Subscription, catchError, of, tap } from 'rxjs'; import { StorageService } from '../../services/storage.service'; import { Transaction } from '../../interfaces/electrs.interface'; diff --git a/frontend/src/app/components/tracker/tracker.component.html b/frontend/src/app/components/tracker/tracker.component.html index fc273aaaf..c75e6fec6 100644 --- a/frontend/src/app/components/tracker/tracker.component.html +++ b/frontend/src/app/components/tracker/tracker.component.html @@ -29,7 +29,7 @@
@if (tx && !tx.status?.confirmed && mempoolPosition?.block != null) { -
+
First seen
@if (transactionTime > 0) { @@ -39,7 +39,7 @@ }
-
+
ETA
@@ -48,14 +48,14 @@ } @else { } - @if (isMobile && paymentType === 'cashapp' && accelerationEligible && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { + @if (!showAccelerationSummary && isMobile && paymentType === 'cashapp' && accelerationEligible && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { Accelerate }
} @else if (tx && tx.status?.confirmed) { -
+
Confirmed at
‎{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }} @@ -64,7 +64,7 @@
-
+
Block height
@@ -84,8 +84,8 @@
- @if (showAccelerationSummary) { - + @if (showAccelerationSummary && !accelerationFlowCompleted) { + } @else { @if (tx?.acceleration && !tx.status?.confirmed) {
diff --git a/frontend/src/app/components/tracker/tracker.component.scss b/frontend/src/app/components/tracker/tracker.component.scss index 6d80c7521..90f4cbd4b 100644 --- a/frontend/src/app/components/tracker/tracker.component.scss +++ b/frontend/src/app/components/tracker/tracker.component.scss @@ -92,6 +92,10 @@ white-space: nowrap; text-align: end; } + &.narrower { + padding-top: 0.75em !important; + padding-bottom: 0.75em !important; + } } .tracker-bar { diff --git a/frontend/src/app/components/tracker/tracker.component.ts b/frontend/src/app/components/tracker/tracker.component.ts index e9a6ab2ae..484aa0070 100644 --- a/frontend/src/app/components/tracker/tracker.component.ts +++ b/frontend/src/app/components/tracker/tracker.component.ts @@ -19,11 +19,9 @@ import { WebsocketService } from '../../services/websocket.service'; import { AudioService } from '../../services/audio.service'; import { ApiService } from '../../services/api.service'; import { SeoService } from '../../services/seo.service'; -import { StorageService } from '../../services/storage.service'; import { seoDescriptionNetwork } from '../../shared/common.utils'; import { Filter } from '../../shared/filters.utils'; import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment, Acceleration } from '../../interfaces/node-api.interface'; -import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { PriceService } from '../../services/price.service'; import { ServicesApiServices } from '../../services/services-api.service'; import { EnterpriseService } from '../../services/enterprise.service'; @@ -111,6 +109,7 @@ export class TrackerComponent implements OnInit, OnDestroy { acceleratorAvailable: boolean = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === ''; accelerationEligible: boolean = false; showAccelerationSummary = false; + accelerationFlowCompleted = false; scrollIntoAccelPreview = false; auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; @@ -143,7 +142,7 @@ export class TrackerComponent implements OnInit, OnDestroy { this.acceleratorAvailable = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === ''; - if (this.acceleratorAvailable && this.stateService.ref === 'https://cash.app/') { + if (this.acceleratorAvailable && this.stateService.referrer === 'https://cash.app/') { this.paymentType = 'cashapp'; } const urlParams = new URLSearchParams(window.location.search); @@ -351,6 +350,9 @@ export class TrackerComponent implements OnInit, OnDestroy { } if (txPosition.position?.block > 0 && this.tx.weight < 4000) { this.accelerationEligible = true; + if (this.acceleratorAvailable && this.paymentType === 'cashapp') { + this.showAccelerationSummary = true; + } } } } else { diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index 5cea17f3c..3c9b895d9 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -747,11 +747,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { } resetTransaction() { - if (!this.firstLoad) { - this.stateService.ref = ''; - } else { - this.firstLoad = false; - } + this.firstLoad = false; this.error = undefined; this.tx = null; this.setFeatures(); @@ -847,7 +843,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { } ngOnDestroy() { - this.stateService.ref = ''; this.subscription.unsubscribe(); this.fetchCpfpSubscription.unsubscribe(); this.fetchRbfSubscription.unsubscribe(); diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts index 9dfec85e6..970bfcac3 100644 --- a/frontend/src/app/services/state.service.ts +++ b/frontend/src/app/services/state.service.ts @@ -86,7 +86,7 @@ const defaultEnv: Env = { providedIn: 'root' }) export class StateService { - ref: string = ''; + referrer: string = ''; isBrowser: boolean = isPlatformBrowser(this.platformId); isMempoolSpaceBuild = window['isMempoolSpaceBuild'] ?? false; backend: 'esplora' | 'electrum' | 'none' = 'esplora'; @@ -164,7 +164,7 @@ export class StateService { private router: Router, private storageService: StorageService, ) { - this.ref = window.document.referrer; + this.referrer = window.document.referrer; const browserWindow = window || {}; // @ts-ignore @@ -192,7 +192,7 @@ export class StateService { } }); - if (this.ref === 'https://cash.app/' && window.innerWidth < 850 && window.location.pathname.startsWith('/tx/')) { + if (this.referrer === 'https://cash.app/' && window.innerWidth < 850 && window.location.pathname.startsWith('/tx/')) { this.router.navigate(['/tracker/' + window.location.pathname.slice(4)]); } diff --git a/frontend/src/resources/mempool-accelerator-sparkles-compressed.svg b/frontend/src/resources/mempool-accelerator-sparkles-compressed.svg deleted file mode 100644 index 4a5bac3cc..000000000 --- a/frontend/src/resources/mempool-accelerator-sparkles-compressed.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/resources/mempool-accelerator-sparkles-light.svg b/frontend/src/resources/mempool-accelerator-sparkles-light.svg new file mode 100644 index 000000000..8998e0c22 --- /dev/null +++ b/frontend/src/resources/mempool-accelerator-sparkles-light.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file