Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Player bar Spotify-style right cluster (Mini-player + Fullscreen primary, Speed/

### Playlists ([`docs/features/playlists.md`](docs/features/playlists.md), [`docs/features/smart-playlists.md`](docs/features/smart-playlists.md))

Playlist sort dropdown (custom / title / artist / album / recently added / duration — non-custom modes are display-only via `Intl.Collator`, never touch `playlist_track.position`) · auto-cover (Spotify-style 2×2 grid composite from first 4 tracks; manual upload flips `cover_is_auto=0`) · smart playlists (Daily Mix family + recursive boolean rule tree via `CustomRules`, v1 flat → v2 tree auto-migration) · M3U import/export.
Playlist sort dropdown (custom / title / artist / album / recently added / duration / filename — non-custom modes are display-only via `Intl.Collator`, never touch `playlist_track.position`; filename sorts on the cross-platform basename of `track.file_path`) · auto-cover (Spotify-style 2×2 grid composite from first 4 tracks; manual upload flips `cover_is_auto=0`) · smart playlists (Daily Mix family + recursive boolean rule tree via `CustomRules`, v1 flat → v2 tree auto-migration) · M3U import/export.

### Integrations ([`docs/features/integrations.md`](docs/features/integrations.md))

Expand Down
25 changes: 24 additions & 1 deletion src/components/views/PlaylistView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ type PlaylistSortMode =
| "artist"
| "album"
| "added_at"
| "duration_ms";
| "duration_ms"
| "filename";

const PLAYLIST_SORT_MODES: ReadonlyArray<PlaylistSortMode> = [
"custom",
Expand All @@ -97,8 +98,19 @@ const PLAYLIST_SORT_MODES: ReadonlyArray<PlaylistSortMode> = [
"album",
"added_at",
"duration_ms",
"filename",
];

/** Cross-platform basename — handles both Windows (`\`) and POSIX
* (`/`) separators since profiles can ship libraries scanned on
* either OS, and an imported `.waveflow` archive may cross
* platforms. */
function basename(path: string): string {
const slash = path.lastIndexOf("/");
const back = path.lastIndexOf("\\");
return path.slice(Math.max(slash, back) + 1);
}

function isPlaylistSortMode(value: string): value is PlaylistSortMode {
return (PLAYLIST_SORT_MODES as readonly string[]).includes(value);
}
Expand Down Expand Up @@ -203,6 +215,16 @@ export function PlaylistView({
case "duration_ms":
sorted.sort((a, b) => (b.duration_ms ?? 0) - (a.duration_ms ?? 0));
break;
case "filename":
// Numeric collator gives a natural order on "1 …", "2 …",
// "10 …" filenames — the most common manual-numbering scheme
// (matches Explorer / Finder behaviour). Sorted on the basename
// only so users grouping by parent folder still see filename
// order, not full-path lexicographic order.
sorted.sort((a, b) =>
collator.compare(basename(a.file_path), basename(b.file_path)),
);
break;
}
return sorted;
}, [tracks, sortMode]);
Expand Down Expand Up @@ -1225,6 +1247,7 @@ function PlaylistSortMenu({ current, onChange, t }: PlaylistSortMenuProps) {
album: t("sort.album"),
added_at: t("sort.recentlyAdded", "Recently added"),
duration_ms: t("sort.duration"),
filename: t("sort.filename"),
};

return (
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "عدد الألبومات",
"tracksCount": "عدد الأغاني",
"ascending": "كروسان",
"descending": "تنازلي"
"descending": "تنازلي",
"filename": "اسم الملف"
},
"settings": {
"title": "الإعدادات",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Anzahl der Alben",
"tracksCount": "Anzahl der Titel",
"ascending": "Croissant",
"descending": "Absteigend"
"descending": "Absteigend",
"filename": "Dateiname"
},
"settings": {
"title": "Einstellungen",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,8 @@
"albumsCount": "Number of albums",
"tracksCount": "Number of tracks",
"ascending": "Croissant",
"descending": "Descending"
"descending": "Descending",
"filename": "Filename"
},
"settings": {
"title": "Settings",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "N.º de álbumes",
"tracksCount": "N.º de canciones",
"ascending": "Croissant",
"descending": "Descendente"
"descending": "Descendente",
"filename": "Nombre del archivo"
},
"settings": {
"title": "Configuración",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,8 @@
"albumsCount": "Nb albums",
"tracksCount": "Nb morceaux",
"ascending": "Croissant",
"descending": "Décroissant"
"descending": "Décroissant",
"filename": "Nom de fichier"
},
"settings": {
"title": "Paramètres",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "एल्बमों की संख्या",
"tracksCount": "ट्रैकों की संख्या",
"ascending": "क्रोइसाँ",
"descending": "उतरता हुआ"
"descending": "उतरता हुआ",
"filename": "फ़ाइल का नाम"
},
"settings": {
"title": "सेटिंग्स",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Album",
"tracksCount": "Lagu",
"ascending": "Naik",
"descending": "Menurun"
"descending": "Menurun",
"filename": "Nama berkas"
},
"settings": {
"title": "Pengaturan",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Numero di album",
"tracksCount": "Numero di brani",
"ascending": "Croissant",
"descending": "Decrescente"
"descending": "Decrescente",
"filename": "Nome file"
},
"settings": {
"title": "Impostazioni",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "アルバム数",
"tracksCount": "曲数",
"ascending": "クロワッサン",
"descending": "降順"
"descending": "降順",
"filename": "ファイル名"
},
"settings": {
"title": "設定",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/kr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "앨범 수",
"tracksCount": "곡 수",
"ascending": "크루아상",
"descending": "내림차순"
"descending": "내림차순",
"filename": "파일 이름"
},
"settings": {
"title": "설정",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Aantal albums",
"tracksCount": "Aantal nummers",
"ascending": "Croissant",
"descending": "Afnemend"
"descending": "Afnemend",
"filename": "Bestandsnaam"
},
"settings": {
"title": "Instellingen",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Número de álbuns",
"tracksCount": "Número de faixas",
"ascending": "Croissant",
"descending": "Decrescente"
"descending": "Decrescente",
"filename": "Nome do arquivo"
},
"settings": {
"title": "Configurações",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "N.º de álbuns",
"tracksCount": "N.º de faixas",
"ascending": "Croissant",
"descending": "Decrescente"
"descending": "Decrescente",
"filename": "Nome do ficheiro"
},
"settings": {
"title": "Parâmetros",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Альбомы",
"tracksCount": "Треки",
"ascending": "По возрастанию",
"descending": "По убыванию"
"descending": "По убыванию",
"filename": "Имя файла"
},
"settings": {
"title": "Настройки",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "Albümler",
"tracksCount": "Parçalar",
"ascending": "Artan",
"descending": "Azalan"
"descending": "Azalan",
"filename": "Dosya adı"
},
"settings": {
"title": "Ayarlar",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "专辑数量",
"tracksCount": "曲目数",
"ascending": "牛角包",
"descending": "降序"
"descending": "降序",
"filename": "文件名"
},
"settings": {
"title": "设置",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@
"albumsCount": "專輯數量",
"tracksCount": "曲目數",
"ascending": "可頌",
"descending": "遞減"
"descending": "遞減",
"filename": "檔案名稱"
},
"settings": {
"title": "設定",
Expand Down
Loading