Simple mode redesign w/ sticky button
This commit is contained in:
		
							parent
							
								
									aa0c70bd44
								
							
						
					
					
						commit
						48e16e64c2
					
				| @ -286,14 +286,17 @@ | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="row d-flex justify-content-end align-items-center mr-1" style="height: 48px" *ngIf="!hideCashApp && paymentType === 'cashapp'"> | ||||
|         <div [style]="showSpinner ? 'opacity: 0' : 'opacity: 1'" class="p-2">Accelerate with</div> | ||||
|         <div id="cash-app-pay" style="max-width: 320px" [style]="showSpinner ? 'opacity: 0' : 'opacity: 1'"></div> | ||||
|         <div *ngIf="showSpinner" class="d-flex align-items-center"> | ||||
|           <span class="mr-2">Loading</span> | ||||
|           <div class="spinner-border text-light" style="width: 25px; height: 25px"></div> | ||||
|       @if (!hideCashApp && paymentType === 'cashapp') { | ||||
|         <div #cashappCTA class="cashapp-placeholder {{ stickyCTA }}"></div> | ||||
|         <div class="d-flex justify-content-center align-items-center cashapp-cta {{ stickyCTA }}" (click)="submitCashappPay()"> | ||||
|           <div [style]="showSpinner ? 'opacity: 0' : 'opacity: 1'" class="p-2">Accelerate for <app-fiat [value]="maxCost" [colorClass]="estimate.userBalance < maxCost ? 'red-color' : 'green-color'"></app-fiat> with</div> | ||||
|           <div id="cash-app-pay" style="max-width: 320px" [style]="showSpinner ? 'opacity: 0' : 'opacity: 1'"></div> | ||||
|           <div *ngIf="showSpinner" class="d-flex align-items-center"> | ||||
|             <span class="mr-2">Loading</span> | ||||
|             <div class="spinner-border text-light" style="width: 25px; height: 25px"></div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       } | ||||
|    | ||||
|     </div> | ||||
|   </ng-container> | ||||
|  | ||||
| @ -109,4 +109,53 @@ | ||||
| 
 | ||||
| .item { | ||||
|   white-space: initial; | ||||
| } | ||||
| 
 | ||||
