From 61531171c91b6a7b20f3a26c4bb7237f8e01d10f Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 19 Apr 2023 00:21:02 +0900 Subject: [PATCH] clocktower top blocks & layout adjustment --- .../block-overview-graph/block-scene.ts | 7 +- .../blockchain-blocks.component.html | 71 +++---- .../blockchain-blocks.component.scss | 6 +- .../blockchain-blocks.component.ts | 1 + .../clock-face/clock-face.component.html | 185 +++++++++--------- .../clock-face/clock-face.component.scss | 44 +++-- .../clock-face/clock-face.component.ts | 26 ++- .../components/clock/clock-a.component.html | 36 ++-- .../components/clock/clock-b.component.html | 28 ++- .../app/components/clock/clock-b.component.ts | 7 +- .../app/components/clock/clock.component.scss | 12 +- .../clockchain/clockchain.component.html | 11 ++ .../clockchain/clockchain.component.scss | 120 ++++++++++++ .../clockchain/clockchain.component.ts | 50 +++++ .../mempool-blocks.component.html | 88 ++++++--- .../mempool-blocks.component.scss | 6 +- .../mempool-blocks.component.ts | 12 +- frontend/src/app/shared/shared.module.ts | 3 + 18 files changed, 489 insertions(+), 224 deletions(-) create mode 100644 frontend/src/app/components/clockchain/clockchain.component.html create mode 100644 frontend/src/app/components/clockchain/clockchain.component.scss create mode 100644 frontend/src/app/components/clockchain/clockchain.component.ts diff --git a/frontend/src/app/components/block-overview-graph/block-scene.ts b/frontend/src/app/components/block-overview-graph/block-scene.ts index 5ab0eefea..f1c1b4d77 100644 --- a/frontend/src/app/components/block-overview-graph/block-scene.ts +++ b/frontend/src/app/components/block-overview-graph/block-scene.ts @@ -34,8 +34,9 @@ export default class BlockScene { this.width = width; this.height = height; this.gridSize = this.width / this.gridWidth; - this.unitPadding = this.gridSize / 5; - this.unitWidth = this.gridSize - (this.unitPadding * 2); + this.unitPadding = Math.max(1, Math.floor(this.gridSize / 2.5)); + this.unitWidth = this.gridSize - (this.unitPadding); + console.log(this.gridSize, this.unitPadding, this.unitWidth); this.dirty = true; if (this.initialised && this.scene) { @@ -342,7 +343,7 @@ export default class BlockScene { private gridToScreen(position: Square | void): Square { if (position) { const slotSize = (position.s * this.gridSize); - const squareSize = slotSize - (this.unitPadding * 2); + const squareSize = slotSize - (this.unitPadding); // The grid is laid out notionally left-to-right, bottom-to-top, // so we rotate and/or flip the y axis to match the target configuration. diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html index 373605667..695e7c97d 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html @@ -1,53 +1,56 @@ -
  -
+
-
- ~{{ block?.extras?.medianFee | number:feeRounding }} sat/vB -
- -
-   + +
+ ~{{ block?.extras?.medianFee | number:feeRounding }} sat/vB
- -
- {{ block?.extras?.feeRange?.[0] | number:feeRounding }} - {{ - block?.extras?.feeRange[block?.extras?.feeRange?.length - 1] | number:feeRounding }} sat/vB -
- -
-   + +
+   +
+
+
+ {{ block?.extras?.feeRange?.[0] | number:feeRounding }} - {{ + block?.extras?.feeRange[block?.extras?.feeRange?.length - 1] | number:feeRounding }} sat/vB
- -
- -
-
-
- - {{ i }} transaction - {{ i }} transactions -
-
-
+ +
+   +
+
+
+ +
+
+
+ + {{ i }} transaction + {{ i }} transactions +
+
+
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/frontend/src/app/components/clock-face/clock-face.component.scss b/frontend/src/app/components/clock-face/clock-face.component.scss index fa73ad90a..66d53784f 100644 --- a/frontend/src/app/components/clock-face/clock-face.component.scss +++ b/frontend/src/app/components/clock-face/clock-face.component.scss @@ -1,4 +1,4 @@ -.clock-face { +.clock-wrapper { position: absolute; left: 0; right: 0; @@ -6,18 +6,40 @@ bottom: 0; width: 100%; height: 100%; + display: flex; + flex-direction: column; + justify-content: flex-start; - .cut-out, .demo-dial { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - width: 100%; - height: 100%; + .clockchain-bar, .clock-face { + flex-shrink: 0; + flex-grow: 0; + } - .face { - fill: #11131f; + .clockchain-bar { + position: relative; + height: 15.625%; + // background: #1d1f31; + // box-shadow: 0 0 15px #000; + } + + .clock-face { + position: relative; + height: 84.375%; + margin: auto; + overflow: hidden; + + .cut-out, .demo-dial { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + width: 100%; + height: 100%; + + .face { + fill: #11131f; + } } } } \ No newline at end of file diff --git a/frontend/src/app/components/clock-face/clock-face.component.ts b/frontend/src/app/components/clock-face/clock-face.component.ts index fcd4b75cc..747b6221c 100644 --- a/frontend/src/app/components/clock-face/clock-face.component.ts +++ b/frontend/src/app/components/clock-face/clock-face.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, HostListener, OnInit } from '@angular/core'; @Component({ selector: 'app-clock-face', @@ -6,10 +6,34 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./clock-face.component.scss'], }) export class ClockFaceComponent implements OnInit { + size: number; + wrapperStyle; + chainStyle; + faceStyle; + showDial: boolean = false; constructor() {} ngOnInit(): void { // initialize stuff + this.resizeCanvas(); + } + + @HostListener('window:resize', ['$event']) + resizeCanvas(): void { + this.size = Math.min(window.innerWidth, 0.78125 * window.innerHeight); + this.wrapperStyle = { + '--clock-width': `${this.size}px` + }; + const scaleFactor = window.innerWidth / 1390; + this.chainStyle = { + transform: `translate(2vw, 0.5vw) scale(${scaleFactor})`, + transformOrigin: 'top left', + }; + + this.faceStyle = { + width: `${this.size}px`, + height: `${this.size}px`, + }; } } diff --git a/frontend/src/app/components/clock/clock-a.component.html b/frontend/src/app/components/clock/clock-a.component.html index c7eea67c9..2029b9f24 100644 --- a/frontend/src/app/components/clock/clock-a.component.html +++ b/frontend/src/app/components/clock/clock-a.component.html @@ -1,19 +1,17 @@ -
- -
- -
-
-
-
-
-
-
-
-
-

{{ block.height }}

-
-
-
-
-
\ No newline at end of file + +
+ +
+
+
+
+
+
+
+
+
+

{{ block.height }}

+
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/components/clock/clock-b.component.html b/frontend/src/app/components/clock/clock-b.component.html index f3d65562d..887c0a1cf 100644 --- a/frontend/src/app/components/clock/clock-b.component.html +++ b/frontend/src/app/components/clock/clock-b.component.html @@ -1,15 +1,13 @@ -
- -
- -
- -
-
-
-

{{ block.height }}

-
-
-
-
-
\ No newline at end of file + +
+ +
+ +
+
+
+

{{ block.height }}

+
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/components/clock/clock-b.component.ts b/frontend/src/app/components/clock/clock-b.component.ts index 95ae803b8..626f388b6 100644 --- a/frontend/src/app/components/clock/clock-b.component.ts +++ b/frontend/src/app/components/clock/clock-b.component.ts @@ -44,10 +44,9 @@ export class ClockBComponent implements OnInit { @HostListener('window:resize', ['$event']) resizeCanvas(): void { - const screenSize = Math.min(window.innerWidth, window.innerHeight); - const baseSize = 0.92 * screenSize; - const size = Math.ceil(baseSize / 75) * 75; - const margin = screenSize - size; + const clockSize = Math.min(window.innerWidth, 0.78125 * window.innerHeight); + const size = Math.ceil(clockSize / 75) * 75; + const margin = (clockSize - size) / 2; this.blockSizerStyle = { transform: `translate(${margin}px, ${margin}px)`, width: `${size}px`, diff --git a/frontend/src/app/components/clock/clock.component.scss b/frontend/src/app/components/clock/clock.component.scss index 385df2ea0..c41b33e8a 100644 --- a/frontend/src/app/components/clock/clock.component.scss +++ b/frontend/src/app/components/clock/clock.component.scss @@ -1,13 +1,3 @@ -.clock-wrapper { - --clock-width: min(100vw, 100vh); - position: relative; - width: 100vw; - max-width: var(--clock-width); - height: 100vh; - max-height: var(--clock-width); - margin: auto; -} - .title-wrapper { position: absolute; left: 0; @@ -53,7 +43,7 @@ right: 0; top: 0; bottom: 0; - background: radial-gradient(transparent 0%, transparent 55%, #11131f 65%, #11131f 100%); + background: radial-gradient(transparent 0%, transparent 48%, #11131f 62%, #11131f 100%); } .block-cube { diff --git a/frontend/src/app/components/clockchain/clockchain.component.html b/frontend/src/app/components/clockchain/clockchain.component.html new file mode 100644 index 000000000..0eabc2862 --- /dev/null +++ b/frontend/src/app/components/clockchain/clockchain.component.html @@ -0,0 +1,11 @@ +
+
+ +
+ + +
+
+
+
+
diff --git a/frontend/src/app/components/clockchain/clockchain.component.scss b/frontend/src/app/components/clockchain/clockchain.component.scss new file mode 100644 index 000000000..d6fc00090 --- /dev/null +++ b/frontend/src/app/components/clockchain/clockchain.component.scss @@ -0,0 +1,120 @@ +.divider { + width: 4px; + height: 180px; + left: 0; + top: -40px; + position: absolute; + margin-bottom: 120px; + background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3cline x1='0' y1='0' x2='0' y2='100%' stroke='white' stroke-width='8' stroke-dasharray='18%2c32' stroke-dashoffset='-5' stroke-linecap='square'/%3e%3c/svg%3e"); +} + +.blockchain-wrapper { + height: 250px; + + -webkit-user-select: none; /* Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+/Edge */ + user-select: none; /* Standard */ +} + +.position-container { + position: absolute; + left: 0; + top: 75px; + transform: translateX(50vw); +} + +.position-container.liquid, .position-container.liquidtestnet { + transform: translateX(420px); +} + +.blockchain-wrapper { + .position-container { + transform: translateX(95vw); + } + .position-container.liquid, .position-container.liquidtestnet { + transform: translateX(50vw); + } + .position-container.loading { + transform: translateX(50vw); + } +} +.blockchain-wrapper.time-ltr { + .position-container { + transform: translateX(5vw); + } + .position-container.liquid, .position-container.liquidtestnet { + transform: translateX(50vw); + } + .position-container.loading { + transform: translateX(50vw); + } +} + +.black-background { + background-color: #11131f; + z-index: 100; + position: relative; +} + +.scroll-spacer { + position: absolute; + top: 0; + left: 0; + width: 1px; + height: 1px; + pointer-events: none; +} + +.loading-block { + position: absolute; + text-align: center; + margin: auto; + width: 300px; + left: -150px; + top: 0px; +} + +.time-toggle { + color: white; + font-size: 0.8rem; + position: absolute; + bottom: -1.8em; + left: 1px; + transform: translateX(-50%); + background: none; + border: none; + outline: none; + margin: 0; + padding: 0; +} + +.blockchain-wrapper.ltr-transition .blocks-wrapper, +.blockchain-wrapper.ltr-transition .position-container, +.blockchain-wrapper.ltr-transition .time-toggle { + transition: transform 1s; +} + +.blockchain-wrapper.time-ltr { + .blocks-wrapper { + transform: scaleX(-1); + } + + .time-toggle { + transform: translateX(-50%) scaleX(-1); + } +} + +:host-context(.ltr-layout) { + .blockchain-wrapper.time-ltr .blocks-wrapper, + .blockchain-wrapper .blocks-wrapper { + direction: ltr; + } +} + +:host-context(.rtl-layout) { + .blockchain-wrapper.time-ltr .blocks-wrapper, + .blockchain-wrapper .blocks-wrapper { + direction: rtl; + } +} \ No newline at end of file diff --git a/frontend/src/app/components/clockchain/clockchain.component.ts b/frontend/src/app/components/clockchain/clockchain.component.ts new file mode 100644 index 000000000..e5c63dbe4 --- /dev/null +++ b/frontend/src/app/components/clockchain/clockchain.component.ts @@ -0,0 +1,50 @@ +import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input } from '@angular/core'; +import { firstValueFrom, Subscription } from 'rxjs'; +import { StateService } from '../../services/state.service'; + +@Component({ + selector: 'app-clockchain', + templateUrl: './clockchain.component.html', + styleUrls: ['./clockchain.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ClockchainComponent implements OnInit, OnDestroy { + network: string; + timeLtrSubscription: Subscription; + timeLtr: boolean = this.stateService.timeLtr.value; + ltrTransitionEnabled = false; + connectionStateSubscription: Subscription; + loadingTip: boolean = true; + connected: boolean = true; + + constructor( + public stateService: StateService, + ) {} + + ngOnInit() { + this.network = this.stateService.network; + this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => { + this.timeLtr = !!ltr; + }); + this.connectionStateSubscription = this.stateService.connectionState$.subscribe(state => { + this.connected = (state === 2); + }) + firstValueFrom(this.stateService.chainTip$).then(tip => { + this.loadingTip = false; + }); + } + + ngOnDestroy() { + this.timeLtrSubscription.unsubscribe(); + this.connectionStateSubscription.unsubscribe(); + } + + trackByPageFn(index: number, item: { index: number }) { + return item.index; + } + + toggleTimeDirection() { + this.ltrTransitionEnabled = true; + this.stateService.timeLtr.next(!this.timeLtr); + } +} diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html index 6e397dee7..b11fbb888 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html @@ -1,40 +1,68 @@ - +
-
+
 
-
- ~{{ projectedBlock.medianFee | number:feeRounding }} sat/vB -
-
- {{ projectedBlock.feeRange[0] | number:feeRounding }} - {{ projectedBlock.feeRange[projectedBlock.feeRange.length - 1] | number:feeRounding }} sat/vB -
-
- -
-
-
- - {{ i }} transaction - {{ i }} transactions -
-
- - - - - - -
- -
- () - {{ i }} blocks + +
+ ~{{ projectedBlock.medianFee | number:feeRounding }} sat/vB
- +
+ {{ projectedBlock.feeRange[0] | number:feeRounding }} - {{ projectedBlock.feeRange[projectedBlock.feeRange.length - 1] | number:feeRounding }} sat/vB +
+
+ +
+
+
+ + {{ i }} transaction + {{ i }} transactions +
+
+ + + + + + +
+ +
+ () + {{ i }} blocks +
+
+ {{ projectedBlock.feeRange[0] | number:feeRounding }} - {{ projectedBlock.feeRange[projectedBlock.feeRange.length - 1] | number:feeRounding }} sat/vB +
+
+ +
+
+
+ + {{ i }} transaction + {{ i }} transactions +
+
+ + + + + + +
+ +
+ () + {{ i }} blocks +
+
+
+
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss index 565d4b302..a0140f55c 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss @@ -1,7 +1,7 @@ .bitcoin-block { width: 125px; height: 125px; - transition: background 2s, right 2s, transform 1s; + transition: background 2s, right 2s, transform 1s, opacity 1s; } .block-size { @@ -100,6 +100,10 @@ background-color: #2d2825; } +.mempool-block.last-block { + opacity: 0; +} + .black-background { background-color: #11131f; z-index: 100; 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 91273169c..b711ce805 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener } from '@angular/core'; +import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener, Input } from '@angular/core'; import { Subscription, Observable, fromEvent, merge, of, combineLatest } from 'rxjs'; import { MempoolBlock } from '../../interfaces/websocket.interface'; import { StateService } from '../../services/state.service'; @@ -24,6 +24,9 @@ import { animate, style, transition, trigger } from '@angular/animations'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class MempoolBlocksComponent implements OnInit, OnDestroy { + @Input() tiny: boolean = false; + @Input() count: number = null; + specialBlocks = specialBlocks; mempoolBlocks: MempoolBlock[] = []; mempoolEmptyBlocks: MempoolBlock[] = this.mountEmptyBlocks(); @@ -238,7 +241,12 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] { const innerWidth = this.stateService.env.BASE_MODULE !== 'liquid' && window.innerWidth <= 767.98 ? window.innerWidth : window.innerWidth / 2; - const blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding))); + let blocksAmount; + if (this.count) { + blocksAmount = this.count; + } else { + blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding))); + } while (blocks.length > blocksAmount) { const block = blocks.pop(); const lastBlock = blocks[blocks.length - 1]; diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 4dd915889..0765298bd 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -91,6 +91,7 @@ import { TestnetAlertComponent } from './components/testnet-alert/testnet-alert. import { GlobalFooterComponent } from './components/global-footer/global-footer.component'; import { MempoolBlockOverviewComponent } from '../components/mempool-block-overview/mempool-block-overview.component'; +import { ClockchainComponent } from '../components/clockchain/clockchain.component'; import { ClockFaceComponent } from '../components/clock-face/clock-face.component'; import { ClockAComponent } from '../components/clock/clock-a.component'; import { ClockBComponent } from '../components/clock/clock-b.component'; @@ -179,6 +180,7 @@ import { ClockBComponent } from '../components/clock/clock-b.component'; GlobalFooterComponent, MempoolBlockOverviewComponent, + ClockchainComponent, ClockAComponent, ClockBComponent, ClockFaceComponent, @@ -291,6 +293,7 @@ import { ClockBComponent } from '../components/clock/clock-b.component'; GlobalFooterComponent, MempoolBlockOverviewComponent, + ClockchainComponent, ClockAComponent, ClockBComponent, ClockFaceComponent,