[PR #1704] feat: add playback queue #1667

Open
opened 2026-04-25 00:00:29 +02:00 by adam · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/advplyr/audiobookshelf-app/pull/1704
Author: @andykelk
Created: 10/20/2025
Status: 🔄 Open

Base: masterHead: feature/playback-queue


📝 Commits (10+)

  • 66903d1 Add playback queue state management and strings
  • 3815f8d feat: use device storage to persist queue
  • 89d6f79 Add QueueModal component for queue management
  • 4347335 fix: update close modal pattern
  • 901c3e5 feat: add queue button for items and episodes
  • 37d8d47 feat: add queue button to latest podcast episodes
  • ee82ad7 feat: allow queue access from the side drawer
  • 1ff116d feat: preserve playback progress when adding items to queue
  • c6d547b fix: use correct images for queue items
  • 74ba76f fix: queue modal button functionality and drag interactions

📊 Changes

19 files changed (+845 additions, -21 deletions)

View changed files

android/app/src/main/java/com/audiobookshelf/app/data/PlaybackQueueItem.kt (+62 -0)
android/app/src/main/java/com/audiobookshelf/app/managers/QueueManager.kt (+74 -0)
📝 android/app/src/main/java/com/audiobookshelf/app/media/MediaProgressSyncer.kt (+57 -8)
📝 android/app/src/main/java/com/audiobookshelf/app/player/AbMediaDescriptionAdapter.kt (+5 -0)
📝 android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt (+99 -3)
📝 android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt (+4 -0)
📝 components/app/AudioPlayer.vue (+13 -3)
📝 components/app/SideDrawer.vue (+10 -0)
📝 components/modals/ItemMoreMenuModal.vue (+22 -2)
components/modals/QueueModal.vue (+187 -0)
📝 components/tables/podcast/EpisodeRow.vue (+22 -1)
📝 components/tables/podcast/LatestEpisodeRow.vue (+20 -1)
📝 layouts/default.vue (+4 -0)
mixins/queueMixin.js (+58 -0)
📝 pages/item/_id/_episode/index.vue (+19 -1)
📝 plugins/localStore.js (+19 -0)
📝 store/globals.js (+5 -1)
📝 store/index.js (+160 -1)
📝 strings/en-us.json (+5 -0)

📄 Description

Summary

Adds a playback queue feature allowing users to line up items to play sequentially. The queue persists across sessions and is managed at both the JavaScript/Vue layer and the native Android layer for seamless background playback.

  • Queue management UI: New QueueModal component with drag-to-reorder, play from position, and individual item removal. Accessible via a queue button in the audio player, side drawer, and item more menus
  • Add to queue: Queue buttons added to item/episode more menus, podcast latest episode rows, and the episode detail page
  • Persistent storage: Queue is saved to Capacitor Preferences (SharedPreferences on Android) and restored on app launch
  • Native Android auto-advance: QueueManager reads the queue directly from SharedPreferences so the Android PlayerNotificationService can advance to the next item on playback completion, even when the app is backgrounded
  • Progress preservation: Current playback position is saved in the queue item so playback resumes from where it left off
  • Native→JS sync: When the native layer advances the queue, it emits onQueueChanged so the Vue store reloads from storage and stays in sync

Changed files

  • store/index.js — queue state, getters, mutations and actions
  • store/globals.jsshowQueueModal flag
  • plugins/localStore.jsgetPlaybackQueue / setPlaybackQueue methods
  • mixins/queueMixin.js — shared addItemToQueue helper used across components
  • components/modals/QueueModal.vue — queue management modal
  • components/app/AudioPlayer.vue — queue button + onQueueChanged listener
  • components/app/SideDrawer.vue — queue menu item
  • components/modals/ItemMoreMenuModal.vue — "Add to Queue" action
  • components/tables/podcast/LatestEpisodeRow.vue — queue button
  • pages/item/_id/_episode/index.vue — "Add to Queue" action
  • layouts/default.vue — mount QueueModal, load saved queue on init
  • android/.../data/PlaybackQueueItem.kt — data model matching JS queue item structure
  • android/.../managers/QueueManager.kt — reads/writes queue from SharedPreferences
  • android/.../media/MediaProgressSyncer.kt — mark finished even when timer is stopped
  • android/.../player/PlayerNotificationService.kt — native queue auto-advance on playback end
  • android/.../player/AbMediaDescriptionAdapter.ktinvalidateCache() for cover art refresh
  • android/.../plugins/AbsAudioPlayer.ktonQueueChanged event bridge
  • strings/en-us.jsonButtonAddToQueue, ButtonClearQueue, LabelQueue, MessageQueueEmpty

Test plan

  • Add an audiobook to the queue from the item more menu; verify it appears in the queue modal
  • Add a podcast episode to the queue from the episode page and latest episodes list
  • Drag items to reorder in the queue modal; verify order is persisted after closing and reopening
  • Delete an item from the queue; verify it is removed
  • Play an item from the queue modal while something is already playing; verify the current item is added back to the front of the queue
  • Let playback finish; verify the next queue item starts automatically
  • Force-close the app and reopen; verify the queue is restored from storage
  • Test background auto-advance (screen off, app backgrounded) on Android

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/advplyr/audiobookshelf-app/pull/1704 **Author:** [@andykelk](https://github.com/andykelk) **Created:** 10/20/2025 **Status:** 🔄 Open **Base:** `master` ← **Head:** `feature/playback-queue` --- ### 📝 Commits (10+) - [`66903d1`](https://github.com/advplyr/audiobookshelf-app/commit/66903d118fdba6cc325f11f025329a7b07cb956e) Add playback queue state management and strings - [`3815f8d`](https://github.com/advplyr/audiobookshelf-app/commit/3815f8d651ee67f9454168611dbd75aa6e22279a) feat: use device storage to persist queue - [`89d6f79`](https://github.com/advplyr/audiobookshelf-app/commit/89d6f796bb16712102239ae58b1169797bbabe48) Add QueueModal component for queue management - [`4347335`](https://github.com/advplyr/audiobookshelf-app/commit/434733523bb73f343d145d0e21279dc7137d8f49) fix: update close modal pattern - [`901c3e5`](https://github.com/advplyr/audiobookshelf-app/commit/901c3e58072f07dc715c3ca2fc21df54297ad9a2) feat: add queue button for items and episodes - [`37d8d47`](https://github.com/advplyr/audiobookshelf-app/commit/37d8d4748f51a860d3533e0d0e4d364cf945a774) feat: add queue button to latest podcast episodes - [`ee82ad7`](https://github.com/advplyr/audiobookshelf-app/commit/ee82ad7c898c079c88d4f8f73c6dd7a1d347ef36) feat: allow queue access from the side drawer - [`1ff116d`](https://github.com/advplyr/audiobookshelf-app/commit/1ff116d08bfaf8479663ad4ccf44821e24cf51ea) feat: preserve playback progress when adding items to queue - [`c6d547b`](https://github.com/advplyr/audiobookshelf-app/commit/c6d547bc35d131f96e00314059852f0f8af20df3) fix: use correct images for queue items - [`74ba76f`](https://github.com/advplyr/audiobookshelf-app/commit/74ba76ffe81d906f1db413b1a99eea2187eed018) fix: queue modal button functionality and drag interactions ### 📊 Changes **19 files changed** (+845 additions, -21 deletions) <details> <summary>View changed files</summary> ➕ `android/app/src/main/java/com/audiobookshelf/app/data/PlaybackQueueItem.kt` (+62 -0) ➕ `android/app/src/main/java/com/audiobookshelf/app/managers/QueueManager.kt` (+74 -0) 📝 `android/app/src/main/java/com/audiobookshelf/app/media/MediaProgressSyncer.kt` (+57 -8) 📝 `android/app/src/main/java/com/audiobookshelf/app/player/AbMediaDescriptionAdapter.kt` (+5 -0) 📝 `android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt` (+99 -3) 📝 `android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt` (+4 -0) 📝 `components/app/AudioPlayer.vue` (+13 -3) 📝 `components/app/SideDrawer.vue` (+10 -0) 📝 `components/modals/ItemMoreMenuModal.vue` (+22 -2) ➕ `components/modals/QueueModal.vue` (+187 -0) 📝 `components/tables/podcast/EpisodeRow.vue` (+22 -1) 📝 `components/tables/podcast/LatestEpisodeRow.vue` (+20 -1) 📝 `layouts/default.vue` (+4 -0) ➕ `mixins/queueMixin.js` (+58 -0) 📝 `pages/item/_id/_episode/index.vue` (+19 -1) 📝 `plugins/localStore.js` (+19 -0) 📝 `store/globals.js` (+5 -1) 📝 `store/index.js` (+160 -1) 📝 `strings/en-us.json` (+5 -0) </details> ### 📄 Description ## Summary Adds a playback queue feature allowing users to line up items to play sequentially. The queue persists across sessions and is managed at both the JavaScript/Vue layer and the native Android layer for seamless background playback. - **Queue management UI**: New `QueueModal` component with drag-to-reorder, play from position, and individual item removal. Accessible via a queue button in the audio player, side drawer, and item more menus - **Add to queue**: Queue buttons added to item/episode more menus, podcast latest episode rows, and the episode detail page - **Persistent storage**: Queue is saved to Capacitor `Preferences` (SharedPreferences on Android) and restored on app launch - **Native Android auto-advance**: `QueueManager` reads the queue directly from SharedPreferences so the Android `PlayerNotificationService` can advance to the next item on playback completion, even when the app is backgrounded - **Progress preservation**: Current playback position is saved in the queue item so playback resumes from where it left off - **Native→JS sync**: When the native layer advances the queue, it emits `onQueueChanged` so the Vue store reloads from storage and stays in sync ## Changed files - `store/index.js` — queue state, getters, mutations and actions - `store/globals.js` — `showQueueModal` flag - `plugins/localStore.js` — `getPlaybackQueue` / `setPlaybackQueue` methods - `mixins/queueMixin.js` — shared `addItemToQueue` helper used across components - `components/modals/QueueModal.vue` — queue management modal - `components/app/AudioPlayer.vue` — queue button + `onQueueChanged` listener - `components/app/SideDrawer.vue` — queue menu item - `components/modals/ItemMoreMenuModal.vue` — "Add to Queue" action - `components/tables/podcast/LatestEpisodeRow.vue` — queue button - `pages/item/_id/_episode/index.vue` — "Add to Queue" action - `layouts/default.vue` — mount `QueueModal`, load saved queue on init - `android/.../data/PlaybackQueueItem.kt` — data model matching JS queue item structure - `android/.../managers/QueueManager.kt` — reads/writes queue from SharedPreferences - `android/.../media/MediaProgressSyncer.kt` — mark finished even when timer is stopped - `android/.../player/PlayerNotificationService.kt` — native queue auto-advance on playback end - `android/.../player/AbMediaDescriptionAdapter.kt` — `invalidateCache()` for cover art refresh - `android/.../plugins/AbsAudioPlayer.kt` — `onQueueChanged` event bridge - `strings/en-us.json` — `ButtonAddToQueue`, `ButtonClearQueue`, `LabelQueue`, `MessageQueueEmpty` ## Test plan - [ ] Add an audiobook to the queue from the item more menu; verify it appears in the queue modal - [ ] Add a podcast episode to the queue from the episode page and latest episodes list - [ ] Drag items to reorder in the queue modal; verify order is persisted after closing and reopening - [ ] Delete an item from the queue; verify it is removed - [ ] Play an item from the queue modal while something is already playing; verify the current item is added back to the front of the queue - [ ] Let playback finish; verify the next queue item starts automatically - [ ] Force-close the app and reopen; verify the queue is restored from storage - [ ] Test background auto-advance (screen off, app backgrounded) on Android --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
adam added the pull-request label 2026-04-25 00:00:29 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf-app#1667