fix(android): zone image falls back to server URL when not cached (#78)

A multi-zone layout's zone rendered its image from the local content cache
only. If the content wasn't cached yet at first render (first-sync download
still in flight, or the preloader hadn't fetched that zone's content), the
zone drew blank - and a static (single, unscheduled) zone has no rotation
timer to redraw, so it stayed blank until the app was restarted.

Mirror the video branch: when getCachedFile returns null, load the image
straight from the server (the item's remote_url, else /api/content/<id>/file)
instead of leaving the zone blank.

Verified live on a 2-zone layout with two single-unscheduled items and fresh
content: both zones render with no restart, with only one item actually in
the on-device cache (the other displayed via the URL fallback).

Closes #78

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ScreenTinker 2026-06-12 08:39:09 -05:00 committed by screentinker
parent 68367cb3a3
commit bd732f4c48

View file

@ -252,17 +252,26 @@ class ZoneManager(
} else {
Log.w(TAG, "Zone ${zone.name}: skipping unloadable image $contentId")
}
} else if (!remoteUrl.isNullOrEmpty()) {
Thread {
val bitmap = com.remotedisplay.player.util.ImageLoader.decodeUrl(remoteUrl, targetW, targetH)
if (bitmap != null) {
imageView.post {
try { imageView.setImageBitmap(bitmap) } catch (e: Throwable) { Log.e(TAG, "setImageBitmap failed: ${e.message}") }
} else {
// #78: not in the local cache yet (first-sync download still in flight, or a
// zone whose content the preloader hasn't fetched). Load straight from the
// server - mirrors how the video branch above falls back to a server URL -
// so the zone isn't blank until a restart populates the cache.
val imgUrl = if (!remoteUrl.isNullOrEmpty()) remoteUrl
else if (contentId != null) "$renderServerUrl/api/content/$contentId/file"
else null
if (imgUrl != null) {
Thread {
val bitmap = com.remotedisplay.player.util.ImageLoader.decodeUrl(imgUrl, targetW, targetH)
if (bitmap != null) {
imageView.post {
try { imageView.setImageBitmap(bitmap) } catch (e: Throwable) { Log.e(TAG, "setImageBitmap failed: ${e.message}") }
}
} else {
Log.w(TAG, "Zone ${zone.name}: unloadable image $contentId via $imgUrl")
}
} else {
Log.w(TAG, "Zone ${zone.name}: skipping unloadable remote image")
}
}.start()
}.start()
}
}
container.addView(imageView); zoneViews[zone.id] = imageView
if (multi) scheduleZoneAdvance(zone.id, durationMs, advance)