Thread viewer for Bluesky

estimate and show download progress

Changed files
+42 -2
+42 -2
posting_stats_page.js
··· 7 7 /** @type {number | undefined} */ 8 8 scanStartTime; 9 9 10 + /** @type {Record<string, { pages: number, progress: number }>} */ 11 + userProgress; 12 + 10 13 constructor() { 11 14 this.pageElement = $id('posting_stats_page'); 12 15 this.form = $(this.pageElement.querySelector('form'), HTMLFormElement); ··· 17 20 this.table = $(this.pageElement.querySelector('table.scan-result')); 18 21 19 22 this.setupEvents(); 23 + 24 + this.userProgress = {}; 20 25 } 21 26 22 27 setupEvents() { ··· 151 156 let users = textarea.value.split(/\n/).map(x => x.trim()).filter(x => x.length > 0); 152 157 let dids = await Promise.all(users.map(u => accountAPI.resolveHandle(u))); 153 158 154 - let requests = dids.map(d => accountAPI.loadUserTimeline(d, requestedDays, { 159 + this.resetUserProgress(dids); 160 + 161 + let requests = dids.map(did => accountAPI.loadUserTimeline(did, requestedDays, { 155 162 filter: 'posts_no_replies', 156 163 onPageLoad: (data) => { 157 164 if (this.scanStartTime != startTime) { 158 165 return { cancel: true }; 159 166 } 160 167 161 - //this.updateProgress(data, startTime); 168 + this.updateUserProgress(did, data, startTime, requestedDays); 162 169 }, 163 170 keepLastPage: true 164 171 })); ··· 201 208 let daysBack = (startTime - lastDate) / 86400 / 1000; 202 209 203 210 this.progressBar.value = daysBack; 211 + } 212 + 213 + 214 + /** @param {string[]} dids */ 215 + 216 + resetUserProgress(dids) { 217 + this.userProgress = {}; 218 + 219 + for (let did of dids) { 220 + this.userProgress[did] = { pages: 0, progress: 0 }; 221 + } 222 + } 223 + 224 + /** @param {string} did, @param {json[]} dataPage, @param {number} startTime, @param {number} requestedDays */ 225 + 226 + updateUserProgress(did, dataPage, startTime, requestedDays) { 227 + let last = dataPage.at(-1); 228 + 229 + if (!last) { return } 230 + 231 + let lastTimestamp = last.reason ? last.reason.indexedAt : last.post.record.createdAt; 232 + let lastDate = Date.parse(lastTimestamp); 233 + let daysBack = (startTime - lastDate) / 86400 / 1000; 234 + 235 + this.userProgress[did].pages += 1; 236 + this.userProgress[did].progress = Math.min(daysBack / requestedDays, 1.0); 237 + 238 + let expectedPages = Object.values(this.userProgress).map(x => x.pages / x.progress); 239 + let known = expectedPages.filter(x => !isNaN(x)); 240 + let expectedTotalPages = known.reduce((a, b) => a + b) / known.length * expectedPages.length; 241 + let fetchedPages = Object.values(this.userProgress).map(x => x.pages).reduce((a, b) => a + b); 242 + 243 + this.progressBar.value = Math.max(this.progressBar.value, (fetchedPages / expectedTotalPages) * requestedDays); 204 244 } 205 245 206 246 /** @param {json} a, @param {json} b, @returns {number} */