Releases: bilbospocketses/abs-app
Release list
Android TV v1.0.11
Android TV fork release v1.0.11 (on upstream audiobookshelf-app v0.13.0-beta).
Highlights
- Fixed the long-standing grid focus column-drift bug — on virtualized bookshelf grids (library / series / collections / playlists), a fast Down-scroll could land focus in the wrong column (the last column). Root-caused to the native Android-TV focus engine re-homing focus when the
LazyBookshelfvirtualizer unmounts the focused card mid-scroll; fixed by tracking and re-asserting the user's intended column. - TV init hardening (I2) — inject the
android-tvclass atWebViewClient.onPageStartedso it lands before the Nuxt TV plugin boots (fixes the occasional "first navigation dead on cold start" race), with a JS-side poll fallback. - Hide "Go to Web Client" in the side drawer on Android TV — TV devices typically have no browser, so the action dead-ended; now hidden on TV (phone/tablet unchanged).
- Spatial-nav performance (I4) — per-keypress
getBoundingClientRectsnapshotting removes repeated forced reflows. - Selector robustness (I5) — stable
data-tv-*hooks replace fragile Tailwind-class selectors for the side drawer and play button. - Loading-overlay dots follow the focus-ring color on TV.
Verified via the full 13-batch on-device smoke on the Google TV Streamer 4K.
APK: abs-android-tv-release-1.0.11.apk
SHA256: 4B8A653D98CB1AE077A52253CA0D300D3CD675E991DBAAAF2C5C273B6BB21B67
android-tv-v1.0.10 - Internal refactor (modularize tv-navigation)
Internal refactor release - no user-visible changes. Behaves identically to v1.0.9.
Modularizes the Android TV navigation engine: the 1,675-line plugins/tv-navigation.js monolith is split into 18 focused modules under plugins/tv/ - behavior-preserving (every function keeps its name + signature; shared state moves into a tvContext singleton). Foundation for the upcoming upstream PR series.
Validated by the full 13-batch TV smoke walkthrough (64 TV + 3 phone checks) on Google TV Streamer 4K + Pixel 9 - zero regressions.
Also includes the repo-level security hardening pass (Dependabot, CodeQL, secret scanning, branch/tag rulesets, Sigstore release attestation) from the same timeframe.
Upstream base: v0.13.0-beta - APK: abs-android-tv-release-1.0.10.apk
android-tv-v1.0.9 — upstream v0.13.0-beta sync
Changed
- Synced upstream
advplyr/audiobookshelf-apptov0.13.0-beta(40 commits). - Cover image color sampling now uses CapacitorHttp, fixing the case where the WebView strips the origin header from cover requests.
- Focus-regain progress sync no longer double-fetches when the app returns to the foreground while connected to a server.
- 30+ second socket reconnects now reconcile media-open progress on resume.
- Removed several debug log statements (upstream cleanup).
Added
- Belarusian and Bulgarian language options (upstream).
- Podcast episode results included in search (upstream).
Android TV v1.0.8
Android TV v1.0.8
Adds a user-customizable D-pad focus-ring color picker for Android TV, plus the underlying refactor that makes runtime color overrides possible.
Added
- TV Settings → Focus Ring Color picker on the Settings page (Android TV only). Choose from 7 curated presets — ABS Green (default), Sky, Amber, Red, Violet, Yellow, White. Selection persists across app restarts (device-wide, like every other setting in this app) and applies live to every focus-ring surface — library cards, author cards, item detail covers, modal items, drawer rows, generic buttons/inputs, settings dropdowns, and player controls.
- ★ glyph marks the in-use swatch; D-pad focus draws a black-then-colored ring around the focused swatch (readable even when the focused swatch matches the current focus color).
- Picker is hidden on phone/tablet — zero footprint outside TV.
Changed
assets/css/tv-focus.cssnow defines the focus-ring color as a single--tv-focus-colorCSS custom property on:root.android-tv. All 8 focus-ring presentations reference the variable instead of hardcoding#1ad691. A single setProperty call retints every surface.
Verification
26-item manual test checklist passed on Google TV Streamer 4K, plus phone-visibility check — see docs/superpowers/plans/2026-04-25-tv-focus-color-picker-test-checklist.md.
Sideload
abs-android-tv-release-1.0.8.apk
Android TV v1.0.7 — Fire TV Focus Debug Build
This is a diagnostic build, not a fix. Intended only for users investigating a Fire TV Stick 4K (2nd gen) / Fire OS 8 focus bug where D-pad navigation into Home/Library/Authors content is only possible while holding the down button during the connect phase.
If you are not actively helping diagnose this specific issue, use Android TV v1.0.8 instead.
Update 2026-04-24 — logs screen UX fix
The previous build in this tag had a usability problem: every D-pad keypress appended a new focus-debug log entry to the Settings → Logs screen, and the screen auto-scrolled to the bottom on each new entry, fighting users trying to D-pad up to the Copy/Share buttons.
This build reverses the display order on the Logs screen — newest entries appear at the top, right next to the Copy and Share buttons. New entries no longer yank the scroll position. Underlying log storage is unchanged, so the shared .txt file is still oldest-first as before. This is a temporary UX tweak scoped to this diagnostic branch only; the general-release Logs screen stays chronological.
Re-sideload this APK over the previous -firetv-focus-debug install to pick up the fix.
What this build does
Adds extra logging to the TV navigation plugin so that every focus attempt and every D-pad keypress is recorded to the in-app log viewer (Settings → Logs). Behaviour is otherwise identical to v1.0.7.
For the reporter
- Sideload this APK over your current v1.0.7 install.
- Open the app and navigate to Settings → Logs → ⋮ menu → Clear Logs, then close the app.
- Reproduce the failing case: open the app, don't touch the remote, wait until fully loaded, then press down once and try to navigate.
- Close the app and reproduce the working case: open the app and hold down during connect.
- Open Settings → Logs — newest entries are at the top alongside the Copy and Share buttons. Tap Share and send the log file to your email / cloud / etc.
- Attach the log to the GitHub issue so we can diagnose.
For developers
Branch: fire-tv-focus-handling. See docs/FIRE_TV_FOCUS_DEBUG.md on that branch for the full instrumentation layout and signal interpretation guide.
The actual fix will be a separate PR once the reporter's logs tell us whether we need a post-connect focus pulse (Option 1) or a synthetic user-interaction event (Option 2). Do not merge this instrumentation to master as-is.
Android TV v1.0.7
Post-v1.0.6 Regression Fixes — TV-only
Three pre-existing regressions surfaced during the v1.0.6 QA pass — each was present in v1.0.5 and earlier but not caught until now. All fixes are TV-gated and have zero effect on phone/tablet/iOS.
Fixes
History option no longer breaks the fullscreen player
- Selecting History from the fullscreen audio player's ellipsis menu on TV used to collapse the player into a stale mini-player state (the mini player was retired in an earlier release). History is now hidden from the fullscreen ellipsis on TV. It remains accessible from book detail pages, the normal entry point.
Library sort modal D-pad wrap-around fixed
- Pressing D-pad Down from the last option in a long sort modal (e.g. the 13-option library sort) used to wrap to a middle item instead of the first.
- Caused by the focus-tracking overlay filter rejecting options scrolled out of view; fixed by allowing scrolled-off-screen items to remain part of the navigable set within overlays.
scrollIntoViewhandles the visual scroll.
Playlist row play-button fingerprint preserved across player close
- Starting playback from an individual book's play button inside a playlist, then closing the fullscreen player, used to land focus on the playlist's primary Play button instead of the row you started from.
- Fixed by capturing the pre-playback focus at the earliest possible point (the state commit inside the click handler) and restoring it on close — overriding Android TV's native focus engine, which aggressively re-focuses a "nearby" button the instant the player's focused element unmounts.
Scope
- Android TV only. All changes gated behind
isAndroidTvor wired into TV-specific logic paths. - Phone / tablet / iOS: unchanged.
Testing
- Full v1.0.5 + v1.0.6 combined manual checklist re-run 2026-04-21 — all 42 items pass.
- Fix C primary regression verified on 3 different books × 3 different close methods (ellipsis "Close Player", remote Back, collapse span). All returned focus to the correct row play-button.
Android TV v1.0.6
Bug Fix Release — Screensaver Interrupting Playback
Addresses user-reported issue where the Chromecast with Google TV / Android TV Ambient Mode screensaver engaged during playback and killed audio. After ~30 minutes in screensaver state, users were returned to the TV Home screen with no way to resume where they left off.
Fixes
Screen-Wake Lock During Active Playback (TV-only)
- Audio player now holds a screen-wake lock while playback is active, preventing Ambient Mode from engaging mid-chapter.
- Per Android TV developer guidance, audio should continue through Ambient Mode automatically — but CCwGTV firmware behavior diverges from docs and stops playback regardless. This fix works around that platform quirk.
- Wake lock is acquired on every play↔pause transition via the existing
onPlayingUpdatenative event, and released on every session-end path: pause, stop, session close, fullscreen-collapse-close, playback failure, and component destroy.
Scope
- Active playback on TV: screen stays on; Ambient Mode never starts; audio never gets killed.
- Paused on TV: wake lock released — screensaver engages normally after idle; standard Android TV "Home after 30 min" behavior applies (matches all other TV media apps).
- Phone / tablet / iOS: zero behavior change — all new logic gated behind
isAndroidTvVuex state.
Implementation
components/app/AudioPlayer.vue— addedupdateKeepAwake(shouldKeepAwake)helper; wired intoonPlayingUpdate(chokepoint for play↔pause state) andendPlayback(chokepoint for all session teardown).- Uses
@capacitor-community/keep-awakeplugin — already installed and used by the e-reader (Reader.vue); no new dependencies. - Try/catch around plugin calls logs errors without disrupting playback.
Testing
Validated via direct sideload on Chromecast with Google TV hardware. Full v1.0.5 + v1.0.6 combined manual test pass: 35 of 40 TV tests passing; 2 phone tests pending post-release sideload. Three pre-existing regressions surfaced during QA have been logged for post-v1.0.6 patch (playlist row play-button fingerprint, fullscreen ellipsis History route, long-list sort modal D-pad wrap) — none block this release.
Android TV v1.0.5
Bug Fix Release — Full Code Audit
Comprehensive code audit identified 35 findings (5 HIGH, 15 MEDIUM, 15 LOW). This release fixes all HIGH and actionable MEDIUM issues.
Fixes
Critical Safety (H2 + M1)
- Vertical navigation
setTimeoutcallbacks now wrapped intry/finally— if an exception occurs, the nav guard always clears instead of permanently disabling focus recovery - Added
CSS.escapepolyfill for older Android TV WebViews (Chrome < 46) that lack native support - Fixed unescaped CSS selectors in fingerprint system that could throw on special-character IDs
Double-Fire Prevention (H4)
- Added
.preventmodifier to 11@keydown.enterhandlers across 8 components (cards, toolbar, modal, drawer) — prevents Enter from firing both keydown and synthesized click on Android TV D-pad
Connect Page TV Detection (H1)
connect.vuenow setsisAndroidTvin Vuex store on init — fixes broken TV layout on first launch when no server is saved (the blank layout bypassesdefault.vuewhere this was previously set)
Vuex Reactivity Fix (H3)
- Replaced direct
store.state.lastBookshelfScrollData = {}mutation with proper VuexresetLastBookshelfScrollDatamutation — fixes scroll position restoration on library tab switches
Phone/Tablet Safety (M2)
- All TV-only listeners (focusout, store watchers, router hooks, eventBus) now gated behind
android-tvinitialization check — preventsfocusFirstContentElement()from firing on phones when modals close
Focus Interval Stacking (M3 + M4)
refocusAfterContentChangenow tracks and clears its interval before creating a new one — prevents parallel polling loops from fighting over focusfocusLossTimercleared on route navigation — prevents stale focusout recovery from causing focus flash during page transitions
Player Controls + Accessibility (M10 + M14)
- Hidden fullscreen player controls (
v-show) now use dynamictabindex— invisible jump-chapter buttons no longer receive D-pad focus - Removed blanket
:not(.android-tv) *:focus { outline: none }rule — restores focus indicators for phone/tablet keyboard/accessibility users
Testing
33-item manual test checklist covering all fixes + regression tests.
Android TV v1.0.4
Back Arrow Fingerprint Restoration Fix
A single-line fix with major impact on user experience. The on-screen back arrow (top-left of detail pages) now restores focus to the correct card — identical behavior to the remote's hardware back button.
The Problem
When using the on-screen back arrow to return from a detail page (book, podcast, playlist, etc.) to a grid/list page, focus always jumped to the first card instead of returning to the card the user navigated from. The remote's back button worked correctly.
Users expect "back" to mean "back to where I was." The back arrow violated that expectation on every single detail page in the app.
Root Cause
The router.beforeEach hook in tv-navigation.js uses document.activeElement to determine the navigation context. It distinguishes between:
- Forward navigation (clicking a library tab, search icon) — clears the destination's saved fingerprint so focus starts fresh
- Back navigation (remote back button) — preserves the fingerprint for restoration
The on-screen back arrow lives inside #appbar. The isExplicitNavElement check matched any focused element inside #appbar, #bookshelf-navbar, or #bookshelf-toolbar — treating the back arrow identically to a forward navigation link. This caused the destination's saved fingerprint to be deleted just before navigation, so router.afterEach found no fingerprint and defaulted to the first card.
The remote back button was never affected because it fires via a Capacitor native listener while focus remains on a content card, bypassing the appbar check entirely.
Fix
Exclude the back arrow from the isExplicitNavElement check by detecting aria-label="Back". One condition added, zero side effects.
Affected Pages
Every detail page that has a back arrow — book details, podcast details, playlist details, collection details, series details, author details, episode details, history pages. All now correctly restore focus on back-arrow navigation.
Documentation
TV_FOCUS_SYSTEM.md updated with a new "Back Arrow vs Remote Back Button" section explaining the distinction and why the exclusion is necessary.
Android TV v1.0.3
Connect Page D-pad Navigation Overhaul
What started as a quick visual tweak to the server/user selection screen turned into a deep dive into Android TV WebView D-pad focus management. Every change below exists so that D-pad navigation on this screen feels completely intuitive — no user guide needed.
Visual Improvements
- Focus box wraps username + server URL — both lines are now inside a single focusable container, so the D-pad highlight covers the full entry
- Username matches server URL styling — same font size and color (
text-base text-fg) instead of the previoustext-lg text-white font-bold - Focus box breathing room — 6px symmetric padding on left/right edges prevents text cutoff at the focus ring boundary
- GitHub links scrollable on TV — changed from
position: fixedto normal document flow so D-pad can actually reach and scroll to them
D-pad Navigation
- Full left/right sub-icon chain: Entry row →right→ ellipsis →right→ delete, then delete →left→ ellipsis →left→ back to entry row
- Up/down always lands on the entry row, never on an adjacent row's icon — cross-row icon focus is intercepted and redirected
- First entry scroll-to-top — focusing the first server entry always scrolls the page to the top, keeping the back arrow visible and reachable
Bugs Fixed
- Double-jump on up/down from icons — native D-pad engine and programmatic focus were both moving focus, causing rows to be skipped
- Bounce on right from ellipsis to delete — keydown events bubbling from icons to the parent entry row caused competing deferred focus calls
- Left from ellipsis stuck — native D-pad cannot navigate from a child element to its parent; explicit handler added
- Page oscillation on row 1 — native focus-scroll behavior caused the viewport to jitter when cycling between icons; all focus calls now save/restore scroll position
- Left from entry row entering children — native D-pad was entering the row's children from the right side, landing on the delete icon
Technical Approach
The Android TV WebView's native D-pad spatial navigation has fundamental limitations inside nested focusable containers. The solution layers five mechanisms:
dpadFocus()— defers.focus({ preventScroll: true })viasetTimeout(0)to execute after the native engine finishes; saves/restores scroll positionhandleIconFocus()(@focus) — intercepts cross-row focus on icons and redirects to the entry row; respects_dpadFocusActiveflag to avoid interfering with in-flight deferred operations.prevent.stopon icon keydown — prevents both default behavior and event bubbling to the parent entry rowlockScroll()— prevents scroll oscillation on dead-end key presses (e.g., right from delete icon)onEntryRowFocus()— deferred scroll-to-top when first entry receives focus
Documentation updated in TV_FOCUS_SYSTEM.md with full D-pad navigation map and mechanism table.