feat(domains): Favicons laden und im Filter anzeigen
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 1m16s

Für jede Whitelist-Domain wird das Favicon jetzt einmalig geladen und
im image-Verzeichnis abgelegt. SearchFilter zeigt das Icon neben dem
Domain-Namen im Filter-Dropdown.

- Migration 009: allowed_domain.favicon_path (NULL = noch nicht geladen).
- Neues Modul $lib/server/domains/favicons.ts:
  fetchAndStoreFavicon(domain, imageDir) + ensureFavicons(db, imageDir)
  für Bulk-Nachzug; 8 parallele Worker mit 3s-Timeout.
- Reihenfolge: erst /favicon.ico der Domain, Fallback Google-Service.
- GET /api/domains zieht fehlende Favicons auf Abruf nach;
  POST /api/domains lädt direkt im selben Call.
- .ico + .svg jetzt in der /images/[filename]-Route erlaubt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-18 08:17:44 +02:00
parent d004430854
commit a590cf0a57
8 changed files with 189 additions and 6 deletions

View File

@@ -7,7 +7,9 @@ export function normalizeDomain(raw: string): string {
export function listDomains(db: Database.Database): AllowedDomain[] {
return db
.prepare('SELECT id, domain, display_name FROM allowed_domain ORDER BY domain')
.prepare(
'SELECT id, domain, display_name, favicon_path FROM allowed_domain ORDER BY domain'
)
.all() as AllowedDomain[];
}
@@ -22,7 +24,7 @@ export function addDomain(
.prepare(
`INSERT INTO allowed_domain(domain, display_name, added_by_profile_id)
VALUES (?, ?, ?)
RETURNING id, domain, display_name`
RETURNING id, domain, display_name, favicon_path`
)
.get(normalized, displayName, addedByProfileId) as AllowedDomain;
return row;
@@ -31,3 +33,14 @@ export function addDomain(
export function removeDomain(db: Database.Database, id: number): void {
db.prepare('DELETE FROM allowed_domain WHERE id = ?').run(id);
}
export function setDomainFavicon(
db: Database.Database,
id: number,
faviconPath: string | null
): void {
db.prepare('UPDATE allowed_domain SET favicon_path = ? WHERE id = ?').run(
faviconPath,
id
);
}