diff --git a/backend/app.go b/backend/app.go index e00877d..5e41e50 100644 --- a/backend/app.go +++ b/backend/app.go @@ -65,7 +65,6 @@ func NewYellowJacketApp( } yjApp.appConfig = appConfig - yjApp.assetHandler.RegisterHandler("/config", yjApp.appConfig) // create frontendUtil feUtil, err := frontendutil.NewFrontendUtil() diff --git a/backend/config/config-form.templ b/backend/config/config-form.templ deleted file mode 100644 index 2ee7d6b..0000000 --- a/backend/config/config-form.templ +++ /dev/null @@ -1,15 +0,0 @@ -package config - -import "yellowjacket/pkg/templcomp" - -templ (c *Config) form() { - @templcomp.ToForm(c, templ.URL("/config"), "config") -} - -templ (c *Config) formSubmitError(msg string) { - Error: { msg } -} - -templ (c *Config) formSubmitSuccess() { -
Config saved
-} diff --git a/backend/config/config-form_templ.go b/backend/config/config-form_templ.go deleted file mode 100644 index 593600d..0000000 --- a/backend/config/config-form_templ.go +++ /dev/null @@ -1,113 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.977 -package config - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "yellowjacket/pkg/templcomp" - -func (c *Config) form() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templcomp.ToForm(c, templ.URL("/config"), "config").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func (c *Config) formSubmitError(msg string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var2 := templ.GetChildren(ctx) - if templ_7745c5c3_Var2 == nil { - templ_7745c5c3_Var2 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Error: ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(msg) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `config/config-form.templ`, Line: 10, Col: 21} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func (c *Config) formSubmitSuccess() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var4 := templ.GetChildren(ctx) - if templ_7745c5c3_Var4 == nil { - templ_7745c5c3_Var4 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "Config saved
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/backend/config/config.go b/backend/config/config.go index 85fedd8..d2739f8 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "log/slog" - "net/http" "os" "path" @@ -16,17 +15,17 @@ import ( "yellowjacket/backend/events" "yellowjacket/backend/library" "yellowjacket/backend/system" + "yellowjacket/backend/theme" ) // Config represents the application configuration. type Config struct { ctx context.Context logger *slog.Logger - serveMux *http.ServeMux filePath string // required - Library *library.Config `form:"Library" schema:"library,required"` - - Window *WindowConfig `toml:"Window"` + Library *library.Config `toml:"Library"` + Theme *theme.Config `toml:"Theme"` + Window *WindowConfig `toml:"Window"` } // NewConfig creates a new config by loading it from disk. @@ -38,11 +37,9 @@ func NewConfig(logger *slog.Logger) (*Config, error) { conf := &Config{ filePath: path.Join(confDir, "config.toml"), - serveMux: http.NewServeMux(), } conf.applyDefaults() conf.logger = logger.WithGroup("config").With("config", conf) - conf.serveMux.HandleFunc("/", conf.handle) if err := conf.Load(); err != nil { return nil, fmt.Errorf("could not load config: %w", err) @@ -67,8 +64,17 @@ func (c *Config) Validate() error { } } + if c.Theme != nil { + if err := c.Theme.Validate(); err != nil { + configErrs = errors.Join(configErrs, err) + } + } + if configErrs != nil { - return fmt.Errorf("one or more config parts are invalid: %w", configErrs) + return fmt.Errorf( + "one or more config parts are invalid: %w", + configErrs, + ) } return nil @@ -148,6 +154,12 @@ func (c *Config) applyDefaults() { if c.Library != nil { c.Library.ApplyDefaults() } + + if c.Theme == nil { + c.Theme = &theme.Config{} + } + + c.Theme.ApplyDefaults() } // SetContext sets the Wails runtime context for event emission. @@ -245,3 +257,103 @@ func (c *Config) SetScanConcurrency(mode string) error { return nil } + +// GetThemeAccentColor returns the configured accent colour. +func (c *Config) GetThemeAccentColor() string { + if c.Theme == nil { + return theme.DefaultAccentColor + } + + return c.Theme.AccentColor +} + +// GetThemeBackgroundShade returns the configured background shade. +func (c *Config) GetThemeBackgroundShade() string { + if c.Theme == nil { + return string(theme.DefaultBackgroundShade) + } + + return string(c.Theme.BackgroundShade) +} + +// SetThemeAccentColor validates and saves a new accent colour. +func (c *Config) SetThemeAccentColor( + color string, +) error { + if c.Theme == nil { + c.Theme = &theme.Config{} + c.Theme.ApplyDefaults() + } + + c.Theme.AccentColor = color + + if err := c.Theme.Validate(); err != nil { + return fmt.Errorf( + "invalid theme accent color: %w", err, + ) + } + + if err := c.Save(); err != nil { + return fmt.Errorf( + "could not save config: %w", err, + ) + } + + c.emitThemeChanged() + + c.logger.Info( + "theme accent color updated", + "color", color, + ) + + return nil +} + +// SetThemeBackgroundShade validates and saves a new background shade. +func (c *Config) SetThemeBackgroundShade( + shade string, +) error { + if c.Theme == nil { + c.Theme = &theme.Config{} + c.Theme.ApplyDefaults() + } + + c.Theme.BackgroundShade = theme.BackgroundShade(shade) + + if err := c.Theme.Validate(); err != nil { + return fmt.Errorf( + "invalid theme background shade: %w", err, + ) + } + + if err := c.Save(); err != nil { + return fmt.Errorf( + "could not save config: %w", err, + ) + } + + c.emitThemeChanged() + + c.logger.Info( + "theme background shade updated", + "shade", shade, + ) + + return nil +} + +// emitThemeChanged sends the ThemeConfigChanged event to the frontend. +func (c *Config) emitThemeChanged() { + if c.ctx == nil || c.Theme == nil { + return + } + + runtime.EventsEmit( + c.ctx, + events.ThemeConfigChanged, + map[string]any{ + "AccentColor": c.Theme.AccentColor, + "BackgroundShade": string(c.Theme.BackgroundShade), + }, + ) +} diff --git a/backend/config/httphandler.go b/backend/config/httphandler.go deleted file mode 100644 index 8aa509f..0000000 --- a/backend/config/httphandler.go +++ /dev/null @@ -1,80 +0,0 @@ -package config - -import ( - "fmt" - "net/http" - - "github.com/gorilla/schema" - "github.com/wailsapp/wails/v2/pkg/runtime" - - "yellowjacket/backend/events" -) - -var formDecoder = schema.NewDecoder() - -func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) { - c.serveMux.ServeHTTP(w, r) -} - -func (c *Config) handle(w http.ResponseWriter, r *http.Request) { - c.logger.Debug("handling request from config http handler") - - switch r.Method { - case http.MethodGet: - if err := c.form().Render(r.Context(), w); err != nil { - c.logger.Error("problem getting config html", "err", err.Error()) - w.WriteHeader(http.StatusInternalServerError) - } - case http.MethodPost: - if err := c.handleConfigPost(r); err != nil { - c.logger.Error("problem handling config post request", "err", err.Error()) - - renderErr := c.formSubmitError(err.Error()).Render(r.Context(), w) - if renderErr != nil { - c.logger.Error("problem rendering error response", "err", renderErr.Error()) - } - - w.WriteHeader(http.StatusInternalServerError) - - return - } - - if err := c.formSubmitSuccess().Render(r.Context(), w); err != nil { - c.logger.Error("problem rendering success response", "err", err.Error()) - } - - w.WriteHeader(http.StatusOK) - } -} - -func (c *Config) handleConfigPost(r *http.Request) error { - if err := r.ParseForm(); err != nil { - return fmt.Errorf("could not parse form data: %w", err) - } - - var postedConfig Config - - err := formDecoder.Decode(&postedConfig, r.PostForm) - if err != nil { - return fmt.Errorf("could not decode form data: %w", err) - } - - c.logger.Debug("decoded config post form data", "postedConfig", postedConfig) - - // Update local config and emit event for listeners - if postedConfig.Library != nil { - c.Library = postedConfig.Library - - if c.ctx != nil { - runtime.EventsEmit(c.ctx, events.LibraryConfigChanged, map[string]any{ - "DirectoryPath": string(c.Library.DirectoryPath), - }) - } - } - - if err := c.Save(); err != nil { - return fmt.Errorf("could not save posted config: %w", err) - } - - return nil -} diff --git a/backend/events/events.go b/backend/events/events.go index 12fc7e4..6635320 100644 --- a/backend/events/events.go +++ b/backend/events/events.go @@ -55,6 +55,7 @@ const ( // Config events. const ( LibraryConfigChanged = "LibraryConfigChanged" + ThemeConfigChanged = "ThemeConfigChanged" ) // Playlist events. diff --git a/backend/library/config.templ b/backend/library/config.templ deleted file mode 100644 index 099fce2..0000000 --- a/backend/library/config.templ +++ /dev/null @@ -1,7 +0,0 @@ -package library - -templ (d Directory) ToFormElement() { - - - -} diff --git a/backend/library/config_templ.go b/backend/library/config_templ.go deleted file mode 100644 index a110626..0000000 --- a/backend/library/config_templ.go +++ /dev/null @@ -1,53 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.977 -package library - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func (d Directory) ToFormElement() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/backend/theme/config.go b/backend/theme/config.go new file mode 100644 index 0000000..c29b8c7 --- /dev/null +++ b/backend/theme/config.go @@ -0,0 +1,80 @@ +// Package theme manages visual theme configuration. +package theme + +import ( + "errors" + "fmt" + "regexp" +) + +var ( + errInvalidHexColor = errors.New("invalid hex color") + errUnknownBackgroundShade = errors.New("unknown background shade") +) + +// hexColorRe matches 3- or 6-digit CSS hex colours (e.g. "#fff", "#ffd43b"). +var hexColorRe = regexp.MustCompile(`^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$`) + +// BackgroundShade controls the base grayscale palette. +type BackgroundShade string + +// Valid BackgroundShade values. +const ( + // BackgroundDarker is an OLED-friendly palette with true black. + BackgroundDarker BackgroundShade = "darker" + + // BackgroundDark is the default dark palette. + BackgroundDark BackgroundShade = "dark" + + // BackgroundLight is a light-mode palette. + BackgroundLight BackgroundShade = "light" +) + +// Defaults. +const ( + DefaultAccentColor = "#ffd43b" + DefaultBackgroundShade = BackgroundDark +) + +// Config holds visual theme preferences. +type Config struct { + AccentColor string `toml:"AccentColor"` + BackgroundShade BackgroundShade `toml:"BackgroundShade"` +} + +// ApplyDefaults fills zero-value fields with sensible defaults. +func (c *Config) ApplyDefaults() { + if c.AccentColor == "" { + c.AccentColor = DefaultAccentColor + } + + if c.BackgroundShade == "" { + c.BackgroundShade = DefaultBackgroundShade + } +} + +// Validate checks that all values are well-formed. +func (c *Config) Validate() error { + c.ApplyDefaults() + + if !hexColorRe.MatchString(c.AccentColor) { + return fmt.Errorf( + "%w: %q", + errInvalidHexColor, + c.AccentColor, + ) + } + + switch c.BackgroundShade { + case BackgroundDarker, BackgroundDark, BackgroundLight: + // Valid. + default: + return fmt.Errorf( + "%w: %q", + errUnknownBackgroundShade, + c.BackgroundShade, + ) + } + + return nil +} diff --git a/frontend/index.css b/frontend/index.css index dd50ca3..9edc5f8 100644 --- a/frontend/index.css +++ b/frontend/index.css @@ -10,8 +10,8 @@ html { } body { - background-color: black; - color: white; + background-color: var(--yj-bg-base, black); + color: var(--yj-text-primary, white); margin: 0; height: 100vh; display: grid; @@ -32,7 +32,7 @@ p { display: flex; justify-content: space-between; align-items: center; - background-color: #343a40; + background-color: var(--yj-bg-elevated, #343a40); } ul { @@ -51,14 +51,14 @@ ul { body div.sidebar { grid-area: sidebar; - background-color: #212529; + background-color: var(--yj-bg-surface, #212529); overflow: hidden; } .bottom-bar { grid-area: bottom-bar; padding: 0.25em; - background-color: #343a40; + background-color: var(--yj-bg-elevated, #343a40); display: grid; grid-template-columns: var(--now-playing-width, 200px) 1fr auto; align-items: center; @@ -75,7 +75,7 @@ body div.sidebar { height: 3.5em; min-height: 3.5em; border-radius: 0.25em; - background-color: #ffd43b; + background-color: var(--yj-accent, #ffd43b); } #track-info { @@ -114,12 +114,12 @@ body div.sidebar { } #queue-button:hover { - color: #ffd43b; + color: var(--yj-accent, #ffd43b); } #queue-button.drag-over { - color: #ffd43b; - outline: 2px dashed #ffd43b; + color: var(--yj-accent, #ffd43b); + outline: 2px dashed var(--yj-accent, #ffd43b); outline-offset: -2px; border-radius: 4px; } @@ -135,7 +135,7 @@ body div.sidebar { flex: 1; min-width: 0; padding: 0.25em; - background-color: #212529; + background-color: var(--yj-bg-surface, #212529); overflow: hidden; } diff --git a/frontend/index.html b/frontend/index.html index 0a89701..06c1258 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -15,9 +15,6 @@Coming soon: ${view}
+ ${this.schema.description} +
` + : nothing} +Unsupported field type
`; + } + } + + private renderText() { + return html` + + `; + } + + private renderNumber() { + return html` + + `; + } + + private renderSelect() { + const current = String(this.value ?? ''); + + return html` + + `; + } + + private renderColor() { + const hex = String(this.value ?? '#ffffff'); + + return html` ++ Scan Results +
+ ++ Per-format and per-operation times + are cumulative across + ${Object.values( + m.formatCount ?? {}, + ).reduce((a, b) => a + b, 0)} + files +
+ + ${formatEntries.length > 0 + ? html` ++ Generated concurrently; cumulative + CPU time may exceed wall-clock +
+ ${this.renderMetricRow('Cumulative CPU Time', fmtNs(m.thumbnailGeneration))} + ${this.renderMetricRow('Small (_sm)', fmtNs(m.thumbnailSmall))} + ${this.renderMetricRow('Medium (_md)', fmtNs(m.thumbnailMedium))} + ${this.renderMetricRow('Large (_lg)', fmtNs(m.thumbnailLarge))} ++ ${this.description} +
` + : nothing} +${item.label}
`; diff --git a/frontend/src/components/track-info/track-info.ts b/frontend/src/components/track-info/track-info.ts index f9f07b7..5f382e3 100644 --- a/frontend/src/components/track-info/track-info.ts +++ b/frontend/src/components/track-info/track-info.ts @@ -63,14 +63,14 @@ export class TrackInfo extends LitElement { .cover-placeholder { width: 100%; height: 100%; - background-color: #2a2d30; + background-color: var(--yj-bg-elevated, #2a2d30); display: flex; align-items: center; justify-content: center; } .cover-placeholder wa-icon { - color: #666; + color: var(--yj-text-tertiary, #666); font-size: 18px; } @@ -85,7 +85,7 @@ export class TrackInfo extends LitElement { .title { font-size: 13px; font-weight: 500; - color: #fff; + color: var(--yj-text-primary, #fff); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -93,7 +93,7 @@ export class TrackInfo extends LitElement { .secondary { font-size: 11px; - color: #888; + color: var(--yj-text-tertiary, #888); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -101,7 +101,7 @@ export class TrackInfo extends LitElement { .duration { font-size: 12px; - color: #888; + color: var(--yj-text-tertiary, #888); flex-shrink: 0; font-variant-numeric: tabular-nums; } diff --git a/frontend/src/components/track-list/track-list.ts b/frontend/src/components/track-list/track-list.ts index dc210e4..8ffdb33 100644 --- a/frontend/src/components/track-list/track-list.ts +++ b/frontend/src/components/track-list/track-list.ts @@ -252,8 +252,8 @@ export class TrackList extends LitElement implements SelectionHost { grid-template-columns: var(--grid-cols, 1fr 1fr 80px); padding: 8px; font-weight: bold; - color: #fff; - border-bottom: 1px solid #666; + color: var(--yj-text-primary, #fff); + border-bottom: 1px solid var(--yj-text-tertiary, #666); flex-shrink: 0; } @@ -277,7 +277,7 @@ export class TrackList extends LitElement implements SelectionHost { width: 1px; cursor: col-resize; pointer-events: auto; - background-color: #444; + background-color: var(--yj-border, #444); transition: background-color 0.15s ease; } @@ -292,7 +292,7 @@ export class TrackList extends LitElement implements SelectionHost { .col-resize-handle:hover, .col-resize-handle.active { - background-color: #6c757d; + background-color: var(--yj-text-tertiary, #6c757d); } lit-virtualizer { @@ -307,7 +307,7 @@ export class TrackList extends LitElement implements SelectionHost { grid-template-columns: var(--grid-cols, 1fr 1fr 80px); font-size: 12px; padding: 8px; - border-bottom: 1px solid #333; + border-bottom: 1px solid var(--yj-border-subtle, #333); align-items: center; width: 100%; cursor: default; @@ -324,23 +324,23 @@ export class TrackList extends LitElement implements SelectionHost { } .track-row:hover { - background-color: rgba(255, 255, 255, 0.05); + background-color: var(--yj-hover-overlay, rgba(255, 255, 255, 0.05)); } .track-row.selected { - background-color: rgba(100, 160, 255, 0.15); + background-color: var(--yj-selection-bg, rgba(100, 160, 255, 0.15)); } .track-row.active { - background-color: rgba(255, 212, 59, 0.1); + background-color: var(--yj-accent-bg, rgba(255, 212, 59, 0.1)); } .track-row.active { - color: #ffd43b; + color: var(--yj-accent, #ffd43b); } .track-row.selected.active { - background-color: rgba(100, 160, 255, 0.15); + background-color: var(--yj-selection-bg, rgba(100, 160, 255, 0.15)); } .track-name { @@ -363,8 +363,8 @@ export class TrackList extends LitElement implements SelectionHost { } .context-menu-panel { - background-color: #343a40; - border: 1px solid #444; + background-color: var(--yj-bg-elevated, #343a40); + border: 1px solid var(--yj-border, #444); border-radius: 6px; padding: 4px 0; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); @@ -376,12 +376,12 @@ export class TrackList extends LitElement implements SelectionHost { } .context-menu-panel wa-dropdown-item { - --wa-color-text-normal: #fff; + --wa-color-text-normal: var(--yj-text-primary, #fff); font-size: 13px; } .context-menu-panel wa-dropdown-item:hover { - background-color: rgba(255, 255, 255, 0.1); + background-color: var(--yj-hover-overlay, rgba(255, 255, 255, 0.1)); } .submenu-item { diff --git a/frontend/src/events.ts b/frontend/src/events.ts index 29dfeec..5c3e274 100644 --- a/frontend/src/events.ts +++ b/frontend/src/events.ts @@ -48,6 +48,9 @@ export const Events = { PlaylistTracksChanged: "PlaylistTracksChanged", PlaylistsRestored: "PlaylistsRestored", + // Config events + ThemeConfigChanged: "ThemeConfigChanged", + // Library events LibraryScanStarted: "LibraryScanStarted", LibraryScanComplete: "LibraryScanComplete", diff --git a/frontend/src/pages/config/config.css b/frontend/src/pages/config/config.css deleted file mode 100644 index a3e4f0d..0000000 --- a/frontend/src/pages/config/config.css +++ /dev/null @@ -1,11 +0,0 @@ -*, -*::before, -*::after { - -webkit-user-select: none; - user-select: none; -} - -body { - background-color: black; - color: white; -} diff --git a/frontend/src/pages/config/config.ts b/frontend/src/pages/config/config.ts deleted file mode 100644 index e4a611b..0000000 --- a/frontend/src/pages/config/config.ts +++ /dev/null @@ -1,42 +0,0 @@ -import 'htmx.org/dist/htmx.js' -import { DirectoryPicker } from '@go/frontendutil/FrontendUtil'; -import { Scan } from '@go/library/Library'; - -declare global { - interface Window { - DirectoryPicker: typeof DirectoryPicker; - Scan: typeof Scan; - selectLibraryDirectory: (pElement: HTMLInputElement) => void; - scanLibrary: (button: HTMLButtonElement) => void; - } -} - -window.DirectoryPicker = DirectoryPicker; -window.Scan = Scan; - -window.selectLibraryDirectory = (pElement: HTMLInputElement) => { - window.DirectoryPicker() - .then((result) => { - if (result.length !== 0) { - pElement.value = result; - } - }) - .catch((err: unknown) => { - console.error('error with directory picker: ' + err); - }); -}; - -window.scanLibrary = (button: HTMLButtonElement) => { - button.disabled = true; - button.textContent = 'Scanning...'; - window.Scan() - .then(() => { - button.textContent = 'Scan Library'; - button.disabled = false; - }) - .catch((err: unknown) => { - console.error('error scanning library: ' + err); - button.textContent = 'Scan Library'; - button.disabled = false; - }); -}; diff --git a/frontend/src/pages/config/index.html b/frontend/src/pages/config/index.html deleted file mode 100644 index 0c932f5..0000000 --- a/frontend/src/pages/config/index.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - -