Commit Graph

724 Commits

Author SHA1 Message Date
ACX
8128269310 feat(stats): add 5 new user statistics charts (#2703)
* feat(stats): add 5 new user statistics charts

* fix(stats): use COALESCE for dateFinished in heartbeat and page turner queries

* refactor(stats): remove heartbeat, genre flow, reading seasons, and abandonment autopsy charts

* feat(stats): add 5 new user statistics charts

* feat(stats): add info tooltips to all 5 new charts

* perf(stats): limit completion race chart to 15 most recent books server-side

* fix(stats): limit completion race to 10 books and cap progress at 100%

* refactor(stats): replace streak bars with GitHub-style activity heatmap calendar

* fix(stats): widen chart info tooltips to prevent tall narrow box

* feat(stats): add info tooltip to Page Turner Score chart

* feat(stats): add info tooltips to 7 existing charts

* refactor(stats): deduplicate chart-info-icon style into global styles.scss

* refactor(stats): fix scoring bugs and improve Reading DNA and Reading Habits charts

* refactor(stats): rebalance Series Progress Tracker layout and unify heatmap footer pills

* feat(stats): add info tooltips to 4 remaining charts

* fix(stats): fix session duration and overlap bugs in Reading Session Timeline
2026-02-12 00:11:49 -07:00
ACX
9ed6a3fe72 feat(reader): add PDF annotations, Range streaming, and optimized chunk loading (#2701) 2026-02-11 16:51:59 -07:00
Balázs Szücs
e8530fa0b7 fix(comicvine): add fallback to issue detail endpoint for missing creator credits (#2694)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-11 10:22:49 -07:00
WorldTeacher
7e6ad212b0 show session numbers in book (#2696) 2026-02-11 10:22:01 -07:00
ACX
6da6e8e373 fix(metadata): improve cover errors, reduce metadata fetch count, and hide attach option (#2690)
* fix(metadata): improve cover regen errors and reduce detailed metadata fetch count

* fix(metadata): hide attach-to-book option in single-format libraries

---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-10 21:14:46 -07:00
ACX
ff11ec57b8 feat(metadata): return full metadata from fetchMetadata instead of previews (#2689)
Amazon, Audible, and GoodReads parsers now fetch full detailed metadata
(4 results each) instead of returning lightweight previews. Adds randomized
500-1500ms delays between requests. GoodReads retries with title-only search
(2 results) when title+author yields no matches.

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-10 15:49:11 -07:00
ACX
0fa84e3424 feat(sort): replace compound sort options with atomic fields and multi-sort support (#2686)
* fix(sidebar): replace routerLinkActive with getter-based route matching to prevent stale highlights

* feat(sort): replace compound sort options with atomic fields and add 6 new sort criteria
2026-02-10 14:27:07 -07:00
ACX
78a8bb4fea fix(settings): use boxed Integer for ScrollerConfig.maxItems to allow null (#2684)
Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-10 10:40:07 -07:00
Balázs Szücs
9444a544f9 feat(cbx-reader): enhance ZIP archive handling with Unicode support and fallback mechanisms (#2593)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-10 09:30:31 -07:00
Balázs Szücs
697de9052f feat(metadata): add custom metadata write to file support for moods, tags, ratings, and external IDs in PDF, and CBZ (#2552)
* feat(metadata): add BookLore custom metadata support for moods, tags, ratings, and external IDs in EPUB, PDF, and CBZ

- Introduce BookLoreSchema for XMP custom fields and BookLoreMetadata for namespace constants
- Write and extract moods, tags, ratings, and external IDs (Goodreads, Amazon, Hardcover, Lubimyczytac, RanobeDB, Google) in EPUB, PDF, and CBZ metadata
- Store BookLore custom fields in ComicInfo.xml notes and Web fields for CBZ
- Add BookLore fields to XMP metadata in PDF, including moods and tags as separate fields
- Update extractors and writers to handle BookLore fields and ensure separation of categories, moods, and tags
- Add comprehensive tests for BookLore metadata extraction and writing

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(metadata): standardize hardcoverBookId as String and improve identifier handling

- Change hardcoverBookId field and related methods to use String instead of Integer for consistency across extractors and writers
- Update metadata copy helpers and tests to reflect new hardcoverBookId type
- Improve identifier prefix handling in EPUB and PDF extractors to be case-insensitive and trim whitespace
- Allow PDF keywords to be split by comma or semicolon
- Rename TaskCreateRequest#getOptions to getOptionsAs for clarity and update usages
- Adjust series number writing in EPUB metadata to preserve decimals when needed

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(metadata): standardize usage of tags over categories and improve BookLore field extraction

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): add rating and ratingLocked fields to BookMetadata and improve PDF metadata extraction

- Add rating and ratingLocked fields to BookMetadata for enhanced rating support
- Refine PDF keyword extraction to handle both comma and semicolon delimiters
- Ensure ISBN fields are only set if cleaned values are non-blank
- Use temp file only stream cache when loading PDFs for metadata writing

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): implement ComicInfo.xml writing via JAXB, ensure XSD compliance and add tests for CBX metadata persistence

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): enhance metadata extraction with additional identifiers and improve parsing logic

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): improve metadata handling by ensuring descriptions are prioritized and enhancing keyword management for PDF compatibility

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(metadata): simplify Pages class structure in ComicInfo.java

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): refine PDF metadata writing by isolating categories for legacy compatibility and removing moods and tags from keywords

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): enhance PDF metadata extraction and writing with support for additional fields and improved handling of series information

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): enhance PDF metadata extraction and writing with support for additional fields and improved handling of series information

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): implement secure XML parsing utility and enhance metadata extraction with improved GTIN validation and debug logging

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(metadata): update package structure to align with new organization naming conventions

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* fix(epub-metadata): streamline cover image extraction logic and improve error handling

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): enhance PDF and comic metadata extraction with additional fields

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat(metadata): migrate to tools.jackson for JSON processing in sidecar metadata handling

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* fix(epub-metadata): streamline cover image extraction and enhance XML parsing security

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

---------

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-10 09:29:25 -07:00
Balázs Szücs
45dba44833 fix(epub-metadata): enhance cover extraction with heuristic fallbacks for manifest and ZIP entries (#2636)
* fix(epub-metadata): enhance cover extraction with heuristic fallbacks for manifest and ZIP entries

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* test(epub-metadata-extractor): add heuristic cover creation methods for EPUB files

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

---------

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-09 16:46:50 -07:00
ACX
ffd4615b87 feat: comic metadata picker, lazy-load providers, and UI improvements (#2679)
* feat: add comic metadata support to metadata picker and fix Comicvine parser

* feat: lazy-load Comicvine issue details on selection

* feat: lazy-load detail metadata for Amazon, GoodReads, and Audible parsers

* fix: prevent spurious comic_metadata row creation for non-comic books

* fix: extract rich previews from Audible search and reorder picker sections

* feat: redesign metadata editor layout with collapsible sections and boolean selects

* fix: implement per-field comic metadata locks replacing grouped locks

* feat: add comic metadata filters and fix visibleFilters backend support

* fix: use human-readable role labels in comic creator filter

* fix: auto-populate comic metadata from ComicVine during metadata fetch

* refactor: clean up ComicvineBookParser remove duplication and comments

* fix: use ComicMetadata webLink for ComicVine favicon URL

* fix: cache library options to prevent Set All dropdowns from resetting

* fix: stream book content from disk instead of loading entire file into memory

* fix: increase max visible filters from 15 to 20

* feat: replace filter multiselect with drag-and-drop reorderable list

* fix: use audiobook-specific cover paths and cache busting for audiobook thumbnail updates

* chore: enforce mandatory screenshots and stricter testing requirements in PR template

* fix: update BookServiceTest to match Resource return type after streaming change

---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-09 16:43:53 -07:00
ACX
bc7ba8b933 Remove nginx and serve Angular directly from Spring Boot (#2662)
* feat: remove nginx and serve Angular directly from Spring Boot

* fix: handle null values in EnabledFields deserialization from persisted JSON

* fix(migration): auto-repair failed Flyway migrations on startup

* fix(migration): replace DB triggers with app-level orphan cleanup

* fix: restore default port to 6060 for backwards compatibility

* fix: align all port references to 6060 and add OPDS compression MIME types

* fix: resolve NG0101 recursive tick error in book browser selection

---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-08 15:02:25 -07:00
dependabot[bot]
843b64969c chore(deps): bump the gradle-dependencies group across 1 directory with 7 updates (#2659)
Bumps the gradle-dependencies group with 7 updates in the /booklore-api directory:

| Package | From | To |
| --- | --- | --- |
| org.flywaydb:flyway-mysql | `11.19.0` | `12.0.0` |
| [io.documentnode:epub4j-core](https://github.com/documentnode/epub4j) | `4.2.2` | `4.2.3` |
| [org.jsoup:jsoup](https://github.com/jhy/jsoup) | `1.21.2` | `1.22.1` |
| [org.springdoc:springdoc-openapi-starter-webmvc-ui](https://github.com/springdoc/springdoc-openapi) | `2.8.14` | `3.0.1` |
| [com.github.ben-manes.caffeine:caffeine](https://github.com/ben-manes/caffeine) | `3.2.0` | `3.2.3` |
| [org.assertj:assertj-core](https://github.com/assertj/assertj) | `3.27.6` | `3.27.7` |
| org.hibernate.orm | `7.2.0.Final` | `7.2.4.Final` |



Updates `org.flywaydb:flyway-mysql` from 11.19.0 to 12.0.0

Updates `io.documentnode:epub4j-core` from 4.2.2 to 4.2.3
- [Commits](https://github.com/documentnode/epub4j/compare/v4.2.2...v4.2.3)

Updates `org.jsoup:jsoup` from 1.21.2 to 1.22.1
- [Release notes](https://github.com/jhy/jsoup/releases)
- [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES.md)
- [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.21.2...jsoup-1.22.1)

Updates `org.springdoc:springdoc-openapi-starter-webmvc-ui` from 2.8.14 to 3.0.1
- [Release notes](https://github.com/springdoc/springdoc-openapi/releases)
- [Changelog](https://github.com/springdoc/springdoc-openapi/blob/v3.0.1/CHANGELOG.md)
- [Commits](https://github.com/springdoc/springdoc-openapi/compare/v2.8.14...v3.0.1)

Updates `com.github.ben-manes.caffeine:caffeine` from 3.2.0 to 3.2.3
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.2.0...v3.2.3)

Updates `org.assertj:assertj-core` from 3.27.6 to 3.27.7
- [Release notes](https://github.com/assertj/assertj/releases)
- [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.6...assertj-build-3.27.7)

Updates `org.hibernate.orm` from 7.2.0.Final to 7.2.4.Final

---
updated-dependencies:
- dependency-name: org.flywaydb:flyway-mysql
  dependency-version: 12.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gradle-dependencies
- dependency-name: io.documentnode:epub4j-core
  dependency-version: 4.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gradle-dependencies
- dependency-name: org.jsoup:jsoup
  dependency-version: 1.22.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle-dependencies
- dependency-name: org.springdoc:springdoc-openapi-starter-webmvc-ui
  dependency-version: 3.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gradle-dependencies
- dependency-name: com.github.ben-manes.caffeine:caffeine
  dependency-version: 3.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gradle-dependencies
- dependency-name: org.assertj:assertj-core
  dependency-version: 3.27.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gradle-dependencies
- dependency-name: org.hibernate.orm
  dependency-version: 7.2.4.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gradle-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-08 13:20:58 -07:00
acx10
855b215ee5 fix(migration): add idempotent guards to V114-V117 migrations
Add IF NOT EXISTS / IF EXISTS / DROP IF EXISTS guards to prevent
failures when migrations are re-run after partial application on
MariaDB which lacks transactional DDL support.
2026-02-08 13:08:08 -07:00
acx10
7f3680dd21 fix(migration): move comic metadata triggers to separate migration
Reverts V114 to its original content to preserve Flyway checksum
for existing installations. Moves orphan-cleanup triggers to new
V117 migration to avoid checksum mismatch failures on MariaDB.
2026-02-08 12:46:25 -07:00
Balázs Szücs
108d94c0f7 feat(api, build): Upgrade to Java 25, Gradle 9, and Spring Boot 4, Jackson 3 (#2597)
* refactor: simplify RestTemplate and ObjectMapper configurations, add no-args constructors to progress classes

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* chore: update Gradle and Java versions in Docker configuration and build files

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* test: enhance header assertions in tests and add spring-boot-test-autoconfigure dependency

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(tests): migrate to SpringBootTest and update entity management in test cases

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* test: update test property configurations for H2 database in Healthcheck and BookOpds repository tests

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* test: clean up HealthcheckControllerTest by removing unnecessary whitespace and comments

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* test: remove unnecessary whitespace in HealthcheckControllerTest

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* chore: downgrade Flyway version from 12.0.0 to 11.14.1 in build.gradle

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* chore: downgrade Flyway version from 12.0.0 to 11.14.1 in build.gradle

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add @DependsOn annotation for Flyway in MultipartConfig

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add @DependsOn annotation for Flyway in LibraryService

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add test configuration for Flyway in HealthcheckControllerTest
chore: remove unused path variable in deleteLibrary method of LibraryService

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: configure Flyway migration and update test configuration

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: enable remote debugging in bootRun configuration

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: update Flyway version and enhance ObjectMapper configuration

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: remove @DependsOn annotation for Flyway in MultipartConfig and LibraryService

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add NoArgsConstructor and AllArgsConstructor annotations to DTO classes

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add NoArgsConstructor and AllArgsConstructor annotations to FileProcessResult, MetadataUpdateContext, and MetadataUpdateWrapper classes

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add DependsOnDatabaseInitialization annotation to MultipartConfig, AppSettingService, LibraryService, and JwtSecretService classes

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add DependsOnDatabaseInitialization annotation to MultipartConfig and CronService classes

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: implement lazy initialization and thread safety for JWT secret retrieval

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add Flyway dependency and update LibraryService initialization to use ApplicationReadyEvent

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor: remove outdated comments from JwtSecretService class

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor: migrate from com.fasterxml.jackson to tools.jackson for JSON processing

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor: remove unused ObjectMapper bean and related imports from JacksonConfig

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: configure async support with VirtualThreadTaskExecutor in WebMvcConfig

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: enhance application performance with virtual threads and HTTP/2 support

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add JsonSetter annotation to skip null values for triggeredByCron field

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: add triggeredByCron field to TaskCreateRequest and initialize in task management

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* feat: enable Spring Data web support with DTO serialization in WebMvcConfig

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(UserDefaultsService): simplify class structure and remove unused methods

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(BookOpdsRepositoryDataJpaTest): simplify test setup and use TestEntityManager

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(BookOpdsRepositoryDataJpaTest): update test configuration and simplify entity persistence

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor: update Jackson dependencies and migrate to Jackson 3

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(build.gradle): update jackson-annotations dependency to use Jackson 3 BOM

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(BookOpdsRepositoryDataJpaTest): remove unused ObjectMapper bean definition

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

* refactor(LibraryService): simplify library deletion logic

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>

---------

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-08 10:15:16 -07:00
ACX
e462b6c197 feat(sidecar): add sidecar JSON metadata file support (#2657)
Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-08 09:31:18 -07:00
ACX
c1c72ea7ba feat(comic-metadata): add extended comic metadata support (#2654)
* feat(metadata): add comic metadata support

* Fix metadata saving

* feat(comic-metadata): normalize comic metadata with relational tables

* feat(comic-metadata): add comic metadata UI components and model

---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-07 21:15:59 -07:00
ACX
b2a4aa7960 feat(email): add format selection to email book dialog (#2650)
Allow users to choose which file format to send when emailing a book.
Includes file size display and large file warnings for files >25MB.

Backend:
- Add optional bookFileId to SendBookByEmailRequest
- Add resolveBookFile() to resolve specific file or fallback to primary
- Update SendEmailV2Service to use specified file path

Frontend:
- Change openCustomSendDialog to accept Book object
- Add format selection with radio buttons showing type/size
- Add "Primary" badge and large file warning banner
- Update book-card and metadata-viewer callers

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-07 12:28:21 -07:00
WorldTeacher
d93f1b8dfb fix(file naming): follow documentation... (#2642)
... and add a leading zero to seriesIndex
2026-02-07 08:36:17 -07:00
Giroux Arthur
14236299f2 feat(icons): Made icons for libraries and shelves optional with no default icons. (#2599)
* feat(icons): Made icons for libraries and shelves optional with no default icon displayed.

* Added tests for making sure the API handles nullable icons for Shelves and Libraries.

* Fixed some issues identified during PR review.

* Rebased on develop.
2026-02-07 08:25:34 -07:00
PhasecoreX
a941ef51b5 fix(hardcover-sync): Don't send repeated read status to Hardcover.app (#2609)
* fix(hardcover-sync): Don't send repeated read status to Hardcover.app

* fix(hardcover-sync): Use progress percentage instead of read status

* fix(hardcover-sync): Add test cases

* fix(hardcover-sync): Also check read status for changes
2026-02-07 08:22:28 -07:00
acx10
11007325b3 Audiobook fixes 2026-02-06 17:47:22 -07:00
Balázs Szücs
f5326ce435 fix(file-move): update empty directory cleanup to handle multiple library paths (#2634)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-06 13:12:38 -07:00
Balázs Szücs
cd428c6fe3 fix(file-move): implement transaction management for file moves and rollback on failure (#2592)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-06 13:11:10 -07:00
Balázs Szücs
37f6417e3d fix(library-service): prevent concurrent library scans with a tracking set (#2637)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-06 13:06:41 -07:00
ACX
37ea0b156f feat(google-books): add optional API key configuration (#2629) 2026-02-05 22:37:12 -07:00
ACX
555cd13f8a fix(auth): resolve DST-related login failure for refresh tokens (#2624) 2026-02-05 20:16:27 -07:00
ACX
9f9c762180 feat(content-restrictions): add age rating and content rating support (#2619) 2026-02-05 17:10:44 -07:00
Balázs Szücs
c7dd23ed85 fix(file-move): implement transaction management for file moves and rollback on failure (#2588)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-05 14:01:34 -07:00
xcashy
539734a3cf feat(kobo-sync): Sync Shelves and Magic Shelves to Kobo Tags (#2236)
* feat(kobo-sync): sync shelves and magic shelves to kobo tags

* refactor(kobo-sync): replace `EntityNotFoundException` with `NoSuchElementException`, update timestamps handling, and add unit tests for `generateTags`

---------

Co-authored-by: ACX <8075870+acx10@users.noreply.github.com>
2026-02-05 13:59:08 -07:00
ACX
d38271de9c Audiobook enhancement (#2611)
* Audiobook enhancement

* Fix choppy virtual scroller with mixed audiobook/ebook cards by using uniform heights

* Fix audiobook cover regeneration for combined books and improve error messages

* Fix cover extraction when attaching audiobook files during rescan

* Set audiobookCoverUpdatedOn for cache busting when generating cover

* Add support for regenerating covers from specific book files

* Fix Continue Reading/Listening scrollers to filter by actual progress instead of primary file type

* Show ebook cover and open ebook reader in Continue Reading scroller for combined books

* Prevent read status from being downgraded when saving audiobook progress

* Fix BookCoverServiceTest to match updated regenerateCover method signature
---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-02-05 13:33:08 -07:00
Ben Szabo
a77cecdf21 feat(kobo-sync): add user scoped 2 way kobo sync (#2452)
* fix(kobo-sync): Kobo reading state sync by returning the device expected shape and improve management with new DTOs and timestamp normalization

- Introduced `KoboReadingStateList` and `KoboReadingStateRequest` DTOs for improved handling of reading states.
- Updated `KoboController` to utilize the new DTOs and log request bodies.
- Enhanced `KoboReadingStateService` to normalize timestamps during reading state updates and merges.
- Adjusted repository queries to include user ID for better data integrity.
- Updated tests to reflect changes in DTOs and repository interactions.

* feat(kobo-sync): Enhance Kobo reading state management with user ID integration

* feat(kobo-sync): Add JSON annotations to KoboReadingStateList for improved serialization

* refactor(kobo-sync): Update repository and service methods to enhance reading state retrieval logic

- Replaced the existing method for fetching reading states with a new query that orders results by priority and timestamps.
- Updated service classes to utilize the new repository method for improved data handling.
- Adjusted unit tests to reflect changes in repository interactions.

* Enhance KoboReadingStateService and add database migration for user_id

- Added a new column `user_id` to the `kobo_reading_state` table with a foreign key constraint referencing the `users` table.
- Updated the `KoboReadingStateService` class by adding a new method to check for blank values, improving code readability and maintainability.
2026-02-02 10:27:58 -07:00
Balázs Szücs
cb5f703c7e fix(epub-cover-extract): improve cover image extraction with fallback handling (#2585)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-02-02 10:26:49 -07:00
acx10
91c0382527 refactor: rename package to org.booklore 2026-02-02 00:02:12 -07:00
acx10
17fef505cb Fix ebook reader text selection and audiobook reader 2026-02-01 23:49:20 -07:00
acx10
a402f98e08 Merge branch 'experimental/fix-adb' into develop
* experimental/fix-adb:
  Fix audiobook player
2026-01-31 15:56:27 -07:00
acx10
b6057588f6 Fix audiobook player 2026-01-31 15:55:42 -07:00
Balázs Szücs
a27c9d57fb Fix: handle file modifications in Bookdrop event handler (#2559)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-01-31 14:49:58 -07:00
acx10
b215dbb692 Fix tests 2026-01-29 18:18:37 -07:00
Balázs Szücs
3a4de95c8c fix(metadata-update): ensure per-book transaction isolation in bulk updates to prevent race conditions (#2536)
Refactor bulkUpdateMetadata to process each book update in its own transaction using PROPAGATION_REQUIRES_NEW, improving concurrency safety. Add BookMetadataServiceConcurrencyTest to verify correct fetching strategy and transactional behavior.

Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-01-29 18:00:27 -07:00
Jadehawk
5ad66daae6 feat(metadata) Save basic metadata to EPUB file - Bonus use Calibre Custom Columns for importing metadata. (#1879)
* feat: Add comprehensive Calibre metadata extraction system - Implemented configurable field mapping system for Calibre user_metadata - Added support for series_total custom column extraction - Pre-built mappings for ALL BookMetadata fields (20+ fields) - Added support for Set fields (tags, moods, categories, authors) - Lowercase field names with underscores (Calibre requirement) - Multiple ISBN support (ISBN-10 and ISBN-13 simultaneously) - ISBN hyphen handling (strips hyphens before validation) - Type-safe parsing (String, Integer, Float, Double, Set) - Professional logging with IDENTIFIER prefix - Added CALIBRE_FIELD_MAPPING_REFERENCE.txt documentation - Updated .gitignore and created .dockerignore for test files

* Updated gitignore

* Delete CALIBRE_FIELD_MAPPING_REFERENCE.txt

* Remove unnecessary files: example.epub and og_metadata.java

* Refactor EpubMetadataExtractor to address PR review feedback

- Eliminate DRY violations in identifier extraction with helper methods
- Fix Build-to-Check anti-pattern using processedFields tracking
- Move regex patterns to static constants to avoid recompilation
- Replace magic numbers with calculated prefix lengths
- Consolidate repetitive Set field and pagecount parsing patterns
- Remove excessive documentation and comments
- Remove unrelated .dockerignore and .gitignore entries

* chore: trigger CI/CD pipeline

* Add @Singular annotation to collection fields to support builder accumulation

* Update identifiers to URN format for Calibre compatibility

* fix: resolve MetadataChangeDetectorTest failures and enhance Calibre EPUB integration

- Fixed NullPointerException in testEdgeCase_emptyCollectionToNull_returnsTrue()

- Fixed NullPointerException in testHasValueChanges_whenEmptySetToNull_returnsTrue()

Implementing @Singular for moods and tags prevents metadata fields from being null,

which then fails edge test cases. Since we are no longer double looping during

metadata extraction, @Singular is not needed. Removing it allows the edge case

tests (by Balázs Szücs) to pass.

- Removed douban fields from persistence layer (kept in DTO for DoubanBookParser)

I was under the impression we were saving this value to the DB, but as far as I

can find, we only use Douban data for searching. Adding to the identifiers section

would raise issues with the database not having where to store that value.

Database modifications are left to the professionals.

- Added support for all identifier formats (URN and simple prefix)

Calibre only detects identifiers during IMPORT if they are in URN format.

However, it saves them back as simple prefix. Booklore now handles both.

- Added removeAllCalibreMetadata() to strip all Calibre traces

Cleans up saved EPUBs in Booklore's library, removing all Calibre metadata traces.

- Ensures clean EPUB 3 compliant output with only booklore:* tags

ALL metadata is now saved by Booklore into EPUBs using booklore:* tags.

This preserves Booklore's metadata and we can read it back during import.

Calibre support is ONLY during IMPORT, as it should be since this is the

Booklore project.

(If Calibre users want to extract Booklore metadata, they can build a Calibre

plugin to extract booklore:* tags.)

No longer use #genres or #categories. We stick to dc:subject as suggested,

and Booklore tags can be read from Calibre custom column #extra_tags.

We store tags as booklore:tags.

Removed all tests that used #genres/#categories.

Added tests to check booklore:* tags extraction.

* fix: Remove DoubanId copy helper call - upstream MetadataClearFlags missing isDoubanId()

* Fix Calibre moods and tags extraction from EPUB metadata

- Add fallback logic to check alternative key names (value, #val#) if #value# is missing

- Maintain compatibility with upstream metadata structure changes

* fix: resolve rebase conflicts and compilation errors - Fixed missing closing brace in MetadataRefreshService.java - Added MoodRepository and TagRepository to BookCreatorService - Added addMoodsToBook() and addTagsToBook() methods - Fixed EpubProcessor to use new methods

* Restore Booklore's metadata persistance, Logic Lost during Rebase + Added support for Lubimyczytac and ranobedb

Fixed lubimyczytac metadata not saving during EPUB bookdrop imports.

Root cause: The Angular bookdrop form was missing lubimyczytacId and lubimyczytacRating fields, preventing these values from being sent to the backend during finalization.

Backend fixes:

- EpubMetadataExtractor: Fixed method references with explicit lambdas for lubimyczytac field setters (ranobedb also updated preventively)

- BookMetadataUpdater: Fixed method references with explicit lambdas for lubimyczytac field updates (ranobedb also updated preventively)

Frontend fix:

- bookdrop-file-review.component.ts: Added lubimyczytacId and lubimyczytacRating form fields to createMetadataForm() and resetMetadata() methods

This ensures lubimyczytac metadata extracted from EPUB booklore:tags flows correctly through: extraction → database → UI form → backend → final book record.

* Restore Original ONLY Calibre custom column name to #pagecount So as not to break other users flow.

* fix: resolve compilation error in EpubProcessor.java - Changed bookEntity.getFileName() to bookEntity.getPrimaryBookFile().getFileName() to fix gradlew build check

* Add EPUB 3 compliant prefix declaration for custom booklore metadata

Declares the booklore: prefix in the package element's prefix attribute according to EPUB 3 specification for custom vocabularies.

* Move hardcoverBookId to standard URN identifier format

Changed hardcoverBookId from custom booklore metadata to standard dc:identifier with urn:hardcoverbook: prefix for consistency with other identifiers.

* UPDATE: migrate hardcover_book_id to VARCHAR and fix related issues

## Changes

### 1. Database Migration
- Changed hardcover_book_id column from INTEGER to VARCHAR(255)
- Supports alphanumeric book IDs from Hardcover API
- Updated HardcoverSyncService to handle String ↔ Integer conversion

### 2. Metadata Editor Fixes
- Fixed metadata change detection for provider-specific fields
- Added missing clearFlags entries: hardcoverBookId, lubimyczytacId, lubimyczytacRating
- Resolves issue where rating/review count fields wouldn't save independently

Affected fields now save properly independently:
- Amazon rating & review count
- Goodreads rating & review count
- Hardcover rating & review count
- Lubimyczytac rating
- Ranobedb rating

### 3. Web Reader Hardcover Sync (Major Fix)
Since I changed the data type for hardcover_book_id I had to update references in the HardCoverSyncService.java This turned out to reveal
the Sync Service was not fully implemented:
- Added Hardcover progress sync to ReadingProgressService
- Previously, HARDCOVER sync only worked for Kobo and KOReader devices
- Web browser reading progress now syncs to Hardcover.app

## Files Modified
- booklore-api/src/main/resources/db/migration/V107__Change_hardcover_book_id_to_varchar.sql
- booklore-api/src/main/java/.../service/hardcover/HardcoverSyncService.java
- booklore-api/src/main/java/.../service/progress/ReadingProgressService.java
- booklore-ui/src/app/features/metadata/.../metadata-editor.component.ts

## Breaking Changes
None - migration handles existing integer IDs gracefully

## Testing
- Hardcover sync tested with web reader
- Metadata editor field updates verified
- Database migration confirmed successful

---------

Co-authored-by: ACX <8075870+acx10@users.noreply.github.com>
2026-01-29 17:59:50 -07:00
PhasecoreX
09d4a3025a fix(api): Select correct Hardcover.app ISBN from lookup results (#2530) 2026-01-29 17:55:30 -07:00
Sergio Visinoni
4db2006afd test(API): add missing tests for BookMapperV2 (#2495)
* fix(API): add missing fields to BookMapperV2

This fixes a regression introduced in the data model refactoring work
for multi-format support.
BookMapperV2 was missing mapping for file-related fields.

* Added missing mappings for BookMapperV2
* Added a test for BookMapperV2 to prevent future regressions

* fix(api): fix the code after rebase
2026-01-29 17:46:14 -07:00
ACX
67269ffe4c fix(audiobook-reader): use preload=none with explicit load() for faster streaming (#2520)
* fix(audiobook-reader): use preload=none with API duration for instant load

* fix(audiobook-reader): debounce seek and limit streaming chunk size to 2MB

* no message

---------

Co-authored-by: acx10 <acx10@users.noreply.github.com>
2026-01-29 17:45:10 -07:00
acx10
17aa633b41 Backend APIs 2026-01-29 17:37:11 -07:00
acx10
2b6cc4be7c feat(mobile-api): add updatedAt to progress DTOs for conflict detection
Add updatedAt timestamp field to EpubProgress, PdfProgress, and CbxProgress
DTOs to support progress conflict detection in the mobile app.

The mobile app uses this timestamp to detect when progress has changed on the
server (e.g., from reading in the web UI) while the app was offline with
local progress, enabling automatic conflict resolution.
2026-01-29 14:44:38 -07:00
acx10
0c56b7b720 feat(user-stats): add monthly heatmap endpoint
- Add GET /api/v1/user-stats/heatmap/monthly endpoint for month-based data
- Keep original /heatmap endpoint unchanged for backward compatibility
- Add findSessionCountsByUserAndYearAndMonth repository method
- Add getSessionHeatmapForMonth service method
2026-01-29 00:21:33 -07:00
Balázs Szücs
bbea391c9c fix(metadata-refresh): filter book shelves by authenticated user (#2481)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
2026-01-27 16:38:47 -07:00