Skip to content

Commit

Permalink
Integrate the latest SR2 build
Browse files Browse the repository at this point in the history
This makes the necessary changes to use the latest SR2 version and,
as such, implements support for the new bookmark views. Bookmarks
go through the same system as Readium 1, and the bookmark data
structure has been extended with chapter index and progress
information. Unfortunately, until Readium 1 is removed from the
codebase, we can't make the bookmark data structures as nice as they
could be (currently, every field is optional!).

Affects: https://jira.nypl.org/browse/SIMPLY-2796
  • Loading branch information
io7m committed Aug 7, 2020
1 parent 2e3bbdc commit 15d8033
Show file tree
Hide file tree
Showing 20 changed files with 459 additions and 204 deletions.
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@
indent_size=2
insert_final_newline=true
disabled_rules=import-ordering

[*.gradle]
indent_size=2
insert_final_newline=true

[*.java]
indent_size=2
insert_final_newline=true
35 changes: 9 additions & 26 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,17 @@ buildscript {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:4.3.1"
classpath "com.nabilhachicha:android-native-dependencies:0.1.2"
classpath "com.vanniktech:gradle-android-junit-jacoco-plugin:0.15.0"
classpath "digital.wup:android-maven-publish:3.6.3"
classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.21.2"
}
}

plugins {
id "com.github.ben-manes.versions" version "0.27.0"
id "com.vanniktech.android.junit.jacoco" version "0.15.0"
id "ru.vyarus.animalsniffer" version "1.5.0"

// Deprecated: Migrate to maven-publish.
// https://developer.android.com/studio/build/maven-publish-plugin
id "digital.wup.android-maven-publish" version "3.6.3"
id "io.codearte.nexus-staging" version "0.21.2"
}

ext {
Expand Down Expand Up @@ -82,18 +78,10 @@ ext {
}

nyplAudioBookAPIVersion = "5.0.0"
nyplR2Version = "0.0.5"
}

