fix: smart playlist UX polish — layout, defaults, free-form input, case-insensitive matching
Details view: - Skip evaluation on new playlists (was returning all 25k tracks) - Go straight to editor on auto-edit instead of awaiting loadTracks Editor: - Default sort to Random instead of None, remove None option - Hide sort direction button when sort is Random - Fixed-width field (160px) and operator (140px) columns, value fills remaining space - Preview fills remaining vertical space (flex layout) instead of fixed 200px max-height - Preview scrolls independently while rules/options stay pinned Combobox: - Accept free-form text on blur and Enter — no longer requires selection from dropdown - Enables typing values like 'indie' that may not be exact DB entries Backend: - Case-insensitive text matching: COLLATE NOCASE on is/is_not/is_any_of operators - Applies to both regular fields and genre subqueries - LIKE operators were already case-insensitive (SQLite default)
This commit is contained in:
@@ -174,8 +174,24 @@ export class YjCombobox extends LitElement {
|
||||
// fire first.
|
||||
requestAnimationFrame(() => {
|
||||
this.open = false;
|
||||
// Restore display text to the confirmed value.
|
||||
this.filterText = this.value;
|
||||
|
||||
// Commit free-form text: if the user typed something that
|
||||
// isn't in the option list, accept it as the value anyway.
|
||||
const typed = this.filterText.trim();
|
||||
if (typed && typed !== this.value) {
|
||||
this.value = typed;
|
||||
this.filterText = typed;
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('combobox-change', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: { value: typed },
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
// Restore display text to the confirmed value.
|
||||
this.filterText = this.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,6 +227,11 @@ export class YjCombobox extends LitElement {
|
||||
) {
|
||||
e.preventDefault();
|
||||
this.selectOption(opts[this.highlightedIndex]!);
|
||||
} else if (this.filterText.trim()) {
|
||||
// Commit free-form text on Enter even without a
|
||||
// highlighted option.
|
||||
e.preventDefault();
|
||||
this.selectOption(this.filterText.trim());
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user