fix(web): Favoriten-Platzhalterbuchstabe verschwindet, sobald das Logo geladen ist
Bei Logos mit durchsichtigem Hintergrund schien der Buchstabe durch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -414,6 +414,25 @@ describe('FavoritesWidget', () => {
|
||||
expect(screen.getByTestId('letter-fallback-fav-id-1')).toHaveTextContent('G');
|
||||
});
|
||||
|
||||
it('06.10.: geladenes Logo blendet den Buchstaben aus (durchsichtige Logos), Fehler zeigt ihn wieder', async () => {
|
||||
render(<FavoritesWidget instanceId="fav-1" config={{}} isEditMode={false} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('GitHub')).toBeInTheDocument();
|
||||
});
|
||||
const proxyImg = screen.getByTestId('icon-proxy-fav-id-1') as HTMLImageElement;
|
||||
expect(screen.getByTestId('letter-fallback-fav-id-1')).toBeInTheDocument();
|
||||
|
||||
act(() => {
|
||||
fireEvent.load(proxyImg);
|
||||
});
|
||||
expect(screen.queryByTestId('letter-fallback-fav-id-1')).not.toBeInTheDocument();
|
||||
|
||||
act(() => {
|
||||
fireEvent.error(proxyImg);
|
||||
});
|
||||
expect(screen.getByTestId('letter-fallback-fav-id-1')).toHaveTextContent('G');
|
||||
});
|
||||
|
||||
it('ausdrueckliche Symbol-Adresse (260929-lh3): Proxy -> Browser laedt iconUrl direkt (no-referrer) -> Origin-Favicon -> Buchstabe', async () => {
|
||||
mockFetch.mockResolvedValue([
|
||||
{
|
||||
|
||||
@@ -543,7 +543,9 @@ function getDirectCandidates(iconUrl: string | null, url: string): string[] {
|
||||
* Browser aber das Bild), dann `{origin}/favicon.ico` (entfaellt, wenn
|
||||
* identisch). Erreicht auch interne Hosts, die der SSRF-Schutz des
|
||||
* Servers absichtlich ablehnt.
|
||||
* 3. `none` — der Buchstaben-Platzhalter liegt IMMER darunter.
|
||||
* 3. `none` — der Buchstaben-Platzhalter steht da, solange kein Bild
|
||||
* geladen ist. Sobald ein Bild geladen ist, verschwindet er: bei Logos mit
|
||||
* durchsichtigem Hintergrund schien er sonst durch (06.10.2026).
|
||||
*
|
||||
* Bewusst KEIN Drittanbieter-Favicon-Dienst: der wuerde Hostnamen nach
|
||||
* aussen geben und interne Hosts ohnehin nicht kennen.
|
||||
@@ -590,15 +592,18 @@ function FavoriteIcon({
|
||||
// 'proxy' | Index in directSrcs | Ende der Kette (Buchstabe).
|
||||
const [stage, setStage] = useState<'proxy' | number>(proxySrc ? 'proxy' : 0);
|
||||
const directSrc = typeof stage === 'number' ? (directSrcs[stage] ?? null) : null;
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
|
||||
return (
|
||||
<div className={`relative flex shrink-0 items-center justify-center bg-muted ${box}`}>
|
||||
<span
|
||||
data-testid={`letter-fallback-${fav.id}`}
|
||||
className={`absolute inset-0 flex items-center justify-center font-semibold text-muted-foreground ${large ? 'text-base' : 'text-xs'}`}
|
||||
>
|
||||
{getFallbackLetter(fav.title)}
|
||||
</span>
|
||||
{!imageLoaded && (
|
||||
<span
|
||||
data-testid={`letter-fallback-${fav.id}`}
|
||||
className={`absolute inset-0 flex items-center justify-center font-semibold text-muted-foreground ${large ? 'text-base' : 'text-xs'}`}
|
||||
>
|
||||
{getFallbackLetter(fav.title)}
|
||||
</span>
|
||||
)}
|
||||
{stage === 'proxy' && proxySrc && (
|
||||
<img
|
||||
data-testid={`icon-proxy-${fav.id}`}
|
||||
@@ -609,7 +614,11 @@ function FavoriteIcon({
|
||||
height={px}
|
||||
loading="lazy"
|
||||
className={`relative rounded-sm ${img}`}
|
||||
onError={() => setStage(0)}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
onError={() => {
|
||||
setImageLoaded(false);
|
||||
setStage(0);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{directSrc && (
|
||||
@@ -623,7 +632,11 @@ function FavoriteIcon({
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
className={`relative rounded-sm ${img}`}
|
||||
onError={() => setStage((prev) => (typeof prev === 'number' ? prev + 1 : 0))}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
onError={() => {
|
||||
setImageLoaded(false);
|
||||
setStage((prev) => (typeof prev === 'number' ? prev + 1 : 0));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user