From 9e88f5ecf8c591b0046e454d186cd8f626d83842 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Fri, 15 Dec 2023 16:58:10 +0100 Subject: [PATCH 1/8] [typo] platinium -> platinum --- frontend/src/app/components/menu/menu.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/menu/menu.component.scss b/frontend/src/app/components/menu/menu.component.scss index 8a2006a4e..99377a564 100644 --- a/frontend/src/app/components/menu/menu.component.scss +++ b/frontend/src/app/components/menu/menu.component.scss @@ -85,6 +85,6 @@ background-color: #f1c40f; } -.badge-platinium { +.badge-platinum { background-color: #653b9c; } \ No newline at end of file From e5f0544cc27c1b78bd3f4986c7c5ad84b68c2d83 Mon Sep 17 00:00:00 2001 From: natsoni Date: Thu, 8 Feb 2024 18:32:07 +0100 Subject: [PATCH 2/8] Fix Liquid dashboard layout for mobile view --- .../lbtc-pegs-graph.component.ts | 2 +- .../app/dashboard/dashboard.component.html | 4 +-- .../app/dashboard/dashboard.component.scss | 2 +- .../src/app/dashboard/dashboard.component.ts | 31 +++++++++++++++---- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/components/lbtc-pegs-graph/lbtc-pegs-graph.component.ts b/frontend/src/app/components/lbtc-pegs-graph/lbtc-pegs-graph.component.ts index e2231e7ce..9931fb78a 100644 --- a/frontend/src/app/components/lbtc-pegs-graph/lbtc-pegs-graph.component.ts +++ b/frontend/src/app/components/lbtc-pegs-graph/lbtc-pegs-graph.component.ts @@ -18,9 +18,9 @@ import { EChartsOption } from '../../graphs/echarts'; }) export class LbtcPegsGraphComponent implements OnInit, OnChanges { @Input() data: any; + @Input() height: number | string = '320'; pegsChartOptions: EChartsOption; - height: number | string = '320'; right: number | string = '10'; top: number | string = '20'; left: number | string = '50'; diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index 9ebc22dd4..a2c46a198 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -44,7 +44,7 @@
- + @@ -187,7 +187,7 @@ - + diff --git a/frontend/src/app/dashboard/dashboard.component.scss b/frontend/src/app/dashboard/dashboard.component.scss index 9bd44ea29..70972ae8e 100644 --- a/frontend/src/app/dashboard/dashboard.component.scss +++ b/frontend/src/app/dashboard/dashboard.component.scss @@ -69,7 +69,7 @@ @media (min-width: 485px) { margin: 0px auto 10px; } - @media (min-width: 785px) { + @media (min-width: 768px) { margin: 0px auto 0px; } &:last-child { diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts index cd393e89f..5dfd68419 100644 --- a/frontend/src/app/dashboard/dashboard.component.ts +++ b/frontend/src/app/dashboard/dashboard.component.ts @@ -1,6 +1,6 @@ import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, OnDestroy, OnInit } from '@angular/core'; -import { combineLatest, EMPTY, merge, Observable, of, Subject, Subscription, timer } from 'rxjs'; -import { catchError, delayWhen, filter, map, scan, share, shareReplay, startWith, switchMap, takeUntil, tap, throttleTime } from 'rxjs/operators'; +import { combineLatest, EMPTY, fromEvent, merge, Observable, of, Subject, Subscription, timer } from 'rxjs'; +import { catchError, delayWhen, distinctUntilChanged, filter, map, scan, share, shareReplay, startWith, switchMap, takeUntil, tap, throttleTime } from 'rxjs/operators'; import { AuditStatus, BlockExtended, CurrentPegs, OptimizedMempoolStats } from '../interfaces/node-api.interface'; import { MempoolInfo, TransactionStripped, ReplacementInfo } from '../interfaces/websocket.interface'; import { ApiService } from '../services/api.service'; @@ -33,6 +33,7 @@ interface MempoolStatsData { }) export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { featuredAssets$: Observable; + nbFeaturedAssets = 6; network$: Observable; mempoolBlocksData$: Observable; mempoolInfoData$: Observable; @@ -58,6 +59,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { currencySubscription: Subscription; currency: string; incomingGraphHeight: number = 300; + lbtcPegGraphHeight: number = 320; private lastPegBlockUpdate: number = 0; private lastPegAmount: string = ''; private lastReservesBlockUpdate: number = 0; @@ -153,16 +155,23 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { }) ); - this.featuredAssets$ = this.apiService.listFeaturedAssets$() - .pipe( - map((featured) => { + const windowResize$ = fromEvent(window, 'resize').pipe( + distinctUntilChanged(), + startWith(null) + ); + + this.featuredAssets$ = combineLatest([ + this.apiService.listFeaturedAssets$(), + windowResize$ + ]).pipe( + map(([featured, _]) => { const newArray = []; for (const feature of featured) { if (feature.ticker !== 'L-BTC' && feature.asset) { newArray.push(feature); } } - return newArray.slice(0, 6); + return newArray.slice(0, this.nbFeaturedAssets); }), ); @@ -362,17 +371,27 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { return block.height; } + getArrayFromNumber(num: number): number[] { + return Array.from({ length: num }, (_, i) => i + 1); + } + @HostListener('window:resize', ['$event']) onResize(): void { if (window.innerWidth >= 992) { this.incomingGraphHeight = 300; this.goggleResolution = 82; + this.lbtcPegGraphHeight = 320; + this.nbFeaturedAssets = 6; } else if (window.innerWidth >= 768) { this.incomingGraphHeight = 215; this.goggleResolution = 80; + this.lbtcPegGraphHeight = 230; + this.nbFeaturedAssets = 4; } else { this.incomingGraphHeight = 180; this.goggleResolution = 86; + this.lbtcPegGraphHeight = 220; + this.nbFeaturedAssets = 4; } } } From 7de4a03f1b04a34df4d2a52e4b7d36cdc69f0428 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 8 Feb 2024 22:50:47 +0000 Subject: [PATCH 3/8] Fix mining/liquid dashboard widget heights --- .../components/mining-dashboard/mining-dashboard.component.scss | 2 +- .../components/mining-dashboard/mining-dashboard.component.ts | 2 +- .../lightning-dashboard/lightning-dashboard.component.scss | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss index 310b9e9de..ce68c97ae 100644 --- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss +++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss @@ -26,7 +26,7 @@ height: 345px; } @media (min-width: 992px) { - height: 472px; + height: 440px; } } diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts index 0a72386cb..cfc8ef230 100644 --- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts +++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts @@ -42,7 +42,7 @@ export class MiningDashboardComponent implements OnInit, AfterViewInit { @HostListener('window:resize', ['$event']) onResize(): void { if (window.innerWidth >= 992) { - this.graphHeight = 375; + this.graphHeight = 335; } else if (window.innerWidth >= 768) { this.graphHeight = 245; } else { diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss index 052ea6227..e6da450df 100644 --- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss +++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss @@ -29,7 +29,7 @@ height: 345px; } @media (min-width: 992px) { - height: 442px; + height: 439px; } } From b3dbe1215c8bacbbf19defb52bca45b51ce9f2d6 Mon Sep 17 00:00:00 2001 From: softsimon Date: Fri, 9 Feb 2024 14:11:12 +0800 Subject: [PATCH 4/8] Adjusting Load more position to match other dashboards --- .../accelerator-dashboard/accelerator-dashboard.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss index d6fb57953..c8755c94e 100644 --- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss +++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss @@ -23,7 +23,7 @@ height: 325px; } @media (min-width: 992px) { - height: 400px; + height: 409px; } } From ddee5f927c170884ca16412e19da3201898509a0 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 8 Feb 2024 17:44:32 +0000 Subject: [PATCH 5/8] Make dashboard filters persistent, add disjunctive filter mode --- .../block-filters.component.html | 11 ++++- .../block-filters.component.scss | 43 +++++++++++++++++ .../block-filters/block-filters.component.ts | 26 +++++++---- .../block-overview-graph.component.ts | 19 +++++--- .../mempool-block-overview.component.ts | 3 +- .../app/dashboard/dashboard.component.html | 6 +-- .../src/app/dashboard/dashboard.component.ts | 46 ++++++++++++++++--- frontend/src/app/services/state.service.ts | 3 +- frontend/src/app/shared/filters.utils.ts | 15 ++++++ 9 files changed, 145 insertions(+), 27 deletions(-) diff --git a/frontend/src/app/components/block-filters/block-filters.component.html b/frontend/src/app/components/block-filters/block-filters.component.html index f60b04cdd..8c79cd438 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.html +++ b/frontend/src/app/components/block-filters/block-filters.component.html @@ -1,4 +1,4 @@ -
+
Match
+
+ + +
{{ group.label }}
diff --git a/frontend/src/app/components/block-filters/block-filters.component.scss b/frontend/src/app/components/block-filters/block-filters.component.scss index 6406a1d93..4830f9540 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.scss +++ b/frontend/src/app/components/block-filters/block-filters.component.scss @@ -77,6 +77,49 @@ } } + &.any-mode { + .filter-tag { + border: solid 1px #1a9436; + &.selected { + background-color: #1a9436; + } + } + } + + .btn-group { + font-size: 0.9em; + margin-right: 0.25em; + } + + .mode-toggle { + padding: 0.2em 0.5em; + pointer-events: all; + line-height: 1.5; + background: #181b2daf; + + &:first-child { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + } + &:last-child { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; + } + + &.blue { + border: solid 1px #105fb0; + &.active { + background: #105fb0; + } + } + &.green { + border: solid 1px #1a9436; + &.active { + background: #1a9436; + } + } + } + :host-context(.block-overview-graph:hover) &, &:hover, &:active { .menu-toggle { opacity: 0.5; diff --git a/frontend/src/app/components/block-filters/block-filters.component.ts b/frontend/src/app/components/block-filters/block-filters.component.ts index 9951984df..a16475c23 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.ts +++ b/frontend/src/app/components/block-filters/block-filters.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Output, HostListener, Input, ChangeDetectorRef, OnChanges, SimpleChanges, OnInit, OnDestroy } from '@angular/core'; -import { FilterGroups, TransactionFilters } from '../../shared/filters.utils'; +import { ActiveFilter, FilterGroups, FilterMode, TransactionFilters } from '../../shared/filters.utils'; import { StateService } from '../../services/state.service'; import { Subscription } from 'rxjs'; @@ -12,7 +12,7 @@ import { Subscription } from 'rxjs'; export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy { @Input() cssWidth: number = 800; @Input() excludeFilters: string[] = []; - @Output() onFilterChanged: EventEmitter = new EventEmitter(); + @Output() onFilterChanged: EventEmitter = new EventEmitter(); filterSubscription: Subscription; @@ -21,6 +21,7 @@ export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy { disabledFilters: { [key: string]: boolean } = {}; activeFilters: string[] = []; filterFlags: { [key: string]: boolean } = {}; + filterMode: FilterMode = 'and'; menuOpen: boolean = false; constructor( @@ -29,15 +30,16 @@ export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy { ) {} ngOnInit(): void { - this.filterSubscription = this.stateService.activeGoggles$.subscribe((activeFilters: string[]) => { + this.filterSubscription = this.stateService.activeGoggles$.subscribe((active: ActiveFilter) => { + this.filterMode = active.mode; for (const key of Object.keys(this.filterFlags)) { this.filterFlags[key] = false; } - for (const key of activeFilters) { + for (const key of active.filters) { this.filterFlags[key] = !this.disabledFilters[key]; } - this.activeFilters = [...activeFilters.filter(key => !this.disabledFilters[key])]; - this.onFilterChanged.emit(this.getBooleanFlags()); + this.activeFilters = [...active.filters.filter(key => !this.disabledFilters[key])]; + this.onFilterChanged.emit({ mode: active.mode, filters: this.activeFilters }); }); } @@ -53,6 +55,12 @@ export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy { } } + setFilterMode(mode): void { + this.filterMode = mode; + this.onFilterChanged.emit({ mode: this.filterMode, filters: this.activeFilters }); + this.stateService.activeGoggles$.next({ mode: this.filterMode, filters: [...this.activeFilters] }); + } + toggleFilter(key): void { const filter = this.filters[key]; this.filterFlags[key] = !this.filterFlags[key]; @@ -73,8 +81,8 @@ export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy { this.activeFilters = this.activeFilters.filter(f => f != key); } const booleanFlags = this.getBooleanFlags(); - this.onFilterChanged.emit(booleanFlags); - this.stateService.activeGoggles$.next([...this.activeFilters]); + this.onFilterChanged.emit({ mode: this.filterMode, filters: this.activeFilters }); + this.stateService.activeGoggles$.next({ mode: this.filterMode, filters: [...this.activeFilters] }); } getBooleanFlags(): bigint | null { @@ -90,7 +98,7 @@ export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy { @HostListener('document:click', ['$event']) onClick(event): boolean { // click away from menu - if (!event.target.closest('button')) { + if (!event.target.closest('button') && !event.target.closest('label')) { this.menuOpen = false; } return true; diff --git a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts index ac1df2bf5..f250f3744 100644 --- a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts +++ b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts @@ -9,6 +9,7 @@ import { Price } from '../../services/price.service'; import { StateService } from '../../services/state.service'; import { Subscription } from 'rxjs'; import { defaultColorFunction, setOpacity, defaultFeeColors, defaultAuditFeeColors, defaultMarginalFeeColors, defaultAuditColors } from './utils'; +import { ActiveFilter, FilterMode, toFlags } from '../../shared/filters.utils'; const unmatchedOpacity = 0.2; const unmatchedFeeColors = defaultFeeColors.map(c => setOpacity(c, unmatchedOpacity)); @@ -42,7 +43,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On @Input() showFilters: boolean = false; @Input() excludeFilters: string[] = []; @Input() filterFlags: bigint | null = null; - @Input() filterMode: 'and' | 'or' = 'and'; + @Input() filterMode: FilterMode = 'and'; @Input() blockConversion: Price; @Input() overrideColors: ((tx: TxView) => Color) | null = null; @Output() txClickEvent = new EventEmitter<{ tx: TransactionStripped, keyModifier: boolean}>(); @@ -119,10 +120,11 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On } } - setFilterFlags(flags?: bigint | null): void { - this.activeFilterFlags = this.filterFlags || flags || null; + setFilterFlags(goggle?: ActiveFilter): void { + this.filterMode = goggle?.mode || this.filterMode; + this.activeFilterFlags = goggle?.filters ? toFlags(goggle.filters) : this.filterFlags; if (this.scene) { - if (this.activeFilterFlags != null) { + if (this.activeFilterFlags != null && this.filtersAvailable) { this.scene.setColorFunction(this.getFilterColorFunction(this.activeFilterFlags)); } else { this.scene.setColorFunction(this.overrideColors); @@ -157,7 +159,11 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On // initialize the scene without any entry transition setup(transactions: TransactionStripped[]): void { - this.filtersAvailable = transactions.reduce((flagSet, tx) => flagSet || tx.flags > 0, false); + const filtersAvailable = transactions.reduce((flagSet, tx) => flagSet || tx.flags > 0, false); + if (filtersAvailable !== this.filtersAvailable) { + this.setFilterFlags(); + } + this.filtersAvailable = filtersAvailable; if (this.scene) { this.scene.setup(transactions); this.readyNextFrame = true; @@ -523,8 +529,9 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On } getFilterColorFunction(flags: bigint): ((tx: TxView) => Color) { + console.log('getting filter color function: ', flags, this.filterMode); return (tx: TxView) => { - if ((this.filterMode === 'and' && (tx.bigintFlags & flags) === flags) || (this.filterMode === 'or' && (tx.bigintFlags & flags) > 0n)) { + if ((this.filterMode === 'and' && (tx.bigintFlags & flags) === flags) || (this.filterMode === 'or' && (flags === 0n || (tx.bigintFlags & flags) > 0n))) { return defaultColorFunction(tx); } else { return defaultColorFunction( diff --git a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts index 7fb036718..ba804912b 100644 --- a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts +++ b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts @@ -10,6 +10,7 @@ import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pi import { Router } from '@angular/router'; import { Color } from '../block-overview-graph/sprite-types'; import TxView from '../block-overview-graph/tx-view'; +import { FilterMode } from '../../shared/filters.utils'; @Component({ selector: 'app-mempool-block-overview', @@ -22,7 +23,7 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang @Input() showFilters: boolean = false; @Input() overrideColors: ((tx: TxView) => Color) | null = null; @Input() filterFlags: bigint | undefined = undefined; - @Input() filterMode: 'and' | 'or' = 'and'; + @Input() filterMode: FilterMode = 'and'; @Output() txPreviewEvent = new EventEmitter(); @ViewChild('blockGraph') blockGraph: BlockOverviewGraphComponent; diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index a2c46a198..6425e3b9a 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -26,7 +26,7 @@
@@ -34,8 +34,8 @@
diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts index 5dfd68419..ce0db77c1 100644 --- a/frontend/src/app/dashboard/dashboard.component.ts +++ b/frontend/src/app/dashboard/dashboard.component.ts @@ -7,6 +7,7 @@ import { ApiService } from '../services/api.service'; import { StateService } from '../services/state.service'; import { WebsocketService } from '../services/websocket.service'; import { SeoService } from '../services/seo.service'; +import { ActiveFilter, FilterMode, toFlags } from '../shared/filters.utils'; interface MempoolBlocksData { blocks: number; @@ -55,6 +56,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { currentReserves$: Observable; fullHistory$: Observable; isLoad: boolean = true; + filterSubscription: Subscription; mempoolInfoSubscription: Subscription; currencySubscription: Subscription; currency: string; @@ -65,13 +67,15 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { private lastReservesBlockUpdate: number = 0; goggleResolution = 82; - goggleCycle = [ - { index: 0, name: 'All' }, - { index: 1, name: 'Consolidations', flag: 0b00000010_00000000_00000000_00000000_00000000n }, - { index: 2, name: 'Coinjoin', flag: 0b00000001_00000000_00000000_00000000_00000000n }, - { index: 3, name: '💩', flag: 0b00000100_00000000_00000000_00000000n | 0b00000010_00000000_00000000_00000000n | 0b00000001_00000000_00000000_00000000n }, + goggleCycle: { index: number, name: string, mode: FilterMode, filters: string[] }[] = [ + { index: 0, name: 'All', mode: 'and', filters: [] }, + { index: 1, name: 'Consolidation', mode: 'and', filters: ['consolidation'] }, + { index: 2, name: 'Coinjoin', mode: 'and', filters: ['coinjoin'] }, + { index: 3, name: '💩', mode: 'or', filters: ['inscription', 'fake_pubkey', 'op_return'] }, ]; - goggleIndex = 0; // Math.floor(Math.random() * this.goggleCycle.length); + goggleFlags = 0n; + goggleMode: FilterMode = 'and'; + goggleIndex = 0; private destroy$ = new Subject(); @@ -87,6 +91,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { } ngOnDestroy(): void { + this.filterSubscription.unsubscribe(); this.mempoolInfoSubscription.unsubscribe(); this.currencySubscription.unsubscribe(); this.websocketService.stopTrackRbfSummary(); @@ -107,6 +112,30 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { map((indicators) => indicators.mempool !== undefined ? indicators.mempool : 100) ); + this.filterSubscription = this.stateService.activeGoggles$.subscribe((active: ActiveFilter) => { + const activeFilters = active.filters.sort().join(','); + for (const goggle of this.goggleCycle) { + if (goggle.mode === active.mode) { + const goggleFilters = goggle.filters.sort().join(','); + if (goggleFilters === activeFilters) { + this.goggleIndex = goggle.index; + this.goggleFlags = toFlags(goggle.filters); + this.goggleMode = goggle.mode; + return; + } + } + } + this.goggleCycle.push({ + index: this.goggleCycle.length, + name: 'Custom', + mode: active.mode, + filters: active.filters, + }); + this.goggleIndex = this.goggleCycle.length - 1; + this.goggleFlags = toFlags(active.filters); + this.goggleMode = active.mode; + }); + this.mempoolInfoData$ = combineLatest([ this.stateService.mempoolInfo$, this.stateService.vbytesPerSecond$ @@ -375,6 +404,11 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { return Array.from({ length: num }, (_, i) => i + 1); } + setFilter(index): void { + const selected = this.goggleCycle[index]; + this.stateService.activeGoggles$.next(selected); + } + @HostListener('window:resize', ['$event']) onResize(): void { if (window.innerWidth >= 992) { diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts index f87a3dc31..8b69546ba 100644 --- a/frontend/src/app/services/state.service.ts +++ b/frontend/src/app/services/state.service.ts @@ -9,6 +9,7 @@ import { filter, map, scan, shareReplay } from 'rxjs/operators'; import { StorageService } from './storage.service'; import { hasTouchScreen } from '../shared/pipes/bytes-pipe/utils'; import { ApiService } from './api.service'; +import { ActiveFilter } from '../shared/filters.utils'; export interface MarkBlockState { blockHeight?: number; @@ -150,7 +151,7 @@ export class StateService { searchFocus$: Subject = new Subject(); menuOpen$: BehaviorSubject = new BehaviorSubject(false); - activeGoggles$: BehaviorSubject = new BehaviorSubject([]); + activeGoggles$: BehaviorSubject = new BehaviorSubject({ mode: 'and', filters: [] }); constructor( @Inject(PLATFORM_ID) private platformId: any, diff --git a/frontend/src/app/shared/filters.utils.ts b/frontend/src/app/shared/filters.utils.ts index 0b652a192..3930dc8ca 100644 --- a/frontend/src/app/shared/filters.utils.ts +++ b/frontend/src/app/shared/filters.utils.ts @@ -7,6 +7,13 @@ export interface Filter { important?: boolean, } +export type FilterMode = 'and' | 'or'; + +export interface ActiveFilter { + mode: FilterMode, + filters: string[], +} + // binary flags for transaction classification export const TransactionFlags = { // features @@ -43,6 +50,14 @@ export const TransactionFlags = { sighash_acp: 0b00010000_00000000_00000000_00000000_00000000_00000000n, }; +export function toFlags(filters: string[]): bigint { + let flag = 0n; + for (const filter of filters) { + flag |= TransactionFlags[filter]; + } + return flag; +} + export const TransactionFilters: { [key: string]: Filter } = { /* features */ rbf: { key: 'rbf', label: 'RBF enabled', flag: TransactionFlags.rbf, toggle: 'rbf', important: true }, From 1e56ac094cd1edd2dd9b328cd6fa1886038f60b0 Mon Sep 17 00:00:00 2001 From: softsimon Date: Fri, 9 Feb 2024 21:29:22 +0800 Subject: [PATCH 6/8] Smaller mobile toggle buttons --- .../components/block-filters/block-filters.component.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/app/components/block-filters/block-filters.component.scss b/frontend/src/app/components/block-filters/block-filters.component.scss index 4830f9540..1009efd72 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.scss +++ b/frontend/src/app/components/block-filters/block-filters.component.scss @@ -175,6 +175,11 @@ .filter-tag { font-size: 0.7em; } + .mode-toggle { + font-size: 0.7em; + margin-bottom: 5px; + margin-top: 2px; + } } &.tiny { From e23de97e0f699fc08fdfa13210a688d8fd356759 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 9 Feb 2024 17:42:20 +0000 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=92=A9=20=3D>=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/dashboard/dashboard.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts index ce0db77c1..1714d3d01 100644 --- a/frontend/src/app/dashboard/dashboard.component.ts +++ b/frontend/src/app/dashboard/dashboard.component.ts @@ -71,7 +71,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { { index: 0, name: 'All', mode: 'and', filters: [] }, { index: 1, name: 'Consolidation', mode: 'and', filters: ['consolidation'] }, { index: 2, name: 'Coinjoin', mode: 'and', filters: ['coinjoin'] }, - { index: 3, name: '💩', mode: 'or', filters: ['inscription', 'fake_pubkey', 'op_return'] }, + { index: 3, name: 'Data', mode: 'or', filters: ['inscription', 'fake_pubkey', 'op_return'] }, ]; goggleFlags = 0n; goggleMode: FilterMode = 'and'; From ade256efc75ac6ce45d1bd242e8deae03a772293 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 9 Feb 2024 18:01:25 +0000 Subject: [PATCH 8/8] Handle missing webgl on dashboards --- .../block-overview-graph.component.html | 5 ++++- .../block-overview-graph.component.scss | 13 +++++++++++++ .../block-overview-graph.component.ts | 17 +++++++++++------ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.html b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.html index 9d27d8d90..34d192678 100644 --- a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.html +++ b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.html @@ -13,6 +13,9 @@ [auditEnabled]="auditHighlighting" [blockConversion]="blockConversion" > - + +
+ Your browser does not support this feature. +
diff --git a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.scss b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.scss index d30dd3305..92964d948 100644 --- a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.scss +++ b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.scss @@ -7,6 +7,19 @@ justify-content: center; align-items: center; grid-column: 1/-1; + + .placeholder { + display: flex; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + height: 100%; + width: 100%; + align-items: center; + justify-content: center; + } } .grid-align { diff --git a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts index f250f3744..95305d72f 100644 --- a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts +++ b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts @@ -10,6 +10,7 @@ import { StateService } from '../../services/state.service'; import { Subscription } from 'rxjs'; import { defaultColorFunction, setOpacity, defaultFeeColors, defaultAuditFeeColors, defaultMarginalFeeColors, defaultAuditColors } from './utils'; import { ActiveFilter, FilterMode, toFlags } from '../../shared/filters.utils'; +import { detectWebGL } from '../../shared/graphs.utils'; const unmatchedOpacity = 0.2; const unmatchedFeeColors = defaultFeeColors.map(c => setOpacity(c, unmatchedOpacity)); @@ -77,11 +78,14 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On filtersAvailable: boolean = true; activeFilterFlags: bigint | null = null; + webGlEnabled = true; + constructor( readonly ngZone: NgZone, readonly elRef: ElementRef, private stateService: StateService, ) { + this.webGlEnabled = detectWebGL(); this.vertexArray = new FastVertexArray(512, TxSprite.dataSize); this.searchSubscription = this.stateService.searchText$.subscribe((text) => { this.searchText = text; @@ -506,11 +510,13 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On } onTxClick(cssX: number, cssY: number, keyModifier: boolean = false) { - const x = cssX * window.devicePixelRatio; - const y = cssY * window.devicePixelRatio; - const selected = this.scene.getTxAt({ x, y }); - if (selected && selected.txid) { - this.txClickEvent.emit({ tx: selected, keyModifier }); + if (this.scene) { + const x = cssX * window.devicePixelRatio; + const y = cssY * window.devicePixelRatio; + const selected = this.scene.getTxAt({ x, y }); + if (selected && selected.txid) { + this.txClickEvent.emit({ tx: selected, keyModifier }); + } } } @@ -529,7 +535,6 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On } getFilterColorFunction(flags: bigint): ((tx: TxView) => Color) { - console.log('getting filter color function: ', flags, this.filterMode); return (tx: TxView) => { if ((this.filterMode === 'and' && (tx.bigintFlags & flags) === flags) || (this.filterMode === 'or' && (flags === 0n || (tx.bigintFlags & flags) > 0n))) { return defaultColorFunction(tx);