Reversible blockchain components
This commit is contained in:
parent
135fbfc4f3
commit
d07bf30737
@ -1,4 +1,4 @@
|
|||||||
<div class="blocks-container blockchain-blocks-container" *ngIf="(loadingBlocks$ | async) === false; else loadingBlocksTemplate">
|
<div class="blocks-container blockchain-blocks-container" [class.time-ltr]="timeLtr" *ngIf="(loadingBlocks$ | async) === false; else loadingBlocksTemplate">
|
||||||
<div *ngFor="let block of blocks; let i = index; trackBy: trackByBlocksFn" >
|
<div *ngFor="let block of blocks; let i = index; trackBy: trackByBlocksFn" >
|
||||||
<div [attr.data-cy]="'bitcoin-block-' + i" class="text-center bitcoin-block mined-block blockchain-blocks-{{ i }}" id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]" [class.blink-bg]="(specialBlocks[block.height] !== undefined)">
|
<div [attr.data-cy]="'bitcoin-block-' + i" class="text-center bitcoin-block mined-block blockchain-blocks-{{ i }}" id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]" [class.blink-bg]="(specialBlocks[block.height] !== undefined)">
|
||||||
<a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }"
|
<a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }"
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-template #loadingBlocksTemplate>
|
<ng-template #loadingBlocksTemplate>
|
||||||
<div class="blocks-container">
|
<div class="blocks-container" [class.time-ltr]="timeLtr">
|
||||||
<div class="flashing">
|
<div class="flashing">
|
||||||
<div *ngFor="let block of emptyBlocks; let i = index; trackBy: trackByBlocksFn" >
|
<div *ngFor="let block of emptyBlocks; let i = index; trackBy: trackByBlocksFn" >
|
||||||
<div class="text-center bitcoin-block mined-block" id="bitcoin-block-{{ block.height }}" [ngStyle]="emptyBlockStyles[i]"></div>
|
<div class="text-center bitcoin-block mined-block" id="bitcoin-block-{{ block.height }}" [ngStyle]="emptyBlockStyles[i]"></div>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.mined-block {
|
.mined-block {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
transition: 2s;
|
transition: background 2s, left 2s, transform 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-size {
|
.block-size {
|
||||||
@ -34,6 +34,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 40px;
|
left: 40px;
|
||||||
|
transition: left 2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-body {
|
.block-body {
|
||||||
@ -145,3 +146,9 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events : none;
|
pointer-events : none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.time-ltr {
|
||||||
|
.bitcoin-block {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,8 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy {
|
|||||||
blocksFilled = false;
|
blocksFilled = false;
|
||||||
transition = '1s';
|
transition = '1s';
|
||||||
showMiningInfo = false;
|
showMiningInfo = false;
|
||||||
|
timeLtrSubscription: Subscription;
|
||||||
|
timeLtr: boolean;
|
||||||
|
|
||||||
gradientColors = {
|
gradientColors = {
|
||||||
'': ['#9339f4', '#105fb0'],
|
'': ['#9339f4', '#105fb0'],
|
||||||
@ -61,6 +63,11 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy {
|
|||||||
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
|
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
|
||||||
|
this.timeLtr = !!ltr;
|
||||||
|
this.cd.markForCheck();
|
||||||
|
});
|
||||||
|
|
||||||
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
|
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
|
||||||
this.feeRounding = '1.0-1';
|
this.feeRounding = '1.0-1';
|
||||||
}
|
}
|
||||||
@ -123,6 +130,7 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy {
|
|||||||
this.networkSubscription.unsubscribe();
|
this.networkSubscription.unsubscribe();
|
||||||
this.tabHiddenSubscription.unsubscribe();
|
this.tabHiddenSubscription.unsubscribe();
|
||||||
this.markBlockSubscription.unsubscribe();
|
this.markBlockSubscription.unsubscribe();
|
||||||
|
this.timeLtrSubscription.unsubscribe();
|
||||||
clearInterval(this.interval);
|
clearInterval(this.interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
<div class="text-center" class="blockchain-wrapper" #container>
|
<div class="text-center" class="blockchain-wrapper" [class.time-ltr]="timeLtr" [class.ltr-transition]="ltrTransitionEnabled" #container>
|
||||||
<div class="position-container {{ network }}">
|
<div class="position-container" [class]="['position-container']">
|
||||||
<span>
|
<span>
|
||||||
<app-mempool-blocks></app-mempool-blocks>
|
<div class="blocks-wrapper">
|
||||||
<app-blockchain-blocks></app-blockchain-blocks>
|
<app-mempool-blocks></app-mempool-blocks>
|
||||||
<div id="divider"></div>
|
<app-blockchain-blocks></app-blockchain-blocks>
|
||||||
|
</div>
|
||||||
|
<div id="divider">
|
||||||
|
<button class="time-toggle" (click)="toggleTimeDirection()"><fa-icon [icon]="['fas', 'arrows-rotate']" [fixedWidth]="true"></fa-icon></button>
|
||||||
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
.blockchain-wrapper {
|
.blockchain-wrapper {
|
||||||
height: 250px;
|
height: 250px;
|
||||||
|
|
||||||
-webkit-user-select: none; /* Safari */
|
-webkit-user-select: none; /* Safari */
|
||||||
-moz-user-select: none; /* Firefox */
|
-moz-user-select: none; /* Firefox */
|
||||||
-ms-user-select: none; /* IE10+/Edge */
|
-ms-user-select: none; /* IE10+/Edge */
|
||||||
user-select: none; /* Standard */
|
user-select: none; /* Standard */
|
||||||
@ -24,23 +24,46 @@
|
|||||||
|
|
||||||
.position-container {
|
.position-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 0;
|
||||||
top: 75px;
|
top: 75px;
|
||||||
|
transform: translateX(50vw);
|
||||||
|
transition: transform 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.position-container.liquid, .position-container.liquidtestnet {
|
.position-container.liquid, .position-container.liquidtestnet {
|
||||||
left: 420px;
|
transform: translateX(420px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.blockchain-wrapper.time-ltr {
|
||||||
|
.position-container.liquid, .position-container.liquidtestnet {
|
||||||
|
transform: translateX(calc(100vw - 420px));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
.position-container {
|
.blockchain-wrapper {
|
||||||
left: 95%;
|
.position-container {
|
||||||
|
transform: translateX(95vw);
|
||||||
|
}
|
||||||
|
.position-container.liquid, .position-container.liquidtestnet {
|
||||||
|
transform: translateX(50vw);
|
||||||
|
}
|
||||||
|
.position-container.loading {
|
||||||
|
transform: translateX(50vw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.position-container.liquid, .position-container.liquidtestnet {
|
.blockchain-wrapper.time-ltr {
|
||||||
left: 50%;
|
.position-container {
|
||||||
}
|
transform: translateX(5vw);
|
||||||
.position-container.loading {
|
}
|
||||||
left: 50%;
|
.position-container.liquid, .position-container.liquidtestnet {
|
||||||
|
transform: translateX(50vw);
|
||||||
|
}
|
||||||
|
.position-container.loading {
|
||||||
|
transform: translateX(50vw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,4 +80,31 @@
|
|||||||
width: 300px;
|
width: 300px;
|
||||||
left: -150px;
|
left: -150px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-toggle {
|
||||||
|
color: white;
|
||||||
|
font-size: 1rem;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1.5em;
|
||||||
|
left: 1px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
transition: transform 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blockchain-wrapper.ltr-transition .blocks-wrapper {
|
||||||
|
transition: transform 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blockchain-wrapper.time-ltr .blocks-wrapper {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blockchain-wrapper.time-ltr .time-toggle {
|
||||||
|
transform: translateX(-50%) scaleX(-1);
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy } from '@angular/core';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -7,8 +8,11 @@ import { StateService } from '../../services/state.service';
|
|||||||
styleUrls: ['./blockchain.component.scss'],
|
styleUrls: ['./blockchain.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class BlockchainComponent implements OnInit {
|
export class BlockchainComponent implements OnInit, OnDestroy {
|
||||||
network: string;
|
network: string;
|
||||||
|
timeLtrSubscription: Subscription;
|
||||||
|
timeLtr: boolean = this.stateService.timeLtr.value;
|
||||||
|
ltrTransitionEnabled = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public stateService: StateService,
|
public stateService: StateService,
|
||||||
@ -16,5 +20,17 @@ export class BlockchainComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.network = this.stateService.network;
|
this.network = this.stateService.network;
|
||||||
|
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
|
||||||
|
this.timeLtr = !!ltr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.timeLtrSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTimeDirection() {
|
||||||
|
this.ltrTransitionEnabled = true;
|
||||||
|
this.stateService.timeLtr.next(!this.timeLtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<ng-container *ngIf="(loadingBlocks$ | async) === false; else loadingBlocks">
|
<ng-container *ngIf="(loadingBlocks$ | async) === false; else loadingBlocks">
|
||||||
<div class="mempool-blocks-container" *ngIf="(difficultyAdjustments$ | async) as da;">
|
<div class="mempool-blocks-container" [class.time-ltr]="timeLtr" *ngIf="(difficultyAdjustments$ | async) as da;">
|
||||||
<div class="flashing">
|
<div class="flashing">
|
||||||
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn">
|
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn">
|
||||||
<div [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
|
<div [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
|
||||||
@ -45,7 +45,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-template #loadingBlocks>
|
<ng-template #loadingBlocks>
|
||||||
<div class="mempool-blocks-container">
|
<div class="mempool-blocks-container" [class.time-ltr]="timeLtr">
|
||||||
<div class="flashing">
|
<div class="flashing">
|
||||||
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolEmptyBlocks" let-i="index" [ngForTrackBy]="trackByFn">
|
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolEmptyBlocks" let-i="index" [ngForTrackBy]="trackByFn">
|
||||||
<div class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolEmptyBlockStyles[i]"></div>
|
<div class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolEmptyBlockStyles[i]"></div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
.bitcoin-block {
|
.bitcoin-block {
|
||||||
width: 125px;
|
width: 125px;
|
||||||
height: 125px;
|
height: 125px;
|
||||||
transition: 2s;
|
transition: background 2s, right 2s, transform 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-size {
|
.block-size {
|
||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
.block-body {
|
.block-body {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
transition: transform 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes opacityPulse {
|
@keyframes opacityPulse {
|
||||||
@ -73,6 +74,7 @@
|
|||||||
background-color: #232838;
|
background-color: #232838;
|
||||||
transform:skew(40deg);
|
transform:skew(40deg);
|
||||||
transform-origin:top;
|
transform-origin:top;
|
||||||
|
transition: transform 1s, left 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bitcoin-block::before {
|
.bitcoin-block::before {
|
||||||
@ -83,9 +85,11 @@
|
|||||||
top: -12px;
|
top: -12px;
|
||||||
left: -20px;
|
left: -20px;
|
||||||
background-color: #191c27;
|
background-color: #191c27;
|
||||||
|
z-index: -1;
|
||||||
|
|
||||||
transform: skewY(50deg);
|
transform: skewY(50deg);
|
||||||
transform-origin: top;
|
transform-origin: top;
|
||||||
|
transition: transform 1s, left 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mempool-block.bitcoin-block::after {
|
.mempool-block.bitcoin-block::after {
|
||||||
@ -128,3 +132,18 @@
|
|||||||
.blockLink:hover {
|
.blockLink:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.time-ltr {
|
||||||
|
.bitcoin-block::after {
|
||||||
|
transform: skew(-40deg);
|
||||||
|
left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bitcoin-block::before {
|
||||||
|
transform: skewY(-50deg);
|
||||||
|
left: 125px;
|
||||||
|
}
|
||||||
|
.block-body {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
}
|
@ -46,7 +46,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
feeRounding = '1.0-0';
|
feeRounding = '1.0-0';
|
||||||
|
|
||||||
rightPosition = 0;
|
rightPosition = 0;
|
||||||
transition = '2s';
|
transition = 'background 2s, right 2s, transform 1s';
|
||||||
|
|
||||||
markIndex: number;
|
markIndex: number;
|
||||||
txFeePerVSize: number;
|
txFeePerVSize: number;
|
||||||
@ -76,6 +76,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
|
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
|
||||||
this.timeLtr = !!ltr;
|
this.timeLtr = !!ltr;
|
||||||
|
this.cd.markForCheck();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
|
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
|
||||||
@ -278,7 +279,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
this.arrowVisible = true;
|
this.arrowVisible = true;
|
||||||
|
|
||||||
this.resetTransitionTimeout = window.setTimeout(() => {
|
this.resetTransitionTimeout = window.setTimeout(() => {
|
||||||
this.transition = '2s';
|
this.transition = 'background 2s, right 2s, transform 1s';
|
||||||
this.cd.markForCheck();
|
this.cd.markForCheck();
|
||||||
}, 100);
|
}, 100);
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user