diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8d2c1dd22..03a922805 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -411,6 +411,7 @@ jobs: BASE_URL=http://localhost:13581 node test-channel-issue-1087-e2e.js 2>&1 | tee -a e2e-output.txt BASE_URL=http://localhost:13581 node test-channel-issue-1111-e2e.js 2>&1 | tee -a e2e-output.txt BASE_URL=http://localhost:13581 node test-channels-client-state-152-e2e.js 2>&1 | tee -a e2e-output.txt + CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-channels-154-155-e2e.js 2>&1 | tee -a e2e-output.txt BASE_URL=http://localhost:13581 node test-map-modal-fluid-e2e.js 2>&1 | tee -a e2e-output.txt CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-map-nodes-pagination-e2e.js 2>&1 | tee -a e2e-output.txt CHROMIUM_REQUIRE=1 BASE_URL=http://localhost:13581 node test-issue-123-map-lifecycle-e2e.js 2>&1 | tee -a e2e-output.txt diff --git a/public/channels.js b/public/channels.js index 2252b2257..a0d45b2b1 100644 --- a/public/channels.js +++ b/public/channels.js @@ -1999,7 +1999,19 @@ if (panel) panel.remove(); } - async function loadChannels(silent) { + // #154: overlapping loadChannels() calls (region changes, the + // show-encrypted toggle, approval, init()) can answer out of order. Only + // the newest request renders; an older response is dropped without a + // render or a reconcile. Same idea as messageRequestId above. + let channelsRequestId = 0; + let latestChannelsLoad = null; + + function loadChannels(silent) { + latestChannelsLoad = loadChannelsFor(++channelsRequestId, silent); + return latestChannelsLoad; + } + + async function loadChannelsFor(requestId, silent) { // #152: WS activity stamped after this point is newer than the snapshot. const seqAtRequestStart = wsActivitySeq; try { @@ -2010,6 +2022,10 @@ if (showEnc) params.push('includeEncrypted=true'); const qs = params.length ? '?' + params.join('&') : ''; const data = await api('/channels' + qs, { ttl: CLIENT_TTL.channels }); + // #154: a newer request owns the list. Resolve when it is done, so a + // caller's follow-up (init()'s deep link, the region handler) sees the + // list that actually renders. + if (requestId !== channelsRequestId) return latestChannelsLoad; const prevChannels = channels; // Copies: api() hands the same cached objects back on a TTL hit, and // mergeUserChannels() below mutates rows. @@ -2032,6 +2048,7 @@ renderChannelList(); reconcileSelectionAfterChannelRefresh(); } catch (e) { + if (requestId !== channelsRequestId) return latestChannelsLoad; if (!silent) { const el = document.getElementById('chList'); if (el) el.innerHTML = `