Thread viewer for Bluesky

added progress bar

+1 -1
index.html
··· 136 136 </p> 137 137 138 138 <p> 139 - <input type="submit" value="Start scan"> 139 + <input type="submit" value="Start scan"> <progress></progress> 140 140 </p> 141 141 </form> 142 142
+67 -2
like_stats_page.js
··· 8 8 9 9 this.rangeInput = $(this.pageElement.querySelector('input[type="range"]'), HTMLInputElement); 10 10 this.submitButton = $(this.pageElement.querySelector('input[type="submit"]'), HTMLInputElement); 11 + this.progressBar = $(this.pageElement.querySelector('input[type=submit] + progress'), HTMLProgressElement); 11 12 12 13 this.receivedTable = $(this.pageElement.querySelector('.received-likes')); 13 14 this.givenTable = $(this.pageElement.querySelector('.given-likes')); ··· 50 51 51 52 let requestedDays = this.selectedDaysRange(); 52 53 54 + this.resetProgress(); 55 + this.progressBar.style.display = 'inline'; 56 + 53 57 let startTime = new Date().getTime(); 54 58 this.scanStartTime = startTime; 59 + 60 + this.receivedTable.style.display = 'none'; 61 + this.givenTable.style.display = 'none'; 55 62 56 63 let fetchGivenLikes = this.fetchGivenLikes(requestedDays); 57 64 ··· 67 74 68 75 this.receivedTable.style.display = 'table'; 69 76 this.givenTable.style.display = 'table'; 77 + 78 + this.submitButton.value = 'Start scan'; 79 + this.progressBar.style.display = 'none'; 80 + this.scanStartTime = undefined; 70 81 } 71 82 72 83 async fetchGivenLikes(requestedDays) { ··· 78 89 limit: 100 79 90 }, { 80 91 field: 'records', 81 - breakWhen: (x) => Date.parse(x['value']['createdAt']) < now - 86400 * requestedDays * 1000 92 + breakWhen: (x) => Date.parse(x['value']['createdAt']) < now - 86400 * requestedDays * 1000, 93 + onPageLoad: (data) => { 94 + if (data.length == 0) { return } 95 + 96 + let last = data[data.length - 1]; 97 + let lastDate = Date.parse(last.value.createdAt); 98 + 99 + let daysBack = (this.scanStartTime - lastDate) / 86400 / 1000; 100 + this.updateProgress({ likeRecords: Math.min(1.0, daysBack / requestedDays) }); 101 + } 82 102 }); 83 103 } 84 104 85 105 async fetchReceivedLikes(requestedDays) { 86 - let myPosts = await this.appView.loadUserTimeline(accountAPI.user.did, requestedDays); 106 + let myPosts = await this.appView.loadUserTimeline(accountAPI.user.did, requestedDays, { 107 + onPageLoad: (data) => { 108 + if (data.length == 0) { return } 109 + 110 + let last = data[data.length - 1]; 111 + let lastTimestamp = last.reason ? last.reason.indexedAt : last.post.record.createdAt; 112 + let lastDate = Date.parse(lastTimestamp); 113 + 114 + let daysBack = (this.scanStartTime - lastDate) / 86400 / 1000; 115 + this.updateProgress({ posts: Math.min(1.0, daysBack / requestedDays) }); 116 + } 117 + }); 118 + 87 119 let likedPosts = myPosts.filter(x => !x['reason'] && x['post']['likeCount'] > 0); 88 120 89 121 let results = []; 90 122 91 123 for (let i = 0; i < likedPosts.length; i += 10) { 92 124 let batch = likedPosts.slice(i, i + 10); 125 + this.updateProgress({ postLikes: i / likedPosts.length }); 93 126 94 127 let fetchBatch = batch.map(x => { 95 128 return this.appView.fetchAll('app.bsky.feed.getLikes', { uri: x['post']['uri'], limit: 100 }, { ··· 100 133 let batchResults = await Promise.all(fetchBatch); 101 134 results = results.concat(batchResults); 102 135 } 136 + 137 + this.updateProgress({ postLikes: 1.0 }); 103 138 104 139 return results.flat(); 105 140 } ··· 120 155 }; 121 156 } 122 157 158 + resetProgress() { 159 + this.progressBar.value = 0; 160 + this.progressPosts = 0; 161 + this.progressLikeRecords = 0; 162 + this.progressPostLikes = 0; 163 + } 164 + 165 + updateProgress(data) { 166 + if (data.posts) { 167 + this.progressPosts = data.posts; 168 + } 169 + 170 + if (data.likeRecords) { 171 + this.progressLikeRecords = data.likeRecords; 172 + } 173 + 174 + if (data.postLikes) { 175 + this.progressPostLikes = data.postLikes; 176 + } 177 + 178 + let totalProgress = ( 179 + 0.1 * this.progressPosts + 180 + 0.65 * this.progressLikeRecords + 181 + 0.25 * this.progressPostLikes 182 + ); 183 + 184 + this.progressBar.value = totalProgress; 185 + } 186 + 123 187 sortResults(a, b) { 124 188 if (a[1] < b[1]) { 125 189 return 1; ··· 132 196 133 197 stopScan() { 134 198 this.submitButton.value = 'Start scan'; 199 + this.progressBar.style.display = 'none'; 135 200 this.scanStartTime = undefined; 136 201 } 137 202 }
+35 -28
style.css
··· 732 732 margin-top: 25px; 733 733 } 734 734 735 - #like_stats_page { 736 - display: none; 737 - } 738 - 739 - #like_stats_page input[type="range"] { 740 - width: 250px; 741 - vertical-align: middle; 742 - } 743 - 744 - #like_stats_page .scan-result { 745 - border: 1px solid #333; 746 - border-collapse: collapse; 747 - display: none; 748 - float: left; 749 - margin-right: 100px; 750 - } 751 - 752 - #like_stats_page .scan-result td, #like_stats_page .scan-result th { 753 - border: 1px solid #333; 754 - padding: 5px 8px; 755 - } 756 - 757 - #like_stats_page .scan-result th { 758 - text-align: center; 759 - background-color: hsl(207, 100%, 86%); 760 - padding: 7px 10px; 761 - } 762 - 763 735 #posting_stats_page { 764 736 display: none; 765 737 } ··· 857 829 858 830 #posting_stats_page .scan-result td.percent { 859 831 min-width: 70px; 832 + } 833 + 834 + #like_stats_page { 835 + display: none; 836 + } 837 + 838 + #like_stats_page input[type="range"] { 839 + width: 250px; 840 + vertical-align: middle; 841 + } 842 + 843 + #like_stats_page progress { 844 + width: 300px; 845 + margin-left: 10px; 846 + vertical-align: middle; 847 + display: none; 848 + } 849 + 850 + #like_stats_page .scan-result { 851 + border: 1px solid #333; 852 + border-collapse: collapse; 853 + display: none; 854 + float: left; 855 + margin-right: 100px; 856 + } 857 + 858 + #like_stats_page .scan-result td, #like_stats_page .scan-result th { 859 + border: 1px solid #333; 860 + padding: 5px 8px; 861 + } 862 + 863 + #like_stats_page .scan-result th { 864 + text-align: center; 865 + background-color: hsl(207, 100%, 86%); 866 + padding: 7px 10px; 860 867 } 861 868 862 869 @media (prefers-color-scheme: dark) {