feat: Improve announcement read tracking and localStorage sync

This commit is contained in:
Ushie
2025-06-26 02:03:48 +03:00
parent accbf09f90
commit 04ab5cf39f
4 changed files with 46 additions and 37 deletions

View File

@@ -2,49 +2,45 @@
import { read_announcements } from '$lib/stores';
import Banner from '$layout/Banners/Banner.svelte';
import { goto } from '$app/navigation';
import type { ResponseAnnouncement } from '$lib/types';
import { browser } from '$app/environment';
import { createQuery } from '@tanstack/svelte-query';
import { queries } from '$data/api';
import moment from 'moment';
let latestUnreadAnnouncement: ResponseAnnouncement | undefined = undefined;
const query = createQuery(queries.announcements());
$: {
if ($query.data?.announcements && $query.data.announcements.length > 0) {
const nonArchived = $query.data.announcements.filter(
(a) => !a.archived_at || moment(a.archived_at).isAfter(moment())
);
const announcement = nonArchived[0];
$: latestUnreadAnnouncement = (() => {
const announcements = $query.data?.announcements ?? [];
if (announcement && !$read_announcements.has(announcement.id)) {
latestUnreadAnnouncement = announcement;
} else {
latestUnreadAnnouncement = undefined;
}
}
}
const nonArchived = announcements.filter(
(a) => !a.archived_at || moment(a.archived_at).isAfter(moment())
);
const announcement = nonArchived[0];
return announcement && !$read_announcements.has(announcement.id) ? announcement : undefined;
})();
function setAsRead() {
if (!latestUnreadAnnouncement) return;
$read_announcements.add(latestUnreadAnnouncement.id);
localStorage.setItem('read_announcements', JSON.stringify(Array.from($read_announcements)));
latestUnreadAnnouncement = undefined;
read_announcements.update((set) => {
const updated = new Set(set);
updated.add(latestUnreadAnnouncement.id);
return updated;
});
}
function handleClick() {
if (latestUnreadAnnouncement) {
goto(`/announcements/${latestUnreadAnnouncement.id}`);
setAsRead();
}
if (!latestUnreadAnnouncement) return;
goto(`/announcements/${latestUnreadAnnouncement.id}`);
setAsRead();
}
function handleClose() {
if (latestUnreadAnnouncement && browser) {
setAsRead();
}
if (!latestUnreadAnnouncement) return;
setAsRead();
}
function getBannerLevel(level: number | undefined): 'info' | 'caution' {

View File

@@ -63,6 +63,12 @@ export const read_announcements = writable<Set<number>>(new Set(), (set) => {
};
});
read_announcements.subscribe((value) => {
if (!browser) return;
localStorage.setItem('read_announcements', JSON.stringify(Array.from(value)));
});
export const passed_login_with_creds = writable(false); // will only change when the user INPUTS the credentials, not if the session is just valid
export const allowAnalytics = writable(false);

View File

@@ -13,7 +13,7 @@
import Search from '$lib/components/Search.svelte';
import { onMount } from 'svelte';
import type { ResponseAnnouncement } from '$lib/types';
import { admin_login } from '$lib/stores';
import { admin_login, read_announcements } from '$lib/stores';
import Button from '$lib/components/Button.svelte';
import moment from 'moment';
import { debounce } from '$util/debounce';
@@ -66,6 +66,16 @@
onMount(() => {
debounce(update)();
if ($read_announcements.size === 0) {
query.subscribe((data) => {
read_announcements.update((set) => {
const updated = new Set(set);
data.data?.announcements.forEach((a) => updated.add(a.id));
return updated;
});
});
}
});
</script>

View File

@@ -18,7 +18,7 @@
const client = useQueryClient();
let isRead: boolean;
$: isRead = $read_announcements.has(announcement.id);
function prefetch() {
const query = queries['announcementById'](announcement.id);
@@ -27,10 +27,11 @@
}
function setAnnouncementRead() {
isRead = true;
$read_announcements.add(announcement.id);
localStorage.setItem('read_announcements', JSON.stringify(Array.from($read_announcements)));
read_announcements.update((set) => {
const updated = new Set(set);
updated.add(announcement.id);
return updated;
});
}
function generateSlug(title: string) {
@@ -39,10 +40,6 @@
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
}
onMount(() => {
isRead = $read_announcements.has(announcement.id);
});
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->