iuna

iuna - experimental devnet protocol
git clone https://iuna.jhx.app/git/iuna.git
Log | Files | Refs | README | LICENSE

commit b835a14f6e378f38ea9a11e27e3562809e159c9a
parent 36f7acb1455b59cdc0fc57c550c03dd416b4561d
Author: Joris Hartog <jorishartog@hotmail.com>
Date:   Tue, 11 Aug 2026 10:10:24 +0200

Fix initial block rail rendering

Diffstat:
Msrc/adapters/http/index_html.rs | 2+-
Msrc/adapters/http/tests.rs | 8+++++++-
Mwww/assets/iuna-ui.js | 12+++++++++++-
3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/adapters/http/index_html.rs b/src/adapters/http/index_html.rs @@ -442,7 +442,7 @@ pub(super) const INDEX_HTML: &str = r#"<!doctype html> .block-card { flex-basis: 108px; } } </style> - <script defer src="/assets/iuna-ui.js?v=98"></script> + <script defer src="/assets/iuna-ui.js?v=99"></script> <script defer src="/assets/alpine.min.js"></script> </head> <body x-data="iunaApp()" x-init="init()" @keydown.window.escape="closeModals()" x-cloak> diff --git a/src/adapters/http/tests.rs b/src/adapters/http/tests.rs @@ -1465,7 +1465,7 @@ fn metrics_response_skips_bootstrap_points_for_block_time_and_vdf_rounds() { #[test] fn metrics_screen_includes_block_range_filter() { - assert!(super::INDEX_HTML.contains("iuna-ui.js?v=98")); + assert!(super::INDEX_HTML.contains("iuna-ui.js?v=99")); assert!(super::INDEX_HTML.contains("aria-label=\"Metrics block range\"")); assert!(super::INDEX_HTML.contains("setMetricsRange(100)")); assert!(super::INDEX_HTML.contains("setMetricsRange(1000)")); @@ -1735,11 +1735,17 @@ fn block_detail_finalizer_opens_burn_leader_ranks_modal() { #[test] fn block_loading_skeleton_matches_block_card_layout() { + let app_js = include_str!("../../../www/assets/iuna-ui.js"); assert!(super::INDEX_HTML.contains("block-skeleton-group")); assert!(super::INDEX_HTML.contains("block-card block-card-skeleton skeleton-card")); assert!(super::INDEX_HTML.contains("skeleton-block-height")); assert!(super::INDEX_HTML.contains("skeleton-block-meta")); assert!(super::INDEX_HTML.contains("skeleton-block-miner")); + assert!(app_js.contains("const hadBlocks = this.blocks.length > 0;")); + assert!(app_js.contains("const previousScrollWidth = hadBlocks ? rail?.scrollWidth ?? 0 : 0;")); + assert!(app_js.contains("&& hadBlocks")); + assert!(app_js.contains("this.$nextTick(() => this.resetBlockRailPosition());")); + assert!(app_js.contains("resetBlockRailPosition()")); } #[tokio::test] diff --git a/www/assets/iuna-ui.js b/www/assets/iuna-ui.js @@ -1005,13 +1005,14 @@ window.iunaApp = function iunaApp() { }, mergeFreshBlocks(freshBlocks, options = {}) { + const hadBlocks = this.blocks.length > 0; const previousHeights = new Set(this.blocks.map((block) => block.height)); const previousHead = this.blocks[0]?.height; const previousHeadHash = this.blocks[0]?.hash; const wasFollowingHead = !this.selectedBlock || (previousHeadHash && this.selectedBlock.hash === previousHeadHash); const rail = this.$refs.blockRail; - const previousScrollWidth = rail?.scrollWidth ?? 0; + const previousScrollWidth = hadBlocks ? rail?.scrollWidth ?? 0 : 0; const known = new Map(this.blocks.map((block) => [block.hash, block])); for (const block of freshBlocks) { known.set(block.hash, block); @@ -1030,6 +1031,7 @@ window.iunaApp = function iunaApp() { !this.blocks.some((block) => block.height === 0); const newHeadBlocks = options.animateHead + && hadBlocks ? this.blocks.filter( (block) => !previousHeights.has(block.height) && @@ -1041,6 +1043,8 @@ window.iunaApp = function iunaApp() { this.$nextTick(() => this.slideNewHeadBlocks(previousScrollWidth, { force: wasFollowingHead }) ); + } else if (!hadBlocks) { + this.$nextTick(() => this.resetBlockRailPosition()); } this.$nextTick(() => this.maybeLoadOlderBlocksFromRail()); }, @@ -1065,6 +1069,12 @@ window.iunaApp = function iunaApp() { rail.scrollTo({ left: 0, behavior: "smooth" }); }, + resetBlockRailPosition() { + const rail = this.$refs.blockRail; + if (!rail) return; + rail.scrollLeft = 0; + }, + selectBlock(block) { this.selectedBlock = block; },