diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index f0aea21931..67054cb3ad 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -49,6 +49,7 @@ import { beforeNavigate } from '$app/navigation'; import { updated } from '$app/state'; + import Spinner from '$lib/components/common/Spinner.svelte'; // handle frontend updates (https://svelte.dev/docs/kit/configuration#version) beforeNavigate(({ willUnload, to }) => { @@ -64,6 +65,8 @@ let loaded = false; let tokenTimer = null; + let showRefresh = false; + const BREAKPOINT = 768; const setupSocket = async (enableWebsocket) => { @@ -468,6 +471,36 @@ }; onMount(async () => { + let touchstartY = 0; + + function isNavOrDescendant(el) { + const nav = document.querySelector('nav'); // change selector if needed + return nav && (el === nav || nav.contains(el)); + } + + document.addEventListener('touchstart', (e) => { + if (!isNavOrDescendant(e.target)) return; + touchstartY = e.touches[0].clientY; + }); + + document.addEventListener('touchmove', (e) => { + if (!isNavOrDescendant(e.target)) return; + const touchY = e.touches[0].clientY; + const touchDiff = touchY - touchstartY; + if (touchDiff > 50 && window.scrollY === 0) { + showRefresh = true; + e.preventDefault(); + } + }); + + document.addEventListener('touchend', (e) => { + if (!isNavOrDescendant(e.target)) return; + if (showRefresh) { + showRefresh = false; + location.reload(); + } + }); + if (typeof window !== 'undefined' && window.applyTheme) { window.applyTheme(); } @@ -651,6 +684,12 @@ +{#if showRefresh} +
+ +
+{/if} + {#if loaded} {#if $isApp}