feat(systemviews): add config editing controls
- commit
- 9da5cc35e9393221aa73b3271ec292afe16b890b
- author
- brice · · 2026-04-24 03:02 UTC
- parent
- 18449b5
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
8 files · +1790 -106
M assets/systemviews/systemviews.css +37 -3
| @@ -411,7 +411,8 @@ body { | |||
| 411 | 411 | } | |
| 412 | 412 | ||
| 413 | 413 | .sv-card-form label, | |
| 414 | - | .sv-inline-form label { | |
| 414 | + | .sv-inline-form label, | |
| 415 | + | .sv-fieldset label { | |
| 415 | 416 | display: grid; | |
| 416 | 417 | gap: 0.25rem; | |
| 417 | 418 | min-width: min(14rem, 100%); | |
| @@ -423,7 +424,9 @@ body { | |||
| 423 | 424 | .sv-card-form input, | |
| 424 | 425 | .sv-card-form select, | |
| 425 | 426 | .sv-inline-form input, | |
| 426 | - | .sv-inline-form select { | |
| 427 | + | .sv-inline-form select, | |
| 428 | + | .sv-fieldset input, | |
| 429 | + | .sv-fieldset select { | |
| 427 | 430 | border: 1px solid var(--sv-border, #2a313d); | |
| 428 | 431 | border-radius: 0.55rem; | |
| 429 | 432 | padding: 0.5rem 0.6rem; | |
| @@ -432,6 +435,35 @@ body { | |||
| 432 | 435 | font: inherit; | |
| 433 | 436 | } | |
| 434 | 437 | ||
| 438 | + | .sv-config-form, | |
| 439 | + | .sv-fieldset { | |
| 440 | + | display: flex; | |
| 441 | + | flex-wrap: wrap; | |
| 442 | + | gap: 0.65rem; | |
| 443 | + | align-items: end; | |
| 444 | + | } | |
| 445 | + | ||
| 446 | + | .sv-fieldset { | |
| 447 | + | width: 100%; | |
| 448 | + | margin: 0; | |
| 449 | + | padding: 0.75rem; | |
| 450 | + | border: 1px solid var(--sv-border, #2a313d); | |
| 451 | + | border-radius: 0.65rem; | |
| 452 | + | } | |
| 453 | + | ||
| 454 | + | .sv-fieldset legend { | |
| 455 | + | color: var(--sv-muted, #9aa3b2); | |
| 456 | + | font-weight: 700; | |
| 457 | + | padding: 0 0.35rem; | |
| 458 | + | } | |
| 459 | + | ||
| 460 | + | .sv-keybinding-row { | |
| 461 | + | display: grid; | |
| 462 | + | grid-template-columns: minmax(0, 1fr) minmax(18rem, auto); | |
| 463 | + | gap: 1rem; | |
| 464 | + | align-items: start; | |
| 465 | + | } | |
| 466 | + | ||
| 435 | 467 | .sv-filter-panel { | |
| 436 | 468 | display: grid; | |
| 437 | 469 | gap: 0.6rem; | |
| @@ -478,7 +510,9 @@ body { | |||
| 478 | 510 | } | |
| 479 | 511 | ||
| 480 | 512 | @media (max-width: 720px) { | |
| 481 | - | .sv-favorite-header { | |
| 513 | + | .sv-favorite-header, | |
| 514 | + | .sv-keybinding-row { | |
| 482 | 515 | display: grid; | |
| 516 | + | grid-template-columns: 1fr; | |
| 483 | 517 | } | |
| 484 | 518 | } | |
| @@ -411,7 +411,8 @@ body { | |||||
| 411 | } | 411 | } | ||
| 412 | 412 | ||||
| 413 | .sv-card-form label, | 413 | .sv-card-form label, | ||
| 414 | - | .sv-inline-form label { | 414 | + | .sv-inline-form label, |
| 415 | + | .sv-fieldset label { | |||
| 415 | display: grid; | 416 | display: grid; | ||
| 416 | gap: 0.25rem; | 417 | gap: 0.25rem; | ||
| 417 | min-width: min(14rem, 100%); | 418 | min-width: min(14rem, 100%); | ||
| @@ -423,7 +424,9 @@ body { | |||||
| 423 | .sv-card-form input, | 424 | .sv-card-form input, | ||
| 424 | .sv-card-form select, | 425 | .sv-card-form select, | ||
| 425 | .sv-inline-form input, | 426 | .sv-inline-form input, | ||
| 426 | - | .sv-inline-form select { | 427 | + | .sv-inline-form select, |
| 428 | + | .sv-fieldset input, | |||
| 429 | + | .sv-fieldset select { | |||
| 427 | border: 1px solid var(--sv-border, #2a313d); | 430 | border: 1px solid var(--sv-border, #2a313d); | ||
| 428 | border-radius: 0.55rem; | 431 | border-radius: 0.55rem; | ||
| 429 | padding: 0.5rem 0.6rem; | 432 | padding: 0.5rem 0.6rem; | ||
| @@ -432,6 +435,35 @@ body { | |||||
| 432 | font: inherit; | 435 | font: inherit; | ||
| 433 | } | 436 | } | ||
| 434 | 437 | ||||
| 438 | + | .sv-config-form, | |||
| 439 | + | .sv-fieldset { | |||
| 440 | + | display: flex; | |||
| 441 | + | flex-wrap: wrap; | |||
| 442 | + | gap: 0.65rem; | |||
| 443 | + | align-items: end; | |||
| 444 | + | } | |||
| 445 | + | ||||
| 446 | + | .sv-fieldset { | |||
| 447 | + | width: 100%; | |||
| 448 | + | margin: 0; | |||
| 449 | + | padding: 0.75rem; | |||
| 450 | + | border: 1px solid var(--sv-border, #2a313d); | |||
| 451 | + | border-radius: 0.65rem; | |||
| 452 | + | } | |||
| 453 | + | ||||
| 454 | + | .sv-fieldset legend { | |||
| 455 | + | color: var(--sv-muted, #9aa3b2); | |||
| 456 | + | font-weight: 700; | |||
| 457 | + | padding: 0 0.35rem; | |||
| 458 | + | } | |||
| 459 | + | ||||
| 460 | + | .sv-keybinding-row { | |||
| 461 | + | display: grid; | |||
| 462 | + | grid-template-columns: minmax(0, 1fr) minmax(18rem, auto); | |||
| 463 | + | gap: 1rem; | |||
| 464 | + | align-items: start; | |||
| 465 | + | } | |||
| 466 | + | ||||
| 435 | .sv-filter-panel { | 467 | .sv-filter-panel { | ||
| 436 | display: grid; | 468 | display: grid; | ||
| 437 | gap: 0.6rem; | 469 | gap: 0.6rem; | ||
| @@ -478,7 +510,9 @@ body { | |||||
| 478 | } | 510 | } | ||
| 479 | 511 | ||||
| 480 | @media (max-width: 720px) { | 512 | @media (max-width: 720px) { | ||
| 481 | - | .sv-favorite-header { | 513 | + | .sv-favorite-header, |
| 514 | + | .sv-keybinding-row { | |||
| 482 | display: grid; | 515 | display: grid; | ||
| 516 | + | grid-template-columns: 1fr; | |||
| 483 | } | 517 | } | ||
| 484 | } | 518 | } | ||
M internal/ui/systemviews/app.go +10 -1
| @@ -38,6 +38,8 @@ type App struct { | |||
| 38 | 38 | favoritesError string | |
| 39 | 39 | config *port.SystemviewConfigPayload | |
| 40 | 40 | keybindings any | |
| 41 | + | configNotice string | |
| 42 | + | configError string | |
| 41 | 43 | renderedHTML string | |
| 42 | 44 | } | |
| 43 | 45 | ||
| @@ -261,7 +263,12 @@ func (a *App) loadConfigRoute(ctx context.Context) error { | |||
| 261 | 263 | a.renderedHTML = renderAppFrame(renderedPage{ | |
| 262 | 264 | route: RouteConfig, | |
| 263 | 265 | subtitle: "Browser settings", | |
| 264 | - | body: configHTML(config, keybindings), | |
| 266 | + | body: configHTML(configRenderData{ | |
| 267 | + | Config: config, | |
| 268 | + | Keybindings: keybindings, | |
| 269 | + | Notice: a.configNotice, | |
| 270 | + | Error: a.configError, | |
| 271 | + | }), | |
| 265 | 272 | }, a.shellTheme) | |
| 266 | 273 | return nil | |
| 267 | 274 | } | |
| @@ -300,6 +307,8 @@ func (a *App) resetRouteState() { | |||
| 300 | 307 | a.favoritesError = "" | |
| 301 | 308 | a.config = nil | |
| 302 | 309 | a.keybindings = nil | |
| 310 | + | a.configNotice = "" | |
| 311 | + | a.configError = "" | |
| 303 | 312 | } | |
| 304 | 313 | ||
| 305 | 314 | func (a *App) CurrentRoute() Route { | |
| @@ -38,6 +38,8 @@ type App struct { | |||||
| 38 | favoritesError string | 38 | favoritesError string | ||
| 39 | config *port.SystemviewConfigPayload | 39 | config *port.SystemviewConfigPayload | ||
| 40 | keybindings any | 40 | keybindings any | ||
| 41 | + | configNotice string | |||
| 42 | + | configError string | |||
| 41 | renderedHTML string | 43 | renderedHTML string | ||
| 42 | } | 44 | } | ||
| 43 | 45 | ||||
| @@ -261,7 +263,12 @@ func (a *App) loadConfigRoute(ctx context.Context) error { | |||||
| 261 | a.renderedHTML = renderAppFrame(renderedPage{ | 263 | a.renderedHTML = renderAppFrame(renderedPage{ | ||
| 262 | route: RouteConfig, | 264 | route: RouteConfig, | ||
| 263 | subtitle: "Browser settings", | 265 | subtitle: "Browser settings", | ||
| 264 | - | body: configHTML(config, keybindings), | 266 | + | body: configHTML(configRenderData{ |
| 267 | + | Config: config, | |||
| 268 | + | Keybindings: keybindings, | |||
| 269 | + | Notice: a.configNotice, | |||
| 270 | + | Error: a.configError, | |||
| 271 | + | }), | |||
| 265 | }, a.shellTheme) | 272 | }, a.shellTheme) | ||
| 266 | return nil | 273 | return nil | ||
| 267 | } | 274 | } | ||
| @@ -300,6 +307,8 @@ func (a *App) resetRouteState() { | |||||
| 300 | a.favoritesError = "" | 307 | a.favoritesError = "" | ||
| 301 | a.config = nil | 308 | a.config = nil | ||
| 302 | a.keybindings = nil | 309 | a.keybindings = nil | ||
| 310 | + | a.configNotice = "" | |||
| 311 | + | a.configError = "" | |||
| 303 | } | 312 | } | ||
| 304 | 313 | ||||
| 305 | func (a *App) CurrentRoute() Route { | 314 | func (a *App) CurrentRoute() Route { | ||
M internal/ui/systemviews/app_test.go +161 -5
| @@ -455,12 +455,149 @@ func TestAppLoadInitialConfigRouteRendersData(t *testing.T) { | |||
| 455 | 455 | func TestConfigHTMLFallsBackForMalformedKeybindings(t *testing.T) { | |
| 456 | 456 | t.Parallel() | |
| 457 | 457 | ||
| 458 | - | html := configHTML(port.SystemviewConfigPayload{}, map[string]any{"groups": "oops"}) | |
| 458 | + | html := configHTML(configRenderData{Config: port.SystemviewConfigPayload{}, Keybindings: map[string]any{"groups": "oops"}}) | |
| 459 | 459 | ||
| 460 | 460 | assert.Contains(t, html, "Keybindings unavailable") | |
| 461 | 461 | assert.NotContains(t, html, "groups[0].bindings[0].action") | |
| 462 | 462 | } | |
| 463 | 463 | ||
| 464 | + | func TestAppLoadInitialConfigRouteRendersEditControls(t *testing.T) { | |
| 465 | + | t.Parallel() | |
| 466 | + | ||
| 467 | + | service := &fakeConfigService{ | |
| 468 | + | current: testConfigPayload(), | |
| 469 | + | keybindings: port.KeybindingsConfig{Groups: []port.KeybindingGroup{{ | |
| 470 | + | Mode: "default", | |
| 471 | + | DisplayName: "Default", | |
| 472 | + | Bindings: []port.KeybindingEntry{{ | |
| 473 | + | Action: "toggle_history_systemview", | |
| 474 | + | Description: "Toggle history", | |
| 475 | + | Keys: []string{"ctrl+h"}, | |
| 476 | + | DefaultKeys: []string{"ctrl+h"}, | |
| 477 | + | }}, | |
| 478 | + | }}}, | |
| 479 | + | } | |
| 480 | + | app := NewApp(Dependencies{Config: service, LocationURI: "dumb://config"}) | |
| 481 | + | ||
| 482 | + | require.NoError(t, app.LoadInitial(context.Background())) | |
| 483 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.appearance.save"`) | |
| 484 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.appearance.reset"`) | |
| 485 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.search.save"`) | |
| 486 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.searchShortcut.create"`) | |
| 487 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.searchShortcut.update"`) | |
| 488 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.searchShortcut.delete"`) | |
| 489 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.performance.save"`) | |
| 490 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.keybinding.set"`) | |
| 491 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.keybinding.reset"`) | |
| 492 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.keybinding.resetAll"`) | |
| 493 | + | assert.Contains(t, app.renderedHTML, "may require restarting") | |
| 494 | + | } | |
| 495 | + | ||
| 496 | + | func TestAppHandleConfigActionsRefreshesDOM(t *testing.T) { | |
| 497 | + | dom := &fakeDOM{} | |
| 498 | + | service := &fakeConfigService{ | |
| 499 | + | current: testConfigPayload(), | |
| 500 | + | defaultCfg: testDefaultConfigPayload(), | |
| 501 | + | keybindings: port.KeybindingsConfig{Groups: []port.KeybindingGroup{{ | |
| 502 | + | Mode: "default", | |
| 503 | + | DisplayName: "Default", | |
| 504 | + | Bindings: []port.KeybindingEntry{{ | |
| 505 | + | Action: "toggle_history_systemview", | |
| 506 | + | Description: "Toggle history", | |
| 507 | + | Keys: []string{"ctrl+h"}, | |
| 508 | + | DefaultKeys: []string{"ctrl+h"}, | |
| 509 | + | }}, | |
| 510 | + | }}}, | |
| 511 | + | setResp: port.SetKeybindingResponse{}, | |
| 512 | + | } | |
| 513 | + | app := NewApp(Dependencies{DOM: dom, Config: service, LocationURI: "dumb://config"}) | |
| 514 | + | ||
| 515 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |
| 516 | + | Action: configActionSaveAppearance, | |
| 517 | + | Data: map[string]string{ | |
| 518 | + | "sans_font": "Inter", "serif_font": "Georgia", "monospace_font": "JetBrains Mono", | |
| 519 | + | "default_font_size": "18", "default_ui_scale": "1.25", "color_scheme": "prefer-light", | |
| 520 | + | "light_background": "#ffffff", "light_surface": "#fafafa", "light_surface_variant": "#eeeeee", "light_text": "#111111", "light_muted": "#666666", "light_accent": "#0055ff", "light_border": "#dddddd", | |
| 521 | + | "dark_background": "#111111", "dark_surface": "#1a1a1a", "dark_surface_variant": "#2a2a2a", "dark_text": "#f5f5f5", "dark_muted": "#a0a0a0", "dark_accent": "#66aaff", "dark_border": "#333333", | |
| 522 | + | }, | |
| 523 | + | })) | |
| 524 | + | assert.True(t, service.calledSave) | |
| 525 | + | assert.Equal(t, 18, service.savedConfig.Appearance.DefaultFontSize) | |
| 526 | + | assert.Equal(t, 1.25, service.savedConfig.DefaultUIScale) | |
| 527 | + | assert.Contains(t, dom.html, "Saved appearance settings") | |
| 528 | + | assert.Contains(t, dom.html, `class="sv-app sv-light"`) | |
| 529 | + | ||
| 530 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |
| 531 | + | Action: configActionCreateSearchShortcut, | |
| 532 | + | Data: map[string]string{"key": "g", "url": "https://google.com/search?q=%s", "description": "Google"}, | |
| 533 | + | })) | |
| 534 | + | assert.Equal(t, "Google", service.savedConfig.SearchShortcuts["g"].Description) | |
| 535 | + | assert.Contains(t, dom.html, "Created search shortcut g") | |
| 536 | + | ||
| 537 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |
| 538 | + | Action: configActionSavePerformance, | |
| 539 | + | Data: map[string]string{ | |
| 540 | + | "profile": "custom", "skia_cpu_threads": "4", "skia_gpu_threads": "2", | |
| 541 | + | "web_process_memory_mb": "2048", "network_process_memory_mb": "512", "webview_pool_prewarm": "4", | |
| 542 | + | }, | |
| 543 | + | })) | |
| 544 | + | assert.Equal(t, "custom", service.savedConfig.Performance.Profile) | |
| 545 | + | assert.Equal(t, 2048, service.savedConfig.Performance.Custom.WebProcessMemoryMB) | |
| 546 | + | assert.Contains(t, dom.html, "Saved performance settings") | |
| 547 | + | ||
| 548 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |
| 549 | + | Action: configActionSetKeybinding, | |
| 550 | + | Data: map[string]string{"mode": "default", "action": "toggle_history_systemview", "keys": "ctrl+h, alt+h"}, | |
| 551 | + | })) | |
| 552 | + | assert.True(t, service.calledSet) | |
| 553 | + | assert.Equal(t, []string{"ctrl+h", "alt+h"}, service.setReq.Keys) | |
| 554 | + | assert.Contains(t, dom.html, "Saved keybinding toggle_history_systemview") | |
| 555 | + | ||
| 556 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |
| 557 | + | Action: configActionResetKeybinding, | |
| 558 | + | Data: map[string]string{"mode": "default", "action": "toggle_history_systemview"}, | |
| 559 | + | })) | |
| 560 | + | assert.True(t, service.calledReset) | |
| 561 | + | assert.Equal(t, "toggle_history_systemview", service.resetReq.Action) | |
| 562 | + | assert.Contains(t, dom.html, "Reset keybinding toggle_history_systemview") | |
| 563 | + | ||
| 564 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{Action: configActionResetAllKeybindings})) | |
| 565 | + | assert.True(t, service.calledResetAll) | |
| 566 | + | assert.Contains(t, dom.html, "Reset all keybindings to defaults") | |
| 567 | + | } | |
| 568 | + | ||
| 569 | + | func testConfigPayload() port.SystemviewConfigPayload { | |
| 570 | + | return port.SystemviewConfigPayload{ | |
| 571 | + | EngineType: "webkit", | |
| 572 | + | Appearance: port.WebUIAppearanceConfig{ | |
| 573 | + | ColorScheme: "prefer-dark", | |
| 574 | + | SansFont: "Inter", | |
| 575 | + | SerifFont: "Georgia", | |
| 576 | + | MonospaceFont: "JetBrains Mono", | |
| 577 | + | DefaultFontSize: 16, | |
| 578 | + | LightPalette: port.ColorPalette{Background: "#ffffff", Surface: "#fafafa", SurfaceVariant: "#eeeeee", Text: "#111111", Muted: "#666666", Accent: "#0055ff", Border: "#dddddd"}, | |
| 579 | + | DarkPalette: port.ColorPalette{Background: "#111111", Surface: "#1a1a1a", SurfaceVariant: "#2a2a2a", Text: "#f5f5f5", Muted: "#a0a0a0", Accent: "#66aaff", Border: "#333333"}, | |
| 580 | + | }, | |
| 581 | + | DefaultUIScale: 1, | |
| 582 | + | DefaultSearchEngine: "https://duckduckgo.com/?q=%s", | |
| 583 | + | SearchShortcuts: map[string]port.SearchShortcut{ | |
| 584 | + | "ddg": {URL: "https://duckduckgo.com/?q=%s", Description: "DuckDuckGo"}, | |
| 585 | + | }, | |
| 586 | + | Performance: port.SystemviewPerformancePayload{ | |
| 587 | + | Profile: "default", | |
| 588 | + | Custom: port.SystemviewCustomPerformancePayload{SkiaCPUThreads: 2, SkiaGPUThreads: 1, WebProcessMemoryMB: 1024, NetworkProcessMemoryMB: 256, WebViewPoolPrewarm: 2}, | |
| 589 | + | Hardware: port.SystemviewHardwarePayload{CPUCores: 4, CPUThreads: 8, TotalRAMMB: 16384, GPUVendor: "AMD", GPUName: "Radeon", VRAMMB: 4096}, | |
| 590 | + | }, | |
| 591 | + | } | |
| 592 | + | } | |
| 593 | + | ||
| 594 | + | func testDefaultConfigPayload() port.SystemviewConfigPayload { | |
| 595 | + | cfg := testConfigPayload() | |
| 596 | + | cfg.Appearance.DefaultFontSize = 14 | |
| 597 | + | cfg.DefaultUIScale = 1 | |
| 598 | + | return cfg | |
| 599 | + | } | |
| 600 | + | ||
| 464 | 601 | type fakeDOM struct { | |
| 465 | 602 | mounted bool | |
| 466 | 603 | html string | |
| @@ -641,6 +778,10 @@ type fakeConfigService struct { | |||
| 641 | 778 | current port.SystemviewConfigPayload | |
| 642 | 779 | defaultCfg port.SystemviewConfigPayload | |
| 643 | 780 | keybindings any | |
| 781 | + | savedConfig port.WebUIConfig | |
| 782 | + | setReq port.SetKeybindingRequest | |
| 783 | + | setResp any | |
| 784 | + | resetReq port.ResetKeybindingRequest | |
| 644 | 785 | } | |
| 645 | 786 | ||
| 646 | 787 | func (s *fakeConfigService) Current(context.Context) (port.SystemviewConfigPayload, error) { | |
| @@ -653,8 +794,21 @@ func (s *fakeConfigService) Default(context.Context) (port.SystemviewConfigPaylo | |||
| 653 | 794 | return s.defaultCfg, nil | |
| 654 | 795 | } | |
| 655 | 796 | ||
| 656 | - | func (s *fakeConfigService) Save(context.Context, port.WebUIConfig) error { | |
| 797 | + | func (s *fakeConfigService) Save(_ context.Context, cfg port.WebUIConfig) error { | |
| 657 | 798 | s.calledSave = true | |
| 799 | + | s.savedConfig = cfg | |
| 800 | + | s.current.Appearance = cfg.Appearance | |
| 801 | + | s.current.DefaultUIScale = cfg.DefaultUIScale | |
| 802 | + | s.current.DefaultSearchEngine = cfg.DefaultSearchEngine | |
| 803 | + | s.current.SearchShortcuts = cfg.SearchShortcuts | |
| 804 | + | s.current.Performance.Profile = cfg.Performance.Profile | |
| 805 | + | s.current.Performance.Custom = port.SystemviewCustomPerformancePayload{ | |
| 806 | + | SkiaCPUThreads: cfg.Performance.Custom.SkiaCPUThreads, | |
| 807 | + | SkiaGPUThreads: cfg.Performance.Custom.SkiaGPUThreads, | |
| 808 | + | WebProcessMemoryMB: cfg.Performance.Custom.WebProcessMemoryMB, | |
| 809 | + | NetworkProcessMemoryMB: cfg.Performance.Custom.NetworkProcessMemoryMB, | |
| 810 | + | WebViewPoolPrewarm: cfg.Performance.Custom.WebViewPoolPrewarm, | |
| 811 | + | } | |
| 658 | 812 | return nil | |
| 659 | 813 | } | |
| 660 | 814 | ||
| @@ -663,13 +817,15 @@ func (s *fakeConfigService) GetKeybindings(context.Context) (any, error) { | |||
| 663 | 817 | return s.keybindings, nil | |
| 664 | 818 | } | |
| 665 | 819 | ||
| 666 | - | func (s *fakeConfigService) SetKeybinding(context.Context, port.SetKeybindingRequest) (any, error) { | |
| 820 | + | func (s *fakeConfigService) SetKeybinding(_ context.Context, req port.SetKeybindingRequest) (any, error) { | |
| 667 | 821 | s.calledSet = true | |
| 668 | - | return nil, nil | |
| 822 | + | s.setReq = req | |
| 823 | + | return s.setResp, nil | |
| 669 | 824 | } | |
| 670 | 825 | ||
| 671 | - | func (s *fakeConfigService) ResetKeybinding(context.Context, port.ResetKeybindingRequest) error { | |
| 826 | + | func (s *fakeConfigService) ResetKeybinding(_ context.Context, req port.ResetKeybindingRequest) error { | |
| 672 | 827 | s.calledReset = true | |
| 828 | + | s.resetReq = req | |
| 673 | 829 | return nil | |
| 674 | 830 | } | |
| 675 | 831 | ||
| @@ -455,12 +455,149 @@ func TestAppLoadInitialConfigRouteRendersData(t *testing.T) { | |||||
| 455 | func TestConfigHTMLFallsBackForMalformedKeybindings(t *testing.T) { | 455 | func TestConfigHTMLFallsBackForMalformedKeybindings(t *testing.T) { | ||
| 456 | t.Parallel() | 456 | t.Parallel() | ||
| 457 | 457 | ||||
| 458 | - | html := configHTML(port.SystemviewConfigPayload{}, map[string]any{"groups": "oops"}) | 458 | + | html := configHTML(configRenderData{Config: port.SystemviewConfigPayload{}, Keybindings: map[string]any{"groups": "oops"}}) |
| 459 | 459 | ||||
| 460 | assert.Contains(t, html, "Keybindings unavailable") | 460 | assert.Contains(t, html, "Keybindings unavailable") | ||
| 461 | assert.NotContains(t, html, "groups[0].bindings[0].action") | 461 | assert.NotContains(t, html, "groups[0].bindings[0].action") | ||
| 462 | } | 462 | } | ||
| 463 | 463 | ||||
| 464 | + | func TestAppLoadInitialConfigRouteRendersEditControls(t *testing.T) { | |||
| 465 | + | t.Parallel() | |||
| 466 | + | ||||
| 467 | + | service := &fakeConfigService{ | |||
| 468 | + | current: testConfigPayload(), | |||
| 469 | + | keybindings: port.KeybindingsConfig{Groups: []port.KeybindingGroup{{ | |||
| 470 | + | Mode: "default", | |||
| 471 | + | DisplayName: "Default", | |||
| 472 | + | Bindings: []port.KeybindingEntry{{ | |||
| 473 | + | Action: "toggle_history_systemview", | |||
| 474 | + | Description: "Toggle history", | |||
| 475 | + | Keys: []string{"ctrl+h"}, | |||
| 476 | + | DefaultKeys: []string{"ctrl+h"}, | |||
| 477 | + | }}, | |||
| 478 | + | }}}, | |||
| 479 | + | } | |||
| 480 | + | app := NewApp(Dependencies{Config: service, LocationURI: "dumb://config"}) | |||
| 481 | + | ||||
| 482 | + | require.NoError(t, app.LoadInitial(context.Background())) | |||
| 483 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.appearance.save"`) | |||
| 484 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.appearance.reset"`) | |||
| 485 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.search.save"`) | |||
| 486 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.searchShortcut.create"`) | |||
| 487 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.searchShortcut.update"`) | |||
| 488 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.searchShortcut.delete"`) | |||
| 489 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.performance.save"`) | |||
| 490 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.keybinding.set"`) | |||
| 491 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.keybinding.reset"`) | |||
| 492 | + | assert.Contains(t, app.renderedHTML, `data-sv-action="config.keybinding.resetAll"`) | |||
| 493 | + | assert.Contains(t, app.renderedHTML, "may require restarting") | |||
| 494 | + | } | |||
| 495 | + | ||||
| 496 | + | func TestAppHandleConfigActionsRefreshesDOM(t *testing.T) { | |||
| 497 | + | dom := &fakeDOM{} | |||
| 498 | + | service := &fakeConfigService{ | |||
| 499 | + | current: testConfigPayload(), | |||
| 500 | + | defaultCfg: testDefaultConfigPayload(), | |||
| 501 | + | keybindings: port.KeybindingsConfig{Groups: []port.KeybindingGroup{{ | |||
| 502 | + | Mode: "default", | |||
| 503 | + | DisplayName: "Default", | |||
| 504 | + | Bindings: []port.KeybindingEntry{{ | |||
| 505 | + | Action: "toggle_history_systemview", | |||
| 506 | + | Description: "Toggle history", | |||
| 507 | + | Keys: []string{"ctrl+h"}, | |||
| 508 | + | DefaultKeys: []string{"ctrl+h"}, | |||
| 509 | + | }}, | |||
| 510 | + | }}}, | |||
| 511 | + | setResp: port.SetKeybindingResponse{}, | |||
| 512 | + | } | |||
| 513 | + | app := NewApp(Dependencies{DOM: dom, Config: service, LocationURI: "dumb://config"}) | |||
| 514 | + | ||||
| 515 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |||
| 516 | + | Action: configActionSaveAppearance, | |||
| 517 | + | Data: map[string]string{ | |||
| 518 | + | "sans_font": "Inter", "serif_font": "Georgia", "monospace_font": "JetBrains Mono", | |||
| 519 | + | "default_font_size": "18", "default_ui_scale": "1.25", "color_scheme": "prefer-light", | |||
| 520 | + | "light_background": "#ffffff", "light_surface": "#fafafa", "light_surface_variant": "#eeeeee", "light_text": "#111111", "light_muted": "#666666", "light_accent": "#0055ff", "light_border": "#dddddd", | |||
| 521 | + | "dark_background": "#111111", "dark_surface": "#1a1a1a", "dark_surface_variant": "#2a2a2a", "dark_text": "#f5f5f5", "dark_muted": "#a0a0a0", "dark_accent": "#66aaff", "dark_border": "#333333", | |||
| 522 | + | }, | |||
| 523 | + | })) | |||
| 524 | + | assert.True(t, service.calledSave) | |||
| 525 | + | assert.Equal(t, 18, service.savedConfig.Appearance.DefaultFontSize) | |||
| 526 | + | assert.Equal(t, 1.25, service.savedConfig.DefaultUIScale) | |||
| 527 | + | assert.Contains(t, dom.html, "Saved appearance settings") | |||
| 528 | + | assert.Contains(t, dom.html, `class="sv-app sv-light"`) | |||
| 529 | + | ||||
| 530 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |||
| 531 | + | Action: configActionCreateSearchShortcut, | |||
| 532 | + | Data: map[string]string{"key": "g", "url": "https://google.com/search?q=%s", "description": "Google"}, | |||
| 533 | + | })) | |||
| 534 | + | assert.Equal(t, "Google", service.savedConfig.SearchShortcuts["g"].Description) | |||
| 535 | + | assert.Contains(t, dom.html, "Created search shortcut g") | |||
| 536 | + | ||||
| 537 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |||
| 538 | + | Action: configActionSavePerformance, | |||
| 539 | + | Data: map[string]string{ | |||
| 540 | + | "profile": "custom", "skia_cpu_threads": "4", "skia_gpu_threads": "2", | |||
| 541 | + | "web_process_memory_mb": "2048", "network_process_memory_mb": "512", "webview_pool_prewarm": "4", | |||
| 542 | + | }, | |||
| 543 | + | })) | |||
| 544 | + | assert.Equal(t, "custom", service.savedConfig.Performance.Profile) | |||
| 545 | + | assert.Equal(t, 2048, service.savedConfig.Performance.Custom.WebProcessMemoryMB) | |||
| 546 | + | assert.Contains(t, dom.html, "Saved performance settings") | |||
| 547 | + | ||||
| 548 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |||
| 549 | + | Action: configActionSetKeybinding, | |||
| 550 | + | Data: map[string]string{"mode": "default", "action": "toggle_history_systemview", "keys": "ctrl+h, alt+h"}, | |||
| 551 | + | })) | |||
| 552 | + | assert.True(t, service.calledSet) | |||
| 553 | + | assert.Equal(t, []string{"ctrl+h", "alt+h"}, service.setReq.Keys) | |||
| 554 | + | assert.Contains(t, dom.html, "Saved keybinding toggle_history_systemview") | |||
| 555 | + | ||||
| 556 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{ | |||
| 557 | + | Action: configActionResetKeybinding, | |||
| 558 | + | Data: map[string]string{"mode": "default", "action": "toggle_history_systemview"}, | |||
| 559 | + | })) | |||
| 560 | + | assert.True(t, service.calledReset) | |||
| 561 | + | assert.Equal(t, "toggle_history_systemview", service.resetReq.Action) | |||
| 562 | + | assert.Contains(t, dom.html, "Reset keybinding toggle_history_systemview") | |||
| 563 | + | ||||
| 564 | + | require.NoError(t, app.HandleDOMAction(context.Background(), DOMAction{Action: configActionResetAllKeybindings})) | |||
| 565 | + | assert.True(t, service.calledResetAll) | |||
| 566 | + | assert.Contains(t, dom.html, "Reset all keybindings to defaults") | |||
| 567 | + | } | |||
| 568 | + | ||||
| 569 | + | func testConfigPayload() port.SystemviewConfigPayload { | |||
| 570 | + | return port.SystemviewConfigPayload{ | |||
| 571 | + | EngineType: "webkit", | |||
| 572 | + | Appearance: port.WebUIAppearanceConfig{ | |||
| 573 | + | ColorScheme: "prefer-dark", | |||
| 574 | + | SansFont: "Inter", | |||
| 575 | + | SerifFont: "Georgia", | |||
| 576 | + | MonospaceFont: "JetBrains Mono", | |||
| 577 | + | DefaultFontSize: 16, | |||
| 578 | + | LightPalette: port.ColorPalette{Background: "#ffffff", Surface: "#fafafa", SurfaceVariant: "#eeeeee", Text: "#111111", Muted: "#666666", Accent: "#0055ff", Border: "#dddddd"}, | |||
| 579 | + | DarkPalette: port.ColorPalette{Background: "#111111", Surface: "#1a1a1a", SurfaceVariant: "#2a2a2a", Text: "#f5f5f5", Muted: "#a0a0a0", Accent: "#66aaff", Border: "#333333"}, | |||
| 580 | + | }, | |||
| 581 | + | DefaultUIScale: 1, | |||
| 582 | + | DefaultSearchEngine: "https://duckduckgo.com/?q=%s", | |||
| 583 | + | SearchShortcuts: map[string]port.SearchShortcut{ | |||
| 584 | + | "ddg": {URL: "https://duckduckgo.com/?q=%s", Description: "DuckDuckGo"}, | |||
| 585 | + | }, | |||
| 586 | + | Performance: port.SystemviewPerformancePayload{ | |||
| 587 | + | Profile: "default", | |||
| 588 | + | Custom: port.SystemviewCustomPerformancePayload{SkiaCPUThreads: 2, SkiaGPUThreads: 1, WebProcessMemoryMB: 1024, NetworkProcessMemoryMB: 256, WebViewPoolPrewarm: 2}, | |||
| 589 | + | Hardware: port.SystemviewHardwarePayload{CPUCores: 4, CPUThreads: 8, TotalRAMMB: 16384, GPUVendor: "AMD", GPUName: "Radeon", VRAMMB: 4096}, | |||
| 590 | + | }, | |||
| 591 | + | } | |||
| 592 | + | } | |||
| 593 | + | ||||
| 594 | + | func testDefaultConfigPayload() port.SystemviewConfigPayload { | |||
| 595 | + | cfg := testConfigPayload() | |||
| 596 | + | cfg.Appearance.DefaultFontSize = 14 | |||
| 597 | + | cfg.DefaultUIScale = 1 | |||
| 598 | + | return cfg | |||
| 599 | + | } | |||
| 600 | + | ||||
| 464 | type fakeDOM struct { | 601 | type fakeDOM struct { | ||
| 465 | mounted bool | 602 | mounted bool | ||
| 466 | html string | 603 | html string | ||
| @@ -641,6 +778,10 @@ type fakeConfigService struct { | |||||
| 641 | current port.SystemviewConfigPayload | 778 | current port.SystemviewConfigPayload | ||
| 642 | defaultCfg port.SystemviewConfigPayload | 779 | defaultCfg port.SystemviewConfigPayload | ||
| 643 | keybindings any | 780 | keybindings any | ||
| 781 | + | savedConfig port.WebUIConfig | |||
| 782 | + | setReq port.SetKeybindingRequest | |||
| 783 | + | setResp any | |||
| 784 | + | resetReq port.ResetKeybindingRequest | |||
| 644 | } | 785 | } | ||
| 645 | 786 | ||||
| 646 | func (s *fakeConfigService) Current(context.Context) (port.SystemviewConfigPayload, error) { | 787 | func (s *fakeConfigService) Current(context.Context) (port.SystemviewConfigPayload, error) { | ||
| @@ -653,8 +794,21 @@ func (s *fakeConfigService) Default(context.Context) (port.SystemviewConfigPaylo | |||||
| 653 | return s.defaultCfg, nil | 794 | return s.defaultCfg, nil | ||
| 654 | } | 795 | } | ||
| 655 | 796 | ||||
| 656 | - | func (s *fakeConfigService) Save(context.Context, port.WebUIConfig) error { | 797 | + | func (s *fakeConfigService) Save(_ context.Context, cfg port.WebUIConfig) error { |
| 657 | s.calledSave = true | 798 | s.calledSave = true | ||
| 799 | + | s.savedConfig = cfg | |||
| 800 | + | s.current.Appearance = cfg.Appearance | |||
| 801 | + | s.current.DefaultUIScale = cfg.DefaultUIScale | |||
| 802 | + | s.current.DefaultSearchEngine = cfg.DefaultSearchEngine | |||
| 803 | + | s.current.SearchShortcuts = cfg.SearchShortcuts | |||
| 804 | + | s.current.Performance.Profile = cfg.Performance.Profile | |||
| 805 | + | s.current.Performance.Custom = port.SystemviewCustomPerformancePayload{ | |||
| 806 | + | SkiaCPUThreads: cfg.Performance.Custom.SkiaCPUThreads, | |||
| 807 | + | SkiaGPUThreads: cfg.Performance.Custom.SkiaGPUThreads, | |||
| 808 | + | WebProcessMemoryMB: cfg.Performance.Custom.WebProcessMemoryMB, | |||
| 809 | + | NetworkProcessMemoryMB: cfg.Performance.Custom.NetworkProcessMemoryMB, | |||
| 810 | + | WebViewPoolPrewarm: cfg.Performance.Custom.WebViewPoolPrewarm, | |||
| 811 | + | } | |||
| 658 | return nil | 812 | return nil | ||
| 659 | } | 813 | } | ||
| 660 | 814 | ||||
| @@ -663,13 +817,15 @@ func (s *fakeConfigService) GetKeybindings(context.Context) (any, error) { | |||||
| 663 | return s.keybindings, nil | 817 | return s.keybindings, nil | ||
| 664 | } | 818 | } | ||
| 665 | 819 | ||||
| 666 | - | func (s *fakeConfigService) SetKeybinding(context.Context, port.SetKeybindingRequest) (any, error) { | 820 | + | func (s *fakeConfigService) SetKeybinding(_ context.Context, req port.SetKeybindingRequest) (any, error) { |
| 667 | s.calledSet = true | 821 | s.calledSet = true | ||
| 668 | - | return nil, nil | 822 | + | s.setReq = req |
| 823 | + | return s.setResp, nil | |||
| 669 | } | 824 | } | ||
| 670 | 825 | ||||
| 671 | - | func (s *fakeConfigService) ResetKeybinding(context.Context, port.ResetKeybindingRequest) error { | 826 | + | func (s *fakeConfigService) ResetKeybinding(_ context.Context, req port.ResetKeybindingRequest) error { |
| 672 | s.calledReset = true | 827 | s.calledReset = true | ||
| 828 | + | s.resetReq = req | |||
| 673 | return nil | 829 | return nil | ||
| 674 | } | 830 | } | ||
| 675 | 831 | ||||
M internal/ui/systemviews/config.templ +136 -12
| @@ -1,17 +1,134 @@ | |||
| 1 | 1 | package systemviews | |
| 2 | 2 | ||
| 3 | + | import "github.com/bnema/dumber/internal/application/port" | |
| 4 | + | ||
| 3 | 5 | templ ConfigView(data configRenderData) { | |
| 4 | - | @Section("sv-config-values", "Config values") { | |
| 5 | - | @KV(flattenValues(data.Config)) | |
| 6 | + | @Alert("success", data.Notice) | |
| 7 | + | @Alert("error", data.Error) | |
| 8 | + | @Section("sv-config-appearance", "Appearance") { | |
| 9 | + | @AppearanceForm(data.Config) | |
| 10 | + | } | |
| 11 | + | @Section("sv-config-search", "Search") { | |
| 12 | + | @SearchSettings(data.Config) | |
| 13 | + | } | |
| 14 | + | @Section("sv-config-performance", "Performance") { | |
| 15 | + | @PerformanceSettings(data.Config) | |
| 6 | 16 | } | |
| 7 | 17 | @Section("sv-config-keybindings", "Keybindings") { | |
| 8 | 18 | @Meta(configKeybindingSummary(data.Keybindings)) | |
| 9 | 19 | @ConfigKeybindings(data.Keybindings) | |
| 10 | 20 | } | |
| 21 | + | @Section("sv-config-values", "Current payload") { | |
| 22 | + | @KV(flattenValues(data.Config)) | |
| 23 | + | } | |
| 24 | + | } | |
| 25 | + | ||
| 26 | + | templ AppearanceForm(config port.SystemviewConfigPayload) { | |
| 27 | + | <form class="sv-card-form sv-config-form" data-sv-action="config.appearance.save"> | |
| 28 | + | <label><span>Sans font</span><input name="sans_font" type="text" value={ config.Appearance.SansFont } required/></label> | |
| 29 | + | <label><span>Serif font</span><input name="serif_font" type="text" value={ config.Appearance.SerifFont } required/></label> | |
| 30 | + | <label><span>Monospace font</span><input name="monospace_font" type="text" value={ config.Appearance.MonospaceFont } required/></label> | |
| 31 | + | <label><span>Default font size</span><input name="default_font_size" type="number" min="1" max="72" value={ formatConfigInt(config.Appearance.DefaultFontSize) } required/></label> | |
| 32 | + | <label><span>UI scale</span><input name="default_ui_scale" type="number" min="0.5" max="3" step="0.05" value={ formatConfigFloat(config.DefaultUIScale) } required/></label> | |
| 33 | + | <label><span>Color scheme</span><select name="color_scheme"> | |
| 34 | + | <option value="default" selected?={ colorSchemeSelected(config.Appearance.ColorScheme, "default") }>System default</option> | |
| 35 | + | <option value="prefer-light" selected?={ colorSchemeSelected(config.Appearance.ColorScheme, "prefer-light") }>Prefer light</option> | |
| 36 | + | <option value="prefer-dark" selected?={ colorSchemeSelected(config.Appearance.ColorScheme, "prefer-dark") }>Prefer dark</option> | |
| 37 | + | </select></label> | |
| 38 | + | @PaletteFields("Light palette", "light", config.Appearance.LightPalette) | |
| 39 | + | @PaletteFields("Dark palette", "dark", config.Appearance.DarkPalette) | |
| 40 | + | <div class="sv-button-row sv-form-actions"> | |
| 41 | + | <button class="sv-button" type="submit">Save appearance</button> | |
| 42 | + | <button class="sv-button sv-button-secondary" type="button" data-sv-action="config.appearance.reset" data-sv-confirm="Reset appearance settings to defaults?">Reset appearance</button> | |
| 43 | + | </div> | |
| 44 | + | </form> | |
| 45 | + | } | |
| 46 | + | ||
| 47 | + | templ PaletteFields(title string, prefix string, palette port.ColorPalette) { | |
| 48 | + | <fieldset class="sv-fieldset"> | |
| 49 | + | <legend>{ title }</legend> | |
| 50 | + | <label><span>Background</span><input name={ prefix + "_background" } type="text" value={ palette.Background } required/></label> | |
| 51 | + | <label><span>Surface</span><input name={ prefix + "_surface" } type="text" value={ palette.Surface } required/></label> | |
| 52 | + | <label><span>Surface variant</span><input name={ prefix + "_surface_variant" } type="text" value={ palette.SurfaceVariant } required/></label> | |
| 53 | + | <label><span>Text</span><input name={ prefix + "_text" } type="text" value={ palette.Text } required/></label> | |
| 54 | + | <label><span>Muted</span><input name={ prefix + "_muted" } type="text" value={ palette.Muted } required/></label> | |
| 55 | + | <label><span>Accent</span><input name={ prefix + "_accent" } type="text" value={ palette.Accent } required/></label> | |
| 56 | + | <label><span>Border</span><input name={ prefix + "_border" } type="text" value={ palette.Border } required/></label> | |
| 57 | + | </fieldset> | |
| 58 | + | } | |
| 59 | + | ||
| 60 | + | templ SearchSettings(config port.SystemviewConfigPayload) { | |
| 61 | + | <form class="sv-card-form" data-sv-action="config.search.save"> | |
| 62 | + | <label><span>Default search engine</span><input name="default_search_engine" type="text" value={ config.DefaultSearchEngine } placeholder="https://duckduckgo.com/?q=%s" required/></label> | |
| 63 | + | <button class="sv-button" type="submit">Save search default</button> | |
| 64 | + | </form> | |
| 65 | + | <div class="sv-group"> | |
| 66 | + | <div class="sv-group-header"><h4>Search shortcuts</h4></div> | |
| 67 | + | <p class="sv-meta">Shortcut URLs must include the %s placeholder for the search query.</p> | |
| 68 | + | <form class="sv-inline-form" data-sv-action="config.searchShortcut.create"> | |
| 69 | + | <label><span>Key</span><input name="key" type="text" placeholder="ddg" required/></label> | |
| 70 | + | <label><span>URL</span><input name="url" type="text" placeholder="https://duckduckgo.com/?q=%s" required/></label> | |
| 71 | + | <label><span>Description</span><input name="description" type="text" placeholder="DuckDuckGo" required/></label> | |
| 72 | + | <button class="sv-button sv-button-secondary" type="submit">Add shortcut</button> | |
| 73 | + | </form> | |
| 74 | + | if len(searchShortcutRows(config.SearchShortcuts)) == 0 { | |
| 75 | + | @EmptyState("No search shortcuts configured") | |
| 76 | + | } else { | |
| 77 | + | <ul class="sv-list"> | |
| 78 | + | for _, shortcut := range searchShortcutRows(config.SearchShortcuts) { | |
| 79 | + | @SearchShortcutItem(shortcut) | |
| 80 | + | } | |
| 81 | + | </ul> | |
| 82 | + | } | |
| 83 | + | </div> | |
| 84 | + | } | |
| 85 | + | ||
| 86 | + | templ SearchShortcutItem(shortcut searchShortcutRow) { | |
| 87 | + | <li class="sv-list-row"> | |
| 88 | + | <form class="sv-inline-form" data-sv-action="config.searchShortcut.update"> | |
| 89 | + | <input type="hidden" name="key" value={ shortcut.Key }/> | |
| 90 | + | <label><span>Key</span><input name="new_key" type="text" value={ shortcut.Key } required/></label> | |
| 91 | + | <label><span>URL</span><input name="url" type="text" value={ shortcut.URL } required/></label> | |
| 92 | + | <label><span>Description</span><input name="description" type="text" value={ shortcut.Description } required/></label> | |
| 93 | + | <button class="sv-button sv-button-secondary" type="submit">Save</button> | |
| 94 | + | <button class="sv-button sv-button-secondary sv-button-danger" type="button" data-sv-action="config.searchShortcut.delete" data-key={ shortcut.Key } data-sv-confirm="Delete this search shortcut?">Delete</button> | |
| 95 | + | </form> | |
| 96 | + | </li> | |
| 97 | + | } | |
| 98 | + | ||
| 99 | + | templ PerformanceSettings(config port.SystemviewConfigPayload) { | |
| 100 | + | <form class="sv-card-form sv-config-form" data-sv-action="config.performance.save"> | |
| 101 | + | <label><span>Profile</span><select name="profile"> | |
| 102 | + | <option value="default" selected?={ performanceProfileSelected(config.Performance.Profile, "default") }>Default</option> | |
| 103 | + | <option value="lite" selected?={ performanceProfileSelected(config.Performance.Profile, "lite") }>Lite</option> | |
| 104 | + | <option value="max" selected?={ performanceProfileSelected(config.Performance.Profile, "max") }>Max</option> | |
| 105 | + | <option value="custom" selected?={ performanceProfileSelected(config.Performance.Profile, "custom") }>Custom</option> | |
| 106 | + | </select></label> | |
| 107 | + | <label><span>Skia CPU threads</span><input name="skia_cpu_threads" type="number" min="0" max="8" value={ formatConfigInt(config.Performance.Custom.SkiaCPUThreads) }/></label> | |
| 108 | + | <label><span>Skia GPU threads</span><input name="skia_gpu_threads" type="number" min="-1" max="8" value={ formatConfigInt(config.Performance.Custom.SkiaGPUThreads) }/></label> | |
| 109 | + | <label><span>Web process memory MB</span><input name="web_process_memory_mb" type="number" min="0" max="16384" value={ formatConfigInt(config.Performance.Custom.WebProcessMemoryMB) }/></label> | |
| 110 | + | <label><span>Network process memory MB</span><input name="network_process_memory_mb" type="number" min="0" max="4096" value={ formatConfigInt(config.Performance.Custom.NetworkProcessMemoryMB) }/></label> | |
| 111 | + | <label><span>WebView pool prewarm</span><input name="webview_pool_prewarm" type="number" min="0" max="20" value={ formatConfigInt(config.Performance.Custom.WebViewPoolPrewarm) }/></label> | |
| 112 | + | <button class="sv-button" type="submit">Save performance</button> | |
| 113 | + | </form> | |
| 114 | + | <div class="sv-stat-grid"> | |
| 115 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ formatConfigInt(config.Performance.Hardware.CPUThreads) }</span><span class="sv-stat-label">CPU threads</span></div> | |
| 116 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ formatConfigInt(config.Performance.Hardware.TotalRAMMB) }</span><span class="sv-stat-label">RAM MB</span></div> | |
| 117 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ config.Performance.Hardware.GPUName }</span><span class="sv-stat-label">GPU</span></div> | |
| 118 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ config.EngineType }</span><span class="sv-stat-label">Engine</span></div> | |
| 119 | + | </div> | |
| 120 | + | if !engineIsWebKit(config.EngineType) { | |
| 121 | + | <p class="sv-meta">Performance tuning applies only to the WebKit engine.</p> | |
| 122 | + | } else { | |
| 123 | + | <p class="sv-meta">Performance profile changes may require restarting the browser to affect existing engine processes.</p> | |
| 124 | + | } | |
| 11 | 125 | } | |
| 12 | 126 | ||
| 13 | 127 | templ ConfigKeybindings(keybindings any) { | |
| 14 | 128 | {{ groups := configKeybindingGroups(keybindings) }} | |
| 129 | + | <div class="sv-button-row"> | |
| 130 | + | <button class="sv-button sv-button-secondary sv-button-danger" type="button" data-sv-action="config.keybinding.resetAll" data-sv-confirm="Reset all keybindings to defaults?">Reset all keybindings</button> | |
| 131 | + | </div> | |
| 15 | 132 | if groups == nil { | |
| 16 | 133 | @EmptyState("Keybindings unavailable") | |
| 17 | 134 | } else if len(groups) == 0 { | |
| @@ -39,7 +156,7 @@ templ ConfigKeybindingGroup(group renderedKeybindingGroup) { | |||
| 39 | 156 | } else { | |
| 40 | 157 | <ul class="sv-list"> | |
| 41 | 158 | for _, binding := range group.Bindings { | |
| 42 | - | @ConfigKeybinding(binding) | |
| 159 | + | @ConfigKeybinding(group, binding) | |
| 43 | 160 | } | |
| 44 | 161 | </ul> | |
| 45 | 162 | } | |
| @@ -47,21 +164,28 @@ templ ConfigKeybindingGroup(group renderedKeybindingGroup) { | |||
| 47 | 164 | </div> | |
| 48 | 165 | } | |
| 49 | 166 | ||
| 50 | - | templ ConfigKeybinding(binding renderedKeybinding) { | |
| 167 | + | templ ConfigKeybinding(group renderedKeybindingGroup, binding renderedKeybinding) { | |
| 51 | 168 | <li class="sv-list-row"> | |
| 52 | 169 | <div class="sv-keybinding-row"> | |
| 53 | 170 | <div> | |
| 54 | 171 | <strong>{ keybindingDescription(binding) }</strong> | |
| 55 | 172 | <p class="sv-meta">{ keybindingAction(binding) }</p> | |
| 173 | + | <div class="sv-binding-keys"> | |
| 174 | + | @KeyList(binding.Keys) | |
| 175 | + | <span class="sv-badge">{ keybindingStatus(binding) }</span> | |
| 176 | + | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | |
| 177 | + | <span class="sv-meta">default:</span> | |
| 178 | + | @KeyList(binding.DefaultKeys) | |
| 179 | + | } | |
| 180 | + | </div> | |
| 56 | 181 | </div> | |
| 57 | - | <div class="sv-keybinding-keys"> | |
| 58 | - | @KeyList(binding.Keys) | |
| 59 | - | <span class="sv-badge">{ keybindingStatus(binding) }</span> | |
| 60 | - | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | |
| 61 | - | <span class="sv-meta">default:</span> | |
| 62 | - | @KeyList(binding.DefaultKeys) | |
| 63 | - | } | |
| 64 | - | </div> | |
| 182 | + | <form class="sv-inline-form" data-sv-action="config.keybinding.set"> | |
| 183 | + | <input type="hidden" name="mode" value={ group.Mode }/> | |
| 184 | + | <input type="hidden" name="action" value={ binding.Action }/> | |
| 185 | + | <label><span>Keys</span><input name="keys" type="text" value={ keybindingKeysValue(binding.Keys) } placeholder="ctrl+h" required/></label> | |
| 186 | + | <button class="sv-button sv-button-secondary" type="submit">Save</button> | |
| 187 | + | <button class="sv-button sv-button-secondary" type="button" data-sv-action="config.keybinding.reset" data-mode={ group.Mode } data-action={ binding.Action }>Reset</button> | |
| 188 | + | </form> | |
| 65 | 189 | </div> | |
| 66 | 190 | </li> | |
| 67 | 191 | } | |
| @@ -1,17 +1,134 @@ | |||||
| 1 | package systemviews | 1 | package systemviews | ||
| 2 | 2 | ||||
| 3 | + | import "github.com/bnema/dumber/internal/application/port" | |||
| 4 | + | ||||
| 3 | templ ConfigView(data configRenderData) { | 5 | templ ConfigView(data configRenderData) { | ||
| 4 | - | @Section("sv-config-values", "Config values") { | 6 | + | @Alert("success", data.Notice) |
| 5 | - | @KV(flattenValues(data.Config)) | 7 | + | @Alert("error", data.Error) |
| 8 | + | @Section("sv-config-appearance", "Appearance") { | |||
| 9 | + | @AppearanceForm(data.Config) | |||
| 10 | + | } | |||
| 11 | + | @Section("sv-config-search", "Search") { | |||
| 12 | + | @SearchSettings(data.Config) | |||
| 13 | + | } | |||
| 14 | + | @Section("sv-config-performance", "Performance") { | |||
| 15 | + | @PerformanceSettings(data.Config) | |||
| 6 | } | 16 | } | ||
| 7 | @Section("sv-config-keybindings", "Keybindings") { | 17 | @Section("sv-config-keybindings", "Keybindings") { | ||
| 8 | @Meta(configKeybindingSummary(data.Keybindings)) | 18 | @Meta(configKeybindingSummary(data.Keybindings)) | ||
| 9 | @ConfigKeybindings(data.Keybindings) | 19 | @ConfigKeybindings(data.Keybindings) | ||
| 10 | } | 20 | } | ||
| 21 | + | @Section("sv-config-values", "Current payload") { | |||
| 22 | + | @KV(flattenValues(data.Config)) | |||
| 23 | + | } | |||
| 24 | + | } | |||
| 25 | + | ||||
| 26 | + | templ AppearanceForm(config port.SystemviewConfigPayload) { | |||
| 27 | + | <form class="sv-card-form sv-config-form" data-sv-action="config.appearance.save"> | |||
| 28 | + | <label><span>Sans font</span><input name="sans_font" type="text" value={ config.Appearance.SansFont } required/></label> | |||
| 29 | + | <label><span>Serif font</span><input name="serif_font" type="text" value={ config.Appearance.SerifFont } required/></label> | |||
| 30 | + | <label><span>Monospace font</span><input name="monospace_font" type="text" value={ config.Appearance.MonospaceFont } required/></label> | |||
| 31 | + | <label><span>Default font size</span><input name="default_font_size" type="number" min="1" max="72" value={ formatConfigInt(config.Appearance.DefaultFontSize) } required/></label> | |||
| 32 | + | <label><span>UI scale</span><input name="default_ui_scale" type="number" min="0.5" max="3" step="0.05" value={ formatConfigFloat(config.DefaultUIScale) } required/></label> | |||
| 33 | + | <label><span>Color scheme</span><select name="color_scheme"> | |||
| 34 | + | <option value="default" selected?={ colorSchemeSelected(config.Appearance.ColorScheme, "default") }>System default</option> | |||
| 35 | + | <option value="prefer-light" selected?={ colorSchemeSelected(config.Appearance.ColorScheme, "prefer-light") }>Prefer light</option> | |||
| 36 | + | <option value="prefer-dark" selected?={ colorSchemeSelected(config.Appearance.ColorScheme, "prefer-dark") }>Prefer dark</option> | |||
| 37 | + | </select></label> | |||
| 38 | + | @PaletteFields("Light palette", "light", config.Appearance.LightPalette) | |||
| 39 | + | @PaletteFields("Dark palette", "dark", config.Appearance.DarkPalette) | |||
| 40 | + | <div class="sv-button-row sv-form-actions"> | |||
| 41 | + | <button class="sv-button" type="submit">Save appearance</button> | |||
| 42 | + | <button class="sv-button sv-button-secondary" type="button" data-sv-action="config.appearance.reset" data-sv-confirm="Reset appearance settings to defaults?">Reset appearance</button> | |||
| 43 | + | </div> | |||
| 44 | + | </form> | |||
| 45 | + | } | |||
| 46 | + | ||||
| 47 | + | templ PaletteFields(title string, prefix string, palette port.ColorPalette) { | |||
| 48 | + | <fieldset class="sv-fieldset"> | |||
| 49 | + | <legend>{ title }</legend> | |||
| 50 | + | <label><span>Background</span><input name={ prefix + "_background" } type="text" value={ palette.Background } required/></label> | |||
| 51 | + | <label><span>Surface</span><input name={ prefix + "_surface" } type="text" value={ palette.Surface } required/></label> | |||
| 52 | + | <label><span>Surface variant</span><input name={ prefix + "_surface_variant" } type="text" value={ palette.SurfaceVariant } required/></label> | |||
| 53 | + | <label><span>Text</span><input name={ prefix + "_text" } type="text" value={ palette.Text } required/></label> | |||
| 54 | + | <label><span>Muted</span><input name={ prefix + "_muted" } type="text" value={ palette.Muted } required/></label> | |||
| 55 | + | <label><span>Accent</span><input name={ prefix + "_accent" } type="text" value={ palette.Accent } required/></label> | |||
| 56 | + | <label><span>Border</span><input name={ prefix + "_border" } type="text" value={ palette.Border } required/></label> | |||
| 57 | + | </fieldset> | |||
| 58 | + | } | |||
| 59 | + | ||||
| 60 | + | templ SearchSettings(config port.SystemviewConfigPayload) { | |||
| 61 | + | <form class="sv-card-form" data-sv-action="config.search.save"> | |||
| 62 | + | <label><span>Default search engine</span><input name="default_search_engine" type="text" value={ config.DefaultSearchEngine } placeholder="https://duckduckgo.com/?q=%s" required/></label> | |||
| 63 | + | <button class="sv-button" type="submit">Save search default</button> | |||
| 64 | + | </form> | |||
| 65 | + | <div class="sv-group"> | |||
| 66 | + | <div class="sv-group-header"><h4>Search shortcuts</h4></div> | |||
| 67 | + | <p class="sv-meta">Shortcut URLs must include the %s placeholder for the search query.</p> | |||
| 68 | + | <form class="sv-inline-form" data-sv-action="config.searchShortcut.create"> | |||
| 69 | + | <label><span>Key</span><input name="key" type="text" placeholder="ddg" required/></label> | |||
| 70 | + | <label><span>URL</span><input name="url" type="text" placeholder="https://duckduckgo.com/?q=%s" required/></label> | |||
| 71 | + | <label><span>Description</span><input name="description" type="text" placeholder="DuckDuckGo" required/></label> | |||
| 72 | + | <button class="sv-button sv-button-secondary" type="submit">Add shortcut</button> | |||
| 73 | + | </form> | |||
| 74 | + | if len(searchShortcutRows(config.SearchShortcuts)) == 0 { | |||
| 75 | + | @EmptyState("No search shortcuts configured") | |||
| 76 | + | } else { | |||
| 77 | + | <ul class="sv-list"> | |||
| 78 | + | for _, shortcut := range searchShortcutRows(config.SearchShortcuts) { | |||
| 79 | + | @SearchShortcutItem(shortcut) | |||
| 80 | + | } | |||
| 81 | + | </ul> | |||
| 82 | + | } | |||
| 83 | + | </div> | |||
| 84 | + | } | |||
| 85 | + | ||||
| 86 | + | templ SearchShortcutItem(shortcut searchShortcutRow) { | |||
| 87 | + | <li class="sv-list-row"> | |||
| 88 | + | <form class="sv-inline-form" data-sv-action="config.searchShortcut.update"> | |||
| 89 | + | <input type="hidden" name="key" value={ shortcut.Key }/> | |||
| 90 | + | <label><span>Key</span><input name="new_key" type="text" value={ shortcut.Key } required/></label> | |||
| 91 | + | <label><span>URL</span><input name="url" type="text" value={ shortcut.URL } required/></label> | |||
| 92 | + | <label><span>Description</span><input name="description" type="text" value={ shortcut.Description } required/></label> | |||
| 93 | + | <button class="sv-button sv-button-secondary" type="submit">Save</button> | |||
| 94 | + | <button class="sv-button sv-button-secondary sv-button-danger" type="button" data-sv-action="config.searchShortcut.delete" data-key={ shortcut.Key } data-sv-confirm="Delete this search shortcut?">Delete</button> | |||
| 95 | + | </form> | |||
| 96 | + | </li> | |||
| 97 | + | } | |||
| 98 | + | ||||
| 99 | + | templ PerformanceSettings(config port.SystemviewConfigPayload) { | |||
| 100 | + | <form class="sv-card-form sv-config-form" data-sv-action="config.performance.save"> | |||
| 101 | + | <label><span>Profile</span><select name="profile"> | |||
| 102 | + | <option value="default" selected?={ performanceProfileSelected(config.Performance.Profile, "default") }>Default</option> | |||
| 103 | + | <option value="lite" selected?={ performanceProfileSelected(config.Performance.Profile, "lite") }>Lite</option> | |||
| 104 | + | <option value="max" selected?={ performanceProfileSelected(config.Performance.Profile, "max") }>Max</option> | |||
| 105 | + | <option value="custom" selected?={ performanceProfileSelected(config.Performance.Profile, "custom") }>Custom</option> | |||
| 106 | + | </select></label> | |||
| 107 | + | <label><span>Skia CPU threads</span><input name="skia_cpu_threads" type="number" min="0" max="8" value={ formatConfigInt(config.Performance.Custom.SkiaCPUThreads) }/></label> | |||
| 108 | + | <label><span>Skia GPU threads</span><input name="skia_gpu_threads" type="number" min="-1" max="8" value={ formatConfigInt(config.Performance.Custom.SkiaGPUThreads) }/></label> | |||
| 109 | + | <label><span>Web process memory MB</span><input name="web_process_memory_mb" type="number" min="0" max="16384" value={ formatConfigInt(config.Performance.Custom.WebProcessMemoryMB) }/></label> | |||
| 110 | + | <label><span>Network process memory MB</span><input name="network_process_memory_mb" type="number" min="0" max="4096" value={ formatConfigInt(config.Performance.Custom.NetworkProcessMemoryMB) }/></label> | |||
| 111 | + | <label><span>WebView pool prewarm</span><input name="webview_pool_prewarm" type="number" min="0" max="20" value={ formatConfigInt(config.Performance.Custom.WebViewPoolPrewarm) }/></label> | |||
| 112 | + | <button class="sv-button" type="submit">Save performance</button> | |||
| 113 | + | </form> | |||
| 114 | + | <div class="sv-stat-grid"> | |||
| 115 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ formatConfigInt(config.Performance.Hardware.CPUThreads) }</span><span class="sv-stat-label">CPU threads</span></div> | |||
| 116 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ formatConfigInt(config.Performance.Hardware.TotalRAMMB) }</span><span class="sv-stat-label">RAM MB</span></div> | |||
| 117 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ config.Performance.Hardware.GPUName }</span><span class="sv-stat-label">GPU</span></div> | |||
| 118 | + | <div class="sv-stat-card"><span class="sv-stat-value">{ config.EngineType }</span><span class="sv-stat-label">Engine</span></div> | |||
| 119 | + | </div> | |||
| 120 | + | if !engineIsWebKit(config.EngineType) { | |||
| 121 | + | <p class="sv-meta">Performance tuning applies only to the WebKit engine.</p> | |||
| 122 | + | } else { | |||
| 123 | + | <p class="sv-meta">Performance profile changes may require restarting the browser to affect existing engine processes.</p> | |||
| 124 | + | } | |||
| 11 | } | 125 | } | ||
| 12 | 126 | ||||
| 13 | templ ConfigKeybindings(keybindings any) { | 127 | templ ConfigKeybindings(keybindings any) { | ||
| 14 | {{ groups := configKeybindingGroups(keybindings) }} | 128 | {{ groups := configKeybindingGroups(keybindings) }} | ||
| 129 | + | <div class="sv-button-row"> | |||
| 130 | + | <button class="sv-button sv-button-secondary sv-button-danger" type="button" data-sv-action="config.keybinding.resetAll" data-sv-confirm="Reset all keybindings to defaults?">Reset all keybindings</button> | |||
| 131 | + | </div> | |||
| 15 | if groups == nil { | 132 | if groups == nil { | ||
| 16 | @EmptyState("Keybindings unavailable") | 133 | @EmptyState("Keybindings unavailable") | ||
| 17 | } else if len(groups) == 0 { | 134 | } else if len(groups) == 0 { | ||
| @@ -39,7 +156,7 @@ templ ConfigKeybindingGroup(group renderedKeybindingGroup) { | |||||
| 39 | } else { | 156 | } else { | ||
| 40 | <ul class="sv-list"> | 157 | <ul class="sv-list"> | ||
| 41 | for _, binding := range group.Bindings { | 158 | for _, binding := range group.Bindings { | ||
| 42 | - | @ConfigKeybinding(binding) | 159 | + | @ConfigKeybinding(group, binding) |
| 43 | } | 160 | } | ||
| 44 | </ul> | 161 | </ul> | ||
| 45 | } | 162 | } | ||
| @@ -47,21 +164,28 @@ templ ConfigKeybindingGroup(group renderedKeybindingGroup) { | |||||
| 47 | </div> | 164 | </div> | ||
| 48 | } | 165 | } | ||
| 49 | 166 | ||||
| 50 | - | templ ConfigKeybinding(binding renderedKeybinding) { | 167 | + | templ ConfigKeybinding(group renderedKeybindingGroup, binding renderedKeybinding) { |
| 51 | <li class="sv-list-row"> | 168 | <li class="sv-list-row"> | ||
| 52 | <div class="sv-keybinding-row"> | 169 | <div class="sv-keybinding-row"> | ||
| 53 | <div> | 170 | <div> | ||
| 54 | <strong>{ keybindingDescription(binding) }</strong> | 171 | <strong>{ keybindingDescription(binding) }</strong> | ||
| 55 | <p class="sv-meta">{ keybindingAction(binding) }</p> | 172 | <p class="sv-meta">{ keybindingAction(binding) }</p> | ||
| 173 | + | <div class="sv-binding-keys"> | |||
| 174 | + | @KeyList(binding.Keys) | |||
| 175 | + | <span class="sv-badge">{ keybindingStatus(binding) }</span> | |||
| 176 | + | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | |||
| 177 | + | <span class="sv-meta">default:</span> | |||
| 178 | + | @KeyList(binding.DefaultKeys) | |||
| 179 | + | } | |||
| 180 | + | </div> | |||
| 56 | </div> | 181 | </div> | ||
| 57 | - | <div class="sv-keybinding-keys"> | 182 | + | <form class="sv-inline-form" data-sv-action="config.keybinding.set"> |
| 58 | - | @KeyList(binding.Keys) | 183 | + | <input type="hidden" name="mode" value={ group.Mode }/> |
| 59 | - | <span class="sv-badge">{ keybindingStatus(binding) }</span> | 184 | + | <input type="hidden" name="action" value={ binding.Action }/> |
| 60 | - | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | 185 | + | <label><span>Keys</span><input name="keys" type="text" value={ keybindingKeysValue(binding.Keys) } placeholder="ctrl+h" required/></label> |
| 61 | - | <span class="sv-meta">default:</span> | 186 | + | <button class="sv-button sv-button-secondary" type="submit">Save</button> |
| 62 | - | @KeyList(binding.DefaultKeys) | 187 | + | <button class="sv-button sv-button-secondary" type="button" data-sv-action="config.keybinding.reset" data-mode={ group.Mode } data-action={ binding.Action }>Reset</button> |
| 63 | - | } | 188 | + | </form> |
| 64 | - | </div> | |||
| 65 | </div> | 189 | </div> | ||
| 66 | </li> | 190 | </li> | ||
| 67 | } | 191 | } | ||
A internal/ui/systemviews/config_actions.go +434 -0
| @@ -0,0 +1,434 @@ | |||
| 1 | + | package systemviews | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "context" | |
| 5 | + | "fmt" | |
| 6 | + | "strconv" | |
| 7 | + | "strings" | |
| 8 | + | ||
| 9 | + | "github.com/bnema/dumber/internal/application/port" | |
| 10 | + | ) | |
| 11 | + | ||
| 12 | + | const ( | |
| 13 | + | configActionSaveAppearance = "config.appearance.save" | |
| 14 | + | configActionResetAppearance = "config.appearance.reset" | |
| 15 | + | configActionSaveSearch = "config.search.save" | |
| 16 | + | configActionCreateSearchShortcut = "config.searchShortcut.create" | |
| 17 | + | configActionUpdateSearchShortcut = "config.searchShortcut.update" | |
| 18 | + | configActionDeleteSearchShortcut = "config.searchShortcut.delete" | |
| 19 | + | configActionSavePerformance = "config.performance.save" | |
| 20 | + | configActionSetKeybinding = "config.keybinding.set" | |
| 21 | + | configActionResetKeybinding = "config.keybinding.reset" | |
| 22 | + | configActionResetAllKeybindings = "config.keybinding.resetAll" | |
| 23 | + | configRequestIDPrefix = "systemviews-config" | |
| 24 | + | ) | |
| 25 | + | ||
| 26 | + | func (a *App) handleConfigAction(ctx context.Context, event DOMAction) error { | |
| 27 | + | if a.deps.Config == nil { | |
| 28 | + | return fmt.Errorf("config service not configured") | |
| 29 | + | } | |
| 30 | + | ||
| 31 | + | switch event.Action { | |
| 32 | + | case configActionSaveAppearance: | |
| 33 | + | return a.saveAppearanceConfig(ctx, event.Data) | |
| 34 | + | case configActionResetAppearance: | |
| 35 | + | return a.resetAppearanceConfig(ctx) | |
| 36 | + | case configActionSaveSearch: | |
| 37 | + | return a.saveSearchConfig(ctx, event.Data) | |
| 38 | + | case configActionCreateSearchShortcut: | |
| 39 | + | return a.createSearchShortcut(ctx, event.Data) | |
| 40 | + | case configActionUpdateSearchShortcut: | |
| 41 | + | return a.updateSearchShortcut(ctx, event.Data) | |
| 42 | + | case configActionDeleteSearchShortcut: | |
| 43 | + | return a.deleteSearchShortcut(ctx, event.Data) | |
| 44 | + | case configActionSavePerformance: | |
| 45 | + | return a.savePerformanceConfig(ctx, event.Data) | |
| 46 | + | case configActionSetKeybinding: | |
| 47 | + | return a.setConfigKeybinding(ctx, event.Data) | |
| 48 | + | case configActionResetKeybinding: | |
| 49 | + | return a.resetConfigKeybinding(ctx, event.Data) | |
| 50 | + | case configActionResetAllKeybindings: | |
| 51 | + | if err := a.deps.Config.ResetAllKeybindings(ctx); err != nil { | |
| 52 | + | return err | |
| 53 | + | } | |
| 54 | + | a.configNotice = "Reset all keybindings to defaults" | |
| 55 | + | } | |
| 56 | + | return nil | |
| 57 | + | } | |
| 58 | + | ||
| 59 | + | func (a *App) saveAppearanceConfig(ctx context.Context, data map[string]string) error { | |
| 60 | + | cfg, err := a.editableConfig(ctx) | |
| 61 | + | if err != nil { | |
| 62 | + | return err | |
| 63 | + | } | |
| 64 | + | ||
| 65 | + | fontSize, err := parseConfigInt(data["default_font_size"], "default font size") | |
| 66 | + | if err != nil { | |
| 67 | + | return err | |
| 68 | + | } | |
| 69 | + | uiScale, err := parseConfigFloat(data["default_ui_scale"], "UI scale") | |
| 70 | + | if err != nil { | |
| 71 | + | return err | |
| 72 | + | } | |
| 73 | + | ||
| 74 | + | cfg.Appearance.SansFont = strings.TrimSpace(data["sans_font"]) | |
| 75 | + | cfg.Appearance.SerifFont = strings.TrimSpace(data["serif_font"]) | |
| 76 | + | cfg.Appearance.MonospaceFont = strings.TrimSpace(data["monospace_font"]) | |
| 77 | + | cfg.Appearance.DefaultFontSize = fontSize | |
| 78 | + | cfg.Appearance.ColorScheme = strings.TrimSpace(data["color_scheme"]) | |
| 79 | + | cfg.Appearance.LightPalette = paletteFromForm(data, "light") | |
| 80 | + | cfg.Appearance.DarkPalette = paletteFromForm(data, "dark") | |
| 81 | + | cfg.DefaultUIScale = uiScale | |
| 82 | + | ||
| 83 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 84 | + | return err | |
| 85 | + | } | |
| 86 | + | a.configNotice = "Saved appearance settings" | |
| 87 | + | return nil | |
| 88 | + | } | |
| 89 | + | ||
| 90 | + | func (a *App) resetAppearanceConfig(ctx context.Context) error { | |
| 91 | + | cfg, err := a.editableConfig(ctx) | |
| 92 | + | if err != nil { | |
| 93 | + | return err | |
| 94 | + | } | |
| 95 | + | defaults, err := a.deps.Config.Default(ctx) | |
| 96 | + | if err != nil { | |
| 97 | + | return err | |
| 98 | + | } | |
| 99 | + | cfg.Appearance = defaults.Appearance | |
| 100 | + | cfg.DefaultUIScale = defaults.DefaultUIScale | |
| 101 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 102 | + | return err | |
| 103 | + | } | |
| 104 | + | a.configNotice = "Reset appearance settings to defaults" | |
| 105 | + | return nil | |
| 106 | + | } | |
| 107 | + | ||
| 108 | + | func (a *App) saveSearchConfig(ctx context.Context, data map[string]string) error { | |
| 109 | + | cfg, err := a.editableConfig(ctx) | |
| 110 | + | if err != nil { | |
| 111 | + | return err | |
| 112 | + | } | |
| 113 | + | cfg.DefaultSearchEngine = strings.TrimSpace(data["default_search_engine"]) | |
| 114 | + | if err := validateSearchURL(cfg.DefaultSearchEngine, "default search engine"); err != nil { | |
| 115 | + | return err | |
| 116 | + | } | |
| 117 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 118 | + | return err | |
| 119 | + | } | |
| 120 | + | a.configNotice = "Saved default search engine" | |
| 121 | + | return nil | |
| 122 | + | } | |
| 123 | + | ||
| 124 | + | func (a *App) createSearchShortcut(ctx context.Context, data map[string]string) error { | |
| 125 | + | cfg, err := a.editableConfig(ctx) | |
| 126 | + | if err != nil { | |
| 127 | + | return err | |
| 128 | + | } | |
| 129 | + | key, shortcut, err := searchShortcutFromForm(data, "key") | |
| 130 | + | if err != nil { | |
| 131 | + | return err | |
| 132 | + | } | |
| 133 | + | cfg.SearchShortcuts = cloneSearchShortcuts(cfg.SearchShortcuts) | |
| 134 | + | if _, exists := cfg.SearchShortcuts[key]; exists { | |
| 135 | + | return fmt.Errorf("search shortcut %q already exists", key) | |
| 136 | + | } | |
| 137 | + | cfg.SearchShortcuts[key] = shortcut | |
| 138 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 139 | + | return err | |
| 140 | + | } | |
| 141 | + | a.configNotice = "Created search shortcut " + key | |
| 142 | + | return nil | |
| 143 | + | } | |
| 144 | + | ||
| 145 | + | func (a *App) updateSearchShortcut(ctx context.Context, data map[string]string) error { | |
| 146 | + | cfg, err := a.editableConfig(ctx) | |
| 147 | + | if err != nil { | |
| 148 | + | return err | |
| 149 | + | } | |
| 150 | + | oldKey := strings.TrimSpace(data["key"]) | |
| 151 | + | if oldKey == "" { | |
| 152 | + | return fmt.Errorf("search shortcut key is required") | |
| 153 | + | } | |
| 154 | + | newKey, shortcut, err := searchShortcutFromForm(data, "new_key") | |
| 155 | + | if err != nil { | |
| 156 | + | return err | |
| 157 | + | } | |
| 158 | + | cfg.SearchShortcuts = cloneSearchShortcuts(cfg.SearchShortcuts) | |
| 159 | + | if _, exists := cfg.SearchShortcuts[oldKey]; !exists { | |
| 160 | + | return fmt.Errorf("search shortcut %q not found", oldKey) | |
| 161 | + | } | |
| 162 | + | if newKey != oldKey { | |
| 163 | + | if _, exists := cfg.SearchShortcuts[newKey]; exists { | |
| 164 | + | return fmt.Errorf("search shortcut %q already exists", newKey) | |
| 165 | + | } | |
| 166 | + | delete(cfg.SearchShortcuts, oldKey) | |
| 167 | + | } | |
| 168 | + | cfg.SearchShortcuts[newKey] = shortcut | |
| 169 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 170 | + | return err | |
| 171 | + | } | |
| 172 | + | a.configNotice = "Saved search shortcut " + newKey | |
| 173 | + | return nil | |
| 174 | + | } | |
| 175 | + | ||
| 176 | + | func (a *App) deleteSearchShortcut(ctx context.Context, data map[string]string) error { | |
| 177 | + | cfg, err := a.editableConfig(ctx) | |
| 178 | + | if err != nil { | |
| 179 | + | return err | |
| 180 | + | } | |
| 181 | + | key := strings.TrimSpace(data["key"]) | |
| 182 | + | if key == "" { | |
| 183 | + | return fmt.Errorf("search shortcut key is required") | |
| 184 | + | } | |
| 185 | + | cfg.SearchShortcuts = cloneSearchShortcuts(cfg.SearchShortcuts) | |
| 186 | + | delete(cfg.SearchShortcuts, key) | |
| 187 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 188 | + | return err | |
| 189 | + | } | |
| 190 | + | a.configNotice = "Deleted search shortcut " + key | |
| 191 | + | return nil | |
| 192 | + | } | |
| 193 | + | ||
| 194 | + | func (a *App) savePerformanceConfig(ctx context.Context, data map[string]string) error { | |
| 195 | + | cfg, err := a.editableConfig(ctx) | |
| 196 | + | if err != nil { | |
| 197 | + | return err | |
| 198 | + | } | |
| 199 | + | profile := strings.TrimSpace(data["profile"]) | |
| 200 | + | if !validPerformanceProfile(profile) { | |
| 201 | + | return fmt.Errorf("invalid performance profile") | |
| 202 | + | } | |
| 203 | + | skiaCPU, err := parseConfigInt(data["skia_cpu_threads"], "Skia CPU threads") | |
| 204 | + | if err != nil { | |
| 205 | + | return err | |
| 206 | + | } | |
| 207 | + | skiaGPU, err := parseConfigInt(data["skia_gpu_threads"], "Skia GPU threads") | |
| 208 | + | if err != nil { | |
| 209 | + | return err | |
| 210 | + | } | |
| 211 | + | webMemory, err := parseConfigInt(data["web_process_memory_mb"], "web process memory") | |
| 212 | + | if err != nil { | |
| 213 | + | return err | |
| 214 | + | } | |
| 215 | + | networkMemory, err := parseConfigInt(data["network_process_memory_mb"], "network process memory") | |
| 216 | + | if err != nil { | |
| 217 | + | return err | |
| 218 | + | } | |
| 219 | + | prewarm, err := parseConfigInt(data["webview_pool_prewarm"], "WebView pool prewarm") | |
| 220 | + | if err != nil { | |
| 221 | + | return err | |
| 222 | + | } | |
| 223 | + | ||
| 224 | + | cfg.Performance.Profile = profile | |
| 225 | + | cfg.Performance.Custom = port.WebUICustomPerformanceConfig{ | |
| 226 | + | SkiaCPUThreads: skiaCPU, | |
| 227 | + | SkiaGPUThreads: skiaGPU, | |
| 228 | + | WebProcessMemoryMB: webMemory, | |
| 229 | + | NetworkProcessMemoryMB: networkMemory, | |
| 230 | + | WebViewPoolPrewarm: prewarm, | |
| 231 | + | } | |
| 232 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |
| 233 | + | return err | |
| 234 | + | } | |
| 235 | + | a.configNotice = "Saved performance settings. Restart may be required." | |
| 236 | + | return nil | |
| 237 | + | } | |
| 238 | + | ||
| 239 | + | func (a *App) setConfigKeybinding(ctx context.Context, data map[string]string) error { | |
| 240 | + | mode := strings.TrimSpace(data["mode"]) | |
| 241 | + | action := strings.TrimSpace(data["action"]) | |
| 242 | + | keys := parseKeyList(data["keys"]) | |
| 243 | + | if mode == "" || action == "" { | |
| 244 | + | return fmt.Errorf("mode and action are required") | |
| 245 | + | } | |
| 246 | + | resp, err := a.deps.Config.SetKeybinding(ctx, port.SetKeybindingRequest{ | |
| 247 | + | RequestID: configRequestIDPrefix, | |
| 248 | + | Mode: mode, | |
| 249 | + | Action: action, | |
| 250 | + | Keys: keys, | |
| 251 | + | }) | |
| 252 | + | if err != nil { | |
| 253 | + | return err | |
| 254 | + | } | |
| 255 | + | if conflicts := keybindingConflictCount(resp); conflicts > 0 { | |
| 256 | + | a.configNotice = fmt.Sprintf("Saved keybinding with %d conflict(s)", conflicts) | |
| 257 | + | return nil | |
| 258 | + | } | |
| 259 | + | a.configNotice = "Saved keybinding " + action | |
| 260 | + | return nil | |
| 261 | + | } | |
| 262 | + | ||
| 263 | + | func (a *App) resetConfigKeybinding(ctx context.Context, data map[string]string) error { | |
| 264 | + | mode := strings.TrimSpace(data["mode"]) | |
| 265 | + | action := strings.TrimSpace(data["action"]) | |
| 266 | + | if mode == "" || action == "" { | |
| 267 | + | return fmt.Errorf("mode and action are required") | |
| 268 | + | } | |
| 269 | + | if err := a.deps.Config.ResetKeybinding(ctx, port.ResetKeybindingRequest{ | |
| 270 | + | RequestID: configRequestIDPrefix, | |
| 271 | + | Mode: mode, | |
| 272 | + | Action: action, | |
| 273 | + | }); err != nil { | |
| 274 | + | return err | |
| 275 | + | } | |
| 276 | + | a.configNotice = "Reset keybinding " + action | |
| 277 | + | return nil | |
| 278 | + | } | |
| 279 | + | ||
| 280 | + | func (a *App) editableConfig(ctx context.Context) (port.WebUIConfig, error) { | |
| 281 | + | payload, err := a.currentConfigPayload(ctx) | |
| 282 | + | if err != nil { | |
| 283 | + | return port.WebUIConfig{}, err | |
| 284 | + | } | |
| 285 | + | return webUIConfigFromPayload(payload), nil | |
| 286 | + | } | |
| 287 | + | ||
| 288 | + | func (a *App) currentConfigPayload(ctx context.Context) (port.SystemviewConfigPayload, error) { | |
| 289 | + | if a.config != nil { | |
| 290 | + | return *a.config, nil | |
| 291 | + | } | |
| 292 | + | cfg, err := a.deps.Config.Current(ctx) | |
| 293 | + | if err != nil { | |
| 294 | + | return port.SystemviewConfigPayload{}, err | |
| 295 | + | } | |
| 296 | + | a.config = &cfg | |
| 297 | + | return cfg, nil | |
| 298 | + | } | |
| 299 | + | ||
| 300 | + | func (a *App) saveEditableConfig(ctx context.Context, cfg port.WebUIConfig) error { | |
| 301 | + | if err := a.deps.Config.Save(ctx, cfg); err != nil { | |
| 302 | + | return err | |
| 303 | + | } | |
| 304 | + | a.config = nil | |
| 305 | + | return nil | |
| 306 | + | } | |
| 307 | + | ||
| 308 | + | func webUIConfigFromPayload(payload port.SystemviewConfigPayload) port.WebUIConfig { | |
| 309 | + | return port.WebUIConfig{ | |
| 310 | + | Appearance: payload.Appearance, | |
| 311 | + | DefaultUIScale: payload.DefaultUIScale, | |
| 312 | + | DefaultSearchEngine: payload.DefaultSearchEngine, | |
| 313 | + | SearchShortcuts: cloneSearchShortcuts(payload.SearchShortcuts), | |
| 314 | + | Performance: port.WebUIPerformanceConfig{ | |
| 315 | + | Profile: payload.Performance.Profile, | |
| 316 | + | Custom: port.WebUICustomPerformanceConfig{ | |
| 317 | + | SkiaCPUThreads: payload.Performance.Custom.SkiaCPUThreads, | |
| 318 | + | SkiaGPUThreads: payload.Performance.Custom.SkiaGPUThreads, | |
| 319 | + | WebProcessMemoryMB: payload.Performance.Custom.WebProcessMemoryMB, | |
| 320 | + | NetworkProcessMemoryMB: payload.Performance.Custom.NetworkProcessMemoryMB, | |
| 321 | + | WebViewPoolPrewarm: payload.Performance.Custom.WebViewPoolPrewarm, | |
| 322 | + | }, | |
| 323 | + | }, | |
| 324 | + | } | |
| 325 | + | } | |
| 326 | + | ||
| 327 | + | func cloneSearchShortcuts(shortcuts map[string]port.SearchShortcut) map[string]port.SearchShortcut { | |
| 328 | + | clone := make(map[string]port.SearchShortcut, len(shortcuts)) | |
| 329 | + | for key, shortcut := range shortcuts { | |
| 330 | + | clone[key] = shortcut | |
| 331 | + | } | |
| 332 | + | return clone | |
| 333 | + | } | |
| 334 | + | ||
| 335 | + | func paletteFromForm(data map[string]string, prefix string) port.ColorPalette { | |
| 336 | + | return port.ColorPalette{ | |
| 337 | + | Background: strings.TrimSpace(data[prefix+"_background"]), | |
| 338 | + | Surface: strings.TrimSpace(data[prefix+"_surface"]), | |
| 339 | + | SurfaceVariant: strings.TrimSpace(data[prefix+"_surface_variant"]), | |
| 340 | + | Text: strings.TrimSpace(data[prefix+"_text"]), | |
| 341 | + | Muted: strings.TrimSpace(data[prefix+"_muted"]), | |
| 342 | + | Accent: strings.TrimSpace(data[prefix+"_accent"]), | |
| 343 | + | Border: strings.TrimSpace(data[prefix+"_border"]), | |
| 344 | + | } | |
| 345 | + | } | |
| 346 | + | ||
| 347 | + | func searchShortcutFromForm(data map[string]string, keyField string) (string, port.SearchShortcut, error) { | |
| 348 | + | key := strings.TrimSpace(data[keyField]) | |
| 349 | + | url := strings.TrimSpace(data["url"]) | |
| 350 | + | description := strings.TrimSpace(data["description"]) | |
| 351 | + | if key == "" { | |
| 352 | + | return "", port.SearchShortcut{}, fmt.Errorf("search shortcut key is required") | |
| 353 | + | } | |
| 354 | + | if description == "" { | |
| 355 | + | return "", port.SearchShortcut{}, fmt.Errorf("search shortcut description is required") | |
| 356 | + | } | |
| 357 | + | if err := validateSearchURL(url, "search shortcut URL"); err != nil { | |
| 358 | + | return "", port.SearchShortcut{}, err | |
| 359 | + | } | |
| 360 | + | return key, port.SearchShortcut{URL: url, Description: description}, nil | |
| 361 | + | } | |
| 362 | + | ||
| 363 | + | func validateSearchURL(raw, label string) error { | |
| 364 | + | if strings.TrimSpace(raw) == "" { | |
| 365 | + | return fmt.Errorf("%s is required", label) | |
| 366 | + | } | |
| 367 | + | if !strings.Contains(raw, "%s") { | |
| 368 | + | return fmt.Errorf("%s must contain %%s placeholder", label) | |
| 369 | + | } | |
| 370 | + | return nil | |
| 371 | + | } | |
| 372 | + | ||
| 373 | + | func validPerformanceProfile(profile string) bool { | |
| 374 | + | switch profile { | |
| 375 | + | case "default", "lite", "max", "custom", "": | |
| 376 | + | return true | |
| 377 | + | default: | |
| 378 | + | return false | |
| 379 | + | } | |
| 380 | + | } | |
| 381 | + | ||
| 382 | + | func parseConfigInt(raw, label string) (int, error) { | |
| 383 | + | value, err := strconv.Atoi(strings.TrimSpace(raw)) | |
| 384 | + | if err != nil { | |
| 385 | + | return 0, fmt.Errorf("invalid %s", label) | |
| 386 | + | } | |
| 387 | + | return value, nil | |
| 388 | + | } | |
| 389 | + | ||
| 390 | + | func parseConfigFloat(raw, label string) (float64, error) { | |
| 391 | + | value, err := strconv.ParseFloat(strings.TrimSpace(raw), 64) | |
| 392 | + | if err != nil { | |
| 393 | + | return 0, fmt.Errorf("invalid %s", label) | |
| 394 | + | } | |
| 395 | + | return value, nil | |
| 396 | + | } | |
| 397 | + | ||
| 398 | + | func parseKeyList(raw string) []string { | |
| 399 | + | raw = strings.TrimSpace(raw) | |
| 400 | + | if raw == "" { | |
| 401 | + | return nil | |
| 402 | + | } | |
| 403 | + | parts := strings.Split(raw, ",") | |
| 404 | + | if len(parts) == 1 { | |
| 405 | + | parts = strings.Fields(raw) | |
| 406 | + | } | |
| 407 | + | keys := make([]string, 0, len(parts)) | |
| 408 | + | for _, part := range parts { | |
| 409 | + | key := strings.TrimSpace(part) | |
| 410 | + | if key != "" { | |
| 411 | + | keys = append(keys, key) | |
| 412 | + | } | |
| 413 | + | } | |
| 414 | + | return keys | |
| 415 | + | } | |
| 416 | + | ||
| 417 | + | func keybindingConflictCount(resp any) int { | |
| 418 | + | switch v := resp.(type) { | |
| 419 | + | case nil: | |
| 420 | + | return 0 | |
| 421 | + | case port.SetKeybindingResponse: | |
| 422 | + | return len(v.Conflicts) | |
| 423 | + | case *port.SetKeybindingResponse: | |
| 424 | + | if v == nil { | |
| 425 | + | return 0 | |
| 426 | + | } | |
| 427 | + | return len(v.Conflicts) | |
| 428 | + | case map[string]any: | |
| 429 | + | if conflicts, ok := anySlice(v["conflicts"]); ok { | |
| 430 | + | return len(conflicts) | |
| 431 | + | } | |
| 432 | + | } | |
| 433 | + | return 0 | |
| 434 | + | } | |
| @@ -0,0 +1,434 @@ | |||||
| 1 | + | package systemviews | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "context" | |||
| 5 | + | "fmt" | |||
| 6 | + | "strconv" | |||
| 7 | + | "strings" | |||
| 8 | + | ||||
| 9 | + | "github.com/bnema/dumber/internal/application/port" | |||
| 10 | + | ) | |||
| 11 | + | ||||
| 12 | + | const ( | |||
| 13 | + | configActionSaveAppearance = "config.appearance.save" | |||
| 14 | + | configActionResetAppearance = "config.appearance.reset" | |||
| 15 | + | configActionSaveSearch = "config.search.save" | |||
| 16 | + | configActionCreateSearchShortcut = "config.searchShortcut.create" | |||
| 17 | + | configActionUpdateSearchShortcut = "config.searchShortcut.update" | |||
| 18 | + | configActionDeleteSearchShortcut = "config.searchShortcut.delete" | |||
| 19 | + | configActionSavePerformance = "config.performance.save" | |||
| 20 | + | configActionSetKeybinding = "config.keybinding.set" | |||
| 21 | + | configActionResetKeybinding = "config.keybinding.reset" | |||
| 22 | + | configActionResetAllKeybindings = "config.keybinding.resetAll" | |||
| 23 | + | configRequestIDPrefix = "systemviews-config" | |||
| 24 | + | ) | |||
| 25 | + | ||||
| 26 | + | func (a *App) handleConfigAction(ctx context.Context, event DOMAction) error { | |||
| 27 | + | if a.deps.Config == nil { | |||
| 28 | + | return fmt.Errorf("config service not configured") | |||
| 29 | + | } | |||
| 30 | + | ||||
| 31 | + | switch event.Action { | |||
| 32 | + | case configActionSaveAppearance: | |||
| 33 | + | return a.saveAppearanceConfig(ctx, event.Data) | |||
| 34 | + | case configActionResetAppearance: | |||
| 35 | + | return a.resetAppearanceConfig(ctx) | |||
| 36 | + | case configActionSaveSearch: | |||
| 37 | + | return a.saveSearchConfig(ctx, event.Data) | |||
| 38 | + | case configActionCreateSearchShortcut: | |||
| 39 | + | return a.createSearchShortcut(ctx, event.Data) | |||
| 40 | + | case configActionUpdateSearchShortcut: | |||
| 41 | + | return a.updateSearchShortcut(ctx, event.Data) | |||
| 42 | + | case configActionDeleteSearchShortcut: | |||
| 43 | + | return a.deleteSearchShortcut(ctx, event.Data) | |||
| 44 | + | case configActionSavePerformance: | |||
| 45 | + | return a.savePerformanceConfig(ctx, event.Data) | |||
| 46 | + | case configActionSetKeybinding: | |||
| 47 | + | return a.setConfigKeybinding(ctx, event.Data) | |||
| 48 | + | case configActionResetKeybinding: | |||
| 49 | + | return a.resetConfigKeybinding(ctx, event.Data) | |||
| 50 | + | case configActionResetAllKeybindings: | |||
| 51 | + | if err := a.deps.Config.ResetAllKeybindings(ctx); err != nil { | |||
| 52 | + | return err | |||
| 53 | + | } | |||
| 54 | + | a.configNotice = "Reset all keybindings to defaults" | |||
| 55 | + | } | |||
| 56 | + | return nil | |||
| 57 | + | } | |||
| 58 | + | ||||
| 59 | + | func (a *App) saveAppearanceConfig(ctx context.Context, data map[string]string) error { | |||
| 60 | + | cfg, err := a.editableConfig(ctx) | |||
| 61 | + | if err != nil { | |||
| 62 | + | return err | |||
| 63 | + | } | |||
| 64 | + | ||||
| 65 | + | fontSize, err := parseConfigInt(data["default_font_size"], "default font size") | |||
| 66 | + | if err != nil { | |||
| 67 | + | return err | |||
| 68 | + | } | |||
| 69 | + | uiScale, err := parseConfigFloat(data["default_ui_scale"], "UI scale") | |||
| 70 | + | if err != nil { | |||
| 71 | + | return err | |||
| 72 | + | } | |||
| 73 | + | ||||
| 74 | + | cfg.Appearance.SansFont = strings.TrimSpace(data["sans_font"]) | |||
| 75 | + | cfg.Appearance.SerifFont = strings.TrimSpace(data["serif_font"]) | |||
| 76 | + | cfg.Appearance.MonospaceFont = strings.TrimSpace(data["monospace_font"]) | |||
| 77 | + | cfg.Appearance.DefaultFontSize = fontSize | |||
| 78 | + | cfg.Appearance.ColorScheme = strings.TrimSpace(data["color_scheme"]) | |||
| 79 | + | cfg.Appearance.LightPalette = paletteFromForm(data, "light") | |||
| 80 | + | cfg.Appearance.DarkPalette = paletteFromForm(data, "dark") | |||
| 81 | + | cfg.DefaultUIScale = uiScale | |||
| 82 | + | ||||
| 83 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 84 | + | return err | |||
| 85 | + | } | |||
| 86 | + | a.configNotice = "Saved appearance settings" | |||
| 87 | + | return nil | |||
| 88 | + | } | |||
| 89 | + | ||||
| 90 | + | func (a *App) resetAppearanceConfig(ctx context.Context) error { | |||
| 91 | + | cfg, err := a.editableConfig(ctx) | |||
| 92 | + | if err != nil { | |||
| 93 | + | return err | |||
| 94 | + | } | |||
| 95 | + | defaults, err := a.deps.Config.Default(ctx) | |||
| 96 | + | if err != nil { | |||
| 97 | + | return err | |||
| 98 | + | } | |||
| 99 | + | cfg.Appearance = defaults.Appearance | |||
| 100 | + | cfg.DefaultUIScale = defaults.DefaultUIScale | |||
| 101 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 102 | + | return err | |||
| 103 | + | } | |||
| 104 | + | a.configNotice = "Reset appearance settings to defaults" | |||
| 105 | + | return nil | |||
| 106 | + | } | |||
| 107 | + | ||||
| 108 | + | func (a *App) saveSearchConfig(ctx context.Context, data map[string]string) error { | |||
| 109 | + | cfg, err := a.editableConfig(ctx) | |||
| 110 | + | if err != nil { | |||
| 111 | + | return err | |||
| 112 | + | } | |||
| 113 | + | cfg.DefaultSearchEngine = strings.TrimSpace(data["default_search_engine"]) | |||
| 114 | + | if err := validateSearchURL(cfg.DefaultSearchEngine, "default search engine"); err != nil { | |||
| 115 | + | return err | |||
| 116 | + | } | |||
| 117 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 118 | + | return err | |||
| 119 | + | } | |||
| 120 | + | a.configNotice = "Saved default search engine" | |||
| 121 | + | return nil | |||
| 122 | + | } | |||
| 123 | + | ||||
| 124 | + | func (a *App) createSearchShortcut(ctx context.Context, data map[string]string) error { | |||
| 125 | + | cfg, err := a.editableConfig(ctx) | |||
| 126 | + | if err != nil { | |||
| 127 | + | return err | |||
| 128 | + | } | |||
| 129 | + | key, shortcut, err := searchShortcutFromForm(data, "key") | |||
| 130 | + | if err != nil { | |||
| 131 | + | return err | |||
| 132 | + | } | |||
| 133 | + | cfg.SearchShortcuts = cloneSearchShortcuts(cfg.SearchShortcuts) | |||
| 134 | + | if _, exists := cfg.SearchShortcuts[key]; exists { | |||
| 135 | + | return fmt.Errorf("search shortcut %q already exists", key) | |||
| 136 | + | } | |||
| 137 | + | cfg.SearchShortcuts[key] = shortcut | |||
| 138 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 139 | + | return err | |||
| 140 | + | } | |||
| 141 | + | a.configNotice = "Created search shortcut " + key | |||
| 142 | + | return nil | |||
| 143 | + | } | |||
| 144 | + | ||||
| 145 | + | func (a *App) updateSearchShortcut(ctx context.Context, data map[string]string) error { | |||
| 146 | + | cfg, err := a.editableConfig(ctx) | |||
| 147 | + | if err != nil { | |||
| 148 | + | return err | |||
| 149 | + | } | |||
| 150 | + | oldKey := strings.TrimSpace(data["key"]) | |||
| 151 | + | if oldKey == "" { | |||
| 152 | + | return fmt.Errorf("search shortcut key is required") | |||
| 153 | + | } | |||
| 154 | + | newKey, shortcut, err := searchShortcutFromForm(data, "new_key") | |||
| 155 | + | if err != nil { | |||
| 156 | + | return err | |||
| 157 | + | } | |||
| 158 | + | cfg.SearchShortcuts = cloneSearchShortcuts(cfg.SearchShortcuts) | |||
| 159 | + | if _, exists := cfg.SearchShortcuts[oldKey]; !exists { | |||
| 160 | + | return fmt.Errorf("search shortcut %q not found", oldKey) | |||
| 161 | + | } | |||
| 162 | + | if newKey != oldKey { | |||
| 163 | + | if _, exists := cfg.SearchShortcuts[newKey]; exists { | |||
| 164 | + | return fmt.Errorf("search shortcut %q already exists", newKey) | |||
| 165 | + | } | |||
| 166 | + | delete(cfg.SearchShortcuts, oldKey) | |||
| 167 | + | } | |||
| 168 | + | cfg.SearchShortcuts[newKey] = shortcut | |||
| 169 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 170 | + | return err | |||
| 171 | + | } | |||
| 172 | + | a.configNotice = "Saved search shortcut " + newKey | |||
| 173 | + | return nil | |||
| 174 | + | } | |||
| 175 | + | ||||
| 176 | + | func (a *App) deleteSearchShortcut(ctx context.Context, data map[string]string) error { | |||
| 177 | + | cfg, err := a.editableConfig(ctx) | |||
| 178 | + | if err != nil { | |||
| 179 | + | return err | |||
| 180 | + | } | |||
| 181 | + | key := strings.TrimSpace(data["key"]) | |||
| 182 | + | if key == "" { | |||
| 183 | + | return fmt.Errorf("search shortcut key is required") | |||
| 184 | + | } | |||
| 185 | + | cfg.SearchShortcuts = cloneSearchShortcuts(cfg.SearchShortcuts) | |||
| 186 | + | delete(cfg.SearchShortcuts, key) | |||
| 187 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 188 | + | return err | |||
| 189 | + | } | |||
| 190 | + | a.configNotice = "Deleted search shortcut " + key | |||
| 191 | + | return nil | |||
| 192 | + | } | |||
| 193 | + | ||||
| 194 | + | func (a *App) savePerformanceConfig(ctx context.Context, data map[string]string) error { | |||
| 195 | + | cfg, err := a.editableConfig(ctx) | |||
| 196 | + | if err != nil { | |||
| 197 | + | return err | |||
| 198 | + | } | |||
| 199 | + | profile := strings.TrimSpace(data["profile"]) | |||
| 200 | + | if !validPerformanceProfile(profile) { | |||
| 201 | + | return fmt.Errorf("invalid performance profile") | |||
| 202 | + | } | |||
| 203 | + | skiaCPU, err := parseConfigInt(data["skia_cpu_threads"], "Skia CPU threads") | |||
| 204 | + | if err != nil { | |||
| 205 | + | return err | |||
| 206 | + | } | |||
| 207 | + | skiaGPU, err := parseConfigInt(data["skia_gpu_threads"], "Skia GPU threads") | |||
| 208 | + | if err != nil { | |||
| 209 | + | return err | |||
| 210 | + | } | |||
| 211 | + | webMemory, err := parseConfigInt(data["web_process_memory_mb"], "web process memory") | |||
| 212 | + | if err != nil { | |||
| 213 | + | return err | |||
| 214 | + | } | |||
| 215 | + | networkMemory, err := parseConfigInt(data["network_process_memory_mb"], "network process memory") | |||
| 216 | + | if err != nil { | |||
| 217 | + | return err | |||
| 218 | + | } | |||
| 219 | + | prewarm, err := parseConfigInt(data["webview_pool_prewarm"], "WebView pool prewarm") | |||
| 220 | + | if err != nil { | |||
| 221 | + | return err | |||
| 222 | + | } | |||
| 223 | + | ||||
| 224 | + | cfg.Performance.Profile = profile | |||
| 225 | + | cfg.Performance.Custom = port.WebUICustomPerformanceConfig{ | |||
| 226 | + | SkiaCPUThreads: skiaCPU, | |||
| 227 | + | SkiaGPUThreads: skiaGPU, | |||
| 228 | + | WebProcessMemoryMB: webMemory, | |||
| 229 | + | NetworkProcessMemoryMB: networkMemory, | |||
| 230 | + | WebViewPoolPrewarm: prewarm, | |||
| 231 | + | } | |||
| 232 | + | if err := a.saveEditableConfig(ctx, cfg); err != nil { | |||
| 233 | + | return err | |||
| 234 | + | } | |||
| 235 | + | a.configNotice = "Saved performance settings. Restart may be required." | |||
| 236 | + | return nil | |||
| 237 | + | } | |||
| 238 | + | ||||
| 239 | + | func (a *App) setConfigKeybinding(ctx context.Context, data map[string]string) error { | |||
| 240 | + | mode := strings.TrimSpace(data["mode"]) | |||
| 241 | + | action := strings.TrimSpace(data["action"]) | |||
| 242 | + | keys := parseKeyList(data["keys"]) | |||
| 243 | + | if mode == "" || action == "" { | |||
| 244 | + | return fmt.Errorf("mode and action are required") | |||
| 245 | + | } | |||
| 246 | + | resp, err := a.deps.Config.SetKeybinding(ctx, port.SetKeybindingRequest{ | |||
| 247 | + | RequestID: configRequestIDPrefix, | |||
| 248 | + | Mode: mode, | |||
| 249 | + | Action: action, | |||
| 250 | + | Keys: keys, | |||
| 251 | + | }) | |||
| 252 | + | if err != nil { | |||
| 253 | + | return err | |||
| 254 | + | } | |||
| 255 | + | if conflicts := keybindingConflictCount(resp); conflicts > 0 { | |||
| 256 | + | a.configNotice = fmt.Sprintf("Saved keybinding with %d conflict(s)", conflicts) | |||
| 257 | + | return nil | |||
| 258 | + | } | |||
| 259 | + | a.configNotice = "Saved keybinding " + action | |||
| 260 | + | return nil | |||
| 261 | + | } | |||
| 262 | + | ||||
| 263 | + | func (a *App) resetConfigKeybinding(ctx context.Context, data map[string]string) error { | |||
| 264 | + | mode := strings.TrimSpace(data["mode"]) | |||
| 265 | + | action := strings.TrimSpace(data["action"]) | |||
| 266 | + | if mode == "" || action == "" { | |||
| 267 | + | return fmt.Errorf("mode and action are required") | |||
| 268 | + | } | |||
| 269 | + | if err := a.deps.Config.ResetKeybinding(ctx, port.ResetKeybindingRequest{ | |||
| 270 | + | RequestID: configRequestIDPrefix, | |||
| 271 | + | Mode: mode, | |||
| 272 | + | Action: action, | |||
| 273 | + | }); err != nil { | |||
| 274 | + | return err | |||
| 275 | + | } | |||
| 276 | + | a.configNotice = "Reset keybinding " + action | |||
| 277 | + | return nil | |||
| 278 | + | } | |||
| 279 | + | ||||
| 280 | + | func (a *App) editableConfig(ctx context.Context) (port.WebUIConfig, error) { | |||
| 281 | + | payload, err := a.currentConfigPayload(ctx) | |||
| 282 | + | if err != nil { | |||
| 283 | + | return port.WebUIConfig{}, err | |||
| 284 | + | } | |||
| 285 | + | return webUIConfigFromPayload(payload), nil | |||
| 286 | + | } | |||
| 287 | + | ||||
| 288 | + | func (a *App) currentConfigPayload(ctx context.Context) (port.SystemviewConfigPayload, error) { | |||
| 289 | + | if a.config != nil { | |||
| 290 | + | return *a.config, nil | |||
| 291 | + | } | |||
| 292 | + | cfg, err := a.deps.Config.Current(ctx) | |||
| 293 | + | if err != nil { | |||
| 294 | + | return port.SystemviewConfigPayload{}, err | |||
| 295 | + | } | |||
| 296 | + | a.config = &cfg | |||
| 297 | + | return cfg, nil | |||
| 298 | + | } | |||
| 299 | + | ||||
| 300 | + | func (a *App) saveEditableConfig(ctx context.Context, cfg port.WebUIConfig) error { | |||
| 301 | + | if err := a.deps.Config.Save(ctx, cfg); err != nil { | |||
| 302 | + | return err | |||
| 303 | + | } | |||
| 304 | + | a.config = nil | |||
| 305 | + | return nil | |||
| 306 | + | } | |||
| 307 | + | ||||
| 308 | + | func webUIConfigFromPayload(payload port.SystemviewConfigPayload) port.WebUIConfig { | |||
| 309 | + | return port.WebUIConfig{ | |||
| 310 | + | Appearance: payload.Appearance, | |||
| 311 | + | DefaultUIScale: payload.DefaultUIScale, | |||
| 312 | + | DefaultSearchEngine: payload.DefaultSearchEngine, | |||
| 313 | + | SearchShortcuts: cloneSearchShortcuts(payload.SearchShortcuts), | |||
| 314 | + | Performance: port.WebUIPerformanceConfig{ | |||
| 315 | + | Profile: payload.Performance.Profile, | |||
| 316 | + | Custom: port.WebUICustomPerformanceConfig{ | |||
| 317 | + | SkiaCPUThreads: payload.Performance.Custom.SkiaCPUThreads, | |||
| 318 | + | SkiaGPUThreads: payload.Performance.Custom.SkiaGPUThreads, | |||
| 319 | + | WebProcessMemoryMB: payload.Performance.Custom.WebProcessMemoryMB, | |||
| 320 | + | NetworkProcessMemoryMB: payload.Performance.Custom.NetworkProcessMemoryMB, | |||
| 321 | + | WebViewPoolPrewarm: payload.Performance.Custom.WebViewPoolPrewarm, | |||
| 322 | + | }, | |||
| 323 | + | }, | |||
| 324 | + | } | |||
| 325 | + | } | |||
| 326 | + | ||||
| 327 | + | func cloneSearchShortcuts(shortcuts map[string]port.SearchShortcut) map[string]port.SearchShortcut { | |||
| 328 | + | clone := make(map[string]port.SearchShortcut, len(shortcuts)) | |||
| 329 | + | for key, shortcut := range shortcuts { | |||
| 330 | + | clone[key] = shortcut | |||
| 331 | + | } | |||
| 332 | + | return clone | |||
| 333 | + | } | |||
| 334 | + | ||||
| 335 | + | func paletteFromForm(data map[string]string, prefix string) port.ColorPalette { | |||
| 336 | + | return port.ColorPalette{ | |||
| 337 | + | Background: strings.TrimSpace(data[prefix+"_background"]), | |||
| 338 | + | Surface: strings.TrimSpace(data[prefix+"_surface"]), | |||
| 339 | + | SurfaceVariant: strings.TrimSpace(data[prefix+"_surface_variant"]), | |||
| 340 | + | Text: strings.TrimSpace(data[prefix+"_text"]), | |||
| 341 | + | Muted: strings.TrimSpace(data[prefix+"_muted"]), | |||
| 342 | + | Accent: strings.TrimSpace(data[prefix+"_accent"]), | |||
| 343 | + | Border: strings.TrimSpace(data[prefix+"_border"]), | |||
| 344 | + | } | |||
| 345 | + | } | |||
| 346 | + | ||||
| 347 | + | func searchShortcutFromForm(data map[string]string, keyField string) (string, port.SearchShortcut, error) { | |||
| 348 | + | key := strings.TrimSpace(data[keyField]) | |||
| 349 | + | url := strings.TrimSpace(data["url"]) | |||
| 350 | + | description := strings.TrimSpace(data["description"]) | |||
| 351 | + | if key == "" { | |||
| 352 | + | return "", port.SearchShortcut{}, fmt.Errorf("search shortcut key is required") | |||
| 353 | + | } | |||
| 354 | + | if description == "" { | |||
| 355 | + | return "", port.SearchShortcut{}, fmt.Errorf("search shortcut description is required") | |||
| 356 | + | } | |||
| 357 | + | if err := validateSearchURL(url, "search shortcut URL"); err != nil { | |||
| 358 | + | return "", port.SearchShortcut{}, err | |||
| 359 | + | } | |||
| 360 | + | return key, port.SearchShortcut{URL: url, Description: description}, nil | |||
| 361 | + | } | |||
| 362 | + | ||||
| 363 | + | func validateSearchURL(raw, label string) error { | |||
| 364 | + | if strings.TrimSpace(raw) == "" { | |||
| 365 | + | return fmt.Errorf("%s is required", label) | |||
| 366 | + | } | |||
| 367 | + | if !strings.Contains(raw, "%s") { | |||
| 368 | + | return fmt.Errorf("%s must contain %%s placeholder", label) | |||
| 369 | + | } | |||
| 370 | + | return nil | |||
| 371 | + | } | |||
| 372 | + | ||||
| 373 | + | func validPerformanceProfile(profile string) bool { | |||
| 374 | + | switch profile { | |||
| 375 | + | case "default", "lite", "max", "custom", "": | |||
| 376 | + | return true | |||
| 377 | + | default: | |||
| 378 | + | return false | |||
| 379 | + | } | |||
| 380 | + | } | |||
| 381 | + | ||||
| 382 | + | func parseConfigInt(raw, label string) (int, error) { | |||
| 383 | + | value, err := strconv.Atoi(strings.TrimSpace(raw)) | |||
| 384 | + | if err != nil { | |||
| 385 | + | return 0, fmt.Errorf("invalid %s", label) | |||
| 386 | + | } | |||
| 387 | + | return value, nil | |||
| 388 | + | } | |||
| 389 | + | ||||
| 390 | + | func parseConfigFloat(raw, label string) (float64, error) { | |||
| 391 | + | value, err := strconv.ParseFloat(strings.TrimSpace(raw), 64) | |||
| 392 | + | if err != nil { | |||
| 393 | + | return 0, fmt.Errorf("invalid %s", label) | |||
| 394 | + | } | |||
| 395 | + | return value, nil | |||
| 396 | + | } | |||
| 397 | + | ||||
| 398 | + | func parseKeyList(raw string) []string { | |||
| 399 | + | raw = strings.TrimSpace(raw) | |||
| 400 | + | if raw == "" { | |||
| 401 | + | return nil | |||
| 402 | + | } | |||
| 403 | + | parts := strings.Split(raw, ",") | |||
| 404 | + | if len(parts) == 1 { | |||
| 405 | + | parts = strings.Fields(raw) | |||
| 406 | + | } | |||
| 407 | + | keys := make([]string, 0, len(parts)) | |||
| 408 | + | for _, part := range parts { | |||
| 409 | + | key := strings.TrimSpace(part) | |||
| 410 | + | if key != "" { | |||
| 411 | + | keys = append(keys, key) | |||
| 412 | + | } | |||
| 413 | + | } | |||
| 414 | + | return keys | |||
| 415 | + | } | |||
| 416 | + | ||||
| 417 | + | func keybindingConflictCount(resp any) int { | |||
| 418 | + | switch v := resp.(type) { | |||
| 419 | + | case nil: | |||
| 420 | + | return 0 | |||
| 421 | + | case port.SetKeybindingResponse: | |||
| 422 | + | return len(v.Conflicts) | |||
| 423 | + | case *port.SetKeybindingResponse: | |||
| 424 | + | if v == nil { | |||
| 425 | + | return 0 | |||
| 426 | + | } | |||
| 427 | + | return len(v.Conflicts) | |||
| 428 | + | case map[string]any: | |||
| 429 | + | if conflicts, ok := anySlice(v["conflicts"]); ok { | |||
| 430 | + | return len(conflicts) | |||
| 431 | + | } | |||
| 432 | + | } | |||
| 433 | + | return 0 | |||
| 434 | + | } | |||
M internal/ui/systemviews/config_templ.go +946 -83
| @@ -7,6 +7,8 @@ package systemviews | |||
| 7 | 7 | import "github.com/a-h/templ" | |
| 8 | 8 | import templruntime "github.com/a-h/templ/runtime" | |
| 9 | 9 | ||
| 10 | + | import "github.com/bnema/dumber/internal/application/port" | |
| 11 | + | ||
| 10 | 12 | func ConfigView(data configRenderData) templ.Component { | |
| 11 | 13 | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 12 | 14 | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| @@ -23,63 +25,855 @@ func ConfigView(data configRenderData) templ.Component { | |||
| 23 | 25 | }() | |
| 24 | 26 | } | |
| 25 | 27 | ctx = templ.InitializeContext(ctx) | |
| 26 | - | templ_7745c5c3_Var1 := templ.GetChildren(ctx) | |
| 27 | - | if templ_7745c5c3_Var1 == nil { | |
| 28 | - | templ_7745c5c3_Var1 = templ.NopComponent | |
| 28 | + | templ_7745c5c3_Var1 := templ.GetChildren(ctx) | |
| 29 | + | if templ_7745c5c3_Var1 == nil { | |
| 30 | + | templ_7745c5c3_Var1 = templ.NopComponent | |
| 31 | + | } | |
| 32 | + | ctx = templ.ClearChildren(ctx) | |
| 33 | + | templ_7745c5c3_Err = Alert("success", data.Notice).Render(ctx, templ_7745c5c3_Buffer) | |
| 34 | + | if templ_7745c5c3_Err != nil { | |
| 35 | + | return templ_7745c5c3_Err | |
| 36 | + | } | |
| 37 | + | templ_7745c5c3_Err = Alert("error", data.Error).Render(ctx, templ_7745c5c3_Buffer) | |
| 38 | + | if templ_7745c5c3_Err != nil { | |
| 39 | + | return templ_7745c5c3_Err | |
| 40 | + | } | |
| 41 | + | templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 42 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 43 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 44 | + | if !templ_7745c5c3_IsBuffer { | |
| 45 | + | defer func() { | |
| 46 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 47 | + | if templ_7745c5c3_Err == nil { | |
| 48 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 49 | + | } | |
| 50 | + | }() | |
| 51 | + | } | |
| 52 | + | ctx = templ.InitializeContext(ctx) | |
| 53 | + | templ_7745c5c3_Err = AppearanceForm(data.Config).Render(ctx, templ_7745c5c3_Buffer) | |
| 54 | + | if templ_7745c5c3_Err != nil { | |
| 55 | + | return templ_7745c5c3_Err | |
| 56 | + | } | |
| 57 | + | return nil | |
| 58 | + | }) | |
| 59 | + | templ_7745c5c3_Err = Section("sv-config-appearance", "Appearance").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) | |
| 60 | + | if templ_7745c5c3_Err != nil { | |
| 61 | + | return templ_7745c5c3_Err | |
| 62 | + | } | |
| 63 | + | templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 64 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 65 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 66 | + | if !templ_7745c5c3_IsBuffer { | |
| 67 | + | defer func() { | |
| 68 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 69 | + | if templ_7745c5c3_Err == nil { | |
| 70 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 71 | + | } | |
| 72 | + | }() | |
| 73 | + | } | |
| 74 | + | ctx = templ.InitializeContext(ctx) | |
| 75 | + | templ_7745c5c3_Err = SearchSettings(data.Config).Render(ctx, templ_7745c5c3_Buffer) | |
| 76 | + | if templ_7745c5c3_Err != nil { | |
| 77 | + | return templ_7745c5c3_Err | |
| 78 | + | } | |
| 79 | + | return nil | |
| 80 | + | }) | |
| 81 | + | templ_7745c5c3_Err = Section("sv-config-search", "Search").Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) | |
| 82 | + | if templ_7745c5c3_Err != nil { | |
| 83 | + | return templ_7745c5c3_Err | |
| 84 | + | } | |
| 85 | + | templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 86 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 87 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 88 | + | if !templ_7745c5c3_IsBuffer { | |
| 89 | + | defer func() { | |
| 90 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 91 | + | if templ_7745c5c3_Err == nil { | |
| 92 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 93 | + | } | |
| 94 | + | }() | |
| 95 | + | } | |
| 96 | + | ctx = templ.InitializeContext(ctx) | |
| 97 | + | templ_7745c5c3_Err = PerformanceSettings(data.Config).Render(ctx, templ_7745c5c3_Buffer) | |
| 98 | + | if templ_7745c5c3_Err != nil { | |
| 99 | + | return templ_7745c5c3_Err | |
| 100 | + | } | |
| 101 | + | return nil | |
| 102 | + | }) | |
| 103 | + | templ_7745c5c3_Err = Section("sv-config-performance", "Performance").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) | |
| 104 | + | if templ_7745c5c3_Err != nil { | |
| 105 | + | return templ_7745c5c3_Err | |
| 106 | + | } | |
| 107 | + | templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 108 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 109 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 110 | + | if !templ_7745c5c3_IsBuffer { | |
| 111 | + | defer func() { | |
| 112 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 113 | + | if templ_7745c5c3_Err == nil { | |
| 114 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 115 | + | } | |
| 116 | + | }() | |
| 117 | + | } | |
| 118 | + | ctx = templ.InitializeContext(ctx) | |
| 119 | + | templ_7745c5c3_Err = Meta(configKeybindingSummary(data.Keybindings)).Render(ctx, templ_7745c5c3_Buffer) | |
| 120 | + | if templ_7745c5c3_Err != nil { | |
| 121 | + | return templ_7745c5c3_Err | |
| 122 | + | } | |
| 123 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") | |
| 124 | + | if templ_7745c5c3_Err != nil { | |
| 125 | + | return templ_7745c5c3_Err | |
| 126 | + | } | |
| 127 | + | templ_7745c5c3_Err = ConfigKeybindings(data.Keybindings).Render(ctx, templ_7745c5c3_Buffer) | |
| 128 | + | if templ_7745c5c3_Err != nil { | |
| 129 | + | return templ_7745c5c3_Err | |
| 130 | + | } | |
| 131 | + | return nil | |
| 132 | + | }) | |
| 133 | + | templ_7745c5c3_Err = Section("sv-config-keybindings", "Keybindings").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) | |
| 134 | + | if templ_7745c5c3_Err != nil { | |
| 135 | + | return templ_7745c5c3_Err | |
| 136 | + | } | |
| 137 | + | templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 138 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 139 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 140 | + | if !templ_7745c5c3_IsBuffer { | |
| 141 | + | defer func() { | |
| 142 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 143 | + | if templ_7745c5c3_Err == nil { | |
| 144 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 145 | + | } | |
| 146 | + | }() | |
| 147 | + | } | |
| 148 | + | ctx = templ.InitializeContext(ctx) | |
| 149 | + | templ_7745c5c3_Err = KV(flattenValues(data.Config)).Render(ctx, templ_7745c5c3_Buffer) | |
| 150 | + | if templ_7745c5c3_Err != nil { | |
| 151 | + | return templ_7745c5c3_Err | |
| 152 | + | } | |
| 153 | + | return nil | |
| 154 | + | }) | |
| 155 | + | templ_7745c5c3_Err = Section("sv-config-values", "Current payload").Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) | |
| 156 | + | if templ_7745c5c3_Err != nil { | |
| 157 | + | return templ_7745c5c3_Err | |
| 158 | + | } | |
| 159 | + | return nil | |
| 160 | + | }) | |
| 161 | + | } | |
| 162 | + | ||
| 163 | + | func AppearanceForm(config port.SystemviewConfigPayload) templ.Component { | |
| 164 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 165 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 166 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |
| 167 | + | return templ_7745c5c3_CtxErr | |
| 168 | + | } | |
| 169 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 170 | + | if !templ_7745c5c3_IsBuffer { | |
| 171 | + | defer func() { | |
| 172 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 173 | + | if templ_7745c5c3_Err == nil { | |
| 174 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 175 | + | } | |
| 176 | + | }() | |
| 177 | + | } | |
| 178 | + | ctx = templ.InitializeContext(ctx) | |
| 179 | + | templ_7745c5c3_Var7 := templ.GetChildren(ctx) | |
| 180 | + | if templ_7745c5c3_Var7 == nil { | |
| 181 | + | templ_7745c5c3_Var7 = templ.NopComponent | |
| 182 | + | } | |
| 183 | + | ctx = templ.ClearChildren(ctx) | |
| 184 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<form class=\"sv-card-form sv-config-form\" data-sv-action=\"config.appearance.save\"><label><span>Sans font</span><input name=\"sans_font\" type=\"text\" value=\"") | |
| 185 | + | if templ_7745c5c3_Err != nil { | |
| 186 | + | return templ_7745c5c3_Err | |
| 187 | + | } | |
| 188 | + | var templ_7745c5c3_Var8 string | |
| 189 | + | templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(config.Appearance.SansFont) | |
| 190 | + | if templ_7745c5c3_Err != nil { | |
| 191 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 28, Col: 101} | |
| 192 | + | } | |
| 193 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) | |
| 194 | + | if templ_7745c5c3_Err != nil { | |
| 195 | + | return templ_7745c5c3_Err | |
| 196 | + | } | |
| 197 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" required></label> <label><span>Serif font</span><input name=\"serif_font\" type=\"text\" value=\"") | |
| 198 | + | if templ_7745c5c3_Err != nil { | |
| 199 | + | return templ_7745c5c3_Err | |
| 200 | + | } | |
| 201 | + | var templ_7745c5c3_Var9 string | |
| 202 | + | templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(config.Appearance.SerifFont) | |
| 203 | + | if templ_7745c5c3_Err != nil { | |
| 204 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 29, Col: 104} | |
| 205 | + | } | |
| 206 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) | |
| 207 | + | if templ_7745c5c3_Err != nil { | |
| 208 | + | return templ_7745c5c3_Err | |
| 209 | + | } | |
| 210 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" required></label> <label><span>Monospace font</span><input name=\"monospace_font\" type=\"text\" value=\"") | |
| 211 | + | if templ_7745c5c3_Err != nil { | |
| 212 | + | return templ_7745c5c3_Err | |
| 213 | + | } | |
| 214 | + | var templ_7745c5c3_Var10 string | |
| 215 | + | templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(config.Appearance.MonospaceFont) | |
| 216 | + | if templ_7745c5c3_Err != nil { | |
| 217 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 30, Col: 116} | |
| 218 | + | } | |
| 219 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | |
| 220 | + | if templ_7745c5c3_Err != nil { | |
| 221 | + | return templ_7745c5c3_Err | |
| 222 | + | } | |
| 223 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" required></label> <label><span>Default font size</span><input name=\"default_font_size\" type=\"number\" min=\"1\" max=\"72\" value=\"") | |
| 224 | + | if templ_7745c5c3_Err != nil { | |
| 225 | + | return templ_7745c5c3_Err | |
| 226 | + | } | |
| 227 | + | var templ_7745c5c3_Var11 string | |
| 228 | + | templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Appearance.DefaultFontSize)) | |
| 229 | + | if templ_7745c5c3_Err != nil { | |
| 230 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 31, Col: 160} | |
| 231 | + | } | |
| 232 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | |
| 233 | + | if templ_7745c5c3_Err != nil { | |
| 234 | + | return templ_7745c5c3_Err | |
| 235 | + | } | |
| 236 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" required></label> <label><span>UI scale</span><input name=\"default_ui_scale\" type=\"number\" min=\"0.5\" max=\"3\" step=\"0.05\" value=\"") | |
| 237 | + | if templ_7745c5c3_Err != nil { | |
| 238 | + | return templ_7745c5c3_Err | |
| 239 | + | } | |
| 240 | + | var templ_7745c5c3_Var12 string | |
| 241 | + | templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigFloat(config.DefaultUIScale)) | |
| 242 | + | if templ_7745c5c3_Err != nil { | |
| 243 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 32, Col: 153} | |
| 244 | + | } | |
| 245 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) | |
| 246 | + | if templ_7745c5c3_Err != nil { | |
| 247 | + | return templ_7745c5c3_Err | |
| 248 | + | } | |
| 249 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" required></label> <label><span>Color scheme</span><select name=\"color_scheme\"><option value=\"default\"") | |
| 250 | + | if templ_7745c5c3_Err != nil { | |
| 251 | + | return templ_7745c5c3_Err | |
| 252 | + | } | |
| 253 | + | if colorSchemeSelected(config.Appearance.ColorScheme, "default") { | |
| 254 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " selected") | |
| 255 | + | if templ_7745c5c3_Err != nil { | |
| 256 | + | return templ_7745c5c3_Err | |
| 257 | + | } | |
| 258 | + | } | |
| 259 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, ">System default</option> <option value=\"prefer-light\"") | |
| 260 | + | if templ_7745c5c3_Err != nil { | |
| 261 | + | return templ_7745c5c3_Err | |
| 262 | + | } | |
| 263 | + | if colorSchemeSelected(config.Appearance.ColorScheme, "prefer-light") { | |
| 264 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " selected") | |
| 265 | + | if templ_7745c5c3_Err != nil { | |
| 266 | + | return templ_7745c5c3_Err | |
| 267 | + | } | |
| 268 | + | } | |
| 269 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, ">Prefer light</option> <option value=\"prefer-dark\"") | |
| 270 | + | if templ_7745c5c3_Err != nil { | |
| 271 | + | return templ_7745c5c3_Err | |
| 272 | + | } | |
| 273 | + | if colorSchemeSelected(config.Appearance.ColorScheme, "prefer-dark") { | |
| 274 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, " selected") | |
| 275 | + | if templ_7745c5c3_Err != nil { | |
| 276 | + | return templ_7745c5c3_Err | |
| 277 | + | } | |
| 278 | + | } | |
| 279 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, ">Prefer dark</option></select></label>") | |
| 280 | + | if templ_7745c5c3_Err != nil { | |
| 281 | + | return templ_7745c5c3_Err | |
| 282 | + | } | |
| 283 | + | templ_7745c5c3_Err = PaletteFields("Light palette", "light", config.Appearance.LightPalette).Render(ctx, templ_7745c5c3_Buffer) | |
| 284 | + | if templ_7745c5c3_Err != nil { | |
| 285 | + | return templ_7745c5c3_Err | |
| 286 | + | } | |
| 287 | + | templ_7745c5c3_Err = PaletteFields("Dark palette", "dark", config.Appearance.DarkPalette).Render(ctx, templ_7745c5c3_Buffer) | |
| 288 | + | if templ_7745c5c3_Err != nil { | |
| 289 | + | return templ_7745c5c3_Err | |
| 290 | + | } | |
| 291 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"sv-button-row sv-form-actions\"><button class=\"sv-button\" type=\"submit\">Save appearance</button> <button class=\"sv-button sv-button-secondary\" type=\"button\" data-sv-action=\"config.appearance.reset\" data-sv-confirm=\"Reset appearance settings to defaults?\">Reset appearance</button></div></form>") | |
| 292 | + | if templ_7745c5c3_Err != nil { | |
| 293 | + | return templ_7745c5c3_Err | |
| 294 | + | } | |
| 295 | + | return nil | |
| 296 | + | }) | |
| 297 | + | } | |
| 298 | + | ||
| 299 | + | func PaletteFields(title string, prefix string, palette port.ColorPalette) templ.Component { | |
| 300 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 301 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 302 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |
| 303 | + | return templ_7745c5c3_CtxErr | |
| 304 | + | } | |
| 305 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 306 | + | if !templ_7745c5c3_IsBuffer { | |
| 307 | + | defer func() { | |
| 308 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 309 | + | if templ_7745c5c3_Err == nil { | |
| 310 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 311 | + | } | |
| 312 | + | }() | |
| 313 | + | } | |
| 314 | + | ctx = templ.InitializeContext(ctx) | |
| 315 | + | templ_7745c5c3_Var13 := templ.GetChildren(ctx) | |
| 316 | + | if templ_7745c5c3_Var13 == nil { | |
| 317 | + | templ_7745c5c3_Var13 = templ.NopComponent | |
| 318 | + | } | |
| 319 | + | ctx = templ.ClearChildren(ctx) | |
| 320 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<fieldset class=\"sv-fieldset\"><legend>") | |
| 321 | + | if templ_7745c5c3_Err != nil { | |
| 322 | + | return templ_7745c5c3_Err | |
| 323 | + | } | |
| 324 | + | var templ_7745c5c3_Var14 string | |
| 325 | + | templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(title) | |
| 326 | + | if templ_7745c5c3_Err != nil { | |
| 327 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 49, Col: 17} | |
| 328 | + | } | |
| 329 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) | |
| 330 | + | if templ_7745c5c3_Err != nil { | |
| 331 | + | return templ_7745c5c3_Err | |
| 332 | + | } | |
| 333 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</legend> <label><span>Background</span><input name=\"") | |
| 334 | + | if templ_7745c5c3_Err != nil { | |
| 335 | + | return templ_7745c5c3_Err | |
| 336 | + | } | |
| 337 | + | var templ_7745c5c3_Var15 string | |
| 338 | + | templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_background") | |
| 339 | + | if templ_7745c5c3_Err != nil { | |
| 340 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 50, Col: 68} | |
| 341 | + | } | |
| 342 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) | |
| 343 | + | if templ_7745c5c3_Err != nil { | |
| 344 | + | return templ_7745c5c3_Err | |
| 345 | + | } | |
| 346 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" type=\"text\" value=\"") | |
| 347 | + | if templ_7745c5c3_Err != nil { | |
| 348 | + | return templ_7745c5c3_Err | |
| 349 | + | } | |
| 350 | + | var templ_7745c5c3_Var16 string | |
| 351 | + | templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Background) | |
| 352 | + | if templ_7745c5c3_Err != nil { | |
| 353 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 50, Col: 109} | |
| 354 | + | } | |
| 355 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) | |
| 356 | + | if templ_7745c5c3_Err != nil { | |
| 357 | + | return templ_7745c5c3_Err | |
| 358 | + | } | |
| 359 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" required></label> <label><span>Surface</span><input name=\"") | |
| 360 | + | if templ_7745c5c3_Err != nil { | |
| 361 | + | return templ_7745c5c3_Err | |
| 362 | + | } | |
| 363 | + | var templ_7745c5c3_Var17 string | |
| 364 | + | templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_surface") | |
| 365 | + | if templ_7745c5c3_Err != nil { | |
| 366 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 51, Col: 62} | |
| 367 | + | } | |
| 368 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) | |
| 369 | + | if templ_7745c5c3_Err != nil { | |
| 370 | + | return templ_7745c5c3_Err | |
| 371 | + | } | |
| 372 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" type=\"text\" value=\"") | |
| 373 | + | if templ_7745c5c3_Err != nil { | |
| 374 | + | return templ_7745c5c3_Err | |
| 375 | + | } | |
| 376 | + | var templ_7745c5c3_Var18 string | |
| 377 | + | templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Surface) | |
| 378 | + | if templ_7745c5c3_Err != nil { | |
| 379 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 51, Col: 100} | |
| 380 | + | } | |
| 381 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) | |
| 382 | + | if templ_7745c5c3_Err != nil { | |
| 383 | + | return templ_7745c5c3_Err | |
| 384 | + | } | |
| 385 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" required></label> <label><span>Surface variant</span><input name=\"") | |
| 386 | + | if templ_7745c5c3_Err != nil { | |
| 387 | + | return templ_7745c5c3_Err | |
| 388 | + | } | |
| 389 | + | var templ_7745c5c3_Var19 string | |
| 390 | + | templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_surface_variant") | |
| 391 | + | if templ_7745c5c3_Err != nil { | |
| 392 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 52, Col: 78} | |
| 393 | + | } | |
| 394 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) | |
| 395 | + | if templ_7745c5c3_Err != nil { | |
| 396 | + | return templ_7745c5c3_Err | |
| 397 | + | } | |
| 398 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" type=\"text\" value=\"") | |
| 399 | + | if templ_7745c5c3_Err != nil { | |
| 400 | + | return templ_7745c5c3_Err | |
| 401 | + | } | |
| 402 | + | var templ_7745c5c3_Var20 string | |
| 403 | + | templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(palette.SurfaceVariant) | |
| 404 | + | if templ_7745c5c3_Err != nil { | |
| 405 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 52, Col: 123} | |
| 406 | + | } | |
| 407 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) | |
| 408 | + | if templ_7745c5c3_Err != nil { | |
| 409 | + | return templ_7745c5c3_Err | |
| 410 | + | } | |
| 411 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" required></label> <label><span>Text</span><input name=\"") | |
| 412 | + | if templ_7745c5c3_Err != nil { | |
| 413 | + | return templ_7745c5c3_Err | |
| 414 | + | } | |
| 415 | + | var templ_7745c5c3_Var21 string | |
| 416 | + | templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_text") | |
| 417 | + | if templ_7745c5c3_Err != nil { | |
| 418 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 53, Col: 56} | |
| 419 | + | } | |
| 420 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) | |
| 421 | + | if templ_7745c5c3_Err != nil { | |
| 422 | + | return templ_7745c5c3_Err | |
| 423 | + | } | |
| 424 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" type=\"text\" value=\"") | |
| 425 | + | if templ_7745c5c3_Err != nil { | |
| 426 | + | return templ_7745c5c3_Err | |
| 427 | + | } | |
| 428 | + | var templ_7745c5c3_Var22 string | |
| 429 | + | templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Text) | |
| 430 | + | if templ_7745c5c3_Err != nil { | |
| 431 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 53, Col: 91} | |
| 432 | + | } | |
| 433 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) | |
| 434 | + | if templ_7745c5c3_Err != nil { | |
| 435 | + | return templ_7745c5c3_Err | |
| 436 | + | } | |
| 437 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" required></label> <label><span>Muted</span><input name=\"") | |
| 438 | + | if templ_7745c5c3_Err != nil { | |
| 439 | + | return templ_7745c5c3_Err | |
| 440 | + | } | |
| 441 | + | var templ_7745c5c3_Var23 string | |
| 442 | + | templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_muted") | |
| 443 | + | if templ_7745c5c3_Err != nil { | |
| 444 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 54, Col: 58} | |
| 445 | + | } | |
| 446 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) | |
| 447 | + | if templ_7745c5c3_Err != nil { | |
| 448 | + | return templ_7745c5c3_Err | |
| 449 | + | } | |
| 450 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" type=\"text\" value=\"") | |
| 451 | + | if templ_7745c5c3_Err != nil { | |
| 452 | + | return templ_7745c5c3_Err | |
| 453 | + | } | |
| 454 | + | var templ_7745c5c3_Var24 string | |
| 455 | + | templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Muted) | |
| 456 | + | if templ_7745c5c3_Err != nil { | |
| 457 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 54, Col: 94} | |
| 458 | + | } | |
| 459 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) | |
| 460 | + | if templ_7745c5c3_Err != nil { | |
| 461 | + | return templ_7745c5c3_Err | |
| 462 | + | } | |
| 463 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\" required></label> <label><span>Accent</span><input name=\"") | |
| 464 | + | if templ_7745c5c3_Err != nil { | |
| 465 | + | return templ_7745c5c3_Err | |
| 466 | + | } | |
| 467 | + | var templ_7745c5c3_Var25 string | |
| 468 | + | templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_accent") | |
| 469 | + | if templ_7745c5c3_Err != nil { | |
| 470 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 55, Col: 60} | |
| 471 | + | } | |
| 472 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) | |
| 473 | + | if templ_7745c5c3_Err != nil { | |
| 474 | + | return templ_7745c5c3_Err | |
| 475 | + | } | |
| 476 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" type=\"text\" value=\"") | |
| 477 | + | if templ_7745c5c3_Err != nil { | |
| 478 | + | return templ_7745c5c3_Err | |
| 479 | + | } | |
| 480 | + | var templ_7745c5c3_Var26 string | |
| 481 | + | templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Accent) | |
| 482 | + | if templ_7745c5c3_Err != nil { | |
| 483 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 55, Col: 97} | |
| 484 | + | } | |
| 485 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) | |
| 486 | + | if templ_7745c5c3_Err != nil { | |
| 487 | + | return templ_7745c5c3_Err | |
| 488 | + | } | |
| 489 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" required></label> <label><span>Border</span><input name=\"") | |
| 490 | + | if templ_7745c5c3_Err != nil { | |
| 491 | + | return templ_7745c5c3_Err | |
| 492 | + | } | |
| 493 | + | var templ_7745c5c3_Var27 string | |
| 494 | + | templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_border") | |
| 495 | + | if templ_7745c5c3_Err != nil { | |
| 496 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 56, Col: 60} | |
| 497 | + | } | |
| 498 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) | |
| 499 | + | if templ_7745c5c3_Err != nil { | |
| 500 | + | return templ_7745c5c3_Err | |
| 501 | + | } | |
| 502 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" type=\"text\" value=\"") | |
| 503 | + | if templ_7745c5c3_Err != nil { | |
| 504 | + | return templ_7745c5c3_Err | |
| 505 | + | } | |
| 506 | + | var templ_7745c5c3_Var28 string | |
| 507 | + | templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Border) | |
| 508 | + | if templ_7745c5c3_Err != nil { | |
| 509 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 56, Col: 97} | |
| 510 | + | } | |
| 511 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) | |
| 512 | + | if templ_7745c5c3_Err != nil { | |
| 513 | + | return templ_7745c5c3_Err | |
| 514 | + | } | |
| 515 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\" required></label></fieldset>") | |
| 516 | + | if templ_7745c5c3_Err != nil { | |
| 517 | + | return templ_7745c5c3_Err | |
| 518 | + | } | |
| 519 | + | return nil | |
| 520 | + | }) | |
| 521 | + | } | |
| 522 | + | ||
| 523 | + | func SearchSettings(config port.SystemviewConfigPayload) templ.Component { | |
| 524 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 525 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 526 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |
| 527 | + | return templ_7745c5c3_CtxErr | |
| 528 | + | } | |
| 529 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 530 | + | if !templ_7745c5c3_IsBuffer { | |
| 531 | + | defer func() { | |
| 532 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 533 | + | if templ_7745c5c3_Err == nil { | |
| 534 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 535 | + | } | |
| 536 | + | }() | |
| 537 | + | } | |
| 538 | + | ctx = templ.InitializeContext(ctx) | |
| 539 | + | templ_7745c5c3_Var29 := templ.GetChildren(ctx) | |
| 540 | + | if templ_7745c5c3_Var29 == nil { | |
| 541 | + | templ_7745c5c3_Var29 = templ.NopComponent | |
| 542 | + | } | |
| 543 | + | ctx = templ.ClearChildren(ctx) | |
| 544 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<form class=\"sv-card-form\" data-sv-action=\"config.search.save\"><label><span>Default search engine</span><input name=\"default_search_engine\" type=\"text\" value=\"") | |
| 545 | + | if templ_7745c5c3_Err != nil { | |
| 546 | + | return templ_7745c5c3_Err | |
| 547 | + | } | |
| 548 | + | var templ_7745c5c3_Var30 string | |
| 549 | + | templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(config.DefaultSearchEngine) | |
| 550 | + | if templ_7745c5c3_Err != nil { | |
| 551 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 62, Col: 125} | |
| 552 | + | } | |
| 553 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) | |
| 554 | + | if templ_7745c5c3_Err != nil { | |
| 555 | + | return templ_7745c5c3_Err | |
| 556 | + | } | |
| 557 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" placeholder=\"https://duckduckgo.com/?q=%s\" required></label> <button class=\"sv-button\" type=\"submit\">Save search default</button></form><div class=\"sv-group\"><div class=\"sv-group-header\"><h4>Search shortcuts</h4></div><p class=\"sv-meta\">Shortcut URLs must include the %s placeholder for the search query.</p><form class=\"sv-inline-form\" data-sv-action=\"config.searchShortcut.create\"><label><span>Key</span><input name=\"key\" type=\"text\" placeholder=\"ddg\" required></label> <label><span>URL</span><input name=\"url\" type=\"text\" placeholder=\"https://duckduckgo.com/?q=%s\" required></label> <label><span>Description</span><input name=\"description\" type=\"text\" placeholder=\"DuckDuckGo\" required></label> <button class=\"sv-button sv-button-secondary\" type=\"submit\">Add shortcut</button></form>") | |
| 558 | + | if templ_7745c5c3_Err != nil { | |
| 559 | + | return templ_7745c5c3_Err | |
| 560 | + | } | |
| 561 | + | if len(searchShortcutRows(config.SearchShortcuts)) == 0 { | |
| 562 | + | templ_7745c5c3_Err = EmptyState("No search shortcuts configured").Render(ctx, templ_7745c5c3_Buffer) | |
| 563 | + | if templ_7745c5c3_Err != nil { | |
| 564 | + | return templ_7745c5c3_Err | |
| 565 | + | } | |
| 566 | + | } else { | |
| 567 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<ul class=\"sv-list\">") | |
| 568 | + | if templ_7745c5c3_Err != nil { | |
| 569 | + | return templ_7745c5c3_Err | |
| 570 | + | } | |
| 571 | + | for _, shortcut := range searchShortcutRows(config.SearchShortcuts) { | |
| 572 | + | templ_7745c5c3_Err = SearchShortcutItem(shortcut).Render(ctx, templ_7745c5c3_Buffer) | |
| 573 | + | if templ_7745c5c3_Err != nil { | |
| 574 | + | return templ_7745c5c3_Err | |
| 575 | + | } | |
| 576 | + | } | |
| 577 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</ul>") | |
| 578 | + | if templ_7745c5c3_Err != nil { | |
| 579 | + | return templ_7745c5c3_Err | |
| 580 | + | } | |
| 581 | + | } | |
| 582 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</div>") | |
| 583 | + | if templ_7745c5c3_Err != nil { | |
| 584 | + | return templ_7745c5c3_Err | |
| 585 | + | } | |
| 586 | + | return nil | |
| 587 | + | }) | |
| 588 | + | } | |
| 589 | + | ||
| 590 | + | func SearchShortcutItem(shortcut searchShortcutRow) templ.Component { | |
| 591 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 592 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 593 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |
| 594 | + | return templ_7745c5c3_CtxErr | |
| 595 | + | } | |
| 596 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 597 | + | if !templ_7745c5c3_IsBuffer { | |
| 598 | + | defer func() { | |
| 599 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 600 | + | if templ_7745c5c3_Err == nil { | |
| 601 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 602 | + | } | |
| 603 | + | }() | |
| 604 | + | } | |
| 605 | + | ctx = templ.InitializeContext(ctx) | |
| 606 | + | templ_7745c5c3_Var31 := templ.GetChildren(ctx) | |
| 607 | + | if templ_7745c5c3_Var31 == nil { | |
| 608 | + | templ_7745c5c3_Var31 = templ.NopComponent | |
| 29 | 609 | } | |
| 30 | 610 | ctx = templ.ClearChildren(ctx) | |
| 31 | - | templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 32 | - | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 33 | - | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 34 | - | if !templ_7745c5c3_IsBuffer { | |
| 35 | - | defer func() { | |
| 36 | - | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 37 | - | if templ_7745c5c3_Err == nil { | |
| 38 | - | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 39 | - | } | |
| 40 | - | }() | |
| 41 | - | } | |
| 42 | - | ctx = templ.InitializeContext(ctx) | |
| 43 | - | templ_7745c5c3_Err = KV(flattenValues(data.Config)).Render(ctx, templ_7745c5c3_Buffer) | |
| 611 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<li class=\"sv-list-row\"><form class=\"sv-inline-form\" data-sv-action=\"config.searchShortcut.update\"><input type=\"hidden\" name=\"key\" value=\"") | |
| 612 | + | if templ_7745c5c3_Err != nil { | |
| 613 | + | return templ_7745c5c3_Err | |
| 614 | + | } | |
| 615 | + | var templ_7745c5c3_Var32 string | |
| 616 | + | templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Key) | |
| 617 | + | if templ_7745c5c3_Err != nil { | |
| 618 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 89, Col: 55} | |
| 619 | + | } | |
| 620 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) | |
| 621 | + | if templ_7745c5c3_Err != nil { | |
| 622 | + | return templ_7745c5c3_Err | |
| 623 | + | } | |
| 624 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\"> <label><span>Key</span><input name=\"new_key\" type=\"text\" value=\"") | |
| 625 | + | if templ_7745c5c3_Err != nil { | |
| 626 | + | return templ_7745c5c3_Err | |
| 627 | + | } | |
| 628 | + | var templ_7745c5c3_Var33 string | |
| 629 | + | templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Key) | |
| 630 | + | if templ_7745c5c3_Err != nil { | |
| 631 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 90, Col: 80} | |
| 632 | + | } | |
| 633 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) | |
| 634 | + | if templ_7745c5c3_Err != nil { | |
| 635 | + | return templ_7745c5c3_Err | |
| 636 | + | } | |
| 637 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" required></label> <label><span>URL</span><input name=\"url\" type=\"text\" value=\"") | |
| 638 | + | if templ_7745c5c3_Err != nil { | |
| 639 | + | return templ_7745c5c3_Err | |
| 640 | + | } | |
| 641 | + | var templ_7745c5c3_Var34 string | |
| 642 | + | templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.URL) | |
| 643 | + | if templ_7745c5c3_Err != nil { | |
| 644 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 91, Col: 76} | |
| 645 | + | } | |
| 646 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) | |
| 647 | + | if templ_7745c5c3_Err != nil { | |
| 648 | + | return templ_7745c5c3_Err | |
| 649 | + | } | |
| 650 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\" required></label> <label><span>Description</span><input name=\"description\" type=\"text\" value=\"") | |
| 651 | + | if templ_7745c5c3_Err != nil { | |
| 652 | + | return templ_7745c5c3_Err | |
| 653 | + | } | |
| 654 | + | var templ_7745c5c3_Var35 string | |
| 655 | + | templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Description) | |
| 656 | + | if templ_7745c5c3_Err != nil { | |
| 657 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 92, Col: 100} | |
| 658 | + | } | |
| 659 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) | |
| 660 | + | if templ_7745c5c3_Err != nil { | |
| 661 | + | return templ_7745c5c3_Err | |
| 662 | + | } | |
| 663 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\" required></label> <button class=\"sv-button sv-button-secondary\" type=\"submit\">Save</button> <button class=\"sv-button sv-button-secondary sv-button-danger\" type=\"button\" data-sv-action=\"config.searchShortcut.delete\" data-key=\"") | |
| 664 | + | if templ_7745c5c3_Err != nil { | |
| 665 | + | return templ_7745c5c3_Err | |
| 666 | + | } | |
| 667 | + | var templ_7745c5c3_Var36 string | |
| 668 | + | templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Key) | |
| 669 | + | if templ_7745c5c3_Err != nil { | |
| 670 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 94, Col: 149} | |
| 671 | + | } | |
| 672 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) | |
| 673 | + | if templ_7745c5c3_Err != nil { | |
| 674 | + | return templ_7745c5c3_Err | |
| 675 | + | } | |
| 676 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\" data-sv-confirm=\"Delete this search shortcut?\">Delete</button></form></li>") | |
| 677 | + | if templ_7745c5c3_Err != nil { | |
| 678 | + | return templ_7745c5c3_Err | |
| 679 | + | } | |
| 680 | + | return nil | |
| 681 | + | }) | |
| 682 | + | } | |
| 683 | + | ||
| 684 | + | func PerformanceSettings(config port.SystemviewConfigPayload) templ.Component { | |
| 685 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 686 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 687 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |
| 688 | + | return templ_7745c5c3_CtxErr | |
| 689 | + | } | |
| 690 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 691 | + | if !templ_7745c5c3_IsBuffer { | |
| 692 | + | defer func() { | |
| 693 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 694 | + | if templ_7745c5c3_Err == nil { | |
| 695 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 696 | + | } | |
| 697 | + | }() | |
| 698 | + | } | |
| 699 | + | ctx = templ.InitializeContext(ctx) | |
| 700 | + | templ_7745c5c3_Var37 := templ.GetChildren(ctx) | |
| 701 | + | if templ_7745c5c3_Var37 == nil { | |
| 702 | + | templ_7745c5c3_Var37 = templ.NopComponent | |
| 703 | + | } | |
| 704 | + | ctx = templ.ClearChildren(ctx) | |
| 705 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<form class=\"sv-card-form sv-config-form\" data-sv-action=\"config.performance.save\"><label><span>Profile</span><select name=\"profile\"><option value=\"default\"") | |
| 706 | + | if templ_7745c5c3_Err != nil { | |
| 707 | + | return templ_7745c5c3_Err | |
| 708 | + | } | |
| 709 | + | if performanceProfileSelected(config.Performance.Profile, "default") { | |
| 710 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, " selected") | |
| 44 | 711 | if templ_7745c5c3_Err != nil { | |
| 45 | 712 | return templ_7745c5c3_Err | |
| 46 | 713 | } | |
| 47 | - | return nil | |
| 48 | - | }) | |
| 49 | - | templ_7745c5c3_Err = Section("sv-config-values", "Config values").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) | |
| 714 | + | } | |
| 715 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, ">Default</option> <option value=\"lite\"") | |
| 50 | 716 | if templ_7745c5c3_Err != nil { | |
| 51 | 717 | return templ_7745c5c3_Err | |
| 52 | 718 | } | |
| 53 | - | templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 54 | - | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 55 | - | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |
| 56 | - | if !templ_7745c5c3_IsBuffer { | |
| 57 | - | defer func() { | |
| 58 | - | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |
| 59 | - | if templ_7745c5c3_Err == nil { | |
| 60 | - | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |
| 61 | - | } | |
| 62 | - | }() | |
| 63 | - | } | |
| 64 | - | ctx = templ.InitializeContext(ctx) | |
| 65 | - | templ_7745c5c3_Err = Meta(configKeybindingSummary(data.Keybindings)).Render(ctx, templ_7745c5c3_Buffer) | |
| 719 | + | if performanceProfileSelected(config.Performance.Profile, "lite") { | |
| 720 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, " selected") | |
| 66 | 721 | if templ_7745c5c3_Err != nil { | |
| 67 | 722 | return templ_7745c5c3_Err | |
| 68 | 723 | } | |
| 69 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") | |
| 724 | + | } | |
| 725 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, ">Lite</option> <option value=\"max\"") | |
| 726 | + | if templ_7745c5c3_Err != nil { | |
| 727 | + | return templ_7745c5c3_Err | |
| 728 | + | } | |
| 729 | + | if performanceProfileSelected(config.Performance.Profile, "max") { | |
| 730 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, " selected") | |
| 70 | 731 | if templ_7745c5c3_Err != nil { | |
| 71 | 732 | return templ_7745c5c3_Err | |
| 72 | 733 | } | |
| 73 | - | templ_7745c5c3_Err = ConfigKeybindings(data.Keybindings).Render(ctx, templ_7745c5c3_Buffer) | |
| 734 | + | } | |
| 735 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, ">Max</option> <option value=\"custom\"") | |
| 736 | + | if templ_7745c5c3_Err != nil { | |
| 737 | + | return templ_7745c5c3_Err | |
| 738 | + | } | |
| 739 | + | if performanceProfileSelected(config.Performance.Profile, "custom") { | |
| 740 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " selected") | |
| 74 | 741 | if templ_7745c5c3_Err != nil { | |
| 75 | 742 | return templ_7745c5c3_Err | |
| 76 | 743 | } | |
| 77 | - | return nil | |
| 78 | - | }) | |
| 79 | - | templ_7745c5c3_Err = Section("sv-config-keybindings", "Keybindings").Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) | |
| 744 | + | } | |
| 745 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, ">Custom</option></select></label> <label><span>Skia CPU threads</span><input name=\"skia_cpu_threads\" type=\"number\" min=\"0\" max=\"8\" value=\"") | |
| 746 | + | if templ_7745c5c3_Err != nil { | |
| 747 | + | return templ_7745c5c3_Err | |
| 748 | + | } | |
| 749 | + | var templ_7745c5c3_Var38 string | |
| 750 | + | templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.SkiaCPUThreads)) | |
| 751 | + | if templ_7745c5c3_Err != nil { | |
| 752 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 107, Col: 164} | |
| 753 | + | } | |
| 754 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) | |
| 755 | + | if templ_7745c5c3_Err != nil { | |
| 756 | + | return templ_7745c5c3_Err | |
| 757 | + | } | |
| 758 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "\"></label> <label><span>Skia GPU threads</span><input name=\"skia_gpu_threads\" type=\"number\" min=\"-1\" max=\"8\" value=\"") | |
| 759 | + | if templ_7745c5c3_Err != nil { | |
| 760 | + | return templ_7745c5c3_Err | |
| 761 | + | } | |
| 762 | + | var templ_7745c5c3_Var39 string | |
| 763 | + | templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.SkiaGPUThreads)) | |
| 764 | + | if templ_7745c5c3_Err != nil { | |
| 765 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 108, Col: 165} | |
| 766 | + | } | |
| 767 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) | |
| 768 | + | if templ_7745c5c3_Err != nil { | |
| 769 | + | return templ_7745c5c3_Err | |
| 770 | + | } | |
| 771 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\"></label> <label><span>Web process memory MB</span><input name=\"web_process_memory_mb\" type=\"number\" min=\"0\" max=\"16384\" value=\"") | |
| 772 | + | if templ_7745c5c3_Err != nil { | |
| 773 | + | return templ_7745c5c3_Err | |
| 774 | + | } | |
| 775 | + | var templ_7745c5c3_Var40 string | |
| 776 | + | templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.WebProcessMemoryMB)) | |
| 777 | + | if templ_7745c5c3_Err != nil { | |
| 778 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 109, Col: 182} | |
| 779 | + | } | |
| 780 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) | |
| 781 | + | if templ_7745c5c3_Err != nil { | |
| 782 | + | return templ_7745c5c3_Err | |
| 783 | + | } | |
| 784 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\"></label> <label><span>Network process memory MB</span><input name=\"network_process_memory_mb\" type=\"number\" min=\"0\" max=\"4096\" value=\"") | |
| 785 | + | if templ_7745c5c3_Err != nil { | |
| 786 | + | return templ_7745c5c3_Err | |
| 787 | + | } | |
| 788 | + | var templ_7745c5c3_Var41 string | |
| 789 | + | templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.NetworkProcessMemoryMB)) | |
| 790 | + | if templ_7745c5c3_Err != nil { | |
| 791 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 110, Col: 193} | |
| 792 | + | } | |
| 793 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) | |
| 794 | + | if templ_7745c5c3_Err != nil { | |
| 795 | + | return templ_7745c5c3_Err | |
| 796 | + | } | |
| 797 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\"></label> <label><span>WebView pool prewarm</span><input name=\"webview_pool_prewarm\" type=\"number\" min=\"0\" max=\"20\" value=\"") | |
| 798 | + | if templ_7745c5c3_Err != nil { | |
| 799 | + | return templ_7745c5c3_Err | |
| 800 | + | } | |
| 801 | + | var templ_7745c5c3_Var42 string | |
| 802 | + | templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.WebViewPoolPrewarm)) | |
| 803 | + | if templ_7745c5c3_Err != nil { | |
| 804 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 111, Col: 177} | |
| 805 | + | } | |
| 806 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) | |
| 807 | + | if templ_7745c5c3_Err != nil { | |
| 808 | + | return templ_7745c5c3_Err | |
| 809 | + | } | |
| 810 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\"></label> <button class=\"sv-button\" type=\"submit\">Save performance</button></form><div class=\"sv-stat-grid\"><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |
| 811 | + | if templ_7745c5c3_Err != nil { | |
| 812 | + | return templ_7745c5c3_Err | |
| 813 | + | } | |
| 814 | + | var templ_7745c5c3_Var43 string | |
| 815 | + | templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Hardware.CPUThreads)) | |
| 816 | + | if templ_7745c5c3_Err != nil { | |
| 817 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 115, Col: 113} | |
| 818 | + | } | |
| 819 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43)) | |
| 820 | + | if templ_7745c5c3_Err != nil { | |
| 821 | + | return templ_7745c5c3_Err | |
| 822 | + | } | |
| 823 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</span><span class=\"sv-stat-label\">CPU threads</span></div><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |
| 824 | + | if templ_7745c5c3_Err != nil { | |
| 825 | + | return templ_7745c5c3_Err | |
| 826 | + | } | |
| 827 | + | var templ_7745c5c3_Var44 string | |
| 828 | + | templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Hardware.TotalRAMMB)) | |
| 829 | + | if templ_7745c5c3_Err != nil { | |
| 830 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 116, Col: 113} | |
| 831 | + | } | |
| 832 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) | |
| 833 | + | if templ_7745c5c3_Err != nil { | |
| 834 | + | return templ_7745c5c3_Err | |
| 835 | + | } | |
| 836 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "</span><span class=\"sv-stat-label\">RAM MB</span></div><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |
| 837 | + | if templ_7745c5c3_Err != nil { | |
| 838 | + | return templ_7745c5c3_Err | |
| 839 | + | } | |
| 840 | + | var templ_7745c5c3_Var45 string | |
| 841 | + | templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(config.Performance.Hardware.GPUName) | |
| 842 | + | if templ_7745c5c3_Err != nil { | |
| 843 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 117, Col: 93} | |
| 844 | + | } | |
| 845 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45)) | |
| 846 | + | if templ_7745c5c3_Err != nil { | |
| 847 | + | return templ_7745c5c3_Err | |
| 848 | + | } | |
| 849 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</span><span class=\"sv-stat-label\">GPU</span></div><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |
| 850 | + | if templ_7745c5c3_Err != nil { | |
| 851 | + | return templ_7745c5c3_Err | |
| 852 | + | } | |
| 853 | + | var templ_7745c5c3_Var46 string | |
| 854 | + | templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(config.EngineType) | |
| 855 | + | if templ_7745c5c3_Err != nil { | |
| 856 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 118, Col: 75} | |
| 857 | + | } | |
| 858 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) | |
| 80 | 859 | if templ_7745c5c3_Err != nil { | |
| 81 | 860 | return templ_7745c5c3_Err | |
| 82 | 861 | } | |
| 862 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</span><span class=\"sv-stat-label\">Engine</span></div></div>") | |
| 863 | + | if templ_7745c5c3_Err != nil { | |
| 864 | + | return templ_7745c5c3_Err | |
| 865 | + | } | |
| 866 | + | if !engineIsWebKit(config.EngineType) { | |
| 867 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "<p class=\"sv-meta\">Performance tuning applies only to the WebKit engine.</p>") | |
| 868 | + | if templ_7745c5c3_Err != nil { | |
| 869 | + | return templ_7745c5c3_Err | |
| 870 | + | } | |
| 871 | + | } else { | |
| 872 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "<p class=\"sv-meta\">Performance profile changes may require restarting the browser to affect existing engine processes.</p>") | |
| 873 | + | if templ_7745c5c3_Err != nil { | |
| 874 | + | return templ_7745c5c3_Err | |
| 875 | + | } | |
| 876 | + | } | |
| 83 | 877 | return nil | |
| 84 | 878 | }) | |
| 85 | 879 | } | |
| @@ -100,12 +894,16 @@ func ConfigKeybindings(keybindings any) templ.Component { | |||
| 100 | 894 | }() | |
| 101 | 895 | } | |
| 102 | 896 | ctx = templ.InitializeContext(ctx) | |
| 103 | - | templ_7745c5c3_Var4 := templ.GetChildren(ctx) | |
| 104 | - | if templ_7745c5c3_Var4 == nil { | |
| 105 | - | templ_7745c5c3_Var4 = templ.NopComponent | |
| 897 | + | templ_7745c5c3_Var47 := templ.GetChildren(ctx) | |
| 898 | + | if templ_7745c5c3_Var47 == nil { | |
| 899 | + | templ_7745c5c3_Var47 = templ.NopComponent | |
| 106 | 900 | } | |
| 107 | 901 | ctx = templ.ClearChildren(ctx) | |
| 108 | 902 | groups := configKeybindingGroups(keybindings) | |
| 903 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<div class=\"sv-button-row\"><button class=\"sv-button sv-button-secondary sv-button-danger\" type=\"button\" data-sv-action=\"config.keybinding.resetAll\" data-sv-confirm=\"Reset all keybindings to defaults?\">Reset all keybindings</button></div>") | |
| 904 | + | if templ_7745c5c3_Err != nil { | |
| 905 | + | return templ_7745c5c3_Err | |
| 906 | + | } | |
| 109 | 907 | if groups == nil { | |
| 110 | 908 | templ_7745c5c3_Err = EmptyState("Keybindings unavailable").Render(ctx, templ_7745c5c3_Buffer) | |
| 111 | 909 | if templ_7745c5c3_Err != nil { | |
| @@ -144,48 +942,48 @@ func ConfigKeybindingGroup(group renderedKeybindingGroup) templ.Component { | |||
| 144 | 942 | }() | |
| 145 | 943 | } | |
| 146 | 944 | ctx = templ.InitializeContext(ctx) | |
| 147 | - | templ_7745c5c3_Var5 := templ.GetChildren(ctx) | |
| 148 | - | if templ_7745c5c3_Var5 == nil { | |
| 149 | - | templ_7745c5c3_Var5 = templ.NopComponent | |
| 945 | + | templ_7745c5c3_Var48 := templ.GetChildren(ctx) | |
| 946 | + | if templ_7745c5c3_Var48 == nil { | |
| 947 | + | templ_7745c5c3_Var48 = templ.NopComponent | |
| 150 | 948 | } | |
| 151 | 949 | ctx = templ.ClearChildren(ctx) | |
| 152 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"sv-group\"><div class=\"sv-group-header\"><div><h4>") | |
| 950 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "<div class=\"sv-group\"><div class=\"sv-group-header\"><div><h4>") | |
| 153 | 951 | if templ_7745c5c3_Err != nil { | |
| 154 | 952 | return templ_7745c5c3_Err | |
| 155 | 953 | } | |
| 156 | - | var templ_7745c5c3_Var6 string | |
| 157 | - | templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupTitle(group)) | |
| 954 | + | var templ_7745c5c3_Var49 string | |
| 955 | + | templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupTitle(group)) | |
| 158 | 956 | if templ_7745c5c3_Err != nil { | |
| 159 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 30, Col: 37} | |
| 957 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 147, Col: 37} | |
| 160 | 958 | } | |
| 161 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) | |
| 959 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) | |
| 162 | 960 | if templ_7745c5c3_Err != nil { | |
| 163 | 961 | return templ_7745c5c3_Err | |
| 164 | 962 | } | |
| 165 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h4>") | |
| 963 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</h4>") | |
| 166 | 964 | if templ_7745c5c3_Err != nil { | |
| 167 | 965 | return templ_7745c5c3_Err | |
| 168 | 966 | } | |
| 169 | 967 | if keybindingGroupMeta(group) != "" { | |
| 170 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<p class=\"sv-meta\">") | |
| 968 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "<p class=\"sv-meta\">") | |
| 171 | 969 | if templ_7745c5c3_Err != nil { | |
| 172 | 970 | return templ_7745c5c3_Err | |
| 173 | 971 | } | |
| 174 | - | var templ_7745c5c3_Var7 string | |
| 175 | - | templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupMeta(group)) | |
| 972 | + | var templ_7745c5c3_Var50 string | |
| 973 | + | templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupMeta(group)) | |
| 176 | 974 | if templ_7745c5c3_Err != nil { | |
| 177 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 32, Col: 52} | |
| 975 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 149, Col: 52} | |
| 178 | 976 | } | |
| 179 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) | |
| 977 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var50)) | |
| 180 | 978 | if templ_7745c5c3_Err != nil { | |
| 181 | 979 | return templ_7745c5c3_Err | |
| 182 | 980 | } | |
| 183 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</p>") | |
| 981 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "</p>") | |
| 184 | 982 | if templ_7745c5c3_Err != nil { | |
| 185 | 983 | return templ_7745c5c3_Err | |
| 186 | 984 | } | |
| 187 | 985 | } | |
| 188 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div></div><div class=\"sv-group-body\">") | |
| 986 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</div></div><div class=\"sv-group-body\">") | |
| 189 | 987 | if templ_7745c5c3_Err != nil { | |
| 190 | 988 | return templ_7745c5c3_Err | |
| 191 | 989 | } | |
| @@ -195,22 +993,22 @@ func ConfigKeybindingGroup(group renderedKeybindingGroup) templ.Component { | |||
| 195 | 993 | return templ_7745c5c3_Err | |
| 196 | 994 | } | |
| 197 | 995 | } else { | |
| 198 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<ul class=\"sv-list\">") | |
| 996 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<ul class=\"sv-list\">") | |
| 199 | 997 | if templ_7745c5c3_Err != nil { | |
| 200 | 998 | return templ_7745c5c3_Err | |
| 201 | 999 | } | |
| 202 | 1000 | for _, binding := range group.Bindings { | |
| 203 | - | templ_7745c5c3_Err = ConfigKeybinding(binding).Render(ctx, templ_7745c5c3_Buffer) | |
| 1001 | + | templ_7745c5c3_Err = ConfigKeybinding(group, binding).Render(ctx, templ_7745c5c3_Buffer) | |
| 204 | 1002 | if templ_7745c5c3_Err != nil { | |
| 205 | 1003 | return templ_7745c5c3_Err | |
| 206 | 1004 | } | |
| 207 | 1005 | } | |
| 208 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</ul>") | |
| 1006 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "</ul>") | |
| 209 | 1007 | if templ_7745c5c3_Err != nil { | |
| 210 | 1008 | return templ_7745c5c3_Err | |
| 211 | 1009 | } | |
| 212 | 1010 | } | |
| 213 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></div>") | |
| 1011 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "</div></div>") | |
| 214 | 1012 | if templ_7745c5c3_Err != nil { | |
| 215 | 1013 | return templ_7745c5c3_Err | |
| 216 | 1014 | } | |
| @@ -218,7 +1016,7 @@ func ConfigKeybindingGroup(group renderedKeybindingGroup) templ.Component { | |||
| 218 | 1016 | }) | |
| 219 | 1017 | } | |
| 220 | 1018 | ||
| 221 | - | func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |
| 1019 | + | func ConfigKeybinding(group renderedKeybindingGroup, binding renderedKeybinding) templ.Component { | |
| 222 | 1020 | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |
| 223 | 1021 | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |
| 224 | 1022 | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |
| @@ -234,38 +1032,38 @@ func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |||
| 234 | 1032 | }() | |
| 235 | 1033 | } | |
| 236 | 1034 | ctx = templ.InitializeContext(ctx) | |
| 237 | - | templ_7745c5c3_Var8 := templ.GetChildren(ctx) | |
| 238 | - | if templ_7745c5c3_Var8 == nil { | |
| 239 | - | templ_7745c5c3_Var8 = templ.NopComponent | |
| 1035 | + | templ_7745c5c3_Var51 := templ.GetChildren(ctx) | |
| 1036 | + | if templ_7745c5c3_Var51 == nil { | |
| 1037 | + | templ_7745c5c3_Var51 = templ.NopComponent | |
| 240 | 1038 | } | |
| 241 | 1039 | ctx = templ.ClearChildren(ctx) | |
| 242 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<li class=\"sv-list-row\"><div class=\"sv-keybinding-row\"><div><strong>") | |
| 1040 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "<li class=\"sv-list-row\"><div class=\"sv-keybinding-row\"><div><strong>") | |
| 243 | 1041 | if templ_7745c5c3_Err != nil { | |
| 244 | 1042 | return templ_7745c5c3_Err | |
| 245 | 1043 | } | |
| 246 | - | var templ_7745c5c3_Var9 string | |
| 247 | - | templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingDescription(binding)) | |
| 1044 | + | var templ_7745c5c3_Var52 string | |
| 1045 | + | templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingDescription(binding)) | |
| 248 | 1046 | if templ_7745c5c3_Err != nil { | |
| 249 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 54, Col: 44} | |
| 1047 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 171, Col: 44} | |
| 250 | 1048 | } | |
| 251 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) | |
| 1049 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) | |
| 252 | 1050 | if templ_7745c5c3_Err != nil { | |
| 253 | 1051 | return templ_7745c5c3_Err | |
| 254 | 1052 | } | |
| 255 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</strong><p class=\"sv-meta\">") | |
| 1053 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</strong><p class=\"sv-meta\">") | |
| 256 | 1054 | if templ_7745c5c3_Err != nil { | |
| 257 | 1055 | return templ_7745c5c3_Err | |
| 258 | 1056 | } | |
| 259 | - | var templ_7745c5c3_Var10 string | |
| 260 | - | templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingAction(binding)) | |
| 1057 | + | var templ_7745c5c3_Var53 string | |
| 1058 | + | templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingAction(binding)) | |
| 261 | 1059 | if templ_7745c5c3_Err != nil { | |
| 262 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 55, Col: 50} | |
| 1060 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 172, Col: 50} | |
| 263 | 1061 | } | |
| 264 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | |
| 1062 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53)) | |
| 265 | 1063 | if templ_7745c5c3_Err != nil { | |
| 266 | 1064 | return templ_7745c5c3_Err | |
| 267 | 1065 | } | |
| 268 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</p></div><div class=\"sv-keybinding-keys\">") | |
| 1066 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "</p><div class=\"sv-binding-keys\">") | |
| 269 | 1067 | if templ_7745c5c3_Err != nil { | |
| 270 | 1068 | return templ_7745c5c3_Err | |
| 271 | 1069 | } | |
| @@ -273,25 +1071,25 @@ func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |||
| 273 | 1071 | if templ_7745c5c3_Err != nil { | |
| 274 | 1072 | return templ_7745c5c3_Err | |
| 275 | 1073 | } | |
| 276 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<span class=\"sv-badge\">") | |
| 1074 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "<span class=\"sv-badge\">") | |
| 277 | 1075 | if templ_7745c5c3_Err != nil { | |
| 278 | 1076 | return templ_7745c5c3_Err | |
| 279 | 1077 | } | |
| 280 | - | var templ_7745c5c3_Var11 string | |
| 281 | - | templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingStatus(binding)) | |
| 1078 | + | var templ_7745c5c3_Var54 string | |
| 1079 | + | templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingStatus(binding)) | |
| 282 | 1080 | if templ_7745c5c3_Err != nil { | |
| 283 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 59, Col: 54} | |
| 1081 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 175, Col: 55} | |
| 284 | 1082 | } | |
| 285 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | |
| 1083 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54)) | |
| 286 | 1084 | if templ_7745c5c3_Err != nil { | |
| 287 | 1085 | return templ_7745c5c3_Err | |
| 288 | 1086 | } | |
| 289 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</span> ") | |
| 1087 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "</span> ") | |
| 290 | 1088 | if templ_7745c5c3_Err != nil { | |
| 291 | 1089 | return templ_7745c5c3_Err | |
| 292 | 1090 | } | |
| 293 | 1091 | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | |
| 294 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"sv-meta\">default:</span>") | |
| 1092 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "<span class=\"sv-meta\">default:</span>") | |
| 295 | 1093 | if templ_7745c5c3_Err != nil { | |
| 296 | 1094 | return templ_7745c5c3_Err | |
| 297 | 1095 | } | |
| @@ -300,7 +1098,72 @@ func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |||
| 300 | 1098 | return templ_7745c5c3_Err | |
| 301 | 1099 | } | |
| 302 | 1100 | } | |
| 303 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div></div></li>") | |
| 1101 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "</div></div><form class=\"sv-inline-form\" data-sv-action=\"config.keybinding.set\"><input type=\"hidden\" name=\"mode\" value=\"") | |
| 1102 | + | if templ_7745c5c3_Err != nil { | |
| 1103 | + | return templ_7745c5c3_Err | |
| 1104 | + | } | |
| 1105 | + | var templ_7745c5c3_Var55 string | |
| 1106 | + | templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(group.Mode) | |
| 1107 | + | if templ_7745c5c3_Err != nil { | |
| 1108 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 183, Col: 55} | |
| 1109 | + | } | |
| 1110 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var55)) | |
| 1111 | + | if templ_7745c5c3_Err != nil { | |
| 1112 | + | return templ_7745c5c3_Err | |
| 1113 | + | } | |
| 1114 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "\"> <input type=\"hidden\" name=\"action\" value=\"") | |
| 1115 | + | if templ_7745c5c3_Err != nil { | |
| 1116 | + | return templ_7745c5c3_Err | |
| 1117 | + | } | |
| 1118 | + | var templ_7745c5c3_Var56 string | |
| 1119 | + | templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(binding.Action) | |
| 1120 | + | if templ_7745c5c3_Err != nil { | |
| 1121 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 184, Col: 61} | |
| 1122 | + | } | |
| 1123 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) | |
| 1124 | + | if templ_7745c5c3_Err != nil { | |
| 1125 | + | return templ_7745c5c3_Err | |
| 1126 | + | } | |
| 1127 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\"> <label><span>Keys</span><input name=\"keys\" type=\"text\" value=\"") | |
| 1128 | + | if templ_7745c5c3_Err != nil { | |
| 1129 | + | return templ_7745c5c3_Err | |
| 1130 | + | } | |
| 1131 | + | var templ_7745c5c3_Var57 string | |
| 1132 | + | templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingKeysValue(binding.Keys)) | |
| 1133 | + | if templ_7745c5c3_Err != nil { | |
| 1134 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 185, Col: 100} | |
| 1135 | + | } | |
| 1136 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) | |
| 1137 | + | if templ_7745c5c3_Err != nil { | |
| 1138 | + | return templ_7745c5c3_Err | |
| 1139 | + | } | |
| 1140 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\" placeholder=\"ctrl+h\" required></label> <button class=\"sv-button sv-button-secondary\" type=\"submit\">Save</button> <button class=\"sv-button sv-button-secondary\" type=\"button\" data-sv-action=\"config.keybinding.reset\" data-mode=\"") | |
| 1141 | + | if templ_7745c5c3_Err != nil { | |
| 1142 | + | return templ_7745c5c3_Err | |
| 1143 | + | } | |
| 1144 | + | var templ_7745c5c3_Var58 string | |
| 1145 | + | templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(group.Mode) | |
| 1146 | + | if templ_7745c5c3_Err != nil { | |
| 1147 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 187, Col: 127} | |
| 1148 | + | } | |
| 1149 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) | |
| 1150 | + | if templ_7745c5c3_Err != nil { | |
| 1151 | + | return templ_7745c5c3_Err | |
| 1152 | + | } | |
| 1153 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "\" data-action=\"") | |
| 1154 | + | if templ_7745c5c3_Err != nil { | |
| 1155 | + | return templ_7745c5c3_Err | |
| 1156 | + | } | |
| 1157 | + | var templ_7745c5c3_Var59 string | |
| 1158 | + | templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(binding.Action) | |
| 1159 | + | if templ_7745c5c3_Err != nil { | |
| 1160 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 187, Col: 158} | |
| 1161 | + | } | |
| 1162 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59)) | |
| 1163 | + | if templ_7745c5c3_Err != nil { | |
| 1164 | + | return templ_7745c5c3_Err | |
| 1165 | + | } | |
| 1166 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "\">Reset</button></form></div></li>") | |
| 304 | 1167 | if templ_7745c5c3_Err != nil { | |
| 305 | 1168 | return templ_7745c5c3_Err | |
| 306 | 1169 | } | |
| @@ -7,6 +7,8 @@ package systemviews | |||||
| 7 | import "github.com/a-h/templ" | 7 | import "github.com/a-h/templ" | ||
| 8 | import templruntime "github.com/a-h/templ/runtime" | 8 | import templruntime "github.com/a-h/templ/runtime" | ||
| 9 | 9 | ||||
| 10 | + | import "github.com/bnema/dumber/internal/application/port" | |||
| 11 | + | ||||
| 10 | func ConfigView(data configRenderData) templ.Component { | 12 | func ConfigView(data configRenderData) templ.Component { | ||
| 11 | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | 13 | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | ||
| 12 | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | 14 | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | ||
| @@ -23,63 +25,855 @@ func ConfigView(data configRenderData) templ.Component { | |||||
| 23 | }() | 25 | }() | ||
| 24 | } | 26 | } | ||
| 25 | ctx = templ.InitializeContext(ctx) | 27 | ctx = templ.InitializeContext(ctx) | ||
| 26 | - | templ_7745c5c3_Var1 := templ.GetChildren(ctx) | 28 | + | templ_7745c5c3_Var1 := templ.GetChildren(ctx) |
| 27 | - | if templ_7745c5c3_Var1 == nil { | 29 | + | if templ_7745c5c3_Var1 == nil { |
| 28 | - | templ_7745c5c3_Var1 = templ.NopComponent | 30 | + | templ_7745c5c3_Var1 = templ.NopComponent |
| 31 | + | } | |||
| 32 | + | ctx = templ.ClearChildren(ctx) | |||
| 33 | + | templ_7745c5c3_Err = Alert("success", data.Notice).Render(ctx, templ_7745c5c3_Buffer) | |||
| 34 | + | if templ_7745c5c3_Err != nil { | |||
| 35 | + | return templ_7745c5c3_Err | |||
| 36 | + | } | |||
| 37 | + | templ_7745c5c3_Err = Alert("error", data.Error).Render(ctx, templ_7745c5c3_Buffer) | |||
| 38 | + | if templ_7745c5c3_Err != nil { | |||
| 39 | + | return templ_7745c5c3_Err | |||
| 40 | + | } | |||
| 41 | + | templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 42 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 43 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 44 | + | if !templ_7745c5c3_IsBuffer { | |||
| 45 | + | defer func() { | |||
| 46 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 47 | + | if templ_7745c5c3_Err == nil { | |||
| 48 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 49 | + | } | |||
| 50 | + | }() | |||
| 51 | + | } | |||
| 52 | + | ctx = templ.InitializeContext(ctx) | |||
| 53 | + | templ_7745c5c3_Err = AppearanceForm(data.Config).Render(ctx, templ_7745c5c3_Buffer) | |||
| 54 | + | if templ_7745c5c3_Err != nil { | |||
| 55 | + | return templ_7745c5c3_Err | |||
| 56 | + | } | |||
| 57 | + | return nil | |||
| 58 | + | }) | |||
| 59 | + | templ_7745c5c3_Err = Section("sv-config-appearance", "Appearance").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) | |||
| 60 | + | if templ_7745c5c3_Err != nil { | |||
| 61 | + | return templ_7745c5c3_Err | |||
| 62 | + | } | |||
| 63 | + | templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 64 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 65 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 66 | + | if !templ_7745c5c3_IsBuffer { | |||
| 67 | + | defer func() { | |||
| 68 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 69 | + | if templ_7745c5c3_Err == nil { | |||
| 70 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 71 | + | } | |||
| 72 | + | }() | |||
| 73 | + | } | |||
| 74 | + | ctx = templ.InitializeContext(ctx) | |||
| 75 | + | templ_7745c5c3_Err = SearchSettings(data.Config).Render(ctx, templ_7745c5c3_Buffer) | |||
| 76 | + | if templ_7745c5c3_Err != nil { | |||
| 77 | + | return templ_7745c5c3_Err | |||
| 78 | + | } | |||
| 79 | + | return nil | |||
| 80 | + | }) | |||
| 81 | + | templ_7745c5c3_Err = Section("sv-config-search", "Search").Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) | |||
| 82 | + | if templ_7745c5c3_Err != nil { | |||
| 83 | + | return templ_7745c5c3_Err | |||
| 84 | + | } | |||
| 85 | + | templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 86 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 87 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 88 | + | if !templ_7745c5c3_IsBuffer { | |||
| 89 | + | defer func() { | |||
| 90 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 91 | + | if templ_7745c5c3_Err == nil { | |||
| 92 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 93 | + | } | |||
| 94 | + | }() | |||
| 95 | + | } | |||
| 96 | + | ctx = templ.InitializeContext(ctx) | |||
| 97 | + | templ_7745c5c3_Err = PerformanceSettings(data.Config).Render(ctx, templ_7745c5c3_Buffer) | |||
| 98 | + | if templ_7745c5c3_Err != nil { | |||
| 99 | + | return templ_7745c5c3_Err | |||
| 100 | + | } | |||
| 101 | + | return nil | |||
| 102 | + | }) | |||
| 103 | + | templ_7745c5c3_Err = Section("sv-config-performance", "Performance").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) | |||
| 104 | + | if templ_7745c5c3_Err != nil { | |||
| 105 | + | return templ_7745c5c3_Err | |||
| 106 | + | } | |||
| 107 | + | templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 108 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 109 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 110 | + | if !templ_7745c5c3_IsBuffer { | |||
| 111 | + | defer func() { | |||
| 112 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 113 | + | if templ_7745c5c3_Err == nil { | |||
| 114 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 115 | + | } | |||
| 116 | + | }() | |||
| 117 | + | } | |||
| 118 | + | ctx = templ.InitializeContext(ctx) | |||
| 119 | + | templ_7745c5c3_Err = Meta(configKeybindingSummary(data.Keybindings)).Render(ctx, templ_7745c5c3_Buffer) | |||
| 120 | + | if templ_7745c5c3_Err != nil { | |||
| 121 | + | return templ_7745c5c3_Err | |||
| 122 | + | } | |||
| 123 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") | |||
| 124 | + | if templ_7745c5c3_Err != nil { | |||
| 125 | + | return templ_7745c5c3_Err | |||
| 126 | + | } | |||
| 127 | + | templ_7745c5c3_Err = ConfigKeybindings(data.Keybindings).Render(ctx, templ_7745c5c3_Buffer) | |||
| 128 | + | if templ_7745c5c3_Err != nil { | |||
| 129 | + | return templ_7745c5c3_Err | |||
| 130 | + | } | |||
| 131 | + | return nil | |||
| 132 | + | }) | |||
| 133 | + | templ_7745c5c3_Err = Section("sv-config-keybindings", "Keybindings").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) | |||
| 134 | + | if templ_7745c5c3_Err != nil { | |||
| 135 | + | return templ_7745c5c3_Err | |||
| 136 | + | } | |||
| 137 | + | templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 138 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 139 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 140 | + | if !templ_7745c5c3_IsBuffer { | |||
| 141 | + | defer func() { | |||
| 142 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 143 | + | if templ_7745c5c3_Err == nil { | |||
| 144 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 145 | + | } | |||
| 146 | + | }() | |||
| 147 | + | } | |||
| 148 | + | ctx = templ.InitializeContext(ctx) | |||
| 149 | + | templ_7745c5c3_Err = KV(flattenValues(data.Config)).Render(ctx, templ_7745c5c3_Buffer) | |||
| 150 | + | if templ_7745c5c3_Err != nil { | |||
| 151 | + | return templ_7745c5c3_Err | |||
| 152 | + | } | |||
| 153 | + | return nil | |||
| 154 | + | }) | |||
| 155 | + | templ_7745c5c3_Err = Section("sv-config-values", "Current payload").Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer) | |||
| 156 | + | if templ_7745c5c3_Err != nil { | |||
| 157 | + | return templ_7745c5c3_Err | |||
| 158 | + | } | |||
| 159 | + | return nil | |||
| 160 | + | }) | |||
| 161 | + | } | |||
| 162 | + | ||||
| 163 | + | func AppearanceForm(config port.SystemviewConfigPayload) templ.Component { | |||
| 164 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 165 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 166 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |||
| 167 | + | return templ_7745c5c3_CtxErr | |||
| 168 | + | } | |||
| 169 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 170 | + | if !templ_7745c5c3_IsBuffer { | |||
| 171 | + | defer func() { | |||
| 172 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 173 | + | if templ_7745c5c3_Err == nil { | |||
| 174 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 175 | + | } | |||
| 176 | + | }() | |||
| 177 | + | } | |||
| 178 | + | ctx = templ.InitializeContext(ctx) | |||
| 179 | + | templ_7745c5c3_Var7 := templ.GetChildren(ctx) | |||
| 180 | + | if templ_7745c5c3_Var7 == nil { | |||
| 181 | + | templ_7745c5c3_Var7 = templ.NopComponent | |||
| 182 | + | } | |||
| 183 | + | ctx = templ.ClearChildren(ctx) | |||
| 184 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<form class=\"sv-card-form sv-config-form\" data-sv-action=\"config.appearance.save\"><label><span>Sans font</span><input name=\"sans_font\" type=\"text\" value=\"") | |||
| 185 | + | if templ_7745c5c3_Err != nil { | |||
| 186 | + | return templ_7745c5c3_Err | |||
| 187 | + | } | |||
| 188 | + | var templ_7745c5c3_Var8 string | |||
| 189 | + | templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(config.Appearance.SansFont) | |||
| 190 | + | if templ_7745c5c3_Err != nil { | |||
| 191 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 28, Col: 101} | |||
| 192 | + | } | |||
| 193 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) | |||
| 194 | + | if templ_7745c5c3_Err != nil { | |||
| 195 | + | return templ_7745c5c3_Err | |||
| 196 | + | } | |||
| 197 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" required></label> <label><span>Serif font</span><input name=\"serif_font\" type=\"text\" value=\"") | |||
| 198 | + | if templ_7745c5c3_Err != nil { | |||
| 199 | + | return templ_7745c5c3_Err | |||
| 200 | + | } | |||
| 201 | + | var templ_7745c5c3_Var9 string | |||
| 202 | + | templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(config.Appearance.SerifFont) | |||
| 203 | + | if templ_7745c5c3_Err != nil { | |||
| 204 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 29, Col: 104} | |||
| 205 | + | } | |||
| 206 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) | |||
| 207 | + | if templ_7745c5c3_Err != nil { | |||
| 208 | + | return templ_7745c5c3_Err | |||
| 209 | + | } | |||
| 210 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" required></label> <label><span>Monospace font</span><input name=\"monospace_font\" type=\"text\" value=\"") | |||
| 211 | + | if templ_7745c5c3_Err != nil { | |||
| 212 | + | return templ_7745c5c3_Err | |||
| 213 | + | } | |||
| 214 | + | var templ_7745c5c3_Var10 string | |||
| 215 | + | templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(config.Appearance.MonospaceFont) | |||
| 216 | + | if templ_7745c5c3_Err != nil { | |||
| 217 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 30, Col: 116} | |||
| 218 | + | } | |||
| 219 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | |||
| 220 | + | if templ_7745c5c3_Err != nil { | |||
| 221 | + | return templ_7745c5c3_Err | |||
| 222 | + | } | |||
| 223 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" required></label> <label><span>Default font size</span><input name=\"default_font_size\" type=\"number\" min=\"1\" max=\"72\" value=\"") | |||
| 224 | + | if templ_7745c5c3_Err != nil { | |||
| 225 | + | return templ_7745c5c3_Err | |||
| 226 | + | } | |||
| 227 | + | var templ_7745c5c3_Var11 string | |||
| 228 | + | templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Appearance.DefaultFontSize)) | |||
| 229 | + | if templ_7745c5c3_Err != nil { | |||
| 230 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 31, Col: 160} | |||
| 231 | + | } | |||
| 232 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | |||
| 233 | + | if templ_7745c5c3_Err != nil { | |||
| 234 | + | return templ_7745c5c3_Err | |||
| 235 | + | } | |||
| 236 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" required></label> <label><span>UI scale</span><input name=\"default_ui_scale\" type=\"number\" min=\"0.5\" max=\"3\" step=\"0.05\" value=\"") | |||
| 237 | + | if templ_7745c5c3_Err != nil { | |||
| 238 | + | return templ_7745c5c3_Err | |||
| 239 | + | } | |||
| 240 | + | var templ_7745c5c3_Var12 string | |||
| 241 | + | templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigFloat(config.DefaultUIScale)) | |||
| 242 | + | if templ_7745c5c3_Err != nil { | |||
| 243 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 32, Col: 153} | |||
| 244 | + | } | |||
| 245 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) | |||
| 246 | + | if templ_7745c5c3_Err != nil { | |||
| 247 | + | return templ_7745c5c3_Err | |||
| 248 | + | } | |||
| 249 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" required></label> <label><span>Color scheme</span><select name=\"color_scheme\"><option value=\"default\"") | |||
| 250 | + | if templ_7745c5c3_Err != nil { | |||
| 251 | + | return templ_7745c5c3_Err | |||
| 252 | + | } | |||
| 253 | + | if colorSchemeSelected(config.Appearance.ColorScheme, "default") { | |||
| 254 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " selected") | |||
| 255 | + | if templ_7745c5c3_Err != nil { | |||
| 256 | + | return templ_7745c5c3_Err | |||
| 257 | + | } | |||
| 258 | + | } | |||
| 259 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, ">System default</option> <option value=\"prefer-light\"") | |||
| 260 | + | if templ_7745c5c3_Err != nil { | |||
| 261 | + | return templ_7745c5c3_Err | |||
| 262 | + | } | |||
| 263 | + | if colorSchemeSelected(config.Appearance.ColorScheme, "prefer-light") { | |||
| 264 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " selected") | |||
| 265 | + | if templ_7745c5c3_Err != nil { | |||
| 266 | + | return templ_7745c5c3_Err | |||
| 267 | + | } | |||
| 268 | + | } | |||
| 269 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, ">Prefer light</option> <option value=\"prefer-dark\"") | |||
| 270 | + | if templ_7745c5c3_Err != nil { | |||
| 271 | + | return templ_7745c5c3_Err | |||
| 272 | + | } | |||
| 273 | + | if colorSchemeSelected(config.Appearance.ColorScheme, "prefer-dark") { | |||
| 274 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, " selected") | |||
| 275 | + | if templ_7745c5c3_Err != nil { | |||
| 276 | + | return templ_7745c5c3_Err | |||
| 277 | + | } | |||
| 278 | + | } | |||
| 279 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, ">Prefer dark</option></select></label>") | |||
| 280 | + | if templ_7745c5c3_Err != nil { | |||
| 281 | + | return templ_7745c5c3_Err | |||
| 282 | + | } | |||
| 283 | + | templ_7745c5c3_Err = PaletteFields("Light palette", "light", config.Appearance.LightPalette).Render(ctx, templ_7745c5c3_Buffer) | |||
| 284 | + | if templ_7745c5c3_Err != nil { | |||
| 285 | + | return templ_7745c5c3_Err | |||
| 286 | + | } | |||
| 287 | + | templ_7745c5c3_Err = PaletteFields("Dark palette", "dark", config.Appearance.DarkPalette).Render(ctx, templ_7745c5c3_Buffer) | |||
| 288 | + | if templ_7745c5c3_Err != nil { | |||
| 289 | + | return templ_7745c5c3_Err | |||
| 290 | + | } | |||
| 291 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"sv-button-row sv-form-actions\"><button class=\"sv-button\" type=\"submit\">Save appearance</button> <button class=\"sv-button sv-button-secondary\" type=\"button\" data-sv-action=\"config.appearance.reset\" data-sv-confirm=\"Reset appearance settings to defaults?\">Reset appearance</button></div></form>") | |||
| 292 | + | if templ_7745c5c3_Err != nil { | |||
| 293 | + | return templ_7745c5c3_Err | |||
| 294 | + | } | |||
| 295 | + | return nil | |||
| 296 | + | }) | |||
| 297 | + | } | |||
| 298 | + | ||||
| 299 | + | func PaletteFields(title string, prefix string, palette port.ColorPalette) templ.Component { | |||
| 300 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 301 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 302 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |||
| 303 | + | return templ_7745c5c3_CtxErr | |||
| 304 | + | } | |||
| 305 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 306 | + | if !templ_7745c5c3_IsBuffer { | |||
| 307 | + | defer func() { | |||
| 308 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 309 | + | if templ_7745c5c3_Err == nil { | |||
| 310 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 311 | + | } | |||
| 312 | + | }() | |||
| 313 | + | } | |||
| 314 | + | ctx = templ.InitializeContext(ctx) | |||
| 315 | + | templ_7745c5c3_Var13 := templ.GetChildren(ctx) | |||
| 316 | + | if templ_7745c5c3_Var13 == nil { | |||
| 317 | + | templ_7745c5c3_Var13 = templ.NopComponent | |||
| 318 | + | } | |||
| 319 | + | ctx = templ.ClearChildren(ctx) | |||
| 320 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<fieldset class=\"sv-fieldset\"><legend>") | |||
| 321 | + | if templ_7745c5c3_Err != nil { | |||
| 322 | + | return templ_7745c5c3_Err | |||
| 323 | + | } | |||
| 324 | + | var templ_7745c5c3_Var14 string | |||
| 325 | + | templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(title) | |||
| 326 | + | if templ_7745c5c3_Err != nil { | |||
| 327 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 49, Col: 17} | |||
| 328 | + | } | |||
| 329 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) | |||
| 330 | + | if templ_7745c5c3_Err != nil { | |||
| 331 | + | return templ_7745c5c3_Err | |||
| 332 | + | } | |||
| 333 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</legend> <label><span>Background</span><input name=\"") | |||
| 334 | + | if templ_7745c5c3_Err != nil { | |||
| 335 | + | return templ_7745c5c3_Err | |||
| 336 | + | } | |||
| 337 | + | var templ_7745c5c3_Var15 string | |||
| 338 | + | templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_background") | |||
| 339 | + | if templ_7745c5c3_Err != nil { | |||
| 340 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 50, Col: 68} | |||
| 341 | + | } | |||
| 342 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) | |||
| 343 | + | if templ_7745c5c3_Err != nil { | |||
| 344 | + | return templ_7745c5c3_Err | |||
| 345 | + | } | |||
| 346 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" type=\"text\" value=\"") | |||
| 347 | + | if templ_7745c5c3_Err != nil { | |||
| 348 | + | return templ_7745c5c3_Err | |||
| 349 | + | } | |||
| 350 | + | var templ_7745c5c3_Var16 string | |||
| 351 | + | templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Background) | |||
| 352 | + | if templ_7745c5c3_Err != nil { | |||
| 353 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 50, Col: 109} | |||
| 354 | + | } | |||
| 355 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) | |||
| 356 | + | if templ_7745c5c3_Err != nil { | |||
| 357 | + | return templ_7745c5c3_Err | |||
| 358 | + | } | |||
| 359 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" required></label> <label><span>Surface</span><input name=\"") | |||
| 360 | + | if templ_7745c5c3_Err != nil { | |||
| 361 | + | return templ_7745c5c3_Err | |||
| 362 | + | } | |||
| 363 | + | var templ_7745c5c3_Var17 string | |||
| 364 | + | templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_surface") | |||
| 365 | + | if templ_7745c5c3_Err != nil { | |||
| 366 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 51, Col: 62} | |||
| 367 | + | } | |||
| 368 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) | |||
| 369 | + | if templ_7745c5c3_Err != nil { | |||
| 370 | + | return templ_7745c5c3_Err | |||
| 371 | + | } | |||
| 372 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" type=\"text\" value=\"") | |||
| 373 | + | if templ_7745c5c3_Err != nil { | |||
| 374 | + | return templ_7745c5c3_Err | |||
| 375 | + | } | |||
| 376 | + | var templ_7745c5c3_Var18 string | |||
| 377 | + | templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Surface) | |||
| 378 | + | if templ_7745c5c3_Err != nil { | |||
| 379 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 51, Col: 100} | |||
| 380 | + | } | |||
| 381 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) | |||
| 382 | + | if templ_7745c5c3_Err != nil { | |||
| 383 | + | return templ_7745c5c3_Err | |||
| 384 | + | } | |||
| 385 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" required></label> <label><span>Surface variant</span><input name=\"") | |||
| 386 | + | if templ_7745c5c3_Err != nil { | |||
| 387 | + | return templ_7745c5c3_Err | |||
| 388 | + | } | |||
| 389 | + | var templ_7745c5c3_Var19 string | |||
| 390 | + | templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_surface_variant") | |||
| 391 | + | if templ_7745c5c3_Err != nil { | |||
| 392 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 52, Col: 78} | |||
| 393 | + | } | |||
| 394 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) | |||
| 395 | + | if templ_7745c5c3_Err != nil { | |||
| 396 | + | return templ_7745c5c3_Err | |||
| 397 | + | } | |||
| 398 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" type=\"text\" value=\"") | |||
| 399 | + | if templ_7745c5c3_Err != nil { | |||
| 400 | + | return templ_7745c5c3_Err | |||
| 401 | + | } | |||
| 402 | + | var templ_7745c5c3_Var20 string | |||
| 403 | + | templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(palette.SurfaceVariant) | |||
| 404 | + | if templ_7745c5c3_Err != nil { | |||
| 405 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 52, Col: 123} | |||
| 406 | + | } | |||
| 407 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) | |||
| 408 | + | if templ_7745c5c3_Err != nil { | |||
| 409 | + | return templ_7745c5c3_Err | |||
| 410 | + | } | |||
| 411 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" required></label> <label><span>Text</span><input name=\"") | |||
| 412 | + | if templ_7745c5c3_Err != nil { | |||
| 413 | + | return templ_7745c5c3_Err | |||
| 414 | + | } | |||
| 415 | + | var templ_7745c5c3_Var21 string | |||
| 416 | + | templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_text") | |||
| 417 | + | if templ_7745c5c3_Err != nil { | |||
| 418 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 53, Col: 56} | |||
| 419 | + | } | |||
| 420 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) | |||
| 421 | + | if templ_7745c5c3_Err != nil { | |||
| 422 | + | return templ_7745c5c3_Err | |||
| 423 | + | } | |||
| 424 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" type=\"text\" value=\"") | |||
| 425 | + | if templ_7745c5c3_Err != nil { | |||
| 426 | + | return templ_7745c5c3_Err | |||
| 427 | + | } | |||
| 428 | + | var templ_7745c5c3_Var22 string | |||
| 429 | + | templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Text) | |||
| 430 | + | if templ_7745c5c3_Err != nil { | |||
| 431 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 53, Col: 91} | |||
| 432 | + | } | |||
| 433 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) | |||
| 434 | + | if templ_7745c5c3_Err != nil { | |||
| 435 | + | return templ_7745c5c3_Err | |||
| 436 | + | } | |||
| 437 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" required></label> <label><span>Muted</span><input name=\"") | |||
| 438 | + | if templ_7745c5c3_Err != nil { | |||
| 439 | + | return templ_7745c5c3_Err | |||
| 440 | + | } | |||
| 441 | + | var templ_7745c5c3_Var23 string | |||
| 442 | + | templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_muted") | |||
| 443 | + | if templ_7745c5c3_Err != nil { | |||
| 444 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 54, Col: 58} | |||
| 445 | + | } | |||
| 446 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) | |||
| 447 | + | if templ_7745c5c3_Err != nil { | |||
| 448 | + | return templ_7745c5c3_Err | |||
| 449 | + | } | |||
| 450 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" type=\"text\" value=\"") | |||
| 451 | + | if templ_7745c5c3_Err != nil { | |||
| 452 | + | return templ_7745c5c3_Err | |||
| 453 | + | } | |||
| 454 | + | var templ_7745c5c3_Var24 string | |||
| 455 | + | templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Muted) | |||
| 456 | + | if templ_7745c5c3_Err != nil { | |||
| 457 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 54, Col: 94} | |||
| 458 | + | } | |||
| 459 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) | |||
| 460 | + | if templ_7745c5c3_Err != nil { | |||
| 461 | + | return templ_7745c5c3_Err | |||
| 462 | + | } | |||
| 463 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\" required></label> <label><span>Accent</span><input name=\"") | |||
| 464 | + | if templ_7745c5c3_Err != nil { | |||
| 465 | + | return templ_7745c5c3_Err | |||
| 466 | + | } | |||
| 467 | + | var templ_7745c5c3_Var25 string | |||
| 468 | + | templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_accent") | |||
| 469 | + | if templ_7745c5c3_Err != nil { | |||
| 470 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 55, Col: 60} | |||
| 471 | + | } | |||
| 472 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) | |||
| 473 | + | if templ_7745c5c3_Err != nil { | |||
| 474 | + | return templ_7745c5c3_Err | |||
| 475 | + | } | |||
| 476 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" type=\"text\" value=\"") | |||
| 477 | + | if templ_7745c5c3_Err != nil { | |||
| 478 | + | return templ_7745c5c3_Err | |||
| 479 | + | } | |||
| 480 | + | var templ_7745c5c3_Var26 string | |||
| 481 | + | templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Accent) | |||
| 482 | + | if templ_7745c5c3_Err != nil { | |||
| 483 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 55, Col: 97} | |||
| 484 | + | } | |||
| 485 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) | |||
| 486 | + | if templ_7745c5c3_Err != nil { | |||
| 487 | + | return templ_7745c5c3_Err | |||
| 488 | + | } | |||
| 489 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" required></label> <label><span>Border</span><input name=\"") | |||
| 490 | + | if templ_7745c5c3_Err != nil { | |||
| 491 | + | return templ_7745c5c3_Err | |||
| 492 | + | } | |||
| 493 | + | var templ_7745c5c3_Var27 string | |||
| 494 | + | templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(prefix + "_border") | |||
| 495 | + | if templ_7745c5c3_Err != nil { | |||
| 496 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 56, Col: 60} | |||
| 497 | + | } | |||
| 498 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) | |||
| 499 | + | if templ_7745c5c3_Err != nil { | |||
| 500 | + | return templ_7745c5c3_Err | |||
| 501 | + | } | |||
| 502 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" type=\"text\" value=\"") | |||
| 503 | + | if templ_7745c5c3_Err != nil { | |||
| 504 | + | return templ_7745c5c3_Err | |||
| 505 | + | } | |||
| 506 | + | var templ_7745c5c3_Var28 string | |||
| 507 | + | templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(palette.Border) | |||
| 508 | + | if templ_7745c5c3_Err != nil { | |||
| 509 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 56, Col: 97} | |||
| 510 | + | } | |||
| 511 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) | |||
| 512 | + | if templ_7745c5c3_Err != nil { | |||
| 513 | + | return templ_7745c5c3_Err | |||
| 514 | + | } | |||
| 515 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\" required></label></fieldset>") | |||
| 516 | + | if templ_7745c5c3_Err != nil { | |||
| 517 | + | return templ_7745c5c3_Err | |||
| 518 | + | } | |||
| 519 | + | return nil | |||
| 520 | + | }) | |||
| 521 | + | } | |||
| 522 | + | ||||
| 523 | + | func SearchSettings(config port.SystemviewConfigPayload) templ.Component { | |||
| 524 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 525 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 526 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |||
| 527 | + | return templ_7745c5c3_CtxErr | |||
| 528 | + | } | |||
| 529 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 530 | + | if !templ_7745c5c3_IsBuffer { | |||
| 531 | + | defer func() { | |||
| 532 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 533 | + | if templ_7745c5c3_Err == nil { | |||
| 534 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 535 | + | } | |||
| 536 | + | }() | |||
| 537 | + | } | |||
| 538 | + | ctx = templ.InitializeContext(ctx) | |||
| 539 | + | templ_7745c5c3_Var29 := templ.GetChildren(ctx) | |||
| 540 | + | if templ_7745c5c3_Var29 == nil { | |||
| 541 | + | templ_7745c5c3_Var29 = templ.NopComponent | |||
| 542 | + | } | |||
| 543 | + | ctx = templ.ClearChildren(ctx) | |||
| 544 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<form class=\"sv-card-form\" data-sv-action=\"config.search.save\"><label><span>Default search engine</span><input name=\"default_search_engine\" type=\"text\" value=\"") | |||
| 545 | + | if templ_7745c5c3_Err != nil { | |||
| 546 | + | return templ_7745c5c3_Err | |||
| 547 | + | } | |||
| 548 | + | var templ_7745c5c3_Var30 string | |||
| 549 | + | templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(config.DefaultSearchEngine) | |||
| 550 | + | if templ_7745c5c3_Err != nil { | |||
| 551 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 62, Col: 125} | |||
| 552 | + | } | |||
| 553 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) | |||
| 554 | + | if templ_7745c5c3_Err != nil { | |||
| 555 | + | return templ_7745c5c3_Err | |||
| 556 | + | } | |||
| 557 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" placeholder=\"https://duckduckgo.com/?q=%s\" required></label> <button class=\"sv-button\" type=\"submit\">Save search default</button></form><div class=\"sv-group\"><div class=\"sv-group-header\"><h4>Search shortcuts</h4></div><p class=\"sv-meta\">Shortcut URLs must include the %s placeholder for the search query.</p><form class=\"sv-inline-form\" data-sv-action=\"config.searchShortcut.create\"><label><span>Key</span><input name=\"key\" type=\"text\" placeholder=\"ddg\" required></label> <label><span>URL</span><input name=\"url\" type=\"text\" placeholder=\"https://duckduckgo.com/?q=%s\" required></label> <label><span>Description</span><input name=\"description\" type=\"text\" placeholder=\"DuckDuckGo\" required></label> <button class=\"sv-button sv-button-secondary\" type=\"submit\">Add shortcut</button></form>") | |||
| 558 | + | if templ_7745c5c3_Err != nil { | |||
| 559 | + | return templ_7745c5c3_Err | |||
| 560 | + | } | |||
| 561 | + | if len(searchShortcutRows(config.SearchShortcuts)) == 0 { | |||
| 562 | + | templ_7745c5c3_Err = EmptyState("No search shortcuts configured").Render(ctx, templ_7745c5c3_Buffer) | |||
| 563 | + | if templ_7745c5c3_Err != nil { | |||
| 564 | + | return templ_7745c5c3_Err | |||
| 565 | + | } | |||
| 566 | + | } else { | |||
| 567 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<ul class=\"sv-list\">") | |||
| 568 | + | if templ_7745c5c3_Err != nil { | |||
| 569 | + | return templ_7745c5c3_Err | |||
| 570 | + | } | |||
| 571 | + | for _, shortcut := range searchShortcutRows(config.SearchShortcuts) { | |||
| 572 | + | templ_7745c5c3_Err = SearchShortcutItem(shortcut).Render(ctx, templ_7745c5c3_Buffer) | |||
| 573 | + | if templ_7745c5c3_Err != nil { | |||
| 574 | + | return templ_7745c5c3_Err | |||
| 575 | + | } | |||
| 576 | + | } | |||
| 577 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</ul>") | |||
| 578 | + | if templ_7745c5c3_Err != nil { | |||
| 579 | + | return templ_7745c5c3_Err | |||
| 580 | + | } | |||
| 581 | + | } | |||
| 582 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</div>") | |||
| 583 | + | if templ_7745c5c3_Err != nil { | |||
| 584 | + | return templ_7745c5c3_Err | |||
| 585 | + | } | |||
| 586 | + | return nil | |||
| 587 | + | }) | |||
| 588 | + | } | |||
| 589 | + | ||||
| 590 | + | func SearchShortcutItem(shortcut searchShortcutRow) templ.Component { | |||
| 591 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 592 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 593 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |||
| 594 | + | return templ_7745c5c3_CtxErr | |||
| 595 | + | } | |||
| 596 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 597 | + | if !templ_7745c5c3_IsBuffer { | |||
| 598 | + | defer func() { | |||
| 599 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 600 | + | if templ_7745c5c3_Err == nil { | |||
| 601 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 602 | + | } | |||
| 603 | + | }() | |||
| 604 | + | } | |||
| 605 | + | ctx = templ.InitializeContext(ctx) | |||
| 606 | + | templ_7745c5c3_Var31 := templ.GetChildren(ctx) | |||
| 607 | + | if templ_7745c5c3_Var31 == nil { | |||
| 608 | + | templ_7745c5c3_Var31 = templ.NopComponent | |||
| 29 | } | 609 | } | ||
| 30 | ctx = templ.ClearChildren(ctx) | 610 | ctx = templ.ClearChildren(ctx) | ||
| 31 | - | templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | 611 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<li class=\"sv-list-row\"><form class=\"sv-inline-form\" data-sv-action=\"config.searchShortcut.update\"><input type=\"hidden\" name=\"key\" value=\"") |
| 32 | - | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | 612 | + | if templ_7745c5c3_Err != nil { |
| 33 | - | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | 613 | + | return templ_7745c5c3_Err |
| 34 | - | if !templ_7745c5c3_IsBuffer { | 614 | + | } |
| 35 | - | defer func() { | 615 | + | var templ_7745c5c3_Var32 string |
| 36 | - | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | 616 | + | templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Key) |
| 37 | - | if templ_7745c5c3_Err == nil { | 617 | + | if templ_7745c5c3_Err != nil { |
| 38 | - | templ_7745c5c3_Err = templ_7745c5c3_BufErr | 618 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 89, Col: 55} |
| 39 | - | } | 619 | + | } |
| 40 | - | }() | 620 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) |
| 41 | - | } | 621 | + | if templ_7745c5c3_Err != nil { |
| 42 | - | ctx = templ.InitializeContext(ctx) | 622 | + | return templ_7745c5c3_Err |
| 43 | - | templ_7745c5c3_Err = KV(flattenValues(data.Config)).Render(ctx, templ_7745c5c3_Buffer) | 623 | + | } |
| 624 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\"> <label><span>Key</span><input name=\"new_key\" type=\"text\" value=\"") | |||
| 625 | + | if templ_7745c5c3_Err != nil { | |||
| 626 | + | return templ_7745c5c3_Err | |||
| 627 | + | } | |||
| 628 | + | var templ_7745c5c3_Var33 string | |||
| 629 | + | templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Key) | |||
| 630 | + | if templ_7745c5c3_Err != nil { | |||
| 631 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 90, Col: 80} | |||
| 632 | + | } | |||
| 633 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) | |||
| 634 | + | if templ_7745c5c3_Err != nil { | |||
| 635 | + | return templ_7745c5c3_Err | |||
| 636 | + | } | |||
| 637 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" required></label> <label><span>URL</span><input name=\"url\" type=\"text\" value=\"") | |||
| 638 | + | if templ_7745c5c3_Err != nil { | |||
| 639 | + | return templ_7745c5c3_Err | |||
| 640 | + | } | |||
| 641 | + | var templ_7745c5c3_Var34 string | |||
| 642 | + | templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.URL) | |||
| 643 | + | if templ_7745c5c3_Err != nil { | |||
| 644 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 91, Col: 76} | |||
| 645 | + | } | |||
| 646 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) | |||
| 647 | + | if templ_7745c5c3_Err != nil { | |||
| 648 | + | return templ_7745c5c3_Err | |||
| 649 | + | } | |||
| 650 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\" required></label> <label><span>Description</span><input name=\"description\" type=\"text\" value=\"") | |||
| 651 | + | if templ_7745c5c3_Err != nil { | |||
| 652 | + | return templ_7745c5c3_Err | |||
| 653 | + | } | |||
| 654 | + | var templ_7745c5c3_Var35 string | |||
| 655 | + | templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Description) | |||
| 656 | + | if templ_7745c5c3_Err != nil { | |||
| 657 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 92, Col: 100} | |||
| 658 | + | } | |||
| 659 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) | |||
| 660 | + | if templ_7745c5c3_Err != nil { | |||
| 661 | + | return templ_7745c5c3_Err | |||
| 662 | + | } | |||
| 663 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\" required></label> <button class=\"sv-button sv-button-secondary\" type=\"submit\">Save</button> <button class=\"sv-button sv-button-secondary sv-button-danger\" type=\"button\" data-sv-action=\"config.searchShortcut.delete\" data-key=\"") | |||
| 664 | + | if templ_7745c5c3_Err != nil { | |||
| 665 | + | return templ_7745c5c3_Err | |||
| 666 | + | } | |||
| 667 | + | var templ_7745c5c3_Var36 string | |||
| 668 | + | templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(shortcut.Key) | |||
| 669 | + | if templ_7745c5c3_Err != nil { | |||
| 670 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 94, Col: 149} | |||
| 671 | + | } | |||
| 672 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) | |||
| 673 | + | if templ_7745c5c3_Err != nil { | |||
| 674 | + | return templ_7745c5c3_Err | |||
| 675 | + | } | |||
| 676 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\" data-sv-confirm=\"Delete this search shortcut?\">Delete</button></form></li>") | |||
| 677 | + | if templ_7745c5c3_Err != nil { | |||
| 678 | + | return templ_7745c5c3_Err | |||
| 679 | + | } | |||
| 680 | + | return nil | |||
| 681 | + | }) | |||
| 682 | + | } | |||
| 683 | + | ||||
| 684 | + | func PerformanceSettings(config port.SystemviewConfigPayload) templ.Component { | |||
| 685 | + | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | |||
| 686 | + | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | |||
| 687 | + | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | |||
| 688 | + | return templ_7745c5c3_CtxErr | |||
| 689 | + | } | |||
| 690 | + | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 691 | + | if !templ_7745c5c3_IsBuffer { | |||
| 692 | + | defer func() { | |||
| 693 | + | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 694 | + | if templ_7745c5c3_Err == nil { | |||
| 695 | + | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 696 | + | } | |||
| 697 | + | }() | |||
| 698 | + | } | |||
| 699 | + | ctx = templ.InitializeContext(ctx) | |||
| 700 | + | templ_7745c5c3_Var37 := templ.GetChildren(ctx) | |||
| 701 | + | if templ_7745c5c3_Var37 == nil { | |||
| 702 | + | templ_7745c5c3_Var37 = templ.NopComponent | |||
| 703 | + | } | |||
| 704 | + | ctx = templ.ClearChildren(ctx) | |||
| 705 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<form class=\"sv-card-form sv-config-form\" data-sv-action=\"config.performance.save\"><label><span>Profile</span><select name=\"profile\"><option value=\"default\"") | |||
| 706 | + | if templ_7745c5c3_Err != nil { | |||
| 707 | + | return templ_7745c5c3_Err | |||
| 708 | + | } | |||
| 709 | + | if performanceProfileSelected(config.Performance.Profile, "default") { | |||
| 710 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, " selected") | |||
| 44 | if templ_7745c5c3_Err != nil { | 711 | if templ_7745c5c3_Err != nil { | ||
| 45 | return templ_7745c5c3_Err | 712 | return templ_7745c5c3_Err | ||
| 46 | } | 713 | } | ||
| 47 | - | return nil | 714 | + | } |
| 48 | - | }) | 715 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, ">Default</option> <option value=\"lite\"") |
| 49 | - | templ_7745c5c3_Err = Section("sv-config-values", "Config values").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) | |||
| 50 | if templ_7745c5c3_Err != nil { | 716 | if templ_7745c5c3_Err != nil { | ||
| 51 | return templ_7745c5c3_Err | 717 | return templ_7745c5c3_Err | ||
| 52 | } | 718 | } | ||
| 53 | - | templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | 719 | + | if performanceProfileSelected(config.Performance.Profile, "lite") { |
| 54 | - | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | 720 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, " selected") |
| 55 | - | templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) | |||
| 56 | - | if !templ_7745c5c3_IsBuffer { | |||
| 57 | - | defer func() { | |||
| 58 | - | templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) | |||
| 59 | - | if templ_7745c5c3_Err == nil { | |||
| 60 | - | templ_7745c5c3_Err = templ_7745c5c3_BufErr | |||
| 61 | - | } | |||
| 62 | - | }() | |||
| 63 | - | } | |||
| 64 | - | ctx = templ.InitializeContext(ctx) | |||
| 65 | - | templ_7745c5c3_Err = Meta(configKeybindingSummary(data.Keybindings)).Render(ctx, templ_7745c5c3_Buffer) | |||
| 66 | if templ_7745c5c3_Err != nil { | 721 | if templ_7745c5c3_Err != nil { | ||
| 67 | return templ_7745c5c3_Err | 722 | return templ_7745c5c3_Err | ||
| 68 | } | 723 | } | ||
| 69 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") | 724 | + | } |
| 725 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, ">Lite</option> <option value=\"max\"") | |||
| 726 | + | if templ_7745c5c3_Err != nil { | |||
| 727 | + | return templ_7745c5c3_Err | |||
| 728 | + | } | |||
| 729 | + | if performanceProfileSelected(config.Performance.Profile, "max") { | |||
| 730 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, " selected") | |||
| 70 | if templ_7745c5c3_Err != nil { | 731 | if templ_7745c5c3_Err != nil { | ||
| 71 | return templ_7745c5c3_Err | 732 | return templ_7745c5c3_Err | ||
| 72 | } | 733 | } | ||
| 73 | - | templ_7745c5c3_Err = ConfigKeybindings(data.Keybindings).Render(ctx, templ_7745c5c3_Buffer) | 734 | + | } |
| 735 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, ">Max</option> <option value=\"custom\"") | |||
| 736 | + | if templ_7745c5c3_Err != nil { | |||
| 737 | + | return templ_7745c5c3_Err | |||
| 738 | + | } | |||
| 739 | + | if performanceProfileSelected(config.Performance.Profile, "custom") { | |||
| 740 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " selected") | |||
| 74 | if templ_7745c5c3_Err != nil { | 741 | if templ_7745c5c3_Err != nil { | ||
| 75 | return templ_7745c5c3_Err | 742 | return templ_7745c5c3_Err | ||
| 76 | } | 743 | } | ||
| 77 | - | return nil | 744 | + | } |
| 78 | - | }) | 745 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, ">Custom</option></select></label> <label><span>Skia CPU threads</span><input name=\"skia_cpu_threads\" type=\"number\" min=\"0\" max=\"8\" value=\"") |
| 79 | - | templ_7745c5c3_Err = Section("sv-config-keybindings", "Keybindings").Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer) | 746 | + | if templ_7745c5c3_Err != nil { |
| 747 | + | return templ_7745c5c3_Err | |||
| 748 | + | } | |||
| 749 | + | var templ_7745c5c3_Var38 string | |||
| 750 | + | templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.SkiaCPUThreads)) | |||
| 751 | + | if templ_7745c5c3_Err != nil { | |||
| 752 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 107, Col: 164} | |||
| 753 | + | } | |||
| 754 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) | |||
| 755 | + | if templ_7745c5c3_Err != nil { | |||
| 756 | + | return templ_7745c5c3_Err | |||
| 757 | + | } | |||
| 758 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "\"></label> <label><span>Skia GPU threads</span><input name=\"skia_gpu_threads\" type=\"number\" min=\"-1\" max=\"8\" value=\"") | |||
| 759 | + | if templ_7745c5c3_Err != nil { | |||
| 760 | + | return templ_7745c5c3_Err | |||
| 761 | + | } | |||
| 762 | + | var templ_7745c5c3_Var39 string | |||
| 763 | + | templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.SkiaGPUThreads)) | |||
| 764 | + | if templ_7745c5c3_Err != nil { | |||
| 765 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 108, Col: 165} | |||
| 766 | + | } | |||
| 767 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) | |||
| 768 | + | if templ_7745c5c3_Err != nil { | |||
| 769 | + | return templ_7745c5c3_Err | |||
| 770 | + | } | |||
| 771 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\"></label> <label><span>Web process memory MB</span><input name=\"web_process_memory_mb\" type=\"number\" min=\"0\" max=\"16384\" value=\"") | |||
| 772 | + | if templ_7745c5c3_Err != nil { | |||
| 773 | + | return templ_7745c5c3_Err | |||
| 774 | + | } | |||
| 775 | + | var templ_7745c5c3_Var40 string | |||
| 776 | + | templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.WebProcessMemoryMB)) | |||
| 777 | + | if templ_7745c5c3_Err != nil { | |||
| 778 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 109, Col: 182} | |||
| 779 | + | } | |||
| 780 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) | |||
| 781 | + | if templ_7745c5c3_Err != nil { | |||
| 782 | + | return templ_7745c5c3_Err | |||
| 783 | + | } | |||
| 784 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\"></label> <label><span>Network process memory MB</span><input name=\"network_process_memory_mb\" type=\"number\" min=\"0\" max=\"4096\" value=\"") | |||
| 785 | + | if templ_7745c5c3_Err != nil { | |||
| 786 | + | return templ_7745c5c3_Err | |||
| 787 | + | } | |||
| 788 | + | var templ_7745c5c3_Var41 string | |||
| 789 | + | templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.NetworkProcessMemoryMB)) | |||
| 790 | + | if templ_7745c5c3_Err != nil { | |||
| 791 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 110, Col: 193} | |||
| 792 | + | } | |||
| 793 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) | |||
| 794 | + | if templ_7745c5c3_Err != nil { | |||
| 795 | + | return templ_7745c5c3_Err | |||
| 796 | + | } | |||
| 797 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\"></label> <label><span>WebView pool prewarm</span><input name=\"webview_pool_prewarm\" type=\"number\" min=\"0\" max=\"20\" value=\"") | |||
| 798 | + | if templ_7745c5c3_Err != nil { | |||
| 799 | + | return templ_7745c5c3_Err | |||
| 800 | + | } | |||
| 801 | + | var templ_7745c5c3_Var42 string | |||
| 802 | + | templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Custom.WebViewPoolPrewarm)) | |||
| 803 | + | if templ_7745c5c3_Err != nil { | |||
| 804 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 111, Col: 177} | |||
| 805 | + | } | |||
| 806 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) | |||
| 807 | + | if templ_7745c5c3_Err != nil { | |||
| 808 | + | return templ_7745c5c3_Err | |||
| 809 | + | } | |||
| 810 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\"></label> <button class=\"sv-button\" type=\"submit\">Save performance</button></form><div class=\"sv-stat-grid\"><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |||
| 811 | + | if templ_7745c5c3_Err != nil { | |||
| 812 | + | return templ_7745c5c3_Err | |||
| 813 | + | } | |||
| 814 | + | var templ_7745c5c3_Var43 string | |||
| 815 | + | templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Hardware.CPUThreads)) | |||
| 816 | + | if templ_7745c5c3_Err != nil { | |||
| 817 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 115, Col: 113} | |||
| 818 | + | } | |||
| 819 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43)) | |||
| 820 | + | if templ_7745c5c3_Err != nil { | |||
| 821 | + | return templ_7745c5c3_Err | |||
| 822 | + | } | |||
| 823 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</span><span class=\"sv-stat-label\">CPU threads</span></div><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |||
| 824 | + | if templ_7745c5c3_Err != nil { | |||
| 825 | + | return templ_7745c5c3_Err | |||
| 826 | + | } | |||
| 827 | + | var templ_7745c5c3_Var44 string | |||
| 828 | + | templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(formatConfigInt(config.Performance.Hardware.TotalRAMMB)) | |||
| 829 | + | if templ_7745c5c3_Err != nil { | |||
| 830 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 116, Col: 113} | |||
| 831 | + | } | |||
| 832 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) | |||
| 833 | + | if templ_7745c5c3_Err != nil { | |||
| 834 | + | return templ_7745c5c3_Err | |||
| 835 | + | } | |||
| 836 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "</span><span class=\"sv-stat-label\">RAM MB</span></div><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |||
| 837 | + | if templ_7745c5c3_Err != nil { | |||
| 838 | + | return templ_7745c5c3_Err | |||
| 839 | + | } | |||
| 840 | + | var templ_7745c5c3_Var45 string | |||
| 841 | + | templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(config.Performance.Hardware.GPUName) | |||
| 842 | + | if templ_7745c5c3_Err != nil { | |||
| 843 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 117, Col: 93} | |||
| 844 | + | } | |||
| 845 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45)) | |||
| 846 | + | if templ_7745c5c3_Err != nil { | |||
| 847 | + | return templ_7745c5c3_Err | |||
| 848 | + | } | |||
| 849 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</span><span class=\"sv-stat-label\">GPU</span></div><div class=\"sv-stat-card\"><span class=\"sv-stat-value\">") | |||
| 850 | + | if templ_7745c5c3_Err != nil { | |||
| 851 | + | return templ_7745c5c3_Err | |||
| 852 | + | } | |||
| 853 | + | var templ_7745c5c3_Var46 string | |||
| 854 | + | templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(config.EngineType) | |||
| 855 | + | if templ_7745c5c3_Err != nil { | |||
| 856 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 118, Col: 75} | |||
| 857 | + | } | |||
| 858 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) | |||
| 80 | if templ_7745c5c3_Err != nil { | 859 | if templ_7745c5c3_Err != nil { | ||
| 81 | return templ_7745c5c3_Err | 860 | return templ_7745c5c3_Err | ||
| 82 | } | 861 | } | ||
| 862 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</span><span class=\"sv-stat-label\">Engine</span></div></div>") | |||
| 863 | + | if templ_7745c5c3_Err != nil { | |||
| 864 | + | return templ_7745c5c3_Err | |||
| 865 | + | } | |||
| 866 | + | if !engineIsWebKit(config.EngineType) { | |||
| 867 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "<p class=\"sv-meta\">Performance tuning applies only to the WebKit engine.</p>") | |||
| 868 | + | if templ_7745c5c3_Err != nil { | |||
| 869 | + | return templ_7745c5c3_Err | |||
| 870 | + | } | |||
| 871 | + | } else { | |||
| 872 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "<p class=\"sv-meta\">Performance profile changes may require restarting the browser to affect existing engine processes.</p>") | |||
| 873 | + | if templ_7745c5c3_Err != nil { | |||
| 874 | + | return templ_7745c5c3_Err | |||
| 875 | + | } | |||
| 876 | + | } | |||
| 83 | return nil | 877 | return nil | ||
| 84 | }) | 878 | }) | ||
| 85 | } | 879 | } | ||
| @@ -100,12 +894,16 @@ func ConfigKeybindings(keybindings any) templ.Component { | |||||
| 100 | }() | 894 | }() | ||
| 101 | } | 895 | } | ||
| 102 | ctx = templ.InitializeContext(ctx) | 896 | ctx = templ.InitializeContext(ctx) | ||
| 103 | - | templ_7745c5c3_Var4 := templ.GetChildren(ctx) | 897 | + | templ_7745c5c3_Var47 := templ.GetChildren(ctx) |
| 104 | - | if templ_7745c5c3_Var4 == nil { | 898 | + | if templ_7745c5c3_Var47 == nil { |
| 105 | - | templ_7745c5c3_Var4 = templ.NopComponent | 899 | + | templ_7745c5c3_Var47 = templ.NopComponent |
| 106 | } | 900 | } | ||
| 107 | ctx = templ.ClearChildren(ctx) | 901 | ctx = templ.ClearChildren(ctx) | ||
| 108 | groups := configKeybindingGroups(keybindings) | 902 | groups := configKeybindingGroups(keybindings) | ||
| 903 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<div class=\"sv-button-row\"><button class=\"sv-button sv-button-secondary sv-button-danger\" type=\"button\" data-sv-action=\"config.keybinding.resetAll\" data-sv-confirm=\"Reset all keybindings to defaults?\">Reset all keybindings</button></div>") | |||
| 904 | + | if templ_7745c5c3_Err != nil { | |||
| 905 | + | return templ_7745c5c3_Err | |||
| 906 | + | } | |||
| 109 | if groups == nil { | 907 | if groups == nil { | ||
| 110 | templ_7745c5c3_Err = EmptyState("Keybindings unavailable").Render(ctx, templ_7745c5c3_Buffer) | 908 | templ_7745c5c3_Err = EmptyState("Keybindings unavailable").Render(ctx, templ_7745c5c3_Buffer) | ||
| 111 | if templ_7745c5c3_Err != nil { | 909 | if templ_7745c5c3_Err != nil { | ||
| @@ -144,48 +942,48 @@ func ConfigKeybindingGroup(group renderedKeybindingGroup) templ.Component { | |||||
| 144 | }() | 942 | }() | ||
| 145 | } | 943 | } | ||
| 146 | ctx = templ.InitializeContext(ctx) | 944 | ctx = templ.InitializeContext(ctx) | ||
| 147 | - | templ_7745c5c3_Var5 := templ.GetChildren(ctx) | 945 | + | templ_7745c5c3_Var48 := templ.GetChildren(ctx) |
| 148 | - | if templ_7745c5c3_Var5 == nil { | 946 | + | if templ_7745c5c3_Var48 == nil { |
| 149 | - | templ_7745c5c3_Var5 = templ.NopComponent | 947 | + | templ_7745c5c3_Var48 = templ.NopComponent |
| 150 | } | 948 | } | ||
| 151 | ctx = templ.ClearChildren(ctx) | 949 | ctx = templ.ClearChildren(ctx) | ||
| 152 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"sv-group\"><div class=\"sv-group-header\"><div><h4>") | 950 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "<div class=\"sv-group\"><div class=\"sv-group-header\"><div><h4>") |
| 153 | if templ_7745c5c3_Err != nil { | 951 | if templ_7745c5c3_Err != nil { | ||
| 154 | return templ_7745c5c3_Err | 952 | return templ_7745c5c3_Err | ||
| 155 | } | 953 | } | ||
| 156 | - | var templ_7745c5c3_Var6 string | 954 | + | var templ_7745c5c3_Var49 string |
| 157 | - | templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupTitle(group)) | 955 | + | templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupTitle(group)) |
| 158 | if templ_7745c5c3_Err != nil { | 956 | if templ_7745c5c3_Err != nil { | ||
| 159 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 30, Col: 37} | 957 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 147, Col: 37} |
| 160 | } | 958 | } | ||
| 161 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) | 959 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) |
| 162 | if templ_7745c5c3_Err != nil { | 960 | if templ_7745c5c3_Err != nil { | ||
| 163 | return templ_7745c5c3_Err | 961 | return templ_7745c5c3_Err | ||
| 164 | } | 962 | } | ||
| 165 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h4>") | 963 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</h4>") |
| 166 | if templ_7745c5c3_Err != nil { | 964 | if templ_7745c5c3_Err != nil { | ||
| 167 | return templ_7745c5c3_Err | 965 | return templ_7745c5c3_Err | ||
| 168 | } | 966 | } | ||
| 169 | if keybindingGroupMeta(group) != "" { | 967 | if keybindingGroupMeta(group) != "" { | ||
| 170 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<p class=\"sv-meta\">") | 968 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "<p class=\"sv-meta\">") |
| 171 | if templ_7745c5c3_Err != nil { | 969 | if templ_7745c5c3_Err != nil { | ||
| 172 | return templ_7745c5c3_Err | 970 | return templ_7745c5c3_Err | ||
| 173 | } | 971 | } | ||
| 174 | - | var templ_7745c5c3_Var7 string | 972 | + | var templ_7745c5c3_Var50 string |
| 175 | - | templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupMeta(group)) | 973 | + | templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingGroupMeta(group)) |
| 176 | if templ_7745c5c3_Err != nil { | 974 | if templ_7745c5c3_Err != nil { | ||
| 177 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 32, Col: 52} | 975 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 149, Col: 52} |
| 178 | } | 976 | } | ||
| 179 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) | 977 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var50)) |
| 180 | if templ_7745c5c3_Err != nil { | 978 | if templ_7745c5c3_Err != nil { | ||
| 181 | return templ_7745c5c3_Err | 979 | return templ_7745c5c3_Err | ||
| 182 | } | 980 | } | ||
| 183 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</p>") | 981 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "</p>") |
| 184 | if templ_7745c5c3_Err != nil { | 982 | if templ_7745c5c3_Err != nil { | ||
| 185 | return templ_7745c5c3_Err | 983 | return templ_7745c5c3_Err | ||
| 186 | } | 984 | } | ||
| 187 | } | 985 | } | ||
| 188 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div></div><div class=\"sv-group-body\">") | 986 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</div></div><div class=\"sv-group-body\">") |
| 189 | if templ_7745c5c3_Err != nil { | 987 | if templ_7745c5c3_Err != nil { | ||
| 190 | return templ_7745c5c3_Err | 988 | return templ_7745c5c3_Err | ||
| 191 | } | 989 | } | ||
| @@ -195,22 +993,22 @@ func ConfigKeybindingGroup(group renderedKeybindingGroup) templ.Component { | |||||
| 195 | return templ_7745c5c3_Err | 993 | return templ_7745c5c3_Err | ||
| 196 | } | 994 | } | ||
| 197 | } else { | 995 | } else { | ||
| 198 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<ul class=\"sv-list\">") | 996 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<ul class=\"sv-list\">") |
| 199 | if templ_7745c5c3_Err != nil { | 997 | if templ_7745c5c3_Err != nil { | ||
| 200 | return templ_7745c5c3_Err | 998 | return templ_7745c5c3_Err | ||
| 201 | } | 999 | } | ||
| 202 | for _, binding := range group.Bindings { | 1000 | for _, binding := range group.Bindings { | ||
| 203 | - | templ_7745c5c3_Err = ConfigKeybinding(binding).Render(ctx, templ_7745c5c3_Buffer) | 1001 | + | templ_7745c5c3_Err = ConfigKeybinding(group, binding).Render(ctx, templ_7745c5c3_Buffer) |
| 204 | if templ_7745c5c3_Err != nil { | 1002 | if templ_7745c5c3_Err != nil { | ||
| 205 | return templ_7745c5c3_Err | 1003 | return templ_7745c5c3_Err | ||
| 206 | } | 1004 | } | ||
| 207 | } | 1005 | } | ||
| 208 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</ul>") | 1006 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "</ul>") |
| 209 | if templ_7745c5c3_Err != nil { | 1007 | if templ_7745c5c3_Err != nil { | ||
| 210 | return templ_7745c5c3_Err | 1008 | return templ_7745c5c3_Err | ||
| 211 | } | 1009 | } | ||
| 212 | } | 1010 | } | ||
| 213 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></div>") | 1011 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "</div></div>") |
| 214 | if templ_7745c5c3_Err != nil { | 1012 | if templ_7745c5c3_Err != nil { | ||
| 215 | return templ_7745c5c3_Err | 1013 | return templ_7745c5c3_Err | ||
| 216 | } | 1014 | } | ||
| @@ -218,7 +1016,7 @@ func ConfigKeybindingGroup(group renderedKeybindingGroup) templ.Component { | |||||
| 218 | }) | 1016 | }) | ||
| 219 | } | 1017 | } | ||
| 220 | 1018 | ||||
| 221 | - | func ConfigKeybinding(binding renderedKeybinding) templ.Component { | 1019 | + | func ConfigKeybinding(group renderedKeybindingGroup, binding renderedKeybinding) templ.Component { |
| 222 | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | 1020 | return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { | ||
| 223 | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | 1021 | templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context | ||
| 224 | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | 1022 | if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { | ||
| @@ -234,38 +1032,38 @@ func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |||||
| 234 | }() | 1032 | }() | ||
| 235 | } | 1033 | } | ||
| 236 | ctx = templ.InitializeContext(ctx) | 1034 | ctx = templ.InitializeContext(ctx) | ||
| 237 | - | templ_7745c5c3_Var8 := templ.GetChildren(ctx) | 1035 | + | templ_7745c5c3_Var51 := templ.GetChildren(ctx) |
| 238 | - | if templ_7745c5c3_Var8 == nil { | 1036 | + | if templ_7745c5c3_Var51 == nil { |
| 239 | - | templ_7745c5c3_Var8 = templ.NopComponent | 1037 | + | templ_7745c5c3_Var51 = templ.NopComponent |
| 240 | } | 1038 | } | ||
| 241 | ctx = templ.ClearChildren(ctx) | 1039 | ctx = templ.ClearChildren(ctx) | ||
| 242 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<li class=\"sv-list-row\"><div class=\"sv-keybinding-row\"><div><strong>") | 1040 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "<li class=\"sv-list-row\"><div class=\"sv-keybinding-row\"><div><strong>") |
| 243 | if templ_7745c5c3_Err != nil { | 1041 | if templ_7745c5c3_Err != nil { | ||
| 244 | return templ_7745c5c3_Err | 1042 | return templ_7745c5c3_Err | ||
| 245 | } | 1043 | } | ||
| 246 | - | var templ_7745c5c3_Var9 string | 1044 | + | var templ_7745c5c3_Var52 string |
| 247 | - | templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingDescription(binding)) | 1045 | + | templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingDescription(binding)) |
| 248 | if templ_7745c5c3_Err != nil { | 1046 | if templ_7745c5c3_Err != nil { | ||
| 249 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 54, Col: 44} | 1047 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 171, Col: 44} |
| 250 | } | 1048 | } | ||
| 251 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) | 1049 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) |
| 252 | if templ_7745c5c3_Err != nil { | 1050 | if templ_7745c5c3_Err != nil { | ||
| 253 | return templ_7745c5c3_Err | 1051 | return templ_7745c5c3_Err | ||
| 254 | } | 1052 | } | ||
| 255 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</strong><p class=\"sv-meta\">") | 1053 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</strong><p class=\"sv-meta\">") |
| 256 | if templ_7745c5c3_Err != nil { | 1054 | if templ_7745c5c3_Err != nil { | ||
| 257 | return templ_7745c5c3_Err | 1055 | return templ_7745c5c3_Err | ||
| 258 | } | 1056 | } | ||
| 259 | - | var templ_7745c5c3_Var10 string | 1057 | + | var templ_7745c5c3_Var53 string |
| 260 | - | templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingAction(binding)) | 1058 | + | templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingAction(binding)) |
| 261 | if templ_7745c5c3_Err != nil { | 1059 | if templ_7745c5c3_Err != nil { | ||
| 262 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 55, Col: 50} | 1060 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 172, Col: 50} |
| 263 | } | 1061 | } | ||
| 264 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) | 1062 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53)) |
| 265 | if templ_7745c5c3_Err != nil { | 1063 | if templ_7745c5c3_Err != nil { | ||
| 266 | return templ_7745c5c3_Err | 1064 | return templ_7745c5c3_Err | ||
| 267 | } | 1065 | } | ||
| 268 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</p></div><div class=\"sv-keybinding-keys\">") | 1066 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "</p><div class=\"sv-binding-keys\">") |
| 269 | if templ_7745c5c3_Err != nil { | 1067 | if templ_7745c5c3_Err != nil { | ||
| 270 | return templ_7745c5c3_Err | 1068 | return templ_7745c5c3_Err | ||
| 271 | } | 1069 | } | ||
| @@ -273,25 +1071,25 @@ func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |||||
| 273 | if templ_7745c5c3_Err != nil { | 1071 | if templ_7745c5c3_Err != nil { | ||
| 274 | return templ_7745c5c3_Err | 1072 | return templ_7745c5c3_Err | ||
| 275 | } | 1073 | } | ||
| 276 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<span class=\"sv-badge\">") | 1074 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "<span class=\"sv-badge\">") |
| 277 | if templ_7745c5c3_Err != nil { | 1075 | if templ_7745c5c3_Err != nil { | ||
| 278 | return templ_7745c5c3_Err | 1076 | return templ_7745c5c3_Err | ||
| 279 | } | 1077 | } | ||
| 280 | - | var templ_7745c5c3_Var11 string | 1078 | + | var templ_7745c5c3_Var54 string |
| 281 | - | templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingStatus(binding)) | 1079 | + | templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingStatus(binding)) |
| 282 | if templ_7745c5c3_Err != nil { | 1080 | if templ_7745c5c3_Err != nil { | ||
| 283 | - | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 59, Col: 54} | 1081 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 175, Col: 55} |
| 284 | } | 1082 | } | ||
| 285 | - | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) | 1083 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54)) |
| 286 | if templ_7745c5c3_Err != nil { | 1084 | if templ_7745c5c3_Err != nil { | ||
| 287 | return templ_7745c5c3_Err | 1085 | return templ_7745c5c3_Err | ||
| 288 | } | 1086 | } | ||
| 289 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</span> ") | 1087 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "</span> ") |
| 290 | if templ_7745c5c3_Err != nil { | 1088 | if templ_7745c5c3_Err != nil { | ||
| 291 | return templ_7745c5c3_Err | 1089 | return templ_7745c5c3_Err | ||
| 292 | } | 1090 | } | ||
| 293 | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | 1091 | if keybindingIsCustom(binding) && len(binding.DefaultKeys) > 0 { | ||
| 294 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"sv-meta\">default:</span>") | 1092 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "<span class=\"sv-meta\">default:</span>") |
| 295 | if templ_7745c5c3_Err != nil { | 1093 | if templ_7745c5c3_Err != nil { | ||
| 296 | return templ_7745c5c3_Err | 1094 | return templ_7745c5c3_Err | ||
| 297 | } | 1095 | } | ||
| @@ -300,7 +1098,72 @@ func ConfigKeybinding(binding renderedKeybinding) templ.Component { | |||||
| 300 | return templ_7745c5c3_Err | 1098 | return templ_7745c5c3_Err | ||
| 301 | } | 1099 | } | ||
| 302 | } | 1100 | } | ||
| 303 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div></div></li>") | 1101 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "</div></div><form class=\"sv-inline-form\" data-sv-action=\"config.keybinding.set\"><input type=\"hidden\" name=\"mode\" value=\"") |
| 1102 | + | if templ_7745c5c3_Err != nil { | |||
| 1103 | + | return templ_7745c5c3_Err | |||
| 1104 | + | } | |||
| 1105 | + | var templ_7745c5c3_Var55 string | |||
| 1106 | + | templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(group.Mode) | |||
| 1107 | + | if templ_7745c5c3_Err != nil { | |||
| 1108 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 183, Col: 55} | |||
| 1109 | + | } | |||
| 1110 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var55)) | |||
| 1111 | + | if templ_7745c5c3_Err != nil { | |||
| 1112 | + | return templ_7745c5c3_Err | |||
| 1113 | + | } | |||
| 1114 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "\"> <input type=\"hidden\" name=\"action\" value=\"") | |||
| 1115 | + | if templ_7745c5c3_Err != nil { | |||
| 1116 | + | return templ_7745c5c3_Err | |||
| 1117 | + | } | |||
| 1118 | + | var templ_7745c5c3_Var56 string | |||
| 1119 | + | templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(binding.Action) | |||
| 1120 | + | if templ_7745c5c3_Err != nil { | |||
| 1121 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 184, Col: 61} | |||
| 1122 | + | } | |||
| 1123 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) | |||
| 1124 | + | if templ_7745c5c3_Err != nil { | |||
| 1125 | + | return templ_7745c5c3_Err | |||
| 1126 | + | } | |||
| 1127 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\"> <label><span>Keys</span><input name=\"keys\" type=\"text\" value=\"") | |||
| 1128 | + | if templ_7745c5c3_Err != nil { | |||
| 1129 | + | return templ_7745c5c3_Err | |||
| 1130 | + | } | |||
| 1131 | + | var templ_7745c5c3_Var57 string | |||
| 1132 | + | templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(keybindingKeysValue(binding.Keys)) | |||
| 1133 | + | if templ_7745c5c3_Err != nil { | |||
| 1134 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 185, Col: 100} | |||
| 1135 | + | } | |||
| 1136 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) | |||
| 1137 | + | if templ_7745c5c3_Err != nil { | |||
| 1138 | + | return templ_7745c5c3_Err | |||
| 1139 | + | } | |||
| 1140 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\" placeholder=\"ctrl+h\" required></label> <button class=\"sv-button sv-button-secondary\" type=\"submit\">Save</button> <button class=\"sv-button sv-button-secondary\" type=\"button\" data-sv-action=\"config.keybinding.reset\" data-mode=\"") | |||
| 1141 | + | if templ_7745c5c3_Err != nil { | |||
| 1142 | + | return templ_7745c5c3_Err | |||
| 1143 | + | } | |||
| 1144 | + | var templ_7745c5c3_Var58 string | |||
| 1145 | + | templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(group.Mode) | |||
| 1146 | + | if templ_7745c5c3_Err != nil { | |||
| 1147 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 187, Col: 127} | |||
| 1148 | + | } | |||
| 1149 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) | |||
| 1150 | + | if templ_7745c5c3_Err != nil { | |||
| 1151 | + | return templ_7745c5c3_Err | |||
| 1152 | + | } | |||
| 1153 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "\" data-action=\"") | |||
| 1154 | + | if templ_7745c5c3_Err != nil { | |||
| 1155 | + | return templ_7745c5c3_Err | |||
| 1156 | + | } | |||
| 1157 | + | var templ_7745c5c3_Var59 string | |||
| 1158 | + | templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(binding.Action) | |||
| 1159 | + | if templ_7745c5c3_Err != nil { | |||
| 1160 | + | return templ.Error{Err: templ_7745c5c3_Err, FileName: `config.templ`, Line: 187, Col: 158} | |||
| 1161 | + | } | |||
| 1162 | + | _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59)) | |||
| 1163 | + | if templ_7745c5c3_Err != nil { | |||
| 1164 | + | return templ_7745c5c3_Err | |||
| 1165 | + | } | |||
| 1166 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "\">Reset</button></form></div></li>") | |||
| 304 | if templ_7745c5c3_Err != nil { | 1167 | if templ_7745c5c3_Err != nil { | ||
| 305 | return templ_7745c5c3_Err | 1168 | return templ_7745c5c3_Err | ||
| 306 | } | 1169 | } | ||
M internal/ui/systemviews/config_view.go +55 -2
| @@ -12,10 +12,12 @@ import ( | |||
| 12 | 12 | type configRenderData struct { | |
| 13 | 13 | Config port.SystemviewConfigPayload | |
| 14 | 14 | Keybindings any | |
| 15 | + | Notice string | |
| 16 | + | Error string | |
| 15 | 17 | } | |
| 16 | 18 | ||
| 17 | - | func configHTML(cfg port.SystemviewConfigPayload, keybindings any) string { | |
| 18 | - | return mustRenderComponent(ConfigView(configRenderData{Config: cfg, Keybindings: keybindings})) | |
| 19 | + | func configHTML(data configRenderData) string { | |
| 20 | + | return mustRenderComponent(ConfigView(data)) | |
| 19 | 21 | } | |
| 20 | 22 | ||
| 21 | 23 | func configKeybindingSummary(keybindings any) string { | |
| @@ -94,6 +96,57 @@ func keybindingStatus(binding renderedKeybinding) string { | |||
| 94 | 96 | return "default" | |
| 95 | 97 | } | |
| 96 | 98 | ||
| 99 | + | func keybindingKeysValue(keys []string) string { | |
| 100 | + | return strings.Join(keys, ", ") | |
| 101 | + | } | |
| 102 | + | ||
| 103 | + | type searchShortcutRow struct { | |
| 104 | + | Key string | |
| 105 | + | URL string | |
| 106 | + | Description string | |
| 107 | + | } | |
| 108 | + | ||
| 109 | + | func searchShortcutRows(shortcuts map[string]port.SearchShortcut) []searchShortcutRow { | |
| 110 | + | if len(shortcuts) == 0 { | |
| 111 | + | return nil | |
| 112 | + | } | |
| 113 | + | keys := make([]string, 0, len(shortcuts)) | |
| 114 | + | for key := range shortcuts { | |
| 115 | + | keys = append(keys, key) | |
| 116 | + | } | |
| 117 | + | sort.Strings(keys) | |
| 118 | + | rows := make([]searchShortcutRow, 0, len(keys)) | |
| 119 | + | for _, key := range keys { | |
| 120 | + | shortcut := shortcuts[key] | |
| 121 | + | rows = append(rows, searchShortcutRow{ | |
| 122 | + | Key: key, | |
| 123 | + | URL: shortcut.URL, | |
| 124 | + | Description: shortcut.Description, | |
| 125 | + | }) | |
| 126 | + | } | |
| 127 | + | return rows | |
| 128 | + | } | |
| 129 | + | ||
| 130 | + | func formatConfigInt(value int) string { | |
| 131 | + | return fmt.Sprintf("%d", value) | |
| 132 | + | } | |
| 133 | + | ||
| 134 | + | func formatConfigFloat(value float64) string { | |
| 135 | + | return fmt.Sprintf("%g", value) | |
| 136 | + | } | |
| 137 | + | ||
| 138 | + | func colorSchemeSelected(current, option string) bool { | |
| 139 | + | return strings.EqualFold(strings.TrimSpace(current), option) | |
| 140 | + | } | |
| 141 | + | ||
| 142 | + | func performanceProfileSelected(current, option string) bool { | |
| 143 | + | return strings.EqualFold(strings.TrimSpace(current), option) | |
| 144 | + | } | |
| 145 | + | ||
| 146 | + | func engineIsWebKit(engine string) bool { | |
| 147 | + | return strings.EqualFold(strings.TrimSpace(engine), "webkit") | |
| 148 | + | } | |
| 149 | + | ||
| 97 | 150 | func flattenValues(value any) []kvPair { | |
| 98 | 151 | rows := make([]kvPair, 0) | |
| 99 | 152 | flattenValue(&rows, "", reflect.ValueOf(value)) | |
| @@ -12,10 +12,12 @@ import ( | |||||
| 12 | type configRenderData struct { | 12 | type configRenderData struct { | ||
| 13 | Config port.SystemviewConfigPayload | 13 | Config port.SystemviewConfigPayload | ||
| 14 | Keybindings any | 14 | Keybindings any | ||
| 15 | + | Notice string | |||
| 16 | + | Error string | |||
| 15 | } | 17 | } | ||
| 16 | 18 | ||||
| 17 | - | func configHTML(cfg port.SystemviewConfigPayload, keybindings any) string { | 19 | + | func configHTML(data configRenderData) string { |
| 18 | - | return mustRenderComponent(ConfigView(configRenderData{Config: cfg, Keybindings: keybindings})) | 20 | + | return mustRenderComponent(ConfigView(data)) |
| 19 | } | 21 | } | ||
| 20 | 22 | ||||
| 21 | func configKeybindingSummary(keybindings any) string { | 23 | func configKeybindingSummary(keybindings any) string { | ||
| @@ -94,6 +96,57 @@ func keybindingStatus(binding renderedKeybinding) string { | |||||
| 94 | return "default" | 96 | return "default" | ||
| 95 | } | 97 | } | ||
| 96 | 98 | ||||
| 99 | + | func keybindingKeysValue(keys []string) string { | |||
| 100 | + | return strings.Join(keys, ", ") | |||
| 101 | + | } | |||
| 102 | + | ||||
| 103 | + | type searchShortcutRow struct { | |||
| 104 | + | Key string | |||
| 105 | + | URL string | |||
| 106 | + | Description string | |||
| 107 | + | } | |||
| 108 | + | ||||
| 109 | + | func searchShortcutRows(shortcuts map[string]port.SearchShortcut) []searchShortcutRow { | |||
| 110 | + | if len(shortcuts) == 0 { | |||
| 111 | + | return nil | |||
| 112 | + | } | |||
| 113 | + | keys := make([]string, 0, len(shortcuts)) | |||
| 114 | + | for key := range shortcuts { | |||
| 115 | + | keys = append(keys, key) | |||
| 116 | + | } | |||
| 117 | + | sort.Strings(keys) | |||
| 118 | + | rows := make([]searchShortcutRow, 0, len(keys)) | |||
| 119 | + | for _, key := range keys { | |||
| 120 | + | shortcut := shortcuts[key] | |||
| 121 | + | rows = append(rows, searchShortcutRow{ | |||
| 122 | + | Key: key, | |||
| 123 | + | URL: shortcut.URL, | |||
| 124 | + | Description: shortcut.Description, | |||
| 125 | + | }) | |||
| 126 | + | } | |||
| 127 | + | return rows | |||
| 128 | + | } | |||
| 129 | + | ||||
| 130 | + | func formatConfigInt(value int) string { | |||
| 131 | + | return fmt.Sprintf("%d", value) | |||
| 132 | + | } | |||
| 133 | + | ||||
| 134 | + | func formatConfigFloat(value float64) string { | |||
| 135 | + | return fmt.Sprintf("%g", value) | |||
| 136 | + | } | |||
| 137 | + | ||||
| 138 | + | func colorSchemeSelected(current, option string) bool { | |||
| 139 | + | return strings.EqualFold(strings.TrimSpace(current), option) | |||
| 140 | + | } | |||
| 141 | + | ||||
| 142 | + | func performanceProfileSelected(current, option string) bool { | |||
| 143 | + | return strings.EqualFold(strings.TrimSpace(current), option) | |||
| 144 | + | } | |||
| 145 | + | ||||
| 146 | + | func engineIsWebKit(engine string) bool { | |||
| 147 | + | return strings.EqualFold(strings.TrimSpace(engine), "webkit") | |||
| 148 | + | } | |||
| 149 | + | ||||
| 97 | func flattenValues(value any) []kvPair { | 150 | func flattenValues(value any) []kvPair { | ||
| 98 | rows := make([]kvPair, 0) | 151 | rows := make([]kvPair, 0) | ||
| 99 | flattenValue(&rows, "", reflect.ValueOf(value)) | 152 | flattenValue(&rows, "", reflect.ValueOf(value)) | ||
M internal/ui/systemviews/history_actions.go +11 -0
| @@ -50,6 +50,17 @@ func (a *App) HandleDOMAction(ctx context.Context, event DOMAction) error { | |||
| 50 | 50 | a.renderRouteError(err) | |
| 51 | 51 | } | |
| 52 | 52 | return a.mountRenderedHTML() | |
| 53 | + | case RouteConfig: | |
| 54 | + | a.configError = "" | |
| 55 | + | if err := a.handleConfigAction(ctx, event); err != nil { | |
| 56 | + | a.configNotice = "" | |
| 57 | + | a.configError = err.Error() | |
| 58 | + | } | |
| 59 | + | a.loadShellTheme(ctx) | |
| 60 | + | if err := a.loadConfigRoute(ctx); err != nil { | |
| 61 | + | a.renderRouteError(err) | |
| 62 | + | } | |
| 63 | + | return a.mountRenderedHTML() | |
| 53 | 64 | default: | |
| 54 | 65 | return nil | |
| 55 | 66 | } | |
| @@ -50,6 +50,17 @@ func (a *App) HandleDOMAction(ctx context.Context, event DOMAction) error { | |||||
| 50 | a.renderRouteError(err) | 50 | a.renderRouteError(err) | ||
| 51 | } | 51 | } | ||
| 52 | return a.mountRenderedHTML() | 52 | return a.mountRenderedHTML() | ||
| 53 | + | case RouteConfig: | |||
| 54 | + | a.configError = "" | |||
| 55 | + | if err := a.handleConfigAction(ctx, event); err != nil { | |||
| 56 | + | a.configNotice = "" | |||
| 57 | + | a.configError = err.Error() | |||
| 58 | + | } | |||
| 59 | + | a.loadShellTheme(ctx) | |||
| 60 | + | if err := a.loadConfigRoute(ctx); err != nil { | |||
| 61 | + | a.renderRouteError(err) | |||
| 62 | + | } | |||
| 63 | + | return a.mountRenderedHTML() | |||
| 53 | default: | 64 | default: | ||
| 54 | return nil | 65 | return nil | ||
| 55 | } | 66 | } | ||