feat(artist): sort albums by year on artist detail (#877)

* feat(artist): year sort for albums section on artist detail

Add a sort dropdown next to "Albums by …" with release-type grouping (default),
newest-first, and oldest-first by album year.

* chore: note PR #877 in CHANGELOG and settings credits

* fix(artist): toggle year sort inside release groups, session per server

Replace dropdown with a click-to-toggle newest/oldest button. Keep release-type
blocks; sort albums by year within each group. Persist order in session store.
This commit is contained in:
cucadmuh
2026-05-27 13:04:00 +03:00
committed by GitHub
parent 06da15caf3
commit ee5068c98c
16 changed files with 193 additions and 11 deletions
@@ -0,0 +1,29 @@
import { describe, expect, it } from 'vitest';
import type { SubsonicAlbum } from '../../api/subsonicTypes';
import { sortArtistAlbumsByYear } from './sortArtistAlbums';
const album = (id: string, name: string, year?: number): SubsonicAlbum => ({
id,
name,
artist: 'A',
artistId: 'a',
songCount: 1,
duration: 1,
year,
});
describe('sortArtistAlbumsByYear', () => {
const albums = [
album('3', 'Gamma', 2000),
album('1', 'Alpha', 1990),
album('2', 'Beta', 2000),
];
it('sorts by year descending then name', () => {
expect(sortArtistAlbumsByYear(albums, 'yearDesc').map(a => a.id)).toEqual(['2', '3', '1']);
});
it('sorts by year ascending then name', () => {
expect(sortArtistAlbumsByYear(albums, 'yearAsc').map(a => a.id)).toEqual(['1', '2', '3']);
});
});
+17
View File
@@ -0,0 +1,17 @@
import type { SubsonicAlbum } from '../../api/subsonicTypes';
export type ArtistAlbumYearOrder = 'yearDesc' | 'yearAsc';
export function sortArtistAlbumsByYear(
albums: SubsonicAlbum[],
order: ArtistAlbumYearOrder,
): SubsonicAlbum[] {
const out = [...albums];
out.sort((a, b) => {
const ay = a.year ?? 0;
const by = b.year ?? 0;
if (ay !== by) return order === 'yearDesc' ? by - ay : ay - by;
return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
});
return out;
}