Skip to content

Commit 5bee987

Browse files
Merge pull request #25 from Jamesllllllllll/codex/issue-3-version-sort
Sort search results by updated date
2 parents 9214c5b + 6540fbe commit 5bee987

File tree

4 files changed

+40
-78
lines changed

4 files changed

+40
-78
lines changed

src/components/song-search-panel.tsx

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,6 @@ import { formatPathLabel } from "~/lib/request-policy";
5454
import { cn, getErrorMessage } from "~/lib/utils";
5555

5656
type SearchField = "any" | "title" | "artist" | "album" | "creator";
57-
type SearchSort =
58-
| "relevance"
59-
| "artist"
60-
| "title"
61-
| "album"
62-
| "creator"
63-
| "tuning"
64-
| "duration"
65-
| "downloads"
66-
| "updated";
6757

6858
export interface SearchSong {
6959
id: string;
@@ -129,8 +119,6 @@ export function SongSearchPanel(props: {
129119
const [debouncedQuery, setDebouncedQuery] = useState("");
130120
const [page, setPage] = useState(1);
131121
const [field, setField] = useState<SearchField>("any");
132-
const [sortBy, setSortBy] = useState<SearchSort>("relevance");
133-
const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
134122
const [showAdvanced, setShowAdvanced] = useState(false);
135123
const [copiedCommand, setCopiedCommand] = useState<{
136124
songId: string;
@@ -161,15 +149,13 @@ export function SongSearchPanel(props: {
161149

162150
useEffect(() => {
163151
setPage(1);
164-
}, [debouncedAdvancedFilters, debouncedQuery, field, sortBy, sortDirection]);
152+
}, [debouncedAdvancedFilters, debouncedQuery, field]);
165153

166154
const searchParams = useMemo(() => {
167155
const params = new URLSearchParams({
168156
page: String(page),
169157
pageSize: "25",
170158
field,
171-
sortBy,
172-
sortDirection,
173159
});
174160

175161
if (debouncedQuery.trim()) {
@@ -190,14 +176,7 @@ export function SongSearchPanel(props: {
190176
}
191177

192178
return params;
193-
}, [
194-
debouncedAdvancedFilters,
195-
debouncedQuery,
196-
field,
197-
page,
198-
sortBy,
199-
sortDirection,
200-
]);
179+
}, [debouncedAdvancedFilters, debouncedQuery, field, page]);
201180

202181
const hasSearchInput = useMemo(
203182
() =>
@@ -266,9 +245,7 @@ export function SongSearchPanel(props: {
266245
const catalogTotalQuery = useQuery<Pick<SearchResponse, "total">>({
267246
queryKey: ["song-search-total-count"],
268247
queryFn: async () => {
269-
const response = await fetch(
270-
"/api/search?page=1&pageSize=1&field=any&sortBy=relevance&sortDirection=desc"
271-
);
248+
const response = await fetch("/api/search?page=1&pageSize=1&field=any");
272249
const body = (await response.json().catch(() => null)) as
273250
| SearchResponse
274251
| { message?: string }
@@ -542,39 +519,6 @@ export function SongSearchPanel(props: {
542519
<SelectItem value="creator">Creator only</SelectItem>
543520
</SelectContent>
544521
</Select>
545-
<Select
546-
value={sortBy}
547-
onValueChange={(value) => setSortBy(value as SearchSort)}
548-
>
549-
<SelectTrigger>
550-
<SelectValue placeholder="Sort by" />
551-
</SelectTrigger>
552-
<SelectContent>
553-
<SelectItem value="relevance">Best match</SelectItem>
554-
<SelectItem value="artist">Artist</SelectItem>
555-
<SelectItem value="title">Title</SelectItem>
556-
<SelectItem value="album">Album</SelectItem>
557-
<SelectItem value="creator">Creator</SelectItem>
558-
<SelectItem value="tuning">Tuning</SelectItem>
559-
<SelectItem value="duration">Duration</SelectItem>
560-
<SelectItem value="downloads">Downloads</SelectItem>
561-
<SelectItem value="updated">Recently updated</SelectItem>
562-
</SelectContent>
563-
</Select>
564-
<Select
565-
value={sortDirection}
566-
onValueChange={(value) =>
567-
setSortDirection(value as "asc" | "desc")
568-
}
569-
>
570-
<SelectTrigger>
571-
<SelectValue placeholder="Direction" />
572-
</SelectTrigger>
573-
<SelectContent>
574-
<SelectItem value="desc">Descending</SelectItem>
575-
<SelectItem value="asc">Ascending</SelectItem>
576-
</SelectContent>
577-
</Select>
578522
</div>
579523

580524
<div className="flex flex-wrap items-center justify-start gap-3">

src/lib/server/search.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ function normalizeSearchCacheInput(
5454
year: input.year ?? [],
5555
page: input.page,
5656
pageSize: input.pageSize,
57-
sortBy: input.sortBy,
58-
sortDirection: input.sortDirection,
57+
sortBy: "updated",
58+
sortDirection: "desc",
5959
};
6060
}
6161

@@ -98,6 +98,11 @@ export const searchCatalogSongs = createServerFn({ method: "GET" })
9898
.inputValidator(searchInputSchema)
9999
.handler(async ({ data }) => {
100100
const runtimeEnv = env as AppEnv;
101+
const normalizedInput = {
102+
...data,
103+
sortBy: "updated" as const,
104+
sortDirection: "desc" as const,
105+
};
101106
const identity = await getSearchIdentity(runtimeEnv);
102107
const rateLimit = await consumeSearchRateLimit(runtimeEnv, {
103108
rateLimitKey: identity,
@@ -109,7 +114,7 @@ export const searchCatalogSongs = createServerFn({ method: "GET" })
109114
);
110115
}
111116

112-
const cacheInput = normalizeSearchCacheInput(data);
117+
const cacheInput = normalizeSearchCacheInput(normalizedInput);
113118
const cacheKey = await sha256(JSON.stringify(cacheInput));
114119
const cached = await getCachedSearchResult<SearchResponse>(
115120
runtimeEnv,
@@ -121,7 +126,7 @@ export const searchCatalogSongs = createServerFn({ method: "GET" })
121126
}
122127

123128
const results = normalizeSearchResponse(
124-
await searchCatalogSongsInDb(runtimeEnv, data)
129+
await searchCatalogSongsInDb(runtimeEnv, normalizedInput)
125130
);
126131
await upsertCachedSearchResult(runtimeEnv, {
127132
cacheKey,

src/routes/api/search/route.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ function normalizeSearchCacheInput(
3030
year: input.year ?? [],
3131
page: input.page,
3232
pageSize: input.pageSize,
33-
sortBy: input.sortBy,
34-
sortDirection: input.sortDirection,
33+
sortBy: "updated",
34+
sortDirection: "desc",
3535
};
3636
}
3737

@@ -101,6 +101,12 @@ export const Route = createFileRoute("/api/search")({
101101
return json({ error: "invalid_search", message }, { status: 400 });
102102
}
103103

104+
const normalizedInput = {
105+
...parsed.data,
106+
sortBy: "updated" as const,
107+
sortDirection: "desc" as const,
108+
};
109+
104110
const identity = await getSearchIdentity(request, runtimeEnv);
105111
const rateLimit = await consumeSearchRateLimit(runtimeEnv, {
106112
rateLimitKey: identity,
@@ -118,7 +124,7 @@ export const Route = createFileRoute("/api/search")({
118124
);
119125
}
120126

121-
const cacheInput = normalizeSearchCacheInput(parsed.data);
127+
const cacheInput = normalizeSearchCacheInput(normalizedInput);
122128
const cacheKey = await sha256(JSON.stringify(cacheInput));
123129
const cached = await getCachedSearchResult(runtimeEnv, cacheKey);
124130

@@ -131,7 +137,10 @@ export const Route = createFileRoute("/api/search")({
131137
}
132138

133139
try {
134-
const results = await searchCatalogSongsInDb(runtimeEnv, parsed.data);
140+
const results = await searchCatalogSongsInDb(
141+
runtimeEnv,
142+
normalizedInput
143+
);
135144

136145
await upsertCachedSearchResult(runtimeEnv, {
137146
cacheKey,

src/routes/dashboard/playlist.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ function DashboardPlaylistPage() {
200200
page: "1",
201201
pageSize: "6",
202202
field: "any",
203-
sortBy: "relevance",
204-
sortDirection: "desc",
205203
});
206204
const response = await fetch(`/api/search?${params.toString()}`);
207205
const body = (await response.json().catch(() => null)) as
@@ -808,15 +806,21 @@ function getPlaylistCandidates(candidateMatchesJson?: string) {
808806
function getResolvedCandidates(item: PlaylistItem) {
809807
const candidates = getPlaylistCandidates(item.candidateMatchesJson);
810808
if (candidates.length > 0) {
811-
return candidates.map((candidate) => ({
812-
...candidate,
813-
album: candidate.album ?? item.songAlbum,
814-
sourceUrl: normalizeSongSourceUrl({
815-
source: "library",
816-
sourceUrl: candidate.sourceUrl,
817-
sourceId: candidate.sourceId,
818-
}),
819-
}));
809+
return [...candidates]
810+
.map((candidate) => ({
811+
...candidate,
812+
album: candidate.album ?? item.songAlbum,
813+
sourceUrl: normalizeSongSourceUrl({
814+
source: "library",
815+
sourceUrl: candidate.sourceUrl,
816+
sourceId: candidate.sourceId,
817+
}),
818+
}))
819+
.sort((left, right) => {
820+
const leftUpdatedAt = left.sourceUpdatedAt ?? -1;
821+
const rightUpdatedAt = right.sourceUpdatedAt ?? -1;
822+
return rightUpdatedAt - leftUpdatedAt;
823+
});
820824
}
821825

822826
return [

0 commit comments

Comments
 (0)