commit 0fd31183b0337e6637430ced05d89129dcab250f
parent 889ac402ec70a85e3233cbab38e7fbe8ce482bf3
Author: Joris Hartog <jorishartog@hotmail.com>
Date: Sun, 2 Aug 2026 21:38:59 +0200
Avoid visible loaders during polling
Diffstat:
2 files changed, 39 insertions(+), 19 deletions(-)
diff --git a/src/adapters/http.rs b/src/adapters/http.rs
@@ -2863,7 +2863,7 @@ const INDEX_HTML: &str = r#"<!doctype html>
.block-card { flex-basis: 108px; }
}
</style>
- <script defer src="/assets/iuna-ui.js?v=72"></script>
+ <script defer src="/assets/iuna-ui.js?v=73"></script>
<script defer src="/assets/alpine.min.js"></script>
</head>
<body x-data="iunaApp()" x-init="init()" @keydown.window.escape="closeModals()" x-cloak>
@@ -4742,7 +4742,7 @@ mod tests {
#[test]
fn metrics_screen_includes_block_range_filter() {
- assert!(super::INDEX_HTML.contains("iuna-ui.js?v=72"));
+ assert!(super::INDEX_HTML.contains("iuna-ui.js?v=73"));
assert!(super::INDEX_HTML.contains("aria-label=\"Metrics block range\""));
assert!(super::INDEX_HTML.contains("setMetricsRange(100)"));
assert!(super::INDEX_HTML.contains("setMetricsRange(1000)"));
@@ -4750,6 +4750,14 @@ mod tests {
}
#[test]
+ fn polling_refreshes_paged_datasets_without_visible_loaders() {
+ let app_js = include_str!("../../www/assets/iuna-ui.js");
+ assert!(app_js.contains("setInterval(() => this.refresh({ silent: true }), 5000)"));
+ assert!(app_js.contains("backgroundLoading"));
+ assert!(app_js.contains("options.silent === true ? \"backgroundLoading\" : \"loading\""));
+ }
+
+ #[test]
fn mine_screen_shows_fixed_pow_reward_without_burn_slider() {
let app_js = include_str!("../../www/assets/iuna-ui.js");
assert!(app_js.contains("powMineReward()"));
diff --git a/www/assets/iuna-ui.js b/www/assets/iuna-ui.js
@@ -89,10 +89,10 @@ window.iunaApp = function iunaApp() {
newBlockTimer: null,
blockPageSize: 20,
datasetPageSize: 25,
- walletTxPage: { offset: 0, total: 0, hasMore: true, loading: false },
- walletUtxoPage: { offset: 0, total: 0, hasMore: true, loading: false },
- mempoolPage: { offset: 0, total: 0, hasMore: true, loading: false },
- peerPage: { offset: 0, total: 0, hasMore: true, loading: false },
+ walletTxPage: { offset: 0, total: 0, hasMore: true, loading: false, backgroundLoading: false },
+ walletUtxoPage: { offset: 0, total: 0, hasMore: true, loading: false, backgroundLoading: false },
+ mempoolPage: { offset: 0, total: 0, hasMore: true, loading: false, backgroundLoading: false },
+ peerPage: { offset: 0, total: 0, hasMore: true, loading: false, backgroundLoading: false },
init() {
this.bootstrap();
@@ -119,7 +119,7 @@ window.iunaApp = function iunaApp() {
await this.refresh();
this.checkLatestRelease();
if (!this.pollHandle) {
- this.pollHandle = setInterval(() => this.refresh(), 5000);
+ this.pollHandle = setInterval(() => this.refresh({ silent: true }), 5000);
}
},
@@ -509,7 +509,7 @@ window.iunaApp = function iunaApp() {
}
},
- async refresh() {
+ async refresh(options = {}) {
try {
const [config, status, blocks, p2pMetrics, blockchainMetrics, networkHealth] = await Promise.all([
this.fetchJson("/api/config"),
@@ -520,10 +520,10 @@ window.iunaApp = function iunaApp() {
this.fetchJson("/api/network/health"),
]);
await Promise.all([
- this.refreshPagedDataset("walletTx"),
- this.refreshPagedDataset("walletUtxo"),
- this.refreshPagedDataset("mempool"),
- this.refreshPagedDataset("peer"),
+ this.refreshPagedDataset("walletTx", { silent: options.silent === true }),
+ this.refreshPagedDataset("walletUtxo", { silent: options.silent === true }),
+ this.refreshPagedDataset("mempool", { silent: options.silent === true }),
+ this.refreshPagedDataset("peer", { silent: options.silent === true }),
]);
this.config = config;
this.syncConfigState();
@@ -599,25 +599,36 @@ window.iunaApp = function iunaApp() {
const config = this.datasetConfig(kind);
if (!config) return;
this[config.items] = [];
- Object.assign(this[config.page], { offset: 0, total: 0, hasMore: true, loading: false });
+ Object.assign(this[config.page], {
+ offset: 0,
+ total: 0,
+ hasMore: true,
+ loading: false,
+ backgroundLoading: false,
+ });
await this.refreshPagedDataset(kind);
},
- async refreshPagedDataset(kind) {
+ async refreshPagedDataset(kind, options = {}) {
const config = this.datasetConfig(kind);
if (!config) return;
const page = this[config.page];
- if (page.loading) return;
+ if (page.loading || page.backgroundLoading) return;
const currentLength = this[config.items].length;
const limit = Math.max(this.datasetPageSize, currentLength || 0);
- await this.loadPagedDataset(kind, { offset: 0, limit, replace: true });
+ await this.loadPagedDataset(kind, {
+ offset: 0,
+ limit,
+ replace: true,
+ silent: options.silent === true,
+ });
},
async loadNextPage(kind) {
const config = this.datasetConfig(kind);
if (!config) return;
const page = this[config.page];
- if (page.loading || !page.hasMore) return;
+ if (page.loading || page.backgroundLoading || !page.hasMore) return;
await this.loadPagedDataset(kind, {
offset: page.offset ?? this[config.items].length,
limit: this.datasetPageSize,
@@ -628,7 +639,8 @@ window.iunaApp = function iunaApp() {
async loadPagedDataset(kind, options) {
const config = this.datasetConfig(kind);
const page = this[config.page];
- page.loading = true;
+ const loadingKey = options.silent === true ? "backgroundLoading" : "loading";
+ page[loadingKey] = true;
try {
const payload = await this.fetchJson(
this.paginatedPath(config.path(), options.offset, options.limit)
@@ -647,7 +659,7 @@ window.iunaApp = function iunaApp() {
} catch (error) {
this.showFlash(error.message, "error");
} finally {
- page.loading = false;
+ page[loadingKey] = false;
}
},