+ Safari can delete your bookmarks, highlights, and notes after 1–2 weeks of
+ inactivity. To keep them permanently, add this app to your Home Screen.
+
+
+
+
+{/if}
diff --git a/src/lib/scripts/safariUtils.ts b/src/lib/scripts/safariUtils.ts
new file mode 100644
index 000000000..7699a8ddc
--- /dev/null
+++ b/src/lib/scripts/safariUtils.ts
@@ -0,0 +1,48 @@
+const DISMISSED_KEY = 'safari_annotation_warning_dismissed';
+const DISMISS_DURATION_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
+
+function isSafariWithoutStandalone(): boolean {
+ if (typeof window === 'undefined') {
+ return false;
+ }
+ const ua = navigator.userAgent;
+ const isSafari = /Safari/.test(ua) && !/Chrome|CriOS|FxiOS|EdgiOS/.test(ua);
+ const isStandalone = (navigator as Navigator & { standalone?: boolean }).standalone === true;
+ return isSafari && !isStandalone;
+}
+
+export function shouldShowSafariWarning(): boolean {
+ if (typeof window === 'undefined') {
+ return false;
+ }
+ // Debug override: because the app uses hash routing, append ?debug_safari=true
+ // inside the hash, e.g. /#/bookmarks?debug_safari=true
+ const hashQuery = window.location.hash.split('?')[1] ?? '';
+ if (new URLSearchParams(hashQuery).get('debug_safari') === 'true') {
+ return true;
+ }
+ if (!isSafariWithoutStandalone()) {
+ return false;
+ }
+ try {
+ const dismissed = localStorage.getItem(DISMISSED_KEY);
+ if (!dismissed) {
+ return true;
+ }
+ const dismissedAt = parseInt(dismissed, 10);
+ if (isNaN(dismissedAt)) {
+ return true;
+ }
+ return Date.now() - dismissedAt > DISMISS_DURATION_MS;
+ } catch {
+ return true;
+ }
+}
+
+export function dismissSafariWarning(): void {
+ try {
+ localStorage.setItem(DISMISSED_KEY, Date.now().toString());
+ } catch {
+ // If storage is unavailable, silently ignore — the warning will reappear next visit
+ }
+}
diff --git a/src/routes/bookmarks/+page.svelte b/src/routes/bookmarks/+page.svelte
index 845fd46e9..818bc8401 100644
--- a/src/routes/bookmarks/+page.svelte
+++ b/src/routes/bookmarks/+page.svelte
@@ -3,6 +3,7 @@
import { resolve } from '$app/paths';
import IconCard from '$lib/components/IconCard.svelte';
import Navbar from '$lib/components/Navbar.svelte';
+ import SafariAnnotationWarning from '$lib/components/SafariAnnotationWarning.svelte';
import SortMenu from '$lib/components/SortMenu.svelte';
import { shareAnnotation, shareAnnotations } from '$lib/data/annotation-share';
import { SORT_DATE, SORT_REFERENCE, toSorted } from '$lib/data/annotation-sort';
@@ -82,6 +83,7 @@
class="overflow-y-auto p-2.5 max-w-screen-md mx-auto w-full"
style:font-size="{$bodyFontSize}px"
>
+
{#if data.bookmarks.length === 0}
{$t['Annotation_Bookmarks_None']}
{$t['Annotation_Bookmarks_None_Info']}
diff --git a/src/routes/highlights/+page.svelte b/src/routes/highlights/+page.svelte
index 3fc4bbff3..6e9305496 100644
--- a/src/routes/highlights/+page.svelte
+++ b/src/routes/highlights/+page.svelte
@@ -3,6 +3,7 @@
import { resolve } from '$app/paths';
import IconCard from '$lib/components/IconCard.svelte';
import Navbar from '$lib/components/Navbar.svelte';
+ import SafariAnnotationWarning from '$lib/components/SafariAnnotationWarning.svelte';
import SortMenu from '$lib/components/SortMenu.svelte';
import { shareAnnotation, shareAnnotations } from '$lib/data/annotation-share';
import { SORT_COLOR, SORT_DATE, SORT_REFERENCE, toSorted } from '$lib/data/annotation-sort';
@@ -88,6 +89,7 @@
class="overflow-y-auto p-2.5 max-w-screen-md mx-auto w-full"
style:font-size="{$bodyFontSize}px"
>
+
{#if data.highlights.length === 0}
{$t['Annotation_Highlights_None']}
{$t['Annotation_Highlights_None_Info']}
diff --git a/src/routes/notes/+page.svelte b/src/routes/notes/+page.svelte
index affd97b84..51f22bcb6 100644
--- a/src/routes/notes/+page.svelte
+++ b/src/routes/notes/+page.svelte
@@ -3,6 +3,7 @@
import { resolve } from '$app/paths';
import IconCard from '$lib/components/IconCard.svelte';
import Navbar from '$lib/components/Navbar.svelte';
+ import SafariAnnotationWarning from '$lib/components/SafariAnnotationWarning.svelte';
import SortMenu from '$lib/components/SortMenu.svelte';
import { shareAnnotation, shareAnnotations } from '$lib/data/annotation-share';
import { SORT_DATE, SORT_REFERENCE, toSorted } from '$lib/data/annotation-sort';
@@ -81,6 +82,7 @@
class="overflow-y-auto p-2.5 max-w-screen-md mx-auto w-full"
style:font-size="{$bodyFontSize}px"
>
+
{#if data.notes.length === 0}