Skip to content
This repository has been archived by the owner on Jul 29, 2022. It is now read-only.

Use the new LCP renew API #379

Merged
merged 1 commit into from
Feb 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion r2-testapp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
android:name=".comic.ComicActivity"
android:label="@string/title_activity_epub" />
<activity
android:name=".DRMManagementActivity"
android:name=".drm.DRMManagementActivity"
android:label="DRM Management"
android:theme="@style/AppTheme" />
<activity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import org.readium.r2.navigator.audiobook.R2AudiobookActivity
import org.readium.r2.shared.extensions.putPublicationFrom
import org.readium.r2.shared.publication.Locator
import org.readium.r2.shared.publication.services.isProtected
import org.readium.r2.testapp.DRMManagementActivity
import org.readium.r2.testapp.R
import org.readium.r2.testapp.db.Bookmark
import org.readium.r2.testapp.db.BookmarksDatabase
import org.readium.r2.testapp.db.BooksDatabase
import org.readium.r2.testapp.drm.DRMManagementActivity
import org.readium.r2.testapp.library.LibraryActivity
import org.readium.r2.testapp.library.activitiesLaunched
import org.readium.r2.testapp.outline.R2OutlineActivity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,30 @@
* LICENSE file present in the project repository where this source code is maintained.
*/

package org.readium.r2.testapp
package org.readium.r2.testapp.drm

import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.LinearLayout
import android.widget.Spinner
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.mcxiaoke.koi.ext.onClick
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.jetbrains.anko.*
import org.jetbrains.anko.appcompat.v7.Appcompat
import org.jetbrains.anko.design.coordinatorLayout
import org.jetbrains.anko.design.longSnackbar
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import org.readium.r2.shared.UserException
import org.readium.r2.testapp.utils.extensions.color
import org.readium.r2.testapp.R
import java.io.File
import kotlin.coroutines.CoroutineContext

