github disclosurez/Lumora v5.8
Lumora v5.8

4 hours ago

Lumora v5.8

Fixes

  • An update no longer plays over the top of itself. Pressing Update downloads the new build in the background - the app stays up while the APK comes down, and the system package installer only takes over at the very end. Whatever was playing kept playing through all of it: the fullscreen player, every Multiview pane and the guide's inline preview, all of them decoding while the download had the bandwidth and the decoder. Everything is paused the moment Update is pressed now - the player as the user's own pause, so a cancelled install does not start playing again by itself - and it stays paused until the installer takes over.
  • The app starts faster. Two things were being brought up on the main thread before the first frame, for features most sessions never touch: the Google Cast framework (a Play Services bind - 100-300ms on a cheap stick) and the plugin engine's native library. The Cast framework is now brought up the first time the Cast button is used, and the plugin library is loaded on the thread that runs the plugin, so neither sits in front of the content. The XMLTV guide refresh also waits half a minute before it starts, so it no longer competes with the catalogue load and the first playback for the same CPU, disk and bandwidth.
  • The Live guide scrolls without stuttering. Scrolling the guide asked every visible row where it was on screen, once per scroll event - and a scroll event arrives twice a frame on a fast fling. Each of those questions walked the view hierarchy and composed transforms. The rows' positions now come from where they sit inside the list, which is the same answer for a fraction of the work. The guide's minute tick also no longer rebuilds every visible row: it updated the now/next line and the width of the airing block, and now updates exactly those in place instead of rebuilding every programme block of every row. The rows whose guide has expired - the only ones that needed a fresh fetch - are still refreshed.
  • Home stops walking the whole catalogue for a handful of rows. "Recently Played" looked each of its (at most twenty) ids up by scanning the entire live list, and the favourites row joined the films and series lists together first - a copy of tens of thousands of entries - to filter them by a few ids. Both are index lookups now, and neither allocates a copy of the catalogue.
  • Search's guide pass no longer holds the interface. Searching also looks through the guide, and that pass walked every live channel and every programme title in the guide - a lowercased copy of each - on the interface thread, right after the media results were shown. It runs off the interface thread now, and the guide fetches it asks for are unchanged.
  • Posters are clipped by the platform, not by a mask per poster per frame. Every poster was clipped twice: once by the frame around it and once by a hand-drawn rounded-rectangle clip in the image view itself, which the renderer has to mask the drawing with. The image now clips itself through the platform's own rounded-rectangle outline, which is the cheap path, and the hand-drawn clip stays as a fallback for a renderer that ignores it.
  • A big M3U show's episode list no longer freezes the app. The detail screen asked "which show is this episode from?" for every episode row it bound - watched state, in other words - and answered it by copying the catalogue's entire series list, then walking that copy three more times. An m3u_plus playlist keeps every episode as its own series row, so on a large panel that was hundreds of thousands of allocations per scroll with the heap to match: the list hung, stuttered, or took the app down. The show is now read out of the episode's own name - which is where most providers bake it in, and which yields the same title the catalogue would have answered with - and the catalogue is only consulted for the rows whose name says nothing about the show (a Jellyfin episode is titled "Episode 4"), through an index built once per catalogue. That index also carries the show cards the app derives from an M3U panel: the catalogue itself holds only episodes, which is why those rows fell through to the slow path on every bind. The watched marks themselves are the same ones as before.
  • Watching a film no longer stutters every few seconds. The VOD quality watchdog asks which duplicate group the playing copy belongs to on every tick (2.5s), and for a copy that is not its group's first - a Continue Watching resume, a search hit, the version a chip switched to - and for a film with no duplicate at all, it walked every duplicate group and every member on the main thread each time. The answer is now remembered for the title being played, so it costs one pass per title instead of one per tick.
  • The Sports tab stops sitting on "Loading today's games" for two minutes. The board waits for every sport before it paints, and the football feed (SportAPI.ai) is asked for two dates - one after the other - with the app's own read timeout, which is a minute. When that host stopped answering, the tab sat on its spinner for a minute per date while the other feeds' games were already in hand. The feeds now have their own, much shorter timeouts (a feed that has not said anything in ten seconds is not going to), and the two dates are asked for at once, so a dead host costs one timeout instead of two.
  • Exporting a backup no longer needs room for three copies of it. The export serialised the whole document once with a blank checksum to hash it and then again with the checksum filled in. The document is now serialised once and written out with the digest substituted into the member it belongs to, so a second copy of it is never held - which is what the TV sticks this app targets were running out of, and a failed export there surfaced as an OutOfMemoryError, which the export path's catch (Exception) cannot see. The bytes written are the same ones the old path wrote, so backups stay interchangeable in both directions, and the checksum member is found structurally (the file's own), so a nested member of the same name is never rewritten. Import only re-serialises the document for its fallback checksum when the file's own checksum does not verify, instead of on every import.
  • An import still runs if the app was rebuilt while the file picker was up. The result handler depended on the backup object the tap had stashed on the Activity, which does not survive a process restore or a configuration change behind the system picker - so the pick came back and nothing happened. The handler now builds one for the result when the stashed one is gone, and drops the stashed one when the picker is cancelled.
  • A refresh that fails after a restore can't take the app down. Re-applying the restored settings to the running app (UI language, provider list, Streaming sites pane, DNS, catalogue reload) used to run unguarded after the import had already succeeded, so a failure there crashed on top of a perfectly good restore. Each step is isolated now: the data is on disk either way, and the worst case is a screen that catches up on the next launch.

Installation

Download the APK below and install on your Android TV, Fire TV Stick, or phone.

Don't miss a new Lumora release

NewReleases is sending notifications on new releases.