feat(quick-7): wire frontend pin-default-playlist feature end-to-end
- Add pinDefault state, getter, setter to favorites-store - Add pinDefault getter and setPinDefault to favorites-controller - Update sortedEntries in playlist-view to pin default playlist to top - Add Pin to Top toggle in config page Favorites section - Add Wails bindings for GetPinDefaultPlaylist/SetPinDefaultPlaylist - React to PinDefault in FavoritesConfigChanged event payload
This commit is contained in:
@@ -819,6 +819,21 @@ export class ConfigPage extends LitElement {
|
||||
});
|
||||
};
|
||||
|
||||
private handlePinDefaultChange = (
|
||||
e: CustomEvent<ConfigFieldChangeEvent>,
|
||||
): void => {
|
||||
const pin = Boolean(e.detail.value);
|
||||
|
||||
this.favCtrl
|
||||
.setPinDefault(pin)
|
||||
.catch((err: unknown) => {
|
||||
console.error(
|
||||
'Failed to set pin default:',
|
||||
err,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// TRACK LIST COLUMN HANDLERS
|
||||
// ===================================================================
|
||||
@@ -1082,6 +1097,18 @@ export class ConfigPage extends LitElement {
|
||||
.iconStyle}
|
||||
@config-change=${this.handleFavIconStyleChange}
|
||||
></config-field>
|
||||
|
||||
<config-field
|
||||
.schema=${{
|
||||
key: 'pinDefaultPlaylist',
|
||||
label: 'Pin to Top',
|
||||
description:
|
||||
'Always show the default playlist first, regardless of sort order.',
|
||||
type: 'toggle' as const,
|
||||
}}
|
||||
.value=${this.favCtrl.pinDefault}
|
||||
@config-change=${this.handlePinDefaultChange}
|
||||
></config-field>
|
||||
</config-section>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1042,6 +1042,22 @@ export class PlaylistView
|
||||
this.sortDirection === 'asc' ? 1 : -1;
|
||||
|
||||
return [...entries].sort((a, b) => {
|
||||
// Pin default playlist to top when enabled.
|
||||
if (this.favCtrl.pinDefault) {
|
||||
const aIsDefault =
|
||||
a.summary.ID ===
|
||||
this.favCtrl.playlistId;
|
||||
const bIsDefault =
|
||||
b.summary.ID ===
|
||||
this.favCtrl.playlistId;
|
||||
|
||||
if (aIsDefault && !bIsDefault)
|
||||
return -1;
|
||||
|
||||
if (!aIsDefault && bIsDefault)
|
||||
return 1;
|
||||
}
|
||||
|
||||
let cmp = 0;
|
||||
|
||||
switch (this.sortField) {
|
||||
|
||||
@@ -69,6 +69,10 @@ export class FavoritesController
|
||||
return favoritesStore.getPlaylistId();
|
||||
}
|
||||
|
||||
get pinDefault(): boolean {
|
||||
return favoritesStore.getPinDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon name for the current icon style.
|
||||
*/
|
||||
@@ -113,4 +117,10 @@ export class FavoritesController
|
||||
): Promise<void> {
|
||||
await favoritesStore.setDefaultPlaylist(id);
|
||||
}
|
||||
|
||||
async setPinDefault(
|
||||
pin: boolean,
|
||||
): Promise<void> {
|
||||
await favoritesStore.setPinDefault(pin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import {
|
||||
import {
|
||||
GetFavoritesIconStyle,
|
||||
GetFavoritesPlaylistID,
|
||||
GetPinDefaultPlaylist,
|
||||
SetFavoritesIconStyle,
|
||||
SetFavoritesPlaylistID,
|
||||
SetPinDefaultPlaylist,
|
||||
} from '@go/config/Config';
|
||||
import { Events } from '../events';
|
||||
|
||||
@@ -29,6 +31,7 @@ class FavoritesStore {
|
||||
private playlistId = 0;
|
||||
private playlistName = 'Favorites';
|
||||
private iconStyle: IconStyle = 'heart';
|
||||
private pinDefault = true;
|
||||
private favoritedPaths = new Set<string>();
|
||||
private subscribers = new Set<Subscriber>();
|
||||
private loading = false;
|
||||
@@ -44,10 +47,13 @@ class FavoritesStore {
|
||||
(data: {
|
||||
PlaylistID: number;
|
||||
IconStyle: string;
|
||||
PinDefault: boolean;
|
||||
}) => {
|
||||
this.playlistId = data.PlaylistID;
|
||||
this.iconStyle =
|
||||
data.IconStyle as IconStyle;
|
||||
this.pinDefault = data.PinDefault;
|
||||
this.notify();
|
||||
void this.loadPlaylistName();
|
||||
void this.loadPaths();
|
||||
},
|
||||
@@ -119,6 +125,10 @@ class FavoritesStore {
|
||||
return this.playlistId;
|
||||
}
|
||||
|
||||
getPinDefault(): boolean {
|
||||
return this.pinDefault;
|
||||
}
|
||||
|
||||
isLoading(): boolean {
|
||||
return this.loading;
|
||||
}
|
||||
@@ -203,6 +213,14 @@ class FavoritesStore {
|
||||
await this.loadPaths();
|
||||
}
|
||||
|
||||
async setPinDefault(
|
||||
pin: boolean,
|
||||
): Promise<void> {
|
||||
this.pinDefault = pin;
|
||||
this.notify();
|
||||
await SetPinDefaultPlaylist(pin);
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// SUBSCRIPTION SYSTEM
|
||||
// ===============================================================
|
||||
@@ -223,13 +241,16 @@ class FavoritesStore {
|
||||
|
||||
private async loadConfig(): Promise<void> {
|
||||
try {
|
||||
const [id, style] = await Promise.all([
|
||||
GetFavoritesPlaylistID(),
|
||||
GetFavoritesIconStyle(),
|
||||
]);
|
||||
const [id, style, pin] =
|
||||
await Promise.all([
|
||||
GetFavoritesPlaylistID(),
|
||||
GetFavoritesIconStyle(),
|
||||
GetPinDefaultPlaylist(),
|
||||
]);
|
||||
|
||||
this.playlistId = id;
|
||||
this.iconStyle = style as IconStyle;
|
||||
this.pinDefault = pin;
|
||||
await this.loadPlaylistName();
|
||||
this.notify();
|
||||
} catch {
|
||||
|
||||
+4
@@ -9,6 +9,8 @@ export function GetFavoritesPlaylistID():Promise<number>;
|
||||
|
||||
export function GetLibraryDirectory():Promise<string>;
|
||||
|
||||
export function GetPinDefaultPlaylist():Promise<boolean>;
|
||||
|
||||
export function GetScanConcurrency():Promise<string>;
|
||||
|
||||
export function GetThemeAccentColor():Promise<string>;
|
||||
@@ -29,6 +31,8 @@ export function SetFavoritesPlaylistID(arg1:number):Promise<void>;
|
||||
|
||||
export function SetLibraryDirectory(arg1:string):Promise<void>;
|
||||
|
||||
export function SetPinDefaultPlaylist(arg1:boolean):Promise<void>;
|
||||
|
||||
export function SetScanConcurrency(arg1:string):Promise<void>;
|
||||
|
||||
export function SetThemeAccentColor(arg1:string):Promise<void>;
|
||||
|
||||
@@ -14,6 +14,10 @@ export function GetLibraryDirectory() {
|
||||
return window['go']['config']['Config']['GetLibraryDirectory']();
|
||||
}
|
||||
|
||||
export function GetPinDefaultPlaylist() {
|
||||
return window['go']['config']['Config']['GetPinDefaultPlaylist']();
|
||||
}
|
||||
|
||||
export function GetScanConcurrency() {
|
||||
return window['go']['config']['Config']['GetScanConcurrency']();
|
||||
}
|
||||
@@ -54,6 +58,10 @@ export function SetLibraryDirectory(arg1) {
|
||||
return window['go']['config']['Config']['SetLibraryDirectory'](arg1);
|
||||
}
|
||||
|
||||
export function SetPinDefaultPlaylist(arg1) {
|
||||
return window['go']['config']['Config']['SetPinDefaultPlaylist'](arg1);
|
||||
}
|
||||
|
||||
export function SetScanConcurrency(arg1) {
|
||||
return window['go']['config']['Config']['SetScanConcurrency'](arg1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user