mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-06 07:59:43 +00:00
4.3 KiB
4.3 KiB
Move to Library Feature Documentation
Date: 2026-02-06
Overview
This feature allows users to move audiobooks (and podcasts) between libraries of the same type via a context menu option.
API Endpoint
POST /api/items/:id/move
Request Body:
{
"targetLibraryId": "uuid-of-target-library",
"targetFolderId": "uuid-of-target-folder" // optional, uses first folder if not provided
}
Permissions: Requires delete permission (canDelete)
Validations:
- Target library must exist
- Target library must have same
mediaTypeas source (book ↔ book, podcast ↔ podcast) - Cannot move to the same library
- Destination path must not already exist
Response: Returns updated library item JSON on success
Files Modified
Backend
| File | Line Range | Description |
|---|---|---|
server/controllers/LibraryItemController.js |
~1160-1289 | move() method |
server/routers/ApiRouter.js |
129 | Route registration |
Frontend
| File | Description |
|---|---|
client/components/modals/item/MoveToLibraryModal.vue |
NEW - Modal component |
client/store/globals.js |
State: showMoveToLibraryModal, Mutation: setShowMoveToLibraryModal |
client/components/cards/LazyBookCard.vue |
Menu item openMoveToLibraryModal in moreMenuItems |
client/pages/item/_id/index.vue |
Added "Move to library" to context menu |
client/layouts/default.vue |
Added <modals-item-move-to-library-modal /> |
client/strings/en-us.json |
Localization strings |
Localization Strings Added
ButtonMove,ButtonMoveToLibraryLabelMoveToLibrary,LabelMovingItemLabelSelectTargetLibrary,LabelSelectTargetFolderMessageNoCompatibleLibrariesToastItemMoved,ToastItemMoveFailed
Implementation Details
Backend Flow
- Validate
targetLibraryIdis provided - Check user has delete permission
- Fetch target library with folders
- Validate media type matches source library
- Select target folder (first folder if not specified)
- Calculate new path:
targetFolder.path + itemFolderName - Check destination doesn't exist
- Move files using
fs.move(oldPath, newPath) - Update database:
libraryId,libraryFolderId,path,relPath - Update
libraryFilespaths - Update
audioFilespaths in Book model (for playback to work) - Update
ebookFilepath in Book model (if present) - Update
podcastEpisodesaudio file paths for Podcasts - Handle Series and Authors:
- Moves/merges series and authors to target library
- Copies metadata (description, ASIN) and images if necessary
- Deletes source series/authors if they become empty
- Emit socket events:
item_removed(old library),item_added(new library) - Reset filter data for both libraries
- On error: rollback file move if possible
Frontend Flow
- User clicks "⋮" menu on book card
- "Move to library" option appears (if
userCanDelete) - Click triggers
openMoveToLibraryModal() - Store commits:
setSelectedLibraryItem,setShowMoveToLibraryModal - Modal shows compatible libraries (same mediaType, different id)
- User selects library (and folder if multiple)
- POST to
/api/items/:id/move - Success: toast + close modal; Error: show error toast
Testing
- Create 2+ libraries of same type
- Add an audiobook to one library
- Open context menu → "Move to library"
- Select target library → Click Move
- Verify item moved in UI and filesystem
Known Limitations / Future Work
- Does not support moving to different folder within same library
- No confirmation dialog (could be added)
- No batch move support yet
- Unit tests not yet added to
test/server/controllers/LibraryItemController.test.js