This was supposed to be a small update to add reading lists, but I got carried away again. Instead, while you still get reading lists, you also get a TON of performance improvements, and UX enhancements across the board.
So what are Reading Lists? Reading lists are an order list of chapters that you have complete control over. Great for things like story arcs between multiple series, series that have unique names to read the full arc, or just a way to collect new chapters on your server to read them in one sitting. What's great about our reading lists is you can read through them in the order you defined without closing the reader. This means that once you start reading, even if the first item is a manga and the next is a book, Kavita will handle all that transition logic for you, so you just get the no distractions experience.
Next up is the performance improvements, where I wanted to tackle the memory usage in Kavita. I've planned to do this in 2 passes and what you're seeing now is the first pass. Every API in the system was looked at and optimized for speed and memory pressure. The goal was to reduce the amount of memory used while speeding up how fast Kavita processes items. This lead to changing how we handle cover images resulting in huge gains in memory pressure, but also slightly slower scans and a large migration off the bat. If you have a large library, the first run will be slow as we migrate the cover files to the new storage system. If something goes wrong, a simple scan will fix everything.
This was a really fun release tackling a lot of fun projects, like continuous reading in the webtoon reader and book reader, the performance optimizations, and the multi-selection functionalities. It is jammed pack full of new stuff not mentioned (like WebP support) in the opening post. Next release is focused on our Comic users, with a complete overhaul of the comic parser along with some further enhancements to reading lists and performance.
A few off topic notes:
- Pi users rejoice! @ChristofferGreen worked with our downstream libraries to add support for Pis. This release will now support PDFs for you. You may need to manually install libgdiplus on your system.
- Panels users (iOS OPDS app), will soon be able to interact with Kavita via OPDS. The developer has reached out to me as of this post date that Kavita is now fully functioning on their app and will be out in the next release.
Added
- Added: New reading mode called Incognito. Can be activated from a volume or chapter and persists during continuous reading. When this mode is activated, progress will not be saved to Kavita, allowing you to read a few pages before you decide to track progress. When Incognito is activated, a glasses icon will appear in the reader next to title. (#545)
- Added: Reading Lists can now be created by adding any series, volume, or chapter to an existing or new reading list. Lists can be promoted so all users on the server can read them (RBS still applies, like collection tags). You can read through a reading list (continuous reading support), remove all read items in bulk, and order your items however you want with drag and drop. (#268)
- Added: Continuous Reading for books! Books when on first or last page, will now show a double arrow to indicate that you can move to the next book (if it's in that series).
- Added: WebP support (within archives or raw images). This will work with all browsers except Safari on MacOS < Big Sur 11. Those users will need to use a different browser.
- Added: Continuous Reading between different readers! What if you have a reading list of mixed media, some archives and some epubs? No problem, go ahead and press read and the readers will make sure to move you to the correct ones without leaving the reading interface.
- Added: OPDS support updated with Reading Lists
- Added: Added a parser case for 'Series - - Vol. 03 Ch. 023.5 - Volume 3 Extras.cbz' which is a common name from FMD2
- Added: Added dedicated buttons in book drawer to jump to previous/next chapter
- Added: Added the ability to use continuous reader with webtoon reader without having to open the menu. When you scroll to the top and bottom, a new section will insert prompting you to scroll into the space to trigger the next or prev chapter load. (#565)
- Added: In manga reader, added the ability to press 'b' to bookmark/unbookmark a page. (#571)
- Added: Added a case for 'A Compendium of Ghosts - 031 - The Third Story_ Part 12 (Digital) (Cobalt001)' to be less aggressive in consuming characters until the number.
- Added: Added parser case for 'The Duke of Death and His Black Maid - Ch. 177 - The Ball (3).cbz'
- Added: Added a way for external scripts to use a user api key to authenticate (this essentially allows 3rd party scripts to interact with Kavita).
- Added: Implemented the ability to automatically refresh the web browser after a series scan based on when server finishes. This will push the event to the user and if they are on series detail, the page will automatically update to reflect new status on backend
- Added: Added many more manga and comic parsing cases which leads to catching more file naming conventions
- Added: When you cross a chapter boundary via continuous reading in book reader, a toast will show up
- Added: Added parser case for 'Chapter 63 - The Promise Made for 520 Cenz.cbr' where regex was consuming too many characters
- Added: Admins can now see themselves in the manage users page. No operations are still possible on your current account, create a secondary admin if you need to modify your permissions.
- Added: Added some messaging when you are trying to add a user to a library but haven't setup any libraries yet.
- Added: Added parsing case for 'Batman Beyond 04 (of 6) (1999)' to properly parse out chapter as 4.
Added: Added the ability to perform certain operations on multiple items in one go. For example, you can select volumes 1-10 by clicking volume 1, holding shift then clicking volume 10 and clicking the new bulk operations bar that pops up and marking as read, marking as unread, or adding to a reading list. Integrated on library detail, collection detail, and series detail page. (#549 )
Changed
- Changed: (Performance) Huge performance improvement to GetChapterIdsForSeriesAsync() by reducing a Join and iteration loop. Improvement went from 2 seconds -> 200ms.
- Changed: (Performance) Updated all APIs to use a lighter, faster GetUser call to minimize extra memory pressure where not needed.
- Changed: (Performance) Refactored the performance of GetChapter/BookInfo API to have a 10x speed improvement and to use common code, rather than duplicating code. This should speed up initially opening a book or manga for reading. (#563 )
- Changed: (Performance) Speed up SaveProgress from 50ms -> 10ms on average.
- Changed: (Performance) Speed up GetNextChapterId/GetPrevChapterId from 1.2 seconds on average -> 400ms.
- Changed: (Performance) Refactored OPDS to use faster API lookups for User
- Changed: (Performance) Removed 2 stream copies (stream copy + array copy) for SharpCompress archive cover image code and for PDF page extraction, further reducing unnecessary memory pressure.
- Changed: (Performance) Refactored GetUserByUsernameAsync to have a new flavor and allow the caller to pass in bitwise flags for what to include. This has a get by username or Id variant. Code is much cleaner and snappier as we avoid many extra joins when not needed.
- Changed: (Performance) Performance improvement on metadata service. Now when we scan for cover image changes, we emit when a change occurs and only then do we update parent entities (array copy)
- Changed: (Performance) Implemented ability to send images from archives to the UI without incurring any extra memory pressure.
- Changed: (Performance) Huge updates to metadata refresh. On 650GB, 12k file DB, metadata refresh now only takes 2.2 seconds to check all files to updates to cover images, summary, etc.
- Changed: (Performance) Removed some duplicate API calls from series detail page
- Changed: (Performance) General performance tune ups throughout the code averaging 1-4x speed ups.
- Changed: (Performance) Cover Images are now stored on disk in the covers/ directory. On first run, existing covers will be migrated from the DB to disk, which can take up to 20 mins depending on side of library (20k files took 20 mins). This change significantly decreases memory usage during scanning and during serving cover images without any degradation in experience.
- Changed: Added some extra help information for users on directory picker, since linux users were getting confused (#559)
- Changed: After adding a new library, we now show a toast informing user a scan has been scheduled (#542)
- Changed: (UX) Changed the design of accordions to match more of my style, with dedicated chevrons (#543)
- Changed: (UX) Home page now has libraries at the bottom and tag list to quickly jump between Home, Lists, and Collections
- Changed: (UX) Updated tabs to use a pill shape, rather than normal tab set (#551)
- Changed: (UX) Cleaned up some extra spaces when actionables (overflow dots) isn't shown to the left of titles.
- Changed: In webtoon reader, when you hit end of the scroller, we will automatically force the last page to be read.
- Changed: Upon moving between chapters in continuous reading, a toaster will inform you of the transition.
- Changed: Removed a lot of Volume parsing for Comics that don't make sense
- Changed: Reworked a lot of parsing cases for comics based on naming conventions observed from releases found online.
- Changed: Tweaked a lot of regex for manga parsing to handle some cases where poorly named files, like 'Vol. 03 Ch. 21' would end up parsing as Series 'Vol. 03'.
- Changed: Dropdown menus now have a darker background
- Changed: Fixed how keyboard presses for up/down/left/right work with MANGA_UD reading mode. Up/down only work when using Up/Down mode. (#579)
- Changed: All sliders in the app (user preferences) now use the same style
- Changed: Auth guard will now check if an existing toast is present giving same message before popping the toast.
- Changed: Moved sorters so they aren't reused between multiple threads. Slightly higher memory footprint. There was a rare exception thrown in the sort code due to concurrent access.
- Changed: Tabs within modals are now vertical, unless you are on mobile (#552)
- Changed: Updating wording on card items when total pages is 0 to be 'Cannot Read' since it could be a non-archive file.
- Changed: After a library scan, only cleanup cache directory and leave a full cleanup for scheduled tasks
- Changed: After we scan library, do one last filter to delete any series that have 0 pages total.
- Changed: Series detail will no longer use gutters for card layout to render slightly better on mobile
Fixed
- Fixed: Fixed a bug where marking as unread on a Volume would actually call mark as read instead. You can now mark a volume as unread.
- Fixed: Fixed a bug where pressing save on edit series modal could clear out tags if you didn't interact with tags, like just updating cover image (#561)
- Fixed: Fixed an issue where cover image generation was failing to pick the correct file under rare condition (#491)
- Fixed: Fixed up the parser for 'Kimi no Koto ga Daidaidaidaidaisuki na 100-nin no Kanojo Chapter 11-10'
- Fixed: Ensured we delete bookmarks and reading list items when chapters are deleted (#566 )
- Fixed: Series cover image no longer stretches on larger screen resolutions. (#572)
- Fixed: Fixed 'Could not save progress' errors spamming when reading on webtoon reader. (#570)
- Fixed: Fixed an issue in webtoon reader when we'd load a totally read chapter, we'd actually load second to last page
- Fixed: Fixed an edge case where when tap to paginate was on in Book reader, the reader might look at those elements for saving last scroll position
- Fixed: Fixed an edge case where when tap to paginate was on in Book reader, the reader might look at those elements for saving last scroll position
- Fixed: Fixed 'Could not save progress' errors spamming when reading on webtoon reader. (#570)
- Fixed: Fixed an issue where the scanner when parsing files could throw an exception when a series was deleted but still tried to update volumes for it (#558)
- Fixed: Fixed a bad parser case for 'Batman Beyond 02 (of 6) (1999)' which was consuming too many characters
- Fixed: Fixed an issue if the manga only had one page, the bottom menu would be missing page and chapter controls.
- Fixed: Fixed a bug where on small phones, nav bar could overflow due to scroll to top
- Fixed: Don't force metadata refresh on Scan Series, only on refresh metadata
- Fixed: Fixed a bug when really poorly named files are within a folder that contains the series name, fallback couldn't occur due to it being taken as root folder and would delete the series. Now we detect said condition and will go one level higher, resulting in potentially more I/O, but the series will not be deleted.
- Fixed: Added the Read in Incognito context item for Chapter cards
- Fixed: Fixed an issue where cover image generation could occur due to a bad check on LastWriteTime on the underlying file.
- Fixed: (Webtoon reader) Ensure prefetching uses totalPages + 1 since we pass in totalPages as - 1 from manga reader
- Fixed: (Webtoon reader) Fixed issue where last page of webtoon wouldn't be prefetched due to a < instead of <= on prefetching code
- Fixed: Fixed an issue where after opening a volume's info modal from series detail trying to open a chapter info modal, it wouldn't work
- Fixed: Fixed an issue in which & in folder names wouldn't show nested folders. (#593 )
- Fixed: Fixed an issue where changelog in system view would show previous versions as 'available' even if you were on a latter release.