From 0a52606012ff5cf6f5042d8e2bfadd37256c680a Mon Sep 17 00:00:00 2001 From: Thomas Reitz Date: Tue, 10 Mar 2026 11:23:11 +0100 Subject: [PATCH] fix: use direct favicon.ico, open links in app mode (popup window) - Favicon loaded directly from website's /favicon.ico instead of Google's service (which was unreliable/blocked on internal networks) - Letter-initial fallback when favicon can't be loaded - External links open in popup window (app mode) instead of new tab Co-Authored-By: Claude Opus 4.6 --- .../src/admin/AdminExternalLinksPage.tsx | 6 +- packages/frontend/src/shell/AppLayout.tsx | 79 +++++++++++-------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/packages/frontend/src/admin/AdminExternalLinksPage.tsx b/packages/frontend/src/admin/AdminExternalLinksPage.tsx index 8633765..2b1f846 100644 --- a/packages/frontend/src/admin/AdminExternalLinksPage.tsx +++ b/packages/frontend/src/admin/AdminExternalLinksPage.tsx @@ -7,11 +7,11 @@ function generateId(): string { return Date.now().toString(36) + Math.random().toString(36).slice(2, 10); } -/** Favicon-URL aus einer Website-URL ableiten (Google Favicon Service) */ +/** Favicon-URL direkt von der Webseite laden */ function getFaviconUrl(url: string): string | null { try { - const domain = new URL(url).hostname; - return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`; + const parsed = new URL(url); + return `${parsed.origin}/favicon.ico`; } catch { return null; } diff --git a/packages/frontend/src/shell/AppLayout.tsx b/packages/frontend/src/shell/AppLayout.tsx index 0e586df..2285c5d 100644 --- a/packages/frontend/src/shell/AppLayout.tsx +++ b/packages/frontend/src/shell/AppLayout.tsx @@ -12,11 +12,11 @@ interface ExternalLink { sortOrder: number; } -/** Favicon-URL aus einer Website-URL ableiten (Google Favicon Service) */ +/** Favicon-URL direkt von der Webseite laden */ function getFaviconUrl(url: string): string | null { try { - const domain = new URL(url).hostname; - return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`; + const parsed = new URL(url); + return `${parsed.origin}/favicon.ico`; } catch { return null; } @@ -82,37 +82,52 @@ export function AppLayout() { { + e.preventDefault(); + window.open( + link.url, + link.label, + 'popup,noopener', + ); + }} className={styles.navLink} > - {favicon ? ( - - ) : ( - - - - - - )} + { + // Fallback: erstes Zeichen des Labels als Text-Icon + const el = e.target as HTMLImageElement; + el.style.display = 'none'; + const fallback = el.nextElementSibling; + if (fallback) + (fallback as HTMLElement).style.display = + 'flex'; + }} + /> + + {link.label.charAt(0).toUpperCase()} + {link.label}