Expand All @@ -57,37 +53,11 @@ class DRMManagementActivity : AppCompatActivity(), CoroutineScope {
val pubPath = intent.getStringExtra("publication")
?: throw Exception("publication required")

drmModel = LCPViewModel(File(pubPath), this)

val daysArray = arrayOf(1, 3, 7, 15)

val daysInput = Spinner(this@DRMManagementActivity)
daysInput.dropDownWidth = wrapContent

val adapter = object : ArrayAdapter<Int>(this@DRMManagementActivity, R.layout.item_spinner_days, daysArray) {
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val v: View? = super.getDropDownView(position, null, parent)
// Makes the selected font appear in dark
// If this is the selected item position
if (position == daysInput.selectedItemPosition) {
v!!.setBackgroundColor(context.color(R.color.colorPrimaryDark))
v.findViewById<TextView>(R.id.days_spinner).setTextColor(Color.WHITE)
} else {
// for other views
v!!.setBackgroundColor(Color.WHITE)
v.findViewById<TextView>(R.id.days_spinner).setTextColor(Color.BLACK)
}
return v
drmModel = runBlocking { LCPViewModel.from(File(pubPath), this@DRMManagementActivity) }
?: run {
finish()
return
}
}

daysInput.adapter = adapter
val renewDialog = alert(Appcompat, "How many days do you wish to extend your loan ?") {
this.customView = daysInput
daysInput.setSelection(2)
positiveButton("Renew") { }
negativeButton("Cancel") { }
}.build()

coordinatorLayout {
fitsSystemWindows = true
Expand Down Expand Up @@ -169,7 +139,7 @@ class DRMManagementActivity : AppCompatActivity(), CoroutineScope {
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
textView {
padding = dip(10)
text = drmModel.issued?.toString(DateTimeFormat.shortDateTime())
text = drmModel.issued?.let { DateTime(it) }?.toString(DateTimeFormat.shortDateTime())
textSize = 18f
gravity = Gravity.END
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
Expand All @@ -185,7 +155,7 @@ class DRMManagementActivity : AppCompatActivity(), CoroutineScope {
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
textView {
padding = dip(10)
text = drmModel.updated?.toString(DateTimeFormat.shortDateTime())
text = drmModel.updated?.let { DateTime(it) }?.toString(DateTimeFormat.shortDateTime())
textSize = 18f
gravity = Gravity.END
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
Expand Down Expand Up @@ -244,7 +214,7 @@ class DRMManagementActivity : AppCompatActivity(), CoroutineScope {
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
textView {
padding = dip(10)
text = drmModel.start?.toString(DateTimeFormat.shortDateTime())
text = drmModel.start?.let { DateTime(it) }?.toString(DateTimeFormat.shortDateTime())
textSize = 18f
gravity = Gravity.END
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
Expand All @@ -261,7 +231,7 @@ class DRMManagementActivity : AppCompatActivity(), CoroutineScope {

endTextView = textView {
padding = dip(10)
text = drmModel.end?.toString(DateTimeFormat.shortDateTime())
text = drmModel.end?.let { DateTime(it) }?.toString(DateTimeFormat.shortDateTime())
textSize = 18f
gravity = Gravity.END
}.lparams(width = wrapContent, height = wrapContent, weight = 1f)
Expand All @@ -277,32 +247,16 @@ class DRMManagementActivity : AppCompatActivity(), CoroutineScope {
button {
text = context.getString(R.string.drm_label_renew)
onClick {
renewDialog.apply {
setCancelable(false)
setCanceledOnTouchOutside(false)
setOnShowListener {
val renewButton = getButton(AlertDialog.BUTTON_POSITIVE)
renewButton.setOnClickListener {

val addDays = daysInput.selectedItem.toString().toInt()
val newEndDate = DateTime(drmModel.end).plusDays(addDays)

launch {
drmModel.renewLoan(newEndDate)
.onSuccess {
dismiss()
endTextView.text =
newEndDate?.toString(DateTimeFormat.shortDateTime())
}.onFailure { exception ->
dismiss()
(exception as? UserException)?.getUserMessage(this@DRMManagementActivity)
?.let { longSnackbar(it) }
}
}
launch {
drmModel.renewLoan()
.onSuccess { newDate ->
endTextView.text = newDate?.let { DateTime(it).toString(DateTimeFormat.shortDateTime()) }
}.onFailure { exception ->
(exception as? UserException)?.getUserMessage(this@DRMManagementActivity)
?.let { longSnackbar(it) }
}
}
}
renewDialog.show()

}
}.lparams(width = matchParent, height = wrapContent, weight = 1f)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
* LICENSE file present in the project repository where this source code is maintained.
*/

package org.readium.r2.testapp
package org.readium.r2.testapp.drm

import android.content.Context
import org.joda.time.DateTime
import org.readium.r2.shared.util.Try
import java.io.Serializable
import java.util.*


abstract class DRMViewModel(val context: Context) : Serializable {
Expand All @@ -24,13 +24,13 @@ abstract class DRMViewModel(val context: Context) : Serializable {

open val provider: String? = null

open val issued: DateTime? = null
open val issued: Date? = null

open val updated: DateTime? = null
open val updated: Date? = null

open val start: DateTime? = null
open val start: Date? = null

open val end: DateTime? = null
open val end: Date? = null

open val copiesLeft: String = "unlimited"

Expand All @@ -39,7 +39,7 @@ abstract class DRMViewModel(val context: Context) : Serializable {
open val canRenewLoan: Boolean
get() = false

open suspend fun renewLoan(end: DateTime?): Try<Unit, Exception> =
open suspend fun renewLoan(): Try<Date?, Exception> =
Try.failure(Exception("Renewing a loan is not supported"))

open val canReturnPublication: Boolean
Expand Down
75 changes: 33 additions & 42 deletions r2-testapp/src/main/java/org/readium/r2/testapp/drm/LCPViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,77 +9,68 @@
* LICENSE file present in the project repository where this source code is maintained.
*/

package org.readium.r2.testapp

import android.net.Uri
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import androidx.browser.customtabs.CustomTabsIntent
import kotlinx.coroutines.runBlocking
import org.joda.time.DateTime
package org.readium.r2.testapp.drm

import androidx.fragment.app.FragmentActivity
import org.readium.r2.lcp.LcpLicense
import org.readium.r2.lcp.LcpService
import org.readium.r2.lcp.MaterialRenewListener
import org.readium.r2.shared.util.Try
import java.io.File
import java.io.Serializable
import java.net.URL
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import java.util.*

class LCPViewModel(val lcpLicense: LcpLicense, val activity: FragmentActivity) : DRMViewModel(activity), Serializable {

class LCPViewModel(val file: File, val activity: ComponentActivity) : DRMViewModel(activity), Serializable {
companion object {

suspend fun from(file: File, activity: FragmentActivity): LCPViewModel? {
val service = LcpService(activity) ?: return null
val license = service.retrieveLicense(file, allowUserInteraction = false)?.getOrNull() ?: return null
return LCPViewModel(license, activity)
}

private val lcpLicense: LcpLicense? = runBlocking {
LcpService(activity)!!
.retrieveLicense(file, allowUserInteraction = false)
?.getOrNull()
}

override val type: String = "LCP"

override val state: String? = lcpLicense?.status?.status?.rawValue
override val state: String? = lcpLicense.status?.status?.rawValue

override val provider: String? = lcpLicense?.license?.provider
override val provider: String? = lcpLicense.license.provider

override val issued: DateTime? = lcpLicense?.license?.issued
override val issued: Date? = lcpLicense.license.issued

override val updated: DateTime? = lcpLicense?.license?.updated
override val updated: Date? = lcpLicense.license.updated

override val start: DateTime? = lcpLicense?.license?.rights?.start
override val start: Date? = lcpLicense.license.rights.start

override val end: DateTime? = lcpLicense?.license?.rights?.end
override val end: Date? = lcpLicense.license.rights.end

override val copiesLeft: String =
lcpLicense?.charactersToCopyLeft
lcpLicense.charactersToCopyLeft
?.let { "$it characters" }
?: super.copiesLeft

override val printsLeft: String =
lcpLicense?.pagesToPrintLeft
lcpLicense.pagesToPrintLeft
?.let { "$it pages" }
?: super.printsLeft

override val canRenewLoan: Boolean = lcpLicense?.canRenewLoan ?: false
override val canRenewLoan: Boolean = lcpLicense.canRenewLoan

override suspend fun renewLoan(end: DateTime?): Try<Unit, Exception> {
val lcpLicense = lcpLicense ?: return super.renewLoan(end)
override suspend fun renewLoan(): Try<Date?, Exception> =
lcpLicense.renewLoan(renewListener)

suspend fun urlPresenter(url: URL): Unit = suspendCoroutine { cont ->
val intent = CustomTabsIntent.Builder().build().intent.apply {
data = Uri.parse(url.toString())
}

val launcher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
cont.resume(Unit)
}
launcher.launch(intent)
}

return lcpLicense.renewLoan(end, ::urlPresenter)
}
private val renewListener = MaterialRenewListener(
license = lcpLicense,
caller = activity,
fragmentManager = activity.supportFragmentManager
)

override val canReturnPublication: Boolean
get() = lcpLicense?.canReturnPublication ?: false
get() = lcpLicense.canReturnPublication

override suspend fun returnPublication(): Try<Unit, Exception> =
lcpLicense?.returnPublication() ?: super.returnPublication()
lcpLicense.returnPublication()

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ import org.readium.r2.shared.publication.presentation.presentation
import org.readium.r2.shared.publication.services.isProtected
import org.readium.r2.shared.publication.services.positions
import org.readium.r2.testapp.BuildConfig.DEBUG
import org.readium.r2.testapp.DRMManagementActivity
import org.readium.r2.testapp.R
import org.readium.r2.testapp.db.*
import org.readium.r2.testapp.drm.DRMManagementActivity
import org.readium.r2.testapp.library.LibraryActivity
import org.readium.r2.testapp.library.activitiesLaunched
import org.readium.r2.testapp.outline.R2OutlineActivity
Expand Down
2 changes: 1 addition & 1 deletion r2-testapp/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
Expand Down