Alternative names (#32): - PUT /api/v1/soundtracks/{uuid}/alternative-names replaces a soundtrack's alternative names (trimmed, deduplicated, without the soundtrack's own name). - alternative_names is in the soundtrack and statistics responses. - /find matches them too and shows which name matched. Covers (#12), stored in COVERS_PATH and off when it is not set: - GET, PUT (upload) and DELETE /api/v1/soundtracks/{uuid}/cover, and PUT .../cover/source to pick a SteamGridDB game or AniList anime by ID. Uploaded and picked covers are never replaced automatically. - With STEAMGRIDDB_API_KEY, a background job searches SteamGridDB, then AniList, by name, alternative names and the name without bracketed parts, at startup, after a sync and after names change. Search results are ranked by matching words, so "Civilization IV" gets "Sid Meier's Civilization IV". - cover_modified (Unix seconds) is in the soundtrack and statistics responses, so clients can cache covers. The new columns are added to migration 000006, which is not released yet. Closes #12, closes #32 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
1.9 KiB
Templ
52 lines
1.9 KiB
Templ
package web
|
|
|
|
templ SearchForm() {
|
|
@Base() {
|
|
<button id="dark-mode-toggle">🌙</button>
|
|
<input id="search_term" name="search_term" type="text" hx-post="/find" hx-trigger="load, keyup changed delay:0.25s" hx-target="#soundtracks-container"/>
|
|
<button type="button" id="clear" name="clear">Clear</button>
|
|
<div id="soundtracks-container"></div>
|
|
<script>
|
|
document.addEventListener('readystatechange', () => {
|
|
if (document.readyState == 'complete') {
|
|
document.getElementById("search_term").focus();
|
|
|
|
// Initialize theme from localStorage (default to dark)
|
|
const savedTheme = localStorage.getItem('theme') || 'dark';
|
|
document.documentElement.setAttribute('data-theme', savedTheme);
|
|
document.getElementById('dark-mode-toggle').textContent = savedTheme === 'dark' ? '☀️' : '🌙';
|
|
}
|
|
});
|
|
|
|
// Dark mode toggle functionality
|
|
document.getElementById("dark-mode-toggle").addEventListener("click", function() {
|
|
const html = document.documentElement;
|
|
const currentTheme = html.getAttribute('data-theme');
|
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
|
|
|
html.setAttribute('data-theme', newTheme);
|
|
localStorage.setItem('theme', newTheme);
|
|
|
|
// Update toggle button text
|
|
this.textContent = newTheme === 'dark' ? '☀️' : '🌙';
|
|
});
|
|
|
|
document.getElementById("clear").addEventListener("click", function (event) {
|
|
document.getElementById("search_term").value = "";
|
|
htmx.ajax('POST', '/find', '#soundtracks-container');
|
|
document.getElementById("search_term").focus();
|
|
});
|
|
</script>
|
|
}
|
|
}
|
|
|
|
templ FoundSoundtracks(soundtracks []SearchResult) {
|
|
for _, soundtrack := range soundtracks {
|
|
<div class="bg-green-100 p-4 shadow-md rounded-lg mt-6">
|
|
<p class="soundtrack-text">{ soundtrack.Name }</p>
|
|
if soundtrack.MatchedName != "" {
|
|
<p class="matched-name">Also known as { soundtrack.MatchedName }</p>
|
|
}
|
|
</div>
|
|
}
|
|
} |