Thread viewer for Bluesky
1<script lang="ts">
2 import LikeStatsTable from '../components/LikeStatsTable.svelte';
3 import { LikeStats, type LikeStat } from '../services/like_stats.js';
4 import { numberOfDays } from '../utils.js';
5
6 let timeRangeDays = $state(7);
7 let progress: number | undefined = $state();
8 let scanInProgress = $derived(progress !== undefined);
9 let givenLikesUsers: LikeStat[] | undefined = $state();
10 let receivedLikesUsers: LikeStat[] | undefined = $state();
11
12 let likeStats = new LikeStats();
13
14 async function startScan(e: Event) {
15 e.preventDefault();
16
17 try {
18 if (!scanInProgress) {
19 givenLikesUsers = undefined;
20 receivedLikesUsers = undefined;
21
22 let result = await likeStats.findLikes(timeRangeDays, (p) => { progress = p });
23
24 givenLikesUsers = result.givenLikes;
25 receivedLikesUsers = result.receivedLikes;
26 progress = undefined;
27 } else {
28 likeStats.abortScan();
29 progress = undefined;
30 }
31 } catch (error) {
32 if (error.name !== 'AbortError') {
33 throw error;
34 }
35 }
36 }
37</script>
38
39<main>
40<h2>Like statistics</h2>
41
42<form onsubmit={startScan}>
43 <p>
44 Time range: <input id="like_stats_range" type="range" min="1" max="60" bind:value={timeRangeDays}>
45 <label for="like_stats_range">{numberOfDays(timeRangeDays)}</label>
46 </p>
47
48 <p>
49 <input type="submit" value="{scanInProgress ? 'Cancel' : 'Start scan'}">
50
51 {#if scanInProgress}
52 <progress value={progress} style="display: inline;"></progress>
53 {/if}
54 </p>
55</form>
56
57{#if givenLikesUsers && receivedLikesUsers}
58 <LikeStatsTable cssClass="given-likes" header="❤️ Likes from you:" users={givenLikesUsers} />
59 <LikeStatsTable cssClass="received-likes" header="💛 Likes on your posts:" users={receivedLikesUsers} />
60{/if}
61</main>
62
63<style>
64 input[type="range"] {
65 width: 250px;
66 vertical-align: middle;
67 }
68
69 input[type="submit"] {
70 font-size: 12pt;
71 margin: 5px 0px;
72 padding: 5px 10px;
73 }
74
75 progress {
76 width: 300px;
77 margin-left: 10px;
78 vertical-align: middle;
79 display: none;
80 }
81
82 :global(.scan-result.given-likes) {
83 margin-right: 100px;
84 }
85</style>