diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index 06334c5b5..0146fb535 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -4,6 +4,8 @@ import { AppPreloadingStrategy } from './app.preloading-strategy'
import { StartComponent } from './components/start/start.component';
import { TransactionComponent } from './components/transaction/transaction.component';
import { BlockComponent } from './components/block/block.component';
+import { ClockAComponent } from './components/clock/clock-a.component';
+import { ClockBComponent } from './components/clock/clock-b.component';
import { AddressComponent } from './components/address/address.component';
import { MasterPageComponent } from './components/master-page/master-page.component';
import { AboutComponent } from './components/about/about.component';
@@ -355,6 +357,14 @@ let routes: Routes = [
},
],
},
+ {
+ path: 'clock-face-a',
+ component: ClockAComponent,
+ },
+ {
+ path: 'clock-face-b',
+ component: ClockBComponent,
+ },
{
path: 'status',
data: { networks: ['bitcoin', 'liquid'] },
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 7fb0a1e99..5ab0eefea 100644
--- a/frontend/src/app/components/block-overview-graph/block-scene.ts
+++ b/frontend/src/app/components/block-overview-graph/block-scene.ts
@@ -34,7 +34,7 @@ export default class BlockScene {
this.width = width;
this.height = height;
this.gridSize = this.width / this.gridWidth;
- this.unitPadding = width / 500;
+ this.unitPadding = this.gridSize / 5;
this.unitWidth = this.gridSize - (this.unitPadding * 2);
this.dirty = true;
diff --git a/frontend/src/app/components/clock-face/clock-face.component.html b/frontend/src/app/components/clock-face/clock-face.component.html
new file mode 100644
index 000000000..a5db1538c
--- /dev/null
+++ b/frontend/src/app/components/clock-face/clock-face.component.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
\ 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
new file mode 100644
index 000000000..fa73ad90a
--- /dev/null
+++ b/frontend/src/app/components/clock-face/clock-face.component.scss
@@ -0,0 +1,23 @@
+.clock-face {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ height: 100%;
+
+ .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
new file mode 100644
index 000000000..fcd4b75cc
--- /dev/null
+++ b/frontend/src/app/components/clock-face/clock-face.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-clock-face',
+ templateUrl: './clock-face.component.html',
+ styleUrls: ['./clock-face.component.scss'],
+})
+export class ClockFaceComponent implements OnInit {
+
+ constructor() {}
+
+ ngOnInit(): void {
+ // initialize stuff
+ }
+}
diff --git a/frontend/src/app/components/clock/clock-a.component.html b/frontend/src/app/components/clock/clock-a.component.html
new file mode 100644
index 000000000..c7eea67c9
--- /dev/null
+++ b/frontend/src/app/components/clock/clock-a.component.html
@@ -0,0 +1,19 @@
+
+
+
+
= 0">
+
+
+
{{ block.height }}
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/app/components/clock/clock-a.component.ts b/frontend/src/app/components/clock/clock-a.component.ts
new file mode 100644
index 000000000..0242e0ab8
--- /dev/null
+++ b/frontend/src/app/components/clock/clock-a.component.ts
@@ -0,0 +1,57 @@
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs';
+import { StateService } from '../../services/state.service';
+import { BlockExtended } from '../../interfaces/node-api.interface';
+import { WebsocketService } from '../../services/websocket.service';
+
+@Component({
+ selector: 'app-clock-a',
+ templateUrl: './clock-a.component.html',
+ styleUrls: ['./clock.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class ClockAComponent implements OnInit {
+ blocksSubscription: Subscription;
+ block: BlockExtended;
+ blockStyle;
+
+ gradientColors = {
+ '': ['#9339f4', '#105fb0'],
+ bisq: ['#9339f4', '#105fb0'],
+ liquid: ['#116761', '#183550'],
+ 'liquidtestnet': ['#494a4a', '#272e46'],
+ testnet: ['#1d486f', '#183550'],
+ signet: ['#6f1d5d', '#471850'],
+ };
+
+ constructor(
+ public stateService: StateService,
+ private websocketService: WebsocketService,
+ private cd: ChangeDetectorRef,
+ ) {}
+
+ ngOnInit(): void {
+ this.websocketService.want(['blocks']);
+ this.blocksSubscription = this.stateService.blocks$
+ .subscribe(([block]) => {
+ if (block) {
+ this.block = block;
+ this.blockStyle = this.getStyleForBlock(this.block);
+ this.cd.markForCheck();
+ }
+ });
+ }
+
+ getStyleForBlock(block: BlockExtended) {
+ const greenBackgroundHeight = 100 - (block.weight / this.stateService.env.BLOCK_WEIGHT_UNITS) * 100;
+
+ return {
+ background: `repeating-linear-gradient(
+ #2d3348,
+ #2d3348 ${greenBackgroundHeight}%,
+ ${this.gradientColors[''][0]} ${Math.max(greenBackgroundHeight, 0)}%,
+ ${this.gradientColors[''][1]} 100%
+ )`,
+ };
+ }
+}
diff --git a/frontend/src/app/components/clock/clock-b.component.html b/frontend/src/app/components/clock/clock-b.component.html
new file mode 100644
index 000000000..f3d65562d
--- /dev/null
+++ b/frontend/src/app/components/clock/clock-b.component.html
@@ -0,0 +1,15 @@
+
+
+
+
= 0">
+
+
+
+
{{ 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
new file mode 100644
index 000000000..95ae803b8
--- /dev/null
+++ b/frontend/src/app/components/clock/clock-b.component.ts
@@ -0,0 +1,58 @@
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs';
+import { StateService } from '../../services/state.service';
+import { BlockExtended } from '../../interfaces/node-api.interface';
+import { WebsocketService } from '../../services/websocket.service';
+
+@Component({
+ selector: 'app-clock-b',
+ templateUrl: './clock-b.component.html',
+ styleUrls: ['./clock.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class ClockBComponent implements OnInit {
+ blocksSubscription: Subscription;
+ block: BlockExtended;
+ blockSizerStyle;
+
+ gradientColors = {
+ '': ['#9339f4', '#105fb0'],
+ bisq: ['#9339f4', '#105fb0'],
+ liquid: ['#116761', '#183550'],
+ 'liquidtestnet': ['#494a4a', '#272e46'],
+ testnet: ['#1d486f', '#183550'],
+ signet: ['#6f1d5d', '#471850'],
+ };
+
+ constructor(
+ public stateService: StateService,
+ private websocketService: WebsocketService,
+ private cd: ChangeDetectorRef,
+ ) {}
+
+ ngOnInit(): void {
+ this.resizeCanvas();
+ this.websocketService.want(['blocks']);
+ this.blocksSubscription = this.stateService.blocks$
+ .subscribe(([block]) => {
+ if (block) {
+ this.block = block;
+ this.cd.markForCheck();
+ }
+ });
+ }
+
+ @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;
+ this.blockSizerStyle = {
+ transform: `translate(${margin}px, ${margin}px)`,
+ width: `${size}px`,
+ height: `${size}px`,
+ };
+ this.cd.markForCheck();
+ }
+}
diff --git a/frontend/src/app/components/clock/clock.component.scss b/frontend/src/app/components/clock/clock.component.scss
new file mode 100644
index 000000000..385df2ea0
--- /dev/null
+++ b/frontend/src/app/components/clock/clock.component.scss
@@ -0,0 +1,119 @@
+.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;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+
+ .block-height {
+ font-size: calc(0.2 * var(--clock-width));
+ padding: 0;
+ margin: 0;
+ background: radial-gradient(rgba(0,0,0,0.5), transparent 67%);
+ padding: calc(0.05 * var(--clock-width)) calc(0.15 * var(--clock-width));
+ }
+}
+
+.block-wrapper {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ height: 100%;
+
+ .block-sizer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ }
+
+ .fader {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background: radial-gradient(transparent 0%, transparent 55%, #11131f 65%, #11131f 100%);
+ }
+
+ .block-cube {
+ --side-width: calc(0.4 * var(--clock-width));
+ --half-side: calc(0.2 * var(--clock-width));
+ --neg-half-side: calc(-0.2 * var(--clock-width));
+ transform-style: preserve-3d;
+ animation: block-spin 60s infinite linear;
+ position: absolute;
+ z-index: -1;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: var(--side-width);
+ height: var(--side-width);
+
+ .side {
+ width: var(--side-width);
+ height: var(--side-width);
+ line-height: 100px;
+ text-align: center;
+ background: #232838;
+ display: block;
+ position: absolute;
+ }
+
+ .side.top {
+ transform: rotateX(90deg);
+ margin-top: var(--neg-half-side);
+ }
+
+ .side.bottom {
+ background: #105fb0;
+ transform: rotateX(-90deg);
+ margin-top: var(--half-side);
+ }
+
+ .side.right {
+ transform: rotateY(90deg);
+ margin-left: var(--half-side);
+ }
+
+ .side.left {
+ transform: rotateY(-90deg);
+ margin-left: var(--neg-half-side);
+ }
+
+ .side.front {
+ transform: translateZ(var(--half-side));
+ }
+
+ .side.back {
+ transform: translateZ(var(--neg-half-side));
+ }
+ }
+}
+
+
+
+@keyframes block-spin {
+ 0% {transform: translate(-50%, -50%) rotateX(-20deg) rotateY(0deg);}
+ 100% {transform: translate(-50%, -50%) rotateX(-20deg) rotateY(-360deg);}
+}
\ No newline at end of file
diff --git a/frontend/src/app/graphs/graphs.module.ts b/frontend/src/app/graphs/graphs.module.ts
index 4cb803888..a7e627736 100644
--- a/frontend/src/app/graphs/graphs.module.ts
+++ b/frontend/src/app/graphs/graphs.module.ts
@@ -14,7 +14,7 @@ import { LbtcPegsGraphComponent } from '../components/lbtc-pegs-graph/lbtc-pegs-
import { GraphsComponent } from '../components/graphs/graphs.component';
import { StatisticsComponent } from '../components/statistics/statistics.component';
import { MempoolBlockComponent } from '../components/mempool-block/mempool-block.component';
-import { MempoolBlockOverviewComponent } from '../components/mempool-block-overview/mempool-block-overview.component';
+// import { MempoolBlockOverviewComponent } from '../components/mempool-block-overview/mempool-block-overview.component';
import { PoolRankingComponent } from '../components/pool-ranking/pool-ranking.component';
import { PoolComponent } from '../components/pool/pool.component';
import { TelevisionComponent } from '../components/television/television.component';
@@ -42,7 +42,7 @@ import { CommonModule } from '@angular/common';
BlockFeeRatesGraphComponent,
BlockSizesWeightsGraphComponent,
FeeDistributionGraphComponent,
- MempoolBlockOverviewComponent,
+ // MempoolBlockOverviewComponent,
IncomingTransactionsGraphComponent,
MempoolGraphComponent,
LbtcPegsGraphComponent,
diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts
index 7d3e51d20..4dd915889 100644
--- a/frontend/src/app/shared/shared.module.ts
+++ b/frontend/src/app/shared/shared.module.ts
@@ -90,6 +90,11 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
import { TestnetAlertComponent } from './components/testnet-alert/testnet-alert.component';
import { GlobalFooterComponent } from './components/global-footer/global-footer.component';
+import { MempoolBlockOverviewComponent } from '../components/mempool-block-overview/mempool-block-overview.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';
+
@NgModule({
declarations: [
ClipboardComponent,
@@ -172,6 +177,11 @@ import { GlobalFooterComponent } from './components/global-footer/global-footer.
GeolocationComponent,
TestnetAlertComponent,
GlobalFooterComponent,
+
+ MempoolBlockOverviewComponent,
+ ClockAComponent,
+ ClockBComponent,
+ ClockFaceComponent,
],
imports: [
CommonModule,
@@ -279,6 +289,11 @@ import { GlobalFooterComponent } from './components/global-footer/global-footer.
GeolocationComponent,
PreviewTitleComponent,
GlobalFooterComponent,
+
+ MempoolBlockOverviewComponent,
+ ClockAComponent,
+ ClockBComponent,
+ ClockFaceComponent,
]
})
export class SharedModule {
diff --git a/frontend/src/index.mempool.html b/frontend/src/index.mempool.html
index 60f1b4421..02765c0ba 100644
--- a/frontend/src/index.mempool.html
+++ b/frontend/src/index.mempool.html
@@ -32,7 +32,7 @@
-
+