pstream is dead; long live pstream
taciturnaxolotl.github.io/pstream-ng/
1import { BookmarkMediaItem } from "@/stores/bookmarks";
2import { ProgressMediaItem } from "@/stores/progress";
3import { MediaItem } from "@/utils/mediaTypes";
4
5export type SortOption =
6 | "date"
7 | "title-asc"
8 | "title-desc"
9 | "year-asc"
10 | "year-desc";
11
12export function sortMediaItems(
13 items: MediaItem[],
14 sortBy: SortOption,
15 bookmarks?: Record<string, BookmarkMediaItem>,
16 progressItems?: Record<string, ProgressMediaItem>,
17): MediaItem[] {
18 const sorted = [...items];
19
20 switch (sortBy) {
21 case "date": {
22 sorted.sort((a, b) => {
23 const bookmarkA = bookmarks?.[a.id];
24 const bookmarkB = bookmarks?.[b.id];
25 const progressA = progressItems?.[a.id];
26 const progressB = progressItems?.[b.id];
27
28 const dateA = Math.max(
29 bookmarkA?.updatedAt ?? 0,
30 progressA?.updatedAt ?? 0,
31 );
32 const dateB = Math.max(
33 bookmarkB?.updatedAt ?? 0,
34 progressB?.updatedAt ?? 0,
35 );
36
37 return dateB - dateA; // Newest first
38 });
39 break;
40 }
41
42 case "title-asc": {
43 sorted.sort((a, b) => {
44 const titleA = a.title?.toLowerCase() ?? "";
45 const titleB = b.title?.toLowerCase() ?? "";
46 return titleA.localeCompare(titleB);
47 });
48 break;
49 }
50
51 case "title-desc": {
52 sorted.sort((a, b) => {
53 const titleA = a.title?.toLowerCase() ?? "";
54 const titleB = b.title?.toLowerCase() ?? "";
55 return titleB.localeCompare(titleA);
56 });
57 break;
58 }
59
60 case "year-asc": {
61 sorted.sort((a, b) => {
62 const yearA = a.year ?? Number.MAX_SAFE_INTEGER;
63 const yearB = b.year ?? Number.MAX_SAFE_INTEGER;
64 if (yearA === yearB) {
65 // Secondary sort by title for same year
66 const titleA = a.title?.toLowerCase() ?? "";
67 const titleB = b.title?.toLowerCase() ?? "";
68 return titleA.localeCompare(titleB);
69 }
70 return yearA - yearB;
71 });
72 break;
73 }
74
75 case "year-desc": {
76 sorted.sort((a, b) => {
77 const yearA = a.year ?? 0; // Put undefined years at the end
78 const yearB = b.year ?? 0;
79 if (yearA === yearB) {
80 // Secondary sort by title for same year
81 const titleA = a.title?.toLowerCase() ?? "";
82 const titleB = b.title?.toLowerCase() ?? "";
83 return titleA.localeCompare(titleB);
84 }
85 return yearB - yearA;
86 });
87 break;
88 }
89
90 default: {
91 // Fallback to date sorting for unknown sort options
92 sorted.sort((a, b) => {
93 const bookmarkA = bookmarks?.[a.id];
94 const bookmarkB = bookmarks?.[b.id];
95 const progressA = progressItems?.[a.id];
96 const progressB = progressItems?.[b.id];
97
98 const dateA = Math.max(
99 bookmarkA?.updatedAt ?? 0,
100 progressA?.updatedAt ?? 0,
101 );
102 const dateB = Math.max(
103 bookmarkB?.updatedAt ?? 0,
104 progressB?.updatedAt ?? 0,
105 );
106
107 return dateB - dateA; // Newest first
108 });
109 break;
110 }
111 }
112
113 return sorted;
114}