| .cashapp-cta { | ||||
|   width: 100%; | ||||
|   height: 54px; | ||||
|   background: #653b9c; | ||||
|   position: relative; | ||||
|   bottom: initial; | ||||
|   top: initial; | ||||
|   border-radius: 3px; | ||||
|   font-size: 14px; | ||||
|   line-height: 16px; | ||||
|   text-align: center; | ||||
|   padding: 4px 6px; | ||||
|   cursor: pointer; | ||||
|   box-shadow: 0px 0px 15px 0px #000; | ||||
| 
 | ||||
|   &.sticky-top { | ||||
|     position: fixed; | ||||
|     width: calc(100vw - 30px - 1.5rem); | ||||
|     margin: auto; | ||||
|     z-index: 50; | ||||
|     left: 0; | ||||
|     right: 0; | ||||
|     top: 102px; | ||||
|     @media (min-width: 573px) { | ||||
|       top: 62px; | ||||
|     } | ||||
|   } | ||||
|   &.sticky-bottom { | ||||
|     position: fixed; | ||||
|     width: calc(100vw - 30px - 1.5rem); | ||||
|     margin: auto; | ||||
|     z-index: 50; | ||||
|     left: 0; | ||||
|     right: 0; | ||||
|     bottom: 50px; | ||||
|     @media (min-width: 430px) { | ||||
|       bottom: 56px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .cashapp-placeholder { | ||||
|   height: 54px; | ||||
| 
 | ||||
|   &.non-stick { | ||||
|     height: 0px; | ||||
|   } | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges, HostListener, ChangeDetectorRef } from '@angular/core'; | ||||
| import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges, HostListener, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core'; | ||||
| import { Subscription, catchError, of, tap } from 'rxjs'; | ||||
| import { StorageService } from '../../services/storage.service'; | ||||
| import { Transaction } from '../../interfaces/electrs.interface'; | ||||
| @ -43,6 +43,9 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|   @Input() tx: Transaction | undefined; | ||||
|   @Input() scrollEvent: boolean; | ||||
| 
 | ||||
|   @ViewChild('cashappCTA') | ||||
|   cashappCTA: ElementRef; | ||||
| 
 | ||||
|   math = Math; | ||||
|   error = ''; | ||||
|   showSuccess = false; | ||||
| @ -59,6 +62,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|   selectFeeRateIndex = 1; | ||||
|   isMobile: boolean = window.innerWidth <= 767.98; | ||||
|   user: any = undefined; | ||||
|   stickyCTA: string = 'non-stick'; | ||||
| 
 | ||||
|   maxRateOptions: RateOption[] = []; | ||||
| 
 | ||||
| @ -66,6 +70,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|   paymentType: 'bitcoin' | 'cashapp' = 'bitcoin'; | ||||
|   cashAppSubscription: Subscription; | ||||
|   conversionsSubscription: Subscription; | ||||
|   cashappSubmit: any; | ||||
|   payments: any; | ||||
|   showSpinner = false; | ||||
|   square: any; | ||||
| @ -96,14 +101,14 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|   ngOnInit() { | ||||
|     if (this.stateService.ref === 'https://cash.app/') { | ||||
|       this.paymentType = 'cashapp'; | ||||
|       this.stateService.ref = ''; | ||||
|     } else { | ||||
|       this.paymentType = 'bitcoin'; | ||||
|     } | ||||
|     this.onScroll(); | ||||
|   } | ||||
| 
 | ||||
|   ngOnChanges(changes: SimpleChanges): void { | ||||
|     if (changes.scrollEvent) { | ||||
|     if (changes.scrollEvent && this.paymentType !== 'cashapp') { | ||||
|       this.scrollToPreview('acceleratePreviewAnchor', 'start'); | ||||
|     } | ||||
|   } | ||||
| @ -173,10 +178,11 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|             this.maxCost = this.userBid + this.estimate.mempoolBaseFee + this.estimate.vsizeFee; | ||||
| 
 | ||||
|             if (!this.error) { | ||||
|               this.scrollToPreview('acceleratePreviewAnchor', 'start'); | ||||
|               if (this.paymentType === 'cashapp') { | ||||
|                 this.setupSquare(); | ||||
|               }  | ||||
|               } else { | ||||
|                 this.scrollToPreview('acceleratePreviewAnchor', 'start'); | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }), | ||||
| @ -310,13 +316,15 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|             label: 'Total', | ||||
|             pending: true, | ||||
|             productUrl: `https://mempool.space/tx/${this.tx.txid}`, | ||||
|           } | ||||
|           }, | ||||
|           button: { shape: 'semiround', size: 'small', theme: 'light'} | ||||
|         }); | ||||
|         this.cashAppPay = await this.payments.cashAppPay(paymentRequest, { | ||||
|           redirectURL: `https://mempool.space/tx/${this.tx.txid}`, | ||||
|           referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`, | ||||
|           button: { shape: 'semiround', size: 'small', theme: 'light'} | ||||
|         }); | ||||
|         await this.cashAppPay.attach('#cash-app-pay'); | ||||
|         const renderPromise = this.cashAppPay.CashAppPayInstance.render('#cash-app-pay', { button: { theme: 'light', size: 'small', shape: 'semiround' }, manage: false }); | ||||
|         this.showSpinner = false; | ||||
|          | ||||
|         const that = this; | ||||
| @ -351,6 +359,8 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|             }); | ||||
|           } | ||||
|         }); | ||||
| 
 | ||||
|         this.cashappSubmit = await renderPromise; | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| @ -367,4 +377,28 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges | ||||
|       g.type='text/javascript'; g.src=statsUrl; s.parentNode.insertBefore(g, s); | ||||
|     })(); | ||||
|   } | ||||
| 
 | ||||
|   submitCashappPay(): void { | ||||
|     if (this.cashappSubmit) { | ||||
|       this.cashappSubmit?.begin(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @HostListener('window:scroll', ['$event']) // for window scroll events
 | ||||
|   onScroll() { | ||||
|     if (!this.cashappCTA?.nativeElement || this.paymentType !== 'cashapp' || !this.isMobile) { | ||||
|       return; | ||||
|     } | ||||
|     const cta = this.cashappCTA.nativeElement; | ||||
|     const rect = cta.getBoundingClientRect(); | ||||
|     const topOffset = window.innerWidth <= 572 ? 102 : 62; | ||||
|     const bottomOffset = window.innerWidth < 430 ? 50 : 56; | ||||
|     if (rect.top < topOffset) { | ||||
|       this.stickyCTA = 'sticky-top'; | ||||
|     } else if (rect.top > window.innerHeight - (bottomOffset + 54)) { | ||||
|       this.stickyCTA = 'sticky-bottom'; | ||||
|     } else { | ||||
|       this.stickyCTA = 'non-stick'; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -80,7 +80,9 @@ | ||||
|       <div class="title float-left"> | ||||
|         <h2 i18n="transaction.accelerate|Accelerate button label">Accelerate</h2> | ||||
|       </div> | ||||
|       <button type="button" class="btn btn-outline-info accelerator-toggle btn-sm float-right" (click)="showAccelerationSummary = false" i18n="hide-accelerator">Hide accelerator</button> | ||||
|       @if (!(isMobile && paymentType === 'cashapp')) { | ||||
|         <button type="button" class="btn btn-outline-info accelerator-toggle btn-sm float-right" (click)="showAccelerationSummary = false" i18n="hide-accelerator">Hide accelerator</button> | ||||
|       } | ||||
|       <div class="clearfix"></div> | ||||
| 
 | ||||
|       <div class="box"> | ||||
| @ -409,9 +411,6 @@ | ||||
|   } @else { | ||||
|     <ng-container *ngTemplateOutlet="firstSeenRow"></ng-container> | ||||
|     <ng-container *ngTemplateOutlet="etaRow"></ng-container> | ||||
|     @if (isMobile) { | ||||
|       <ng-container *ngTemplateOutlet="accelerateRow"></ng-container> | ||||
|     } | ||||
|   } | ||||
|   <ng-container *ngTemplateOutlet="featuresRow"></ng-container> | ||||
|   @if (tx?.status?.confirmed) { | ||||
| @ -533,7 +532,7 @@ | ||||
|           } @else if (this.mempoolPosition.block >= 7) { | ||||
|             <span [class]="(acceleratorAvailable && accelerateCtaType === 'button') ? 'etaDeepMempool d-flex justify-content-end align-items-center' : ''"> | ||||
|               <span i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span> | ||||
|               @if (!isMobile && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { | ||||
|               @if (!(isMobile && paymentType === 'cashapp') && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { | ||||
|                 <a [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn btn-sm accelerateDeepMempool btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> | ||||
|               } | ||||
|             </span> | ||||
| @ -542,7 +541,7 @@ | ||||
|           } @else { | ||||
|             <span class="eta justify-content-end" [class]="(acceleratorAvailable && accelerateCtaType === 'button') ? 'd-flex align-items-center' : ''"> | ||||
|               <app-time kind="until" *ngIf="(da$ | async) as da;" [time]="da.adjustedTimeAvg * (this.mempoolPosition.block + 1) + now + da.timeOffset" [fastRender]="false" [fixedRender]="true"></app-time> | ||||
|               @if (!isMobile && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { | ||||
|               @if (!(isMobile && paymentType === 'cashapp') && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { | ||||
|                 <a [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn btn-sm accelerate btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> | ||||
|               } | ||||
|             </span> | ||||
| @ -555,18 +554,6 @@ | ||||
|   } | ||||
| </ng-template> | ||||
| 
 | ||||
| <ng-template #accelerateRow> | ||||
|   @if (!isLoadingTx) { | ||||
|     <tr> | ||||
|       <td class="td-width align-items-center align-middle p-0" colspan="2"> | ||||
|         <a [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn accelerateFullSize" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> | ||||
|       </td> | ||||
|     </tr> | ||||
|   } @else { | ||||
|     <ng-container *ngTemplateOutlet="skeletonDetailsRow"></ng-container> | ||||
|   } | ||||
| </ng-template> | ||||
| 
 | ||||
| <ng-template #gogglesRow> | ||||
|   @if (!isLoadingTx) { | ||||
|     @if (((auditStatus && auditStatus.accelerated) || accelerationInfo || (tx && tx.acceleration)) || filters.length) { | ||||
|  | ||||
| @ -117,6 +117,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | ||||
|   flowEnabled: boolean; | ||||
|   tooltipPosition: { x: number, y: number }; | ||||
|   isMobile: boolean; | ||||
|   paymentType: 'bitcoin' | 'cashapp' = 'bitcoin'; | ||||
|   firstLoad = true; | ||||
| 
 | ||||
|   featuresEnabled: boolean; | ||||
|   segwitEnabled: boolean; | ||||
| @ -154,6 +156,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | ||||
|   ngOnInit() { | ||||
|     this.acceleratorAvailable = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === ''; | ||||
| 
 | ||||
|     if (this.acceleratorAvailable && this.stateService.ref === 'https://cash.app/') { | ||||
|       this.showAccelerationSummary = true; | ||||
|       this.paymentType = 'cashapp'; | ||||
|     } | ||||
| 
 | ||||
|     this.enterpriseService.page(); | ||||
| 
 | ||||
|     this.websocketService.want(['blocks', 'mempool-blocks']); | ||||
| @ -720,6 +727,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | ||||
|   } | ||||
| 
 | ||||
|   resetTransaction() { | ||||
|     if (!this.firstLoad) { | ||||
|       this.stateService.ref = ''; | ||||
|     } else { | ||||
|       this.firstLoad = false; | ||||
|     } | ||||
|     this.error = undefined; | ||||
|     this.tx = null; | ||||
|     this.setFeatures(); | ||||
| @ -814,6 +826,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | ||||
|   } | ||||
| 
 | ||||
|   ngOnDestroy() { | ||||
|     this.stateService.ref = ''; | ||||
|     this.subscription.unsubscribe(); | ||||
|     this.fetchCpfpSubscription.unsubscribe(); | ||||
|     this.fetchRbfSubscription.unsubscribe(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user