-
-
Notifications
You must be signed in to change notification settings - Fork 140
fix(kobo-sync): use KoboSpan for progress sync #253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
alexhb1
wants to merge
26
commits into
grimmory-tools:develop
Choose a base branch
from
alexhb1:fix/issue-36
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
35b736d
fix(kobo-sync): pass file position to device
alexhb1 e5f20be
fix(kobo-sync): preserve CFI value for sync
alexhb1 392486c
fix(kobo-sync): add KEPUB output type
alexhb1 5557173
fix(kobo-sync): Full KoboSpan positioning
alexhb1 0594eb8
fix(kobo-sync): Cleanup and simplification
alexhb1 e5a7bf0
fix(kobo-sync): fix CFI fallback
alexhb1 1d4fcb2
fix(kobo-sync): Better calculate KoboSpan via CFI
alexhb1 1608533
fix(kobo-sync): Strip unwanted CFI elements
alexhb1 d70fc5e
fix(kobo-sync): Improve two-way sync freshness
alexhb1 cf0d98d
fix(kobo-sync): Fix web reader using stale CFI over Kobo position
alexhb1 de6078f
fix(kobo-sync): Fix web reader not parsing Kobo progress
alexhb1 244dbb7
fix(kobo-sync): pass kobo in-chapter progress to grimmory
alexhb1 8387483
fix(kobo-sync): Clean up KEPUB option code
alexhb1 7568228
fix(kobo-sync): Time normalization
alexhb1 eda769b
fix(kobo-sync): Sync batch size increased to 100
alexhb1 964018e
fix(kobo-sync): Re-add KEPUB setting and update language
alexhb1 4fc9819
fix(kobo-sync): review followup + regression tests
alexhb1 794ce34
fix(kobo-sync): Update null check with method ref
alexhb1 72a497b
fix(kobo-sync): code cleanup + freshness fix
alexhb1 ce9a690
fix(kobo-sync): Validate web reader progress for Kobo use
alexhb1 13bd242
fix(kobo-sync): fix Hardcover progress using potentially stale source
alexhb1 9c4cfc4
fix(kobo-sync): Fix kobospan freshness regression
alexhb1 7459a67
fix(kobo-sync): reassert kobospan priority in outbound sync
alexhb1 add1e97
fix(kobo-sync): Re-add chapter progress
alexhb1 c1be069
fix(kobo-sync): remove progress filter
alexhb1 a071cc5
fix(kobo-sync): restore broken filter
alexhb1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
booklore-api/src/main/java/org/booklore/convertor/KoboSpanMapJsonConverter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package org.booklore.convertor; | ||
|
|
||
| import jakarta.persistence.AttributeConverter; | ||
| import jakarta.persistence.Converter; | ||
| import org.booklore.model.dto.kobo.KoboSpanPositionMap; | ||
| import tools.jackson.core.JacksonException; | ||
| import tools.jackson.databind.ObjectMapper; | ||
|
|
||
| @Converter | ||
| public class KoboSpanMapJsonConverter implements AttributeConverter<KoboSpanPositionMap, String> { | ||
|
|
||
| private static final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
|
||
| @Override | ||
| public String convertToDatabaseColumn(KoboSpanPositionMap attribute) { | ||
| if (attribute == null) { | ||
| return null; | ||
| } | ||
| try { | ||
| return objectMapper.writeValueAsString(attribute); | ||
| } catch (JacksonException e) { | ||
| throw new IllegalStateException("Failed to serialize Kobo span map to JSON", e); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public KoboSpanPositionMap convertToEntityAttribute(String dbData) { | ||
| if (dbData == null || dbData.isEmpty()) { | ||
| return null; | ||
| } | ||
| try { | ||
| return objectMapper.readValue(dbData, KoboSpanPositionMap.class); | ||
| } catch (JacksonException e) { | ||
| throw new IllegalStateException("Failed to deserialize Kobo span map from JSON", e); | ||
| } | ||
| } | ||
| } | ||
25 changes: 25 additions & 0 deletions
25
booklore-api/src/main/java/org/booklore/model/dto/kobo/KoboSpanPositionMap.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package org.booklore.model.dto.kobo; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record KoboSpanPositionMap(List<Chapter> chapters) { | ||
|
|
||
| public KoboSpanPositionMap { | ||
| chapters = chapters == null ? List.of() : List.copyOf(chapters); | ||
| } | ||
|
|
||
| public record Chapter(String sourceHref, | ||
| String normalizedHref, | ||
| int spineIndex, | ||
| float globalStartProgress, | ||
| float globalEndProgress, | ||
| List<Span> spans) { | ||
|
|
||
| public Chapter { | ||
| spans = spans == null ? List.of() : List.copyOf(spans); | ||
| } | ||
| } | ||
|
|
||
| public record Span(String id, float progression) { | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
booklore-api/src/main/java/org/booklore/model/entity/KoboSpanMapEntity.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package org.booklore.model.entity; | ||
|
|
||
| import jakarta.persistence.*; | ||
| import lombok.*; | ||
| import org.booklore.convertor.KoboSpanMapJsonConverter; | ||
| import org.booklore.model.dto.kobo.KoboSpanPositionMap; | ||
|
|
||
| import java.time.Instant; | ||
|
|
||
| @Entity | ||
| @Table(name = "kobo_span_map", | ||
| uniqueConstraints = @UniqueConstraint(name = "uk_kobo_span_map_book_file", columnNames = "book_file_id")) | ||
| @Getter | ||
| @Setter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| public class KoboSpanMapEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @OneToOne(fetch = FetchType.LAZY, optional = false) | ||
| @JoinColumn(name = "book_file_id", nullable = false) | ||
| private BookFileEntity bookFile; | ||
|
|
||
| @Column(name = "file_hash", nullable = false, length = 128) | ||
| private String fileHash; | ||
|
|
||
| @Convert(converter = KoboSpanMapJsonConverter.class) | ||
| @Column(name = "span_map_json", nullable = false, columnDefinition = "LONGTEXT") | ||
| private KoboSpanPositionMap spanMap; | ||
|
|
||
| @Column(name = "created_at", nullable = false) | ||
| private Instant createdAt; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
booklore-api/src/main/java/org/booklore/repository/KoboSpanMapRepository.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package org.booklore.repository; | ||
|
|
||
| import org.booklore.model.entity.KoboSpanMapEntity; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.data.jpa.repository.Query; | ||
| import org.springframework.data.repository.query.Param; | ||
| import org.springframework.stereotype.Repository; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
|
|
||
| @Repository | ||
| public interface KoboSpanMapRepository extends JpaRepository<KoboSpanMapEntity, Long> { | ||
|
|
||
| @Query("SELECT ksm FROM KoboSpanMapEntity ksm WHERE ksm.bookFile.id = :bookFileId") | ||
| Optional<KoboSpanMapEntity> findByBookFileId(@Param("bookFileId") Long bookFileId); | ||
|
|
||
| @Query("SELECT ksm FROM KoboSpanMapEntity ksm WHERE ksm.bookFile.id IN :bookFileIds") | ||
| List<KoboSpanMapEntity> findByBookFileIdIn(@Param("bookFileIds") Collection<Long> bookFileIds); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.