detached 2e766c7

fix(gui): restore favicon display in homepage history

commit
2e766c7d5d7089517bb0a80e2bea3725e6f7f436
author
bamen · · 2025-09-15 08:54 UTC
parent
2619383
signature
unsigned
3 files · +30 -3
M CHANGELOG.md +1 -0
@@ -27,6 +27,7 @@ All notable changes to this project will be documented in this file.
2727 - **Homepage protocol**: Fixed dumb://homepage not working after GUI migration with proper Svelte 5 component and API integration
2828 - **Omnibox positioning on homepage**: Fixed omnibox stuck in top-left corner by isolating homepage CSS styles and strengthening omnibox positioning with explicit fixed positioning and CSS isolation
2929 - **Find mode persistence**: Fixed find view persisting after pressing Esc when reopening with Ctrl+L by ensuring toggle() resets mode to 'omnibox'
30+- **Favicon display**: Fixed missing favicons in homepage history after Svelte 5 migration by adding FaviconURL field to API response and implementing proper fallback display logic
3031
3132 ## [0.7.0] - 2025-09-14
3233
@@ -27,6 +27,7 @@ All notable changes to this project will be documented in this file.
27 - **Homepage protocol**: Fixed dumb://homepage not working after GUI migration with proper Svelte 5 component and API integration27 - **Homepage protocol**: Fixed dumb://homepage not working after GUI migration with proper Svelte 5 component and API integration
28 - **Omnibox positioning on homepage**: Fixed omnibox stuck in top-left corner by isolating homepage CSS styles and strengthening omnibox positioning with explicit fixed positioning and CSS isolation28 - **Omnibox positioning on homepage**: Fixed omnibox stuck in top-left corner by isolating homepage CSS styles and strengthening omnibox positioning with explicit fixed positioning and CSS isolation
29 - **Find mode persistence**: Fixed find view persisting after pressing Esc when reopening with Ctrl+L by ensuring toggle() resets mode to 'omnibox'29 - **Find mode persistence**: Fixed find view persisting after pressing Esc when reopening with Ctrl+L by ensuring toggle() resets mode to 'omnibox'
30+- **Favicon display**: Fixed missing favicons in homepage history after Svelte 5 migration by adding FaviconURL field to API response and implementing proper fallback display logic
30 31
31 ## [0.7.0] - 2025-09-1432 ## [0.7.0] - 2025-09-14
32 33
M gui/src/pages/Homepage.svelte +26 -3
@@ -5,6 +5,7 @@
55 id: number;
66 url: string;
77 title: string;
8+ favicon_url?: string;
89 visit_count: number;
910 last_visited: string;
1011 created_at: string;
@@ -135,8 +136,6 @@
135136 fetchHistory();
136137 });
137138
138- // Combined loading state
139- const loading = $derived(historyLoading || shortcutsLoading);
140139 </script>
141140
142141 <div class="homepage-container">
@@ -162,7 +161,31 @@
162161 >
163162 <div class="history-line">
164163 <div class="history-favicon-chip">
165- <div class="history-favicon-fallback">🌐</div>
164+ {#if item.favicon_url}
165+ <img
166+ src={item.favicon_url}
167+ alt=""
168+ class="history-favicon-img"
169+ onerror={(e) => {
170+ const target = e.target as HTMLImageElement;
171+ if (target) {
172+ target.style.display='none';
173+ const fallback = target.nextElementSibling as HTMLElement;
174+ if (fallback) fallback.style.display='block';
175+ }
176+ }}
177+ onload={(e) => {
178+ const target = e.target as HTMLImageElement;
179+ if (target) {
180+ const fallback = target.nextElementSibling as HTMLElement;
181+ if (fallback) fallback.style.display='none';
182+ }
183+ }}
184+ />
185+ <div class="history-favicon-fallback" style="display: none;">🌐</div>
186+ {:else}
187+ <div class="history-favicon-fallback">🌐</div>
188+ {/if}
166189 </div>
167190 <div class="history-title">{item.title || 'Untitled'}</div>
168191 <div class="history-sep">•</div>
@@ -5,6 +5,7 @@
5 id: number;5 id: number;
6 url: string;6 url: string;
7 title: string;7 title: string;
8+ favicon_url?: string;
8 visit_count: number;9 visit_count: number;
9 last_visited: string;10 last_visited: string;
10 created_at: string;11 created_at: string;
@@ -135,8 +136,6 @@
135 fetchHistory();136 fetchHistory();
136 });137 });
137 138
138- // Combined loading state
139- const loading = $derived(historyLoading || shortcutsLoading);
140 </script>139 </script>
141 140
142 <div class="homepage-container">141 <div class="homepage-container">
@@ -162,7 +161,31 @@
162 >161 >
163 <div class="history-line">162 <div class="history-line">
164 <div class="history-favicon-chip">163 <div class="history-favicon-chip">
165- <div class="history-favicon-fallback">🌐</div>164+ {#if item.favicon_url}
165+ <img
166+ src={item.favicon_url}
167+ alt=""
168+ class="history-favicon-img"
169+ onerror={(e) => {
170+ const target = e.target as HTMLImageElement;
171+ if (target) {
172+ target.style.display='none';
173+ const fallback = target.nextElementSibling as HTMLElement;
174+ if (fallback) fallback.style.display='block';
175+ }
176+ }}
177+ onload={(e) => {
178+ const target = e.target as HTMLImageElement;
179+ if (target) {
180+ const fallback = target.nextElementSibling as HTMLElement;
181+ if (fallback) fallback.style.display='none';
182+ }
183+ }}
184+ />
185+ <div class="history-favicon-fallback" style="display: none;">🌐</div>
186+ {:else}
187+ <div class="history-favicon-fallback">🌐</div>
188+ {/if}
166 </div>189 </div>
167 <div class="history-title">{item.title || 'Untitled'}</div>190 <div class="history-title">{item.title || 'Untitled'}</div>
168 <div class="history-sep">•</div>191 <div class="history-sep">•</div>
M services/browser_service.go +3 -0
@@ -64,6 +64,7 @@ type HistoryEntry struct {
6464 ID int64 `json:"id"`
6565 URL string `json:"url"`
6666 Title string `json:"title"`
67+ FaviconURL string `json:"favicon_url"`
6768 VisitCount int32 `json:"visit_count"`
6869 LastVisited time.Time `json:"last_visited"`
6970 CreatedAt time.Time `json:"created_at"`
@@ -239,6 +240,7 @@ func (s *BrowserService) GetRecentHistory(ctx context.Context, limit int) ([]His
239240 ID: entry.ID,
240241 URL: entry.Url,
241242 Title: entry.Title.String,
243+ FaviconURL: entry.FaviconUrl.String,
242244 VisitCount: vc,
243245 LastVisited: entry.LastVisited.Time,
244246 CreatedAt: entry.CreatedAt.Time,
@@ -273,6 +275,7 @@ func (s *BrowserService) SearchHistory(ctx context.Context, query string, limit
273275 ID: entry.ID,
274276 URL: entry.Url,
275277 Title: entry.Title.String,
278+ FaviconURL: entry.FaviconUrl.String,
276279 VisitCount: vc,
277280 LastVisited: entry.LastVisited.Time,
278281 CreatedAt: entry.CreatedAt.Time,
@@ -64,6 +64,7 @@ type HistoryEntry struct {
64 ID int64 `json:"id"`64 ID int64 `json:"id"`
65 URL string `json:"url"`65 URL string `json:"url"`
66 Title string `json:"title"`66 Title string `json:"title"`
67+ FaviconURL string `json:"favicon_url"`
67 VisitCount int32 `json:"visit_count"`68 VisitCount int32 `json:"visit_count"`
68 LastVisited time.Time `json:"last_visited"`69 LastVisited time.Time `json:"last_visited"`
69 CreatedAt time.Time `json:"created_at"`70 CreatedAt time.Time `json:"created_at"`
@@ -239,6 +240,7 @@ func (s *BrowserService) GetRecentHistory(ctx context.Context, limit int) ([]His
239 ID: entry.ID,240 ID: entry.ID,
240 URL: entry.Url,241 URL: entry.Url,
241 Title: entry.Title.String,242 Title: entry.Title.String,
243+ FaviconURL: entry.FaviconUrl.String,
242 VisitCount: vc,244 VisitCount: vc,
243 LastVisited: entry.LastVisited.Time,245 LastVisited: entry.LastVisited.Time,
244 CreatedAt: entry.CreatedAt.Time,246 CreatedAt: entry.CreatedAt.Time,
@@ -273,6 +275,7 @@ func (s *BrowserService) SearchHistory(ctx context.Context, query string, limit
273 ID: entry.ID,275 ID: entry.ID,
274 URL: entry.Url,276 URL: entry.Url,
275 Title: entry.Title.String,277 Title: entry.Title.String,
278+ FaviconURL: entry.FaviconUrl.String,
276 VisitCount: vc,279 VisitCount: vc,
277 LastVisited: entry.LastVisited.Time,280 LastVisited: entry.LastVisited.Time,
278 CreatedAt: entry.CreatedAt.Time,281 CreatedAt: entry.CreatedAt.Time,

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close