detached 9b5fe54

fix(webui): resolve svelte-check type errors

commit
9b5fe54e2daed8e477c141f53f39d93f0f19930a
author
bnema · · 2025-12-21 21:53 UTC
parent
ad3456a
signature
unsigned
3 files · +42 -13
M webui/src/pages/ErrorPage.svelte +21 -4
@@ -3,10 +3,26 @@
33 import { Button } from '$lib/components/ui/button';
44 import * as Card from '$lib/components/ui/card';
55
6+ type ErrorConfig = {
7+ code: number;
8+ title: string;
9+ message: string;
10+ icon: string;
11+ actions: string[];
12+ };
13+
14+ const defaultConfig: ErrorConfig = {
15+ code: 404,
16+ title: 'Page Not Found',
17+ message: 'The page you are looking for does not exist.',
18+ icon: 'warning',
19+ actions: ['back'],
20+ };
21+
622 // Error configurations
7- const errorConfigs: Record<string, { code: number; title: string; message: string; icon: string; actions: string[] }> = {
23+ const errorConfigs: Record<string, ErrorConfig> = {
824 blocked: { code: 0, title: 'Page Blocked', message: 'Content blocked by filter', icon: 'shield', actions: ['whitelist', 'bypass', 'back'] },
9- '404': { code: 404, title: 'Page Not Found', message: 'The page you are looking for does not exist.', icon: 'warning', actions: ['back'] },
25+ '404': defaultConfig,
1026 '500': { code: 500, title: 'Server Error', message: 'Something went wrong on the server.', icon: 'error', actions: ['retry', 'back'] },
1127 '502': { code: 502, title: 'Bad Gateway', message: 'The server received an invalid response.', icon: 'error', actions: ['retry', 'back'] },
1228 '503': { code: 503, title: 'Service Unavailable', message: 'The server is temporarily unavailable.', icon: 'error', actions: ['retry', 'back'] },
@@ -15,7 +31,7 @@
1531 timeout: { code: 0, title: 'Connection Timed Out', message: 'The server took too long to respond.', icon: 'warning', actions: ['retry', 'back'] },
1632 };
1733
18- let config = $state(errorConfigs['404']);
34+ let config = $state<ErrorConfig>(defaultConfig);
1935 let targetUrl = $state('');
2036 let targetDomain = $state('');
2137 let customMessage = $state('');
@@ -26,7 +42,8 @@
2642 const params = new URLSearchParams(window.location.search);
2743 const typeParam = params.get('type') || params.get('code') || '404';
2844
29- config = errorConfigs[typeParam] || {
45+ const selectedConfig = errorConfigs[typeParam];
46+ config = selectedConfig ?? {
3047 code: parseInt(typeParam) || 0,
3148 title: `Error ${typeParam}`,
3249 message: 'An unexpected error occurred.',
@@ -3,10 +3,26 @@
3 import { Button } from '$lib/components/ui/button';3 import { Button } from '$lib/components/ui/button';
4 import * as Card from '$lib/components/ui/card';4 import * as Card from '$lib/components/ui/card';
5 5
6+ type ErrorConfig = {
7+ code: number;
8+ title: string;
9+ message: string;
10+ icon: string;
11+ actions: string[];
12+ };
13+
14+ const defaultConfig: ErrorConfig = {
15+ code: 404,
16+ title: 'Page Not Found',
17+ message: 'The page you are looking for does not exist.',
18+ icon: 'warning',
19+ actions: ['back'],
20+ };
21+
6 // Error configurations22 // Error configurations
7- const errorConfigs: Record<string, { code: number; title: string; message: string; icon: string; actions: string[] }> = {23+ const errorConfigs: Record<string, ErrorConfig> = {
8 blocked: { code: 0, title: 'Page Blocked', message: 'Content blocked by filter', icon: 'shield', actions: ['whitelist', 'bypass', 'back'] },24 blocked: { code: 0, title: 'Page Blocked', message: 'Content blocked by filter', icon: 'shield', actions: ['whitelist', 'bypass', 'back'] },
9- '404': { code: 404, title: 'Page Not Found', message: 'The page you are looking for does not exist.', icon: 'warning', actions: ['back'] },25+ '404': defaultConfig,
10 '500': { code: 500, title: 'Server Error', message: 'Something went wrong on the server.', icon: 'error', actions: ['retry', 'back'] },26 '500': { code: 500, title: 'Server Error', message: 'Something went wrong on the server.', icon: 'error', actions: ['retry', 'back'] },
11 '502': { code: 502, title: 'Bad Gateway', message: 'The server received an invalid response.', icon: 'error', actions: ['retry', 'back'] },27 '502': { code: 502, title: 'Bad Gateway', message: 'The server received an invalid response.', icon: 'error', actions: ['retry', 'back'] },
12 '503': { code: 503, title: 'Service Unavailable', message: 'The server is temporarily unavailable.', icon: 'error', actions: ['retry', 'back'] },28 '503': { code: 503, title: 'Service Unavailable', message: 'The server is temporarily unavailable.', icon: 'error', actions: ['retry', 'back'] },
@@ -15,7 +31,7 @@
15 timeout: { code: 0, title: 'Connection Timed Out', message: 'The server took too long to respond.', icon: 'warning', actions: ['retry', 'back'] },31 timeout: { code: 0, title: 'Connection Timed Out', message: 'The server took too long to respond.', icon: 'warning', actions: ['retry', 'back'] },
16 };32 };
17 33
18- let config = $state(errorConfigs['404']);34+ let config = $state<ErrorConfig>(defaultConfig);
19 let targetUrl = $state('');35 let targetUrl = $state('');
20 let targetDomain = $state('');36 let targetDomain = $state('');
21 let customMessage = $state('');37 let customMessage = $state('');
@@ -26,7 +42,8 @@
26 const params = new URLSearchParams(window.location.search);42 const params = new URLSearchParams(window.location.search);
27 const typeParam = params.get('type') || params.get('code') || '404';43 const typeParam = params.get('type') || params.get('code') || '404';
28 44
29- config = errorConfigs[typeParam] || {45+ const selectedConfig = errorConfigs[typeParam];
46+ config = selectedConfig ?? {
30 code: parseInt(typeParam) || 0,47 code: parseInt(typeParam) || 0,
31 title: `Error ${typeParam}`,48 title: `Error ${typeParam}`,
32 message: 'An unexpected error occurred.',49 message: 'An unexpected error occurred.',
M webui/src/pages/homepage/messaging.ts +0 -9
@@ -142,15 +142,6 @@ function initializeCallbacks(): void {
142142 callbacksInitialized = true;
143143 }
144144
145-function handleLegacyCallback(requestId: string | undefined, data: unknown): void {
146- const request = pendingRequests.get(requestId || 'default');
147- if (request) {
148- clearTimeout(request.timeout);
149- pendingRequests.delete(requestId || 'default');
150- request.resolve(data);
151- }
152-}
153-
154145 // Handle both legacy raw data and new Response object format
155146 function handleLegacyOrResponseCallback(dataOrResponse: unknown): void {
156147 // Check if it's a Response object (has requestId and success fields)
@@ -142,15 +142,6 @@ function initializeCallbacks(): void {
142 callbacksInitialized = true;142 callbacksInitialized = true;
143 }143 }
144 144
145-function handleLegacyCallback(requestId: string | undefined, data: unknown): void {
146- const request = pendingRequests.get(requestId || 'default');
147- if (request) {
148- clearTimeout(request.timeout);
149- pendingRequests.delete(requestId || 'default');
150- request.resolve(data);
151- }
152-}
153-
154 // Handle both legacy raw data and new Response object format145 // Handle both legacy raw data and new Response object format
155 function handleLegacyOrResponseCallback(dataOrResponse: unknown): void {146 function handleLegacyOrResponseCallback(dataOrResponse: unknown): void {
156 // Check if it's a Response object (has requestId and success fields)147 // Check if it's a Response object (has requestId and success fields)
A webui/src/types/generated.ts +21 -0
@@ -0,0 +1,21 @@
1+export interface HistoryEntry {
2+ id: number;
3+ url: string;
4+ title: string | null;
5+ favicon_url: string | null;
6+ visit_count: number;
7+ last_visited: string;
8+ created_at: string;
9+}
10+
11+export type History = HistoryEntry;
12+
13+export interface SearchShortcut {
14+ url: string;
15+ description: string;
16+}
17+
18+export interface Shortcut {
19+ url_template: string;
20+ description?: string;
21+}
@@ -0,0 +1,21 @@
1+export interface HistoryEntry {
2+ id: number;
3+ url: string;
4+ title: string | null;
5+ favicon_url: string | null;
6+ visit_count: number;
7+ last_visited: string;
8+ created_at: string;
9+}
10+
11+export type History = HistoryEntry;
12+
13+export interface SearchShortcut {
14+ url: string;
15+ description: string;
16+}
17+
18+export interface Shortcut {
19+ url_template: string;
20+ description?: string;
21+}

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