subprojects {
// Force version 1.0.2 of appcompat. A bug in 1.1.0 causes a crash on API 21.
//
// https://issuetracker.google.com/issues/141132133#comment42
//
// TODO: Remove once appcompat:1.2.0 is available.
configurations.all {
resolutionStrategy.force 'androidx.appcompat:appcompat:1.0.2'
}

//
// We currently have transitive dependencies that specify dependencies on newer versions
// of SLF4J. These are subtly incompatible with Logback-Android, and it will be a while before
Expand All @@ -107,14 +95,15 @@ subprojects {
ext.libraries = [
androidAsync : "com.koushikdutta.async:androidasync:2.2.1",
androidXActivity : "androidx.activity:activity:1.1.0",
androidXAppCompat : "androidx.appcompat:appcompat:1.0.2",
androidXAppCompat : "androidx.appcompat:appcompat:1.2.0-rc01",
androidXCardView : "androidx.cardview:cardview:1.0.0",
androidXConstraintLayout : "androidx.constraintlayout:constraintlayout:1.1.3",
androidXCore : "androidx.core:core:1.1.0",
androidXFragmentTesting : "androidx.fragment:fragment-testing:1.1.0",
androidXLegacyPreferenceV14 : "androidx.legacy:legacy-preference-v14:1.0.0",
androidXLegacySupport : "androidx.legacy:legacy-support-v4:1.0.0",
androidXLifecycle : "androidx.lifecycle:lifecycle-extensions:2.1.0",
androidXLifecycleViewmodel : "androidx.lifecycle:lifecycle-viewmodel:2.1.0",
androidXPaging : "androidx.paging:paging-runtime-ktx:2.1.0",
androidXPreference : "androidx.preference:preference-ktx:1.1.0",
androidXRecyclerView : "androidx.recyclerview:recyclerview:1.1.0",
Expand All @@ -139,8 +128,8 @@ ext.libraries = [
jacksonKotlin : "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9",
javaxAnnotationAPI : "javax.annotation:javax.annotation-api:1.2-b01",
jcipAnnotations : "com.github.stephenc.jcip:jcip-annotations:1.0-1",
jodahExpiringMap : "net.jodah:expiringmap:0.4.3",
jodaTime : "joda-time:joda-time:2.9.9",
jodahExpiringMap : "net.jodah:expiringmap:0.4.3",
junit : "junit:junit:4.12",
kotlinStdlib : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version",
leakCanary : "com.squareup.leakcanary:leakcanary-android:2.1",
Expand All @@ -164,22 +153,16 @@ ext.libraries = [
nyplDRMCore : "org.librarysimplified.drm:org.librarysimplified.drm.core:1.1.1",
nyplPDFAPI : "edu.umn.minitex.pdf:edu.umn.minitex.pdf.api:0.1.0",
nyplPDFViewer : "edu.umn.minitex.pdf:edu.umn.minitex.pdf.pdfviewer:0.1.0",
nyplR2API : "org.librarysimplified.r2:org.librarysimplified.r2.vanilla:${nyplR2Version}",
nyplR2Vanilla : "org.librarysimplified.r2:org.librarysimplified.r2.api:${nyplR2Version}",
nyplR2Views : "org.librarysimplified.r2:org.librarysimplified.r2.views:${nyplR2Version}",
picasso : "com.squareup.picasso:picasso:2.71828",
readium : "org.librarysimplified:org.librarysimplified.readium:0.30.0",
readiumSharedJS : "org.librarysimplified:org.librarysimplified.readium.shared_js:0.30.0",
rxjava2 : "io.reactivex.rxjava2:rxjava:2.1.13",
slf4j : "org.slf4j:slf4j-api:1.7.25"
slf4j : "org.slf4j:slf4j-api:1.7.25",
]

apply plugin: "io.codearte.nexus-staging"
apply plugin: "com.vanniktech.android.junit.jacoco"

nexusStaging {
packageGroup = "org.librarysimplified"
numberOfRetries = 32
delayBetweenRetriesInMillis = 2000
}

allprojects {
group = project.ext["GROUP"]
version = project.ext["VERSION_NAME"]
Expand Down Expand Up @@ -275,7 +258,7 @@ Automatic-Module-Name: ${POM_AUTOMATIC_MODULE_NAME}

default:
throw new IllegalStateException(
"Unrecognized packaging type ${POM_PACKAGING} for ${project}")
"Unrecognized packaging type ${POM_PACKAGING} for ${project}")
}

task javadocsJar(type: Jar) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.nypl.simplified.books.api

/**
* Progress through a specific chapter.
*/

data class BookChapterProgress(

/**
* The index of the chapter.
*/

val chapterIndex: Int,

/**
* The progress through the chapter.
*/

val chapterProgress: Double
)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.nypl.simplified.books.api

import java.io.Serializable

/**
* The current page. A specific location in an EPUB is identified by a chapter index, or an
* *idref* and a *content CFI*. In some cases, the *content CFI*
* may not be present.
*
* Note: The type is [Serializable] purely because the Android API requires this
* in order pass values of this type between activities. We make absolutely no guarantees
* that serialized values of this class will be compatible with future releases.
*/

data class BookLocation(

/**
* The progress through the chapter, if progress is known.
*/

val progress: BookChapterProgress?,

/**
* @return The content CFI, if any
*/

val contentCFI: String?,

/**
* @return The IDRef
*/

val idRef: String?
) : Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ private BookLocationJSON() {
throw new UnreachableCodeException();
}

/**
* Deserialize chapter progress from the given JSON node.
*
* @param jom A JSON object mapper
* @param node A JSON node
* @return A parsed description
* @throws JSONParseException On parse errors
*/

public static BookChapterProgress deserializeProgressFromJSON(
final ObjectMapper jom,
final JsonNode node)
throws JSONParseException {

Objects.requireNonNull(jom, "Object mapper");
Objects.requireNonNull(node, "JSON");

final ObjectNode obj =
JSONParserUtilities.checkObject(null, node);

return new BookChapterProgress(
JSONParserUtilities.getInteger(obj, "chapterIndex"),
JSONParserUtilities.getDouble(obj, "chapterProgress")
);
}

/**
* Deserialize reader book locations from the given JSON node.
*
Expand All @@ -42,10 +68,21 @@ public static BookLocation deserializeFromJSON(

final ObjectNode obj =
JSONParserUtilities.checkObject(null, node);

return BookLocation.create(
JSONParserUtilities.getStringOptional(obj, "contentCFI"),
JSONParserUtilities.getString(obj, "idref"));
final ObjectNode progressNode =
JSONParserUtilities.getObjectOrNull(obj, "progress");

final BookChapterProgress progress;
if (progressNode != null) {
progress = deserializeProgressFromJSON(jom, progressNode);
} else {
progress = null;
}

return new BookLocation(
progress,
JSONParserUtilities.getStringOrNull(obj, "contentCFI"),
JSONParserUtilities.getStringOrNull(obj, "idref")
);
}

/**
Expand All @@ -63,8 +100,22 @@ public static ObjectNode serializeToJSON(
Objects.requireNonNull(description, "Description");

final ObjectNode jo = jom.createObjectNode();
description.contentCFI().map_(cfi -> jo.put("contentCFI", cfi));
jo.put("idref", description.idRef());
final String contentCFI = description.getContentCFI();
if (contentCFI != null) {
jo.put("contentCFI", contentCFI);
}
final String idRef = description.getIdRef();
if (idRef != null) {
jo.put("idref", idRef);
}

final BookChapterProgress progress = description.getProgress();
if (progress != null) {
final ObjectNode progressNode = jom.createObjectNode();
progressNode.put("chapterIndex", progress.getChapterIndex());
progressNode.put("chapterProgress", progress.getChapterProgress());
jo.set("progress", progressNode);
}
return jo;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.nypl.simplified.books.api

import com.io7m.jfunctional.Some
import org.joda.time.LocalDateTime
import java.io.Serializable
import java.net.URI
Expand Down Expand Up @@ -48,12 +47,6 @@ data class Bookmark(

val chapterTitle: String,

/**
* An estimate of the current chapter progress, in the range [0, 1]
*/

val chapterProgress: Double,

/**
* An estimate of the current book progress, in the range [0, 1]
*/
Expand All @@ -73,6 +66,13 @@ data class Bookmark(
val uri: URI?
) : Serializable {

/**
* An estimate of the current chapter progress, in the range [0, 1]
*/

val chapterProgress: Double =
this.location.progress?.chapterProgress ?: 0.0

/**
* The ID of the book to which the bookmark belongs.
*/
Expand Down Expand Up @@ -116,11 +116,22 @@ data class Bookmark(
val messageDigest = MessageDigest.getInstance("SHA-256")
val utf8 = Charset.forName("UTF-8")
messageDigest.update(book.value().toByteArray(utf8))
val cfiOpt = location.contentCFI()
if (cfiOpt is Some<String>) {
messageDigest.update(cfiOpt.get().toByteArray(utf8))

val chapterProgress = location.progress
if (chapterProgress != null) {
messageDigest.update(chapterProgress.chapterIndex.toString().toByteArray(utf8))
val truncatedProgress = String.format("%.6f", chapterProgress.chapterProgress)
messageDigest.update(truncatedProgress.toByteArray(utf8))
}

val cfi = location.contentCFI
if (cfi != null) {
messageDigest.update(cfi.toByteArray(utf8))
}
val idRef = location.idRef
if (idRef != null) {
messageDigest.update(idRef.toByteArray(utf8))
}
messageDigest.update(location.idRef().toByteArray(utf8))
messageDigest.update(kind.motivationURI.toByteArray(utf8))

val digestResult = messageDigest.digest()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ object BookmarkJSON {
location = BookLocationJSON.deserializeFromJSON(objectMapper, JSONParserUtilities.getObject(node, "location")),
time = LocalDateTime.parse(JSONParserUtilities.getString(node, "time")),
chapterTitle = JSONParserUtilities.getString(node, "chapterTitle"),
chapterProgress = JSONParserUtilities.getDouble(node, "chapterProgress"),
bookProgress = JSONParserUtilities.getDouble(node, "bookProgress"),
uri = toNullable(JSONParserUtilities.getURIOptional(node, "uri")),
deviceID = JSONParserUtilities.getStringDefault(node, "deviceID", null))
Expand Down

0 comments on commit 15d8033

Please sign in to comment.