From 123c8ac2c52e1ae67440a64a3e0a9b3361e8cf43 Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 17:45:36 +0100 Subject: [PATCH 1/7] correctly check for avif support, remove webp --- src/imageresizer/src/index.ts | 6 ++-- .../src/lib/components/CDNImage.svelte | 28 +++++++++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/imageresizer/src/index.ts b/src/imageresizer/src/index.ts index 569b242..f58ccd3 100644 --- a/src/imageresizer/src/index.ts +++ b/src/imageresizer/src/index.ts @@ -46,7 +46,7 @@ app.get("/cdn/:dir/:filename", async (req: Request<{ dir: string; filename: stri } // Validate parameters - const validFormats = ["avif", "webp", "jpg"]; + const validFormats = ["avif", "jpg"]; const validWidths = ["150", "300", "768", "1024", "original"]; if (width && !validWidths.includes(width.toString())) { @@ -57,11 +57,11 @@ app.get("/cdn/:dir/:filename", async (req: Request<{ dir: string; filename: stri if (format && !validFormats.includes(format.toString())) { logger.error(`Invalid format parameter: "${format}"`); - res.status(400).send("Invalid format parameter, must be one of: avif, webp, jpg"); + res.status(400).send("Invalid format parameter, must be one of: avif, jpg"); return; } - const targetFormat = (format as "avif" | "webp" | "jpg") || "jpg"; + const targetFormat = (format as "avif" | "jpg") || "jpg"; const targetWidth = width ? (width === "original" ? undefined : parseInt(width.toString())) : undefined; const originalFilePath = path.join(cdnFiles, filename); diff --git a/src/psaggregator/src/lib/components/CDNImage.svelte b/src/psaggregator/src/lib/components/CDNImage.svelte index 201cd15..41ec804 100644 --- a/src/psaggregator/src/lib/components/CDNImage.svelte +++ b/src/psaggregator/src/lib/components/CDNImage.svelte @@ -11,16 +11,28 @@ let classes = ""; export { classes as class }; - function getPreferredImageFormat() { + let imageSrc = ""; + + function supportsAVIF() { + return new Promise((resolve) => { + const avifImage = + "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="; + const img = new Image(); + img.onload = () => resolve(true); + img.onerror = () => resolve(false); + img.src = avifImage; + }); + } + + async function getPreferredImageFormat() { if (!browser || !window || !window.matchMedia) { return "jpg"; } - if (window.matchMedia && window.matchMedia("(image-avif)").matches) { + if (await supportsAVIF()) { return "avif"; - } else if (window.matchMedia && window.matchMedia("(image-webp)").matches) { - return "webp"; } + return "jpg"; // fallback } @@ -50,9 +62,13 @@ return "300"; // fallback } - $: imageSrc = `${src}?format=${getPreferredImageFormat()}&width=${getPreferredImageSize()}`; + async function calculateImageSrc(src: string | null | undefined) { + imageSrc = `${src}?format=${await getPreferredImageFormat()}&width=${getPreferredImageSize()}`; + } + + $: browser && calculateImageSrc(src); -{#if browser} +{#if imageSrc} {alt {/if} From ebf2f0429b51ab8b609a2dcd8f113598d01c7eef Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 17:51:32 +0100 Subject: [PATCH 2/7] enable gzip --- src/nginx/nginx.conf | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/nginx/nginx.conf b/src/nginx/nginx.conf index 4a17fb8..f7d5993 100644 --- a/src/nginx/nginx.conf +++ b/src/nginx/nginx.conf @@ -6,6 +6,37 @@ events { worker_connections 1024; } http { include mime.types; + + gzip on; + gzip_disable "msie6"; + + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_min_length 256; + gzip_types + application/atom+xml + application/geo+json + application/javascript + application/x-javascript + application/json + application/ld+json + application/manifest+json + application/rdf+xml + application/rss+xml + application/xhtml+xml + application/xml + font/eot + font/otf + font/ttf + image/svg+xml + text/css + text/javascript + text/plain + text/xml; + limit_req_zone $http_x_forwarded_for zone=myhigherlimit:10m rate=10r/s; limit_req_zone $http_x_forwarded_for zone=mylimit:10m rate=3r/s; @@ -51,4 +82,4 @@ http { proxy_pass http://frontend:3000; } } -} \ No newline at end of file +} From a13befbd21de2b8d43c08e96951dde417d4aa504 Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 18:20:01 +0100 Subject: [PATCH 3/7] eager load first images --- .../src/lib/components/InstagramPost.svelte | 9 ++++++++- .../src/lib/components/NewsBig.svelte | 14 +++++++------- .../src/lib/components/NewsSmall.svelte | 15 +++++++-------- .../src/lib/components/PSVideo.svelte | 9 ++++++++- .../src/lib/components/RedditPost.svelte | 3 ++- .../src/lib/components/TwitterPost.svelte | 3 ++- .../lib/components/YouTubeCommunityPost.svelte | 9 ++++++++- src/psaggregator/src/routes/+page.svelte | 16 ++++++++-------- .../src/routes/randomvideo/+page.svelte | 2 +- src/psaggregator/src/routes/videos/+page.svelte | 10 +++++++--- 10 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/psaggregator/src/lib/components/InstagramPost.svelte b/src/psaggregator/src/lib/components/InstagramPost.svelte index e256c13..26ff395 100644 --- a/src/psaggregator/src/lib/components/InstagramPost.svelte +++ b/src/psaggregator/src/lib/components/InstagramPost.svelte @@ -6,6 +6,7 @@ import CdnImage from "./CDNImage.svelte"; export let post: Information & { InformationResource: InformationResource[] }; + export let loading: "lazy" | "eager" = "lazy"; let video: HTMLVideoElement; $: isVideoOnly = @@ -59,7 +60,13 @@ {/each} {:else if post.imageUri} - + {/if} diff --git a/src/psaggregator/src/lib/components/NewsBig.svelte b/src/psaggregator/src/lib/components/NewsBig.svelte index 052e751..01f0010 100644 --- a/src/psaggregator/src/lib/components/NewsBig.svelte +++ b/src/psaggregator/src/lib/components/NewsBig.svelte @@ -88,15 +88,15 @@ }); -
+
YouTube
- {#each youtubeCommunityPosts as youtube} - + {#each youtubeCommunityPosts as youtube, index} + {/each}
{#if loading[ImportType.YouTube]} @@ -109,8 +109,8 @@ Instagram
- {#each instagramPosts as instagram} - + {#each instagramPosts as instagram, index} + {/each}
{#if loading[ImportType.Instagram]} @@ -123,8 +123,8 @@ Twitter
- {#each twitterPosts as twitter} - + {#each twitterPosts as twitter, index} + {/each}
{#if loading[ImportType.Twitter]} diff --git a/src/psaggregator/src/lib/components/NewsSmall.svelte b/src/psaggregator/src/lib/components/NewsSmall.svelte index 50e3497..2b7b5d0 100644 --- a/src/psaggregator/src/lib/components/NewsSmall.svelte +++ b/src/psaggregator/src/lib/components/NewsSmall.svelte @@ -1,8 +1,7 @@ @@ -20,7 +21,7 @@
{#if entry.imageUri} - + {/if}
diff --git a/src/psaggregator/src/lib/components/TwitterPost.svelte b/src/psaggregator/src/lib/components/TwitterPost.svelte index c0e0731..d03a080 100644 --- a/src/psaggregator/src/lib/components/TwitterPost.svelte +++ b/src/psaggregator/src/lib/components/TwitterPost.svelte @@ -6,6 +6,7 @@ import CdnImage from "./CDNImage.svelte"; export let post: Information & { InformationResource: InformationResource[] }; + export let loading: "lazy" | "eager" = "lazy"; function titleCase(str: string | null) { if (!str) return ""; @@ -42,7 +43,7 @@ src={resource.imageUri} alt={resource.remoteId} title={resource.id} - loading="lazy" /> + {loading} /> {/if}
{/each} diff --git a/src/psaggregator/src/lib/components/YouTubeCommunityPost.svelte b/src/psaggregator/src/lib/components/YouTubeCommunityPost.svelte index b5a5ba7..f6d63c0 100644 --- a/src/psaggregator/src/lib/components/YouTubeCommunityPost.svelte +++ b/src/psaggregator/src/lib/components/YouTubeCommunityPost.svelte @@ -6,6 +6,7 @@ import CdnImage from "./CDNImage.svelte"; export let post: Information; + export let loading: "lazy" | "eager" = "lazy"; @@ -15,7 +16,13 @@ {/if}
{post.text}
{#if post.imageUri} - + {/if}
diff --git a/src/psaggregator/src/routes/+page.svelte b/src/psaggregator/src/routes/+page.svelte index 0c633a1..098fd74 100644 --- a/src/psaggregator/src/routes/+page.svelte +++ b/src/psaggregator/src/routes/+page.svelte @@ -69,8 +69,8 @@ YouTube
- {#each data.youtubeCommunityPosts as youtube} - + {#each data.youtubeCommunityPosts as youtube, index} + {/each}
@@ -80,8 +80,8 @@ Instagram
- {#each data.instagramPosts as instagram} - + {#each data.instagramPosts as instagram, index} + {/each}
@@ -91,8 +91,8 @@ Twitter
- {#each data.twitterPosts as twitter} - + {#each data.twitterPosts as twitter, index} + {/each}
@@ -102,8 +102,8 @@ Reddit
- {#each data.redditPosts.slice(0, matches ? 10 : 5) as reddit} - + {#each data.redditPosts.slice(0, matches ? 10 : 5) as reddit, index} + {/each}
diff --git a/src/psaggregator/src/routes/randomvideo/+page.svelte b/src/psaggregator/src/routes/randomvideo/+page.svelte index c61cf4c..098ea3e 100644 --- a/src/psaggregator/src/routes/randomvideo/+page.svelte +++ b/src/psaggregator/src/routes/randomvideo/+page.svelte @@ -11,7 +11,7 @@
- +
- {#each data.videos as video} + {#each data.videos as video, index} {#if video.startDate} {@const newMonth = checkMonth(video.startDate)} {#if newMonth} @@ -228,7 +228,10 @@ {/if} {/if} {#if $VIDEO_COMPLEXE_VIEW} - + {:else} + title={video.title} + loading={index < 10 ? "eager" : "lazy"} /> {/if} {/each} From 38d31a8e255b51959d14f2649a00f0ccf588b975 Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 18:20:12 +0100 Subject: [PATCH 4/7] service static content with 1year cache --- src/nginx/nginx.conf | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/nginx/nginx.conf b/src/nginx/nginx.conf index f7d5993..b6f056c 100644 --- a/src/nginx/nginx.conf +++ b/src/nginx/nginx.conf @@ -48,16 +48,9 @@ http { listen 80; listen [::]:80; - root /var/www/data; - index index.html; - access_log /var/log/nginx/access_custom.log compression; access_log /dev/stdout compression; - location ~ /\.ht { - deny all; - } - location ^~ /cdn/ { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $http_x_forwarded_for; @@ -74,6 +67,16 @@ http { proxy_pass http://frontend:3000; } + location ~ /(brammen\.jpg|chris\.jpg|jay\.jpg|peter\.jpg|sep\.jpg|ps\.png|reddit\-logo\.svg|threads\-logo\.svg|twitch\-logo\.svg)$ { + limit_req zone=mylimit burst=50 nodelay; + + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $http_x_forwarded_for; + proxy_pass http://frontend:3000; + + expires 365d; + } + location / { limit_req zone=mylimit burst=50 nodelay; From 64dc30db705dd676d97258459d54ac83b050d794 Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 19:53:53 +0100 Subject: [PATCH 5/7] adjusted layout for instagram stories --- .../src/lib/components/BigHeader.svelte | 7 +- .../src/lib/components/CDNImage.svelte | 2 +- .../InstagramStoriesContainer.svelte | 104 ++++++++++-------- .../src/lib/components/NewsBig.svelte | 2 +- src/psaggregator/src/routes/news/+page.svelte | 4 +- 5 files changed, 66 insertions(+), 53 deletions(-) diff --git a/src/psaggregator/src/lib/components/BigHeader.svelte b/src/psaggregator/src/lib/components/BigHeader.svelte index 038aa2c..e003845 100644 --- a/src/psaggregator/src/lib/components/BigHeader.svelte +++ b/src/psaggregator/src/lib/components/BigHeader.svelte @@ -8,7 +8,12 @@
diff --git a/src/psaggregator/src/lib/components/CDNImage.svelte b/src/psaggregator/src/lib/components/CDNImage.svelte index 41ec804..e18f883 100644 --- a/src/psaggregator/src/lib/components/CDNImage.svelte +++ b/src/psaggregator/src/lib/components/CDNImage.svelte @@ -70,5 +70,5 @@ {#if imageSrc} - {alt + {alt {/if} diff --git a/src/psaggregator/src/lib/components/InstagramStoriesContainer.svelte b/src/psaggregator/src/lib/components/InstagramStoriesContainer.svelte index 30cc5ff..bb398ed 100644 --- a/src/psaggregator/src/lib/components/InstagramStoriesContainer.svelte +++ b/src/psaggregator/src/lib/components/InstagramStoriesContainer.svelte @@ -184,62 +184,70 @@ {#if active} -
+
-
- {#each stories as story, index} - {@const duration = - story.InformationResource?.length && story.InformationResource[0].videoDuration - ? story.InformationResource[0].videoDuration - : 15} -
index} - class="progress" - on:animationend={playNext} - on:click={() => { - playSpecific(index); - }} - on:keydown={void 0} - role="button" - tabindex="0"> -
- {/each} -
-
-
- {filterKey} - {titleCase(filterKey)} +
+
+ {#each stories as story, index} + {@const duration = + story.InformationResource?.length && story.InformationResource[0].videoDuration + ? story.InformationResource[0].videoDuration + : 15} +
index} + class="progress" + on:animationend={playNext} + on:click={() => { + playSpecific(index); + }} + on:keydown={void 0} + role="button" + tabindex="0"> +
+ {/each}
-
- {#if selectedStory && selectedStory.InformationResource?.length && selectedStory.InformationResource[0].videoUri} - + {/if} + - {/if} - +
+ class="rounded-[20px] object-contain"> {:else} + class="rounded-[20px] object-contain" /> {/if} {/if}
@@ -278,7 +286,7 @@ on:keydown={void 0} role="button" tabindex="0"> - {filterKey} + {filterKey}
{/if} diff --git a/src/psaggregator/src/lib/components/NewsBig.svelte b/src/psaggregator/src/lib/components/NewsBig.svelte index 01f0010..b5ab50c 100644 --- a/src/psaggregator/src/lib/components/NewsBig.svelte +++ b/src/psaggregator/src/lib/components/NewsBig.svelte @@ -88,7 +88,7 @@ }); -
+
diff --git a/src/psaggregator/src/routes/news/+page.svelte b/src/psaggregator/src/routes/news/+page.svelte index ba8cfa0..12f2123 100644 --- a/src/psaggregator/src/routes/news/+page.svelte +++ b/src/psaggregator/src/routes/news/+page.svelte @@ -9,8 +9,8 @@ -
-
+
+
From 45926d609f7178fd1be21bd4d0e4a066a77361a6 Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 19:58:28 +0100 Subject: [PATCH 6/7] bump version --- src/psaggregator/package-lock.json | 23 +++++++++---------- src/psaggregator/package.json | 2 +- .../src/routes/changelog/+page.svelte | 9 ++++++++ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/psaggregator/package-lock.json b/src/psaggregator/package-lock.json index 77dc4da..62dd91c 100644 --- a/src/psaggregator/package-lock.json +++ b/src/psaggregator/package-lock.json @@ -1,12 +1,12 @@ { "name": "psaggregator", - "version": "1.18.0", + "version": "1.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "psaggregator", - "version": "1.18.0", + "version": "1.19.0", "dependencies": { "@internationalized/date": "^3.5.5", "@sentry/sveltekit": "^8.41.0", @@ -2843,16 +2843,15 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.8.5.tgz", - "integrity": "sha512-5ry1jPd4r9knsphDK2eTYUFPhFZMqF0PHFfa8MdMQCqWaKwLSXdFMU/Vevih1I7C1/VNB5MvTuFl1kXu5vx8UA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.9.0.tgz", + "integrity": "sha512-W3E7ed3ChB6kPqRs2H7tcHp+Z7oiTFC6m+lLyAQQuyXeqw6LdNuuwEUla+5VM0OGgqQD+cYD6+7Xq80vVm17Vg==", "hasInstallScript": true, - "license": "MIT", "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", - "esm-env": "^1.0.0", + "esm-env": "^1.2.1", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", @@ -2869,9 +2868,9 @@ "node": ">=18.13" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1", + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", - "vite": "^5.0.3" + "vite": "^5.0.3 || ^6.0.0" } }, "node_modules/@sveltejs/vite-plugin-svelte": { @@ -4339,9 +4338,9 @@ } }, "node_modules/esm-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", - "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz", + "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==" }, "node_modules/espree": { "version": "9.6.1", diff --git a/src/psaggregator/package.json b/src/psaggregator/package.json index a08c459..c65c790 100644 --- a/src/psaggregator/package.json +++ b/src/psaggregator/package.json @@ -1,6 +1,6 @@ { "name": "psaggregator", - "version": "1.18.0", + "version": "1.19.0", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/src/psaggregator/src/routes/changelog/+page.svelte b/src/psaggregator/src/routes/changelog/+page.svelte index 1515f67..373708c 100644 --- a/src/psaggregator/src/routes/changelog/+page.svelte +++ b/src/psaggregator/src/routes/changelog/+page.svelte @@ -16,6 +16,15 @@
+

Version 1.19.0

+
+

Überarbeitungen

+
+ Verbesserte Ladezeiten + Weitere Optimierungen wurden vorgenommen, um die Ladezeiten zu verbessern. +
+
+

Version 1.18.0

Überarbeitungen

From 84378e77580c5caaa84aaa2cf7aeb512bf49bc60 Mon Sep 17 00:00:00 2001 From: zaanposni Date: Sat, 30 Nov 2024 21:03:20 +0100 Subject: [PATCH 7/7] auto reload frontpage every 5minutes --- src/psaggregator/src/routes/+page.svelte | 100 +++++++++++++++++- .../src/routes/changelog/+page.svelte | 23 ++-- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/psaggregator/src/routes/+page.svelte b/src/psaggregator/src/routes/+page.svelte index 098fd74..54ac575 100644 --- a/src/psaggregator/src/routes/+page.svelte +++ b/src/psaggregator/src/routes/+page.svelte @@ -9,11 +9,105 @@ import MediaQuery from "$lib/utils/MediaQuery.svelte"; import InstagramPost from "$lib/components/InstagramPost.svelte"; import TwitchEntry from "$lib/components/TwitchEntry.svelte"; - import { version } from "$app/environment"; + import { browser, version } from "$app/environment"; import TwitterPost from "$lib/components/TwitterPost.svelte"; - import { GITHUB_URL, MAIL_TO_URL } from "../config/config"; + import { GITHUB_URL, LOW_DATA_MODE, MAIL_TO_URL } from "../config/config"; + import { invalidateAll } from "$app/navigation"; + import { onDestroy, onMount } from "svelte"; + import FaviconNotification from "favicon-notification"; + import type { ContentPiece, Information, ScheduledContentPiece } from "@prisma/client"; + import moment from "moment"; export let data: PageServerData; + + let reloadInterval: number | NodeJS.Timeout | undefined = undefined; + let isNotificationVisible = false; + + function findNewestDate() { + const dates = [ + ...(data.today?.map((entry: ScheduledContentPiece) => moment(entry.startDate)) ?? []), + ...(data.youtubeCommunityPosts?.map((entry: Information) => moment(entry.date)) ?? []), + ...(data.instagramPosts?.map((entry: Information) => moment(entry.date)) ?? []), + ...(data.twitterPosts?.map((entry: Information) => moment(entry.date)) ?? []), + ...(data.redditPosts?.map((entry: RedditPost) => moment(entry.date)) ?? []), + ...(data.videos?.map((entry: ContentPiece) => moment(entry.startDate)) ?? []), + ...(data.upcomingStreams?.map((entry: ScheduledContentPiece) => moment(entry.startDate)) ?? []), + moment((data.twitchStatus as TwitchStatus)?.startedAt ?? 0) + ]; + + return Math.max(...dates); + } + + async function reload() { + if ($LOW_DATA_MODE) return; + + const currentLastDate = findNewestDate(); + const currentLastUploadPlanEntriesWithLink = data.today.filter((entry: ScheduledContentPiece) => entry.href).length; + + await invalidateAll(); + + const newLastDate = findNewestDate(); + const newUploadPlanEntriesWithLink = data.today.filter((entry: ScheduledContentPiece) => entry.href).length; + + if ( + (currentLastDate !== newLastDate && currentLastDate && newLastDate) || + currentLastUploadPlanEntriesWithLink !== newUploadPlanEntriesWithLink + ) { + isNotificationVisible = true; + try { + FaviconNotification.add(); + } catch (e) { + console.error(e); + } + } + } + + function onUserActive() { + if (!isNotificationVisible) return; + + isNotificationVisible = false; + try { + FaviconNotification.remove(); + } catch (e) { + console.error(e); + } + } + + function handleVisibilityChange() { + if (document.visibilityState === "visible") { + onUserActive(); + } + } + + function handleUserInteraction() { + onUserActive(); + } + + onMount(() => { + if (browser) { + reloadInterval = setInterval(reload, 1000 * 60 * 5); + + FaviconNotification.init({ + color: "#ff0000", + lineColor: "#000000", + url: "/favicon.png" + }); + + document.addEventListener("visibilitychange", handleVisibilityChange); + window.addEventListener("mousemove", handleUserInteraction); + window.addEventListener("focus", handleUserInteraction); + } + }); + + onDestroy(() => { + if (browser) { + if (reloadInterval) clearInterval(reloadInterval); + + document.removeEventListener("visibilitychange", handleVisibilityChange); + window.removeEventListener("mousemove", handleUserInteraction); + window.removeEventListener("focus", handleUserInteraction); + } + });