|
136 | 136 | // Badges
|
137 | 137 | let previousTab: string = currentRepo;
|
138 | 138 | let visitedTabs: string[] = [];
|
139 |
| - const lastVisitKey = "lastVisit"; |
| 139 | + let loadedTabs: Tab[] = []; |
| 140 | + let isLoadingDone = false; |
| 141 | + $: if (loadedTabs.length === Object.keys(repos).length) { |
| 142 | + isLoadingDone = true; |
| 143 | + } |
| 144 | + const lastVisitKey = "lastVisit" as const; |
140 | 145 | let lastVisitDateString = "";
|
141 | 146 |
|
142 | 147 | // Settings
|
|
184 | 189 | type Entries<T> = {
|
185 | 190 | [K in keyof T]: [K, T[K]];
|
186 | 191 | }[keyof T][];
|
| 192 | +
|
187 | 193 | // https://stackoverflow.com/a/74823834/12070367
|
188 | 194 | function typedEntries<T extends object>(obj: T) {
|
189 | 195 | return Object.entries(obj) as Entries<T>;
|
|
194 | 200 | localStorage.removeItem("displayBetaReleases");
|
195 | 201 | localStorage.removeItem("nonKitReleasesDisplay");
|
196 | 202 |
|
| 203 | + // Get the last visit date for the blinking badge |
197 | 204 | const localItem = localStorage.getItem(lastVisitKey);
|
198 | 205 | const nowDate = new Date().toISOString();
|
199 | 206 | lastVisitDateString = localItem ?? nowDate;
|
|
323 | 330 | {:then releases}
|
324 | 331 | <!-- eslint-disable-next-line @typescript-eslint/no-unused-vars -->
|
325 | 332 | {@const _ = (() => {
|
| 333 | + // Add tab to loaded tabs |
| 334 | + const toSet = new Set(loadedTabs); |
| 335 | + toSet.add(id); |
| 336 | + loadedTabs = [...toSet]; |
| 337 | + |
326 | 338 | // Update the most recent date of a release of the list
|
327 | 339 | const latestRelease = releases.sort(
|
328 | 340 | (a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
331 | 343 | const storedDate = localStorage.getItem(`${id.toLowerCase()}MostRecentUpdate`);
|
332 | 344 | const latestReleaseDate = new Date(latestRelease.created_at);
|
333 | 345 | if (storedDate) {
|
334 |
| - const storedDateObj = new Date(storedDate); |
| 346 | + const storedDateObj = new Date(storedDate.replace(/"/g, "")); |
335 | 347 | if (latestReleaseDate > storedDateObj) {
|
336 | 348 | localStorage.setItem(
|
337 | 349 | `${id.toLowerCase()}MostRecentUpdate`,
|
|
532 | 544 | <!-- Trigger with release name, date and optional prerelease badge -->
|
533 | 545 | <Accordion.Trigger class="group hover:no-underline">
|
534 | 546 | <div class="flex w-full items-center gap-2 xs:items-baseline xs:gap-1">
|
535 |
| - {#if new Date(release.created_at) > new Date(lastVisitDateString) && !visitedTabs.includes(id)} |
536 |
| - <div class="relative ml-1 mr-2 inline-flex"> |
537 |
| - <span |
538 |
| - class="absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" |
539 |
| - /> |
540 |
| - <span class="inline-flex size-2.5 rounded-full bg-primary" /> |
541 |
| - </div> |
542 |
| - {/if} |
| 547 | + <!-- Trigger reactivity (please give me Svelte 5) --> |
| 548 | + {#key isLoadingDone} |
| 549 | + {#if releaseDate > new Date(lastVisitDateString) && !visitedTabs.includes(id)} |
| 550 | + <div class="relative ml-1 mr-2 inline-flex"> |
| 551 | + <span |
| 552 | + class="absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" |
| 553 | + /> |
| 554 | + <span class="inline-flex size-2.5 rounded-full bg-primary" /> |
| 555 | + </div> |
| 556 | + {/if} |
| 557 | + {/key} |
543 | 558 | <div class="flex flex-col items-start gap-1">
|
544 | 559 | <span class="text-left text-lg group-hover:underline">
|
545 | 560 | {release.name}
|
546 | 561 | </span>
|
547 | 562 | <div class="flex items-center gap-2 xs:hidden">
|
548 | 563 | {#if isLatestRelease}
|
549 |
| - <Tooltip.Root> |
| 564 | + <Tooltip.Root openDelay={300}> |
550 | 565 | <Tooltip.Trigger>
|
551 | 566 | <Badge
|
552 | 567 | class="bg-green-600 hover:bg-green-600 dark:bg-green-700 dark:hover:bg-green-700"
|
|
564 | 579 | </Tooltip.Root>
|
565 | 580 | {/if}
|
566 | 581 | {#if isMajorRelease}
|
567 |
| - <Tooltip.Root> |
| 582 | + <Tooltip.Root openDelay={300}> |
568 | 583 | <Tooltip.Trigger>
|
569 | 584 | <Badge>Major</Badge>
|
570 | 585 | </Tooltip.Trigger>
|
|
573 | 588 | </Tooltip.Content>
|
574 | 589 | </Tooltip.Root>
|
575 | 590 | {:else if release.prerelease}
|
576 |
| - <Tooltip.Root> |
| 591 | + <Tooltip.Root openDelay={300}> |
577 | 592 | <Tooltip.Trigger>
|
578 | 593 | <Badge variant="outline" class="border-primary text-primary">
|
579 | 594 | Prerelease
|
|
586 | 601 | </Tooltip.Content>
|
587 | 602 | </Tooltip.Root>
|
588 | 603 | {:else if isMaintenanceRelease}
|
589 |
| - <Tooltip.Root> |
| 604 | + <Tooltip.Root openDelay={300}> |
590 | 605 | <Tooltip.Trigger>
|
591 | 606 | <Badge variant="outline" class="border-blue-600 text-blue-600">
|
592 | 607 | Maintenance
|
|
601 | 616 | </div>
|
602 | 617 | </div>
|
603 | 618 | <span
|
604 |
| - title={isOlderThanAWeek |
605 |
| - ? toRelativeDateString(releaseDate) |
606 |
| - : releaseDate.toLocaleDateString("en")} |
607 | 619 | class="ml-auto mr-4 flex text-right text-sm text-muted-foreground xs:ml-0 xs:mr-2"
|
608 | 620 | >
|
609 | 621 | <span class="mr-1 hidden xs:block">•</span>
|
610 |
| - {isOlderThanAWeek |
611 |
| - ? releaseDate.toLocaleDateString("en") |
612 |
| - : toRelativeDateString(releaseDate)} |
| 622 | + <Tooltip.Root openDelay={300}> |
| 623 | + <Tooltip.Trigger> |
| 624 | + {isOlderThanAWeek |
| 625 | + ? releaseDate.toLocaleDateString("en") |
| 626 | + : toRelativeDateString(releaseDate)} |
| 627 | + </Tooltip.Trigger> |
| 628 | + <Tooltip.Content> |
| 629 | + {isOlderThanAWeek |
| 630 | + ? toRelativeDateString(releaseDate) |
| 631 | + : new Intl.DateTimeFormat("en", { |
| 632 | + dateStyle: "medium", |
| 633 | + timeStyle: "short" |
| 634 | + }).format(releaseDate)} |
| 635 | + </Tooltip.Content> |
| 636 | + </Tooltip.Root> |
613 | 637 | </span>
|
614 | 638 | <div class="hidden items-center gap-2 xs:flex">
|
615 | 639 | {#if isLatestRelease}
|
616 |
| - <Tooltip.Root> |
| 640 | + <Tooltip.Root openDelay={300}> |
617 | 641 | <Tooltip.Trigger>
|
618 | 642 | <Badge
|
619 | 643 | class="bg-green-600 hover:bg-green-600 dark:bg-green-700 dark:hover:bg-green-700"
|
|
631 | 655 | </Tooltip.Root>
|
632 | 656 | {/if}
|
633 | 657 | {#if isMajorRelease}
|
634 |
| - <Tooltip.Root> |
| 658 | + <Tooltip.Root openDelay={300}> |
635 | 659 | <Tooltip.Trigger>
|
636 | 660 | <Badge>Major</Badge>
|
637 | 661 | </Tooltip.Trigger>
|
|
640 | 664 | </Tooltip.Content>
|
641 | 665 | </Tooltip.Root>
|
642 | 666 | {:else if release.prerelease}
|
643 |
| - <Tooltip.Root> |
| 667 | + <Tooltip.Root openDelay={300}> |
644 | 668 | <Tooltip.Trigger>
|
645 | 669 | <Badge variant="outline" class="border-primary text-primary">
|
646 | 670 | Prerelease
|
|
653 | 677 | </Tooltip.Content>
|
654 | 678 | </Tooltip.Root>
|
655 | 679 | {:else if isMaintenanceRelease}
|
656 |
| - <Tooltip.Root> |
| 680 | + <Tooltip.Root openDelay={300}> |
657 | 681 | <Tooltip.Trigger>
|
658 | 682 | <Badge variant="outline" class="border-blue-600 text-blue-600">
|
659 | 683 | Maintenance
|
|
0 commit comments