detached 74a67e9

feat(webui): add performance profile selector to config page

commit
74a67e9ae5d4eb254b9d844247c08ee53808d39d
author
brice · · 2025-12-28 19:23 UTC
committer
brice · · 2025-12-29 17:28 UTC
parent
cf39998
signature
unsigned
1 file · +68 -0
M webui/src/pages/ConfigPage.svelte +68 -0
@@ -26,6 +26,10 @@
2626 description: string;
2727 };
2828
29+ type PerformanceConfig = {
30+ profile: string;
31+ };
32+
2933 type ConfigDTO = {
3034 appearance: {
3135 sans_font: string;
@@ -36,11 +40,19 @@
3640 light_palette: ColorPalette;
3741 dark_palette: ColorPalette;
3842 };
43+ performance: PerformanceConfig;
3944 default_ui_scale: number;
4045 default_search_engine: string;
4146 search_shortcuts: Record<string, SearchShortcut>;
4247 };
4348
49+ const PERFORMANCE_PROFILES = [
50+ { value: "default", label: "Default", description: "No tuning, uses WebKit defaults. Recommended for most users." },
51+ { value: "lite", label: "Lite", description: "Reduced resource usage for low-RAM systems (< 4GB) or battery saving." },
52+ { value: "max", label: "Max", description: "Maximum responsiveness for heavy pages (GitHub PRs, complex SPAs)." },
53+ { value: "custom", label: "Custom", description: "Manual control via config file. Edit config.toml to set individual values." },
54+ ];
55+
4456 const PALETTE_FIELDS: Array<{ key: keyof ColorPalette; label: string }> = [
4557 { key: "background", label: "Background" },
4658 { key: "surface", label: "Surface" },
@@ -250,6 +262,7 @@
250262 <Tabs.List class="bg-muted/60">
251263 <Tabs.Trigger value="appearance">Appearance</Tabs.Trigger>
252264 <Tabs.Trigger value="search">Search</Tabs.Trigger>
265+ <Tabs.Trigger value="performance">Performance</Tabs.Trigger>
253266 </Tabs.List>
254267 </div>
255268
@@ -374,6 +387,61 @@
374387 </Card.Content>
375388 </Card.Root>
376389 </Tabs.Content>
390+
391+ <Tabs.Content value="performance">
392+ <Card.Root class="rounded-none border-0 bg-transparent py-0 shadow-none">
393+ <Card.Header>
394+ <Card.Title>Performance Profile</Card.Title>
395+ <Card.Description>
396+ WebKitGTK rendering and memory tuning presets.
397+ </Card.Description>
398+ </Card.Header>
399+ <Card.Content class="space-y-6">
400+ <!-- Restart warning banner -->
401+ <div class="flex items-start gap-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-4 py-3">
402+ <span class="text-amber-500">⚠</span>
403+ <div class="space-y-1">
404+ <p class="text-sm font-medium text-amber-500">Restart Required</p>
405+ <p class="text-xs text-muted-foreground">
406+ Performance settings are applied at browser startup. Changes will take effect after restarting Dumber.
407+ </p>
408+ </div>
409+ </div>
410+
411+ <!-- Profile selector -->
412+ <div class="space-y-4">
413+ {#each PERFORMANCE_PROFILES as profile (profile.value)}
414+ <label
415+ class="flex cursor-pointer items-start gap-4 rounded-md border p-4 transition-colors hover:bg-muted/50 {config.performance.profile === profile.value ? 'border-primary bg-primary/5' : ''}"
416+ >
417+ <input
418+ type="radio"
419+ name="performance_profile"
420+ value={profile.value}
421+ checked={config.performance.profile === profile.value}
422+ onchange={() => config!.performance.profile = profile.value}
423+ class="mt-1 accent-primary"
424+ />
425+ <div class="space-y-1">
426+ <div class="font-medium">{profile.label}</div>
427+ <div class="text-sm text-muted-foreground">{profile.description}</div>
428+ </div>
429+ </label>
430+ {/each}
431+ </div>
432+
433+ <!-- Custom profile note -->
434+ {#if config.performance.profile === "custom"}
435+ <div class="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
436+ <p>
437+ Custom profile settings are configured in your <code class="rounded bg-muted px-1 py-0.5">config.toml</code> file.
438+ See the <a href="https://github.com/bnema/dumber/blob/main/docs/CONFIG.md#performance-profiles" target="_blank" class="text-primary underline">documentation</a> for available options.
439+ </p>
440+ </div>
441+ {/if}
442+ </Card.Content>
443+ </Card.Root>
444+ </Tabs.Content>
377445 </Tabs.Root>
378446
379447 <div class="flex flex-wrap items-center justify-between gap-4 border-t border-border px-6 py-4">
@@ -26,6 +26,10 @@
26 description: string;26 description: string;
27 };27 };
28 28
29+ type PerformanceConfig = {
30+ profile: string;
31+ };
32+
29 type ConfigDTO = {33 type ConfigDTO = {
30 appearance: {34 appearance: {
31 sans_font: string;35 sans_font: string;
@@ -36,11 +40,19 @@
36 light_palette: ColorPalette;40 light_palette: ColorPalette;
37 dark_palette: ColorPalette;41 dark_palette: ColorPalette;
38 };42 };
43+ performance: PerformanceConfig;
39 default_ui_scale: number;44 default_ui_scale: number;
40 default_search_engine: string;45 default_search_engine: string;
41 search_shortcuts: Record<string, SearchShortcut>;46 search_shortcuts: Record<string, SearchShortcut>;
42 };47 };
43 48
49+ const PERFORMANCE_PROFILES = [
50+ { value: "default", label: "Default", description: "No tuning, uses WebKit defaults. Recommended for most users." },
51+ { value: "lite", label: "Lite", description: "Reduced resource usage for low-RAM systems (< 4GB) or battery saving." },
52+ { value: "max", label: "Max", description: "Maximum responsiveness for heavy pages (GitHub PRs, complex SPAs)." },
53+ { value: "custom", label: "Custom", description: "Manual control via config file. Edit config.toml to set individual values." },
54+ ];
55+
44 const PALETTE_FIELDS: Array<{ key: keyof ColorPalette; label: string }> = [56 const PALETTE_FIELDS: Array<{ key: keyof ColorPalette; label: string }> = [
45 { key: "background", label: "Background" },57 { key: "background", label: "Background" },
46 { key: "surface", label: "Surface" },58 { key: "surface", label: "Surface" },
@@ -250,6 +262,7 @@
250 <Tabs.List class="bg-muted/60">262 <Tabs.List class="bg-muted/60">
251 <Tabs.Trigger value="appearance">Appearance</Tabs.Trigger>263 <Tabs.Trigger value="appearance">Appearance</Tabs.Trigger>
252 <Tabs.Trigger value="search">Search</Tabs.Trigger>264 <Tabs.Trigger value="search">Search</Tabs.Trigger>
265+ <Tabs.Trigger value="performance">Performance</Tabs.Trigger>
253 </Tabs.List>266 </Tabs.List>
254 </div>267 </div>
255 268
@@ -374,6 +387,61 @@
374 </Card.Content>387 </Card.Content>
375 </Card.Root>388 </Card.Root>
376 </Tabs.Content>389 </Tabs.Content>
390+
391+ <Tabs.Content value="performance">
392+ <Card.Root class="rounded-none border-0 bg-transparent py-0 shadow-none">
393+ <Card.Header>
394+ <Card.Title>Performance Profile</Card.Title>
395+ <Card.Description>
396+ WebKitGTK rendering and memory tuning presets.
397+ </Card.Description>
398+ </Card.Header>
399+ <Card.Content class="space-y-6">
400+ <!-- Restart warning banner -->
401+ <div class="flex items-start gap-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-4 py-3">
402+ <span class="text-amber-500">⚠</span>
403+ <div class="space-y-1">
404+ <p class="text-sm font-medium text-amber-500">Restart Required</p>
405+ <p class="text-xs text-muted-foreground">
406+ Performance settings are applied at browser startup. Changes will take effect after restarting Dumber.
407+ </p>
408+ </div>
409+ </div>
410+
411+ <!-- Profile selector -->
412+ <div class="space-y-4">
413+ {#each PERFORMANCE_PROFILES as profile (profile.value)}
414+ <label
415+ class="flex cursor-pointer items-start gap-4 rounded-md border p-4 transition-colors hover:bg-muted/50 {config.performance.profile === profile.value ? 'border-primary bg-primary/5' : ''}"
416+ >
417+ <input
418+ type="radio"
419+ name="performance_profile"
420+ value={profile.value}
421+ checked={config.performance.profile === profile.value}
422+ onchange={() => config!.performance.profile = profile.value}
423+ class="mt-1 accent-primary"
424+ />
425+ <div class="space-y-1">
426+ <div class="font-medium">{profile.label}</div>
427+ <div class="text-sm text-muted-foreground">{profile.description}</div>
428+ </div>
429+ </label>
430+ {/each}
431+ </div>
432+
433+ <!-- Custom profile note -->
434+ {#if config.performance.profile === "custom"}
435+ <div class="rounded-md border border-border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
436+ <p>
437+ Custom profile settings are configured in your <code class="rounded bg-muted px-1 py-0.5">config.toml</code> file.
438+ See the <a href="https://github.com/bnema/dumber/blob/main/docs/CONFIG.md#performance-profiles" target="_blank" class="text-primary underline">documentation</a> for available options.
439+ </p>
440+ </div>
441+ {/if}
442+ </Card.Content>
443+ </Card.Root>
444+ </Tabs.Content>
377 </Tabs.Root>445 </Tabs.Root>
378 446
379 <div class="flex flex-wrap items-center justify-between gap-4 border-t border-border px-6 py-4">447 <div class="flex flex-wrap items-center justify-between gap-4 border-t border-border px-6 py-4">

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