Change soundtrack covers from the app and show the cover with the answer
Build / test (push) Successful in 1m50s
Build / build (push) Successful in 1m14s

Cover menu in the soundtrack popup ("Change cover"):
- Choose picture uploads a JPEG, PNG or WebP picture (up to 10 MB).
- Pick by ID uses a game's cover on SteamGridDB or an anime's on AniList.
- Remove cover deletes it, so the server searches for a new one.
- The server's reason is shown when it refuses a change.
After a change the new cover time is fetched, and the popup, the
statistics card and the quiz show the new cover.

Quiz: once the answer is shown, the soundtrack's cover shows to the left of
the titles. Cover and titles are centered together, left and right and up
and down, and each title keeps to two lines. Cover times come from the
soundtrack list, and songs keep their soundtrack's UUID, also in saves.

Requests can now send any body with its content type, and every 2xx answer
counts as success. Cover frames are 2:3 like the server's covers. Small
copies of real covers are used by the tests and screenshots.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
SansanandClaude Opus 5.5 committed 2026-10-14 23:32:09 +02:00
1 parent ef6ac8f1fd
commit 06421bb63e
33 files changed
+3966 -920

No files matched your search

+19 -6
View File
@@ -15,7 +15,8 @@ const SOUNDTRACKS: Array[String] = [
"Donkey Kong Country 2", "Lufia II", "Illusion of Gaia",
]
const SONG_INFO: Dictionary = {
"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time",
"SongNo": 0, "Soundtrack": "Chrono Trigger", "SoundtrackUuid": "soundtrack-0",
"Song": "Corridors of Time",
}
const SYNC_PROGRESS: Dictionary = {"progress": 40, "time_spent": "00:00:02"}
const SYNC_RESULT: Dictionary = {
@@ -48,6 +49,8 @@ const JAPANESE_SONGS: Array[String] = [
## The character pictures the fake server hands out.
const CHARACTERS_DIR: String = "res://characters"
## Small copies of covers from the MusicServer, 2:3 like all its covers.
const COVERS_DIR: String = "res://tests/data/covers"
## Popups in the order the tour opens them: the state name, then the popup's node. The
## state names are what the popups were first called, so screenshots taken before they
@@ -91,12 +94,18 @@ static func make_server() -> FakeHttpTransport:
server.respond_bytes("/sync", PackedByteArray())
server.respond_json("/sync/progress", SYNC_PROGRESS)
server.respond_json("/statistics/soundtracks", soundtrack_statistics())
# The character pictures stand in for covers
var pictures: Array[String] = character_names()
for i: int in SOUNDTRACKS.size():
# Real covers from the server, made smaller, for every other soundtrack
for i: int in range(0, SOUNDTRACKS.size(), 2):
server.respond_bytes("/soundtracks/soundtrack-%d/cover" % i,
FileAccess.get_file_as_bytes(CHARACTERS_DIR.path_join(
pictures[i % pictures.size()])))
FileAccess.get_file_as_bytes(COVERS_DIR.path_join("cover_%d.jpg" % (i >> 1))))
# The soundtrack list tells the quiz which soundtracks have covers
var soundtracks: Array[Dictionary] = []
for soundtrack: Dictionary in soundtrack_statistics():
soundtracks.append({"uuid": soundtrack.soundtrack_uuid,
"name": soundtrack.soundtrack_name,
"cover_modified": soundtrack.get("cover_modified", 0),
"alternative_names": soundtrack.get("alternative_names", [])})
server.respond_json("/soundtracks", soundtracks)
server.respond_json("/version/history", SERVER_HISTORY)
return server
@@ -307,6 +316,10 @@ func run(on_state: Callable) -> void:
stats_popup.new_name_field.text = "Chrono"
await _settle()
await on_state.call("popup_SoundtrackStats_names", stats_popup)
stats_popup.change_cover()
stats_popup.cover_id_field.text = "5248061"
await _settle()
await on_state.call("popup_SoundtrackStats_cover", stats_popup)
stats_popup.stop_editing()
stats_popup.close()
_main.show_tab(&"quiz")