load highlights when pdf is loaded

This commit is contained in:
Satindar Dhillon
2022-10-03 13:20:44 -07:00
parent 634e178e45
commit d89a8d2158
5 changed files with 102 additions and 74 deletions

View File

@ -1,5 +1,14 @@
package app.omnivore.omnivore.models
import android.graphics.Color
import android.graphics.Rect
import android.graphics.RectF
import app.omnivore.omnivore.networking.CreateHighlightParams
import com.google.gson.Gson
import com.pspdfkit.annotations.AnnotationType
import com.pspdfkit.annotations.BlendMode
import com.pspdfkit.annotations.HighlightAnnotation
data class Highlight(
val id: String,
val shortId: String,
@ -11,4 +20,39 @@ data class Highlight(
val createdAt: Any?,
val updatedAt: Any?,
val createdByMe : Boolean,
)
) {
fun asHighlightAnnotation(): HighlightAnnotation {
val highlightPatch = Gson().fromJson(patch, HighlightPatch::class.java)
var highlightAnnotation = HighlightAnnotation(
highlightPatch.pageIndex,
highlightPatch.rectList()
)
highlightAnnotation.color = Color.parseColor(highlightPatch.color)
highlightAnnotation.boundingBox = highlightPatch.boundingBox()
highlightAnnotation.blendMode = BlendMode.MULTIPLY
return highlightAnnotation
}
}
data class HighlightPatch(
val bbox: List<Float>,
val blendMode: String,
val color: String,
val rects: List<List<Float>>,
val pageIndex: Int
) {
fun rectList(): List<RectF> {
return rects.map {
RectF(it[0], it[1], it[2], it[3])
}
}
fun boundingBox(): RectF {
return RectF(bbox[0], bbox[1], bbox[2], bbox[3])
}
}

View File

@ -2,17 +2,24 @@ package app.omnivore.omnivore.ui.reader
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.annotation.UiThread
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import app.omnivore.omnivore.R
import com.google.gson.Gson
import com.pspdfkit.annotations.HighlightAnnotation
import com.pspdfkit.configuration.PdfConfiguration
import com.pspdfkit.configuration.page.PageScrollDirection
import com.pspdfkit.document.PdfDocument
import com.pspdfkit.listeners.DocumentListener
import com.pspdfkit.ui.PdfFragment
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class PDFReaderActivity: AppCompatActivity() {
class PDFReaderActivity: AppCompatActivity(), DocumentListener {
private var hasLoadedHighlights = false
private lateinit var fragment: PdfFragment
val viewModel: PDFReaderViewModel by viewModels()
@ -26,14 +33,7 @@ class PDFReaderActivity: AppCompatActivity() {
// Create the observer which updates the UI.
val pdfParamsObserver = Observer<PDFReaderParams?> { params ->
if (params != null) {
val configuration = PdfConfiguration.Builder()
.scrollDirection(PageScrollDirection.HORIZONTAL)
.build()
// First, try to restore a previously created fragment.
// If no fragment exists, create a new one.
fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer) as PdfFragment?
?: createFragment(params.localFileUri, configuration)
load(params)
}
}
@ -41,6 +41,42 @@ class PDFReaderActivity: AppCompatActivity() {
viewModel.pdfReaderParamsLiveData.observe(this, pdfParamsObserver)
}
private fun load(params: PDFReaderParams) {
val configuration = PdfConfiguration.Builder()
.scrollDirection(PageScrollDirection.HORIZONTAL)
.build()
// First, try to restore a previously created fragment.
// If no fragment exists, create a new one.
fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer) as PdfFragment?
?: createFragment(params.localFileUri, configuration)
fragment.apply {
addDocumentListener(this@PDFReaderActivity)
}
}
@UiThread
override fun onDocumentLoaded(document: PdfDocument) {
if (hasLoadedHighlights) return
hasLoadedHighlights = true
val params = viewModel.pdfReaderParamsLiveData.value
params?.let {
for (highlight in it.articleContent.highlights) {
Log.d("anno", "adding highlight: ${highlight.patch}")
val highlightAnnotation = highlight.asHighlightAnnotation()
Log.d("anno", "created highlight annotation: $highlightAnnotation")
fragment.addAnnotationToPage(highlightAnnotation, true)
}
}
}
private fun createFragment(documentUri: Uri, configuration: PdfConfiguration): PdfFragment {
val fragment = PdfFragment.newInstance(documentUri, configuration)
supportFragmentManager.beginTransaction()

View File

@ -7,7 +7,6 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.omnivore.omnivore.DatastoreRepository
import app.omnivore.omnivore.models.Highlight
import app.omnivore.omnivore.models.LinkedItem
import app.omnivore.omnivore.networking.Networker
import app.omnivore.omnivore.networking.linkedItem
@ -33,6 +32,7 @@ class PDFReaderViewModel @Inject constructor(
private val networker: Networker
): ViewModel() {
val pdfReaderParamsLiveData = MutableLiveData<PDFReaderParams?>(null)
var annotations: List<Annotation> = listOf()
fun loadItem(slug: String, context: Context) {
viewModelScope.launch {
@ -57,7 +57,7 @@ class PDFReaderViewModel @Inject constructor(
val articleContent = ArticleContent(
title = article.title,
htmlContent = article.content ?: "",
highlightsJSONString = Gson().toJson(articleQueryResult.highlights),
highlights = articleQueryResult.highlights,
contentStatus = "SUCCEEDED",
objectID = "",
labelsJSONString = Gson().toJson(articleQueryResult.labels)
@ -76,62 +76,4 @@ class PDFReaderViewModel @Inject constructor(
fun reset() {
pdfReaderParamsLiveData.value = null
}
// fun makePDFAnnotations(highlights: List<Highlight>): List<Annotation> {
// for (highlight in highlights) {
// Annotation()
// }
// }
// private func applyHighlights(documentProvider: PDFDocumentProvider) {
// viewModel.loadHighlightPatches { [weak self] highlightPatches in
// var annnotations: [Annotation] = []
// for patch in highlightPatches {
// guard let data = patch.data(using: String.Encoding.utf8) else { continue }
// let annotation = try? Annotation(fromInstantJSON: data, documentProvider: documentProvider)
// guard let annotation = annotation else { continue }
// annnotations.append(annotation)
// }
// self?.add(annotations: annnotations)
//
// self?.highlightsApplied = true
// }
// }
}
//2022-10-03 08:39:47.903 22564-22564/app.omnivore.omnivore D/anno: highlights:
//[
//Highlight(
// id=877d4e93-a525-4749-83c1-f49b7045ed32,
// shortId=B30zlzGW,
// quote= especially children, men, and strangers, before he is twelve weeks old. Well-socialized puppies grow up to be wonderful companions, whereas antisocial dogs are difficult, time-consuming, and potentially dangerous. Your puppy needs to learn to enjoy the company of all people and to enjoy being handled by all people, especially children and strangers. As a rule of thumb, your puppy needs to meet at least a hundred people before he is three months old. Since your puppy is still too young to venture out on the,
// prefix=null,
// suffix=null,
// patch={
// "bbox": [47.035999298095703, 361.49798583984375, 303.94073486328125, 145.78799438476562],
// "blendMode": "multiply",
// "color": "#FEE832",
// "createdAt": "2022-09-30T03:33:47Z",
// "creatorName": "satindar",
// "customData": {
// "omnivoreHighlight": {
// "articleId": "c2e87313-59ca-48d2-b008-166c16afee63",
// "id": "877d4e93-a525-4749-83c1-f49b7045ed32",
// "quote": " especially children, men, and strangers, before he is twelve weeks old. Well-socialized puppies grow up to be wonderful companions, whereas antisocial dogs are difficult, time-consuming, and potentially dangerous. Your puppy needs to learn to enjoy the company of all people and to enjoy being handled by all people, especially children and strangers. As a rule of thumb, your puppy needs to meet at least a hundred people before he is three months old. Since your puppy is still too young to venture out on the",
// "shortId": "B30zlzGW"
// }
// },
// "name": "FF1F83A7-8D38-4AAA-A882-07A0DD4BAC86",
// "opacity": 1,
// "pageIndex": 5,
// "rects": [[139.03999328613281, 361.49798583984375, 211.30220031738281, 10.788009643554688], [350.34219360351562, 369.70599365234375, 0, 0], [350.34219360351562, 369.70599365234375, 0, 0], [47.035999298095703, 376.49798583984375, 303.61203002929688, 10.788009643554688], [350.64801025390625, 384.70599365234375, 0, 0], [350.64801025390625, 384.70599365234375, 0, 0], [47.155998229980469, 391.49798583984375, 303.5977783203125, 10.788009643554688], [350.75375366210938, 399.70599365234375, 0, 0], [350.75375366210938, 399.70599365234375, 0, 0], [47.324001312255859, 406.49798583984375, 303.64541625976562, 10.788009643554688], [350.96942138671875, 414.70599365234375, 0, 0], [350.96942138671875, 414.70599365234375, 0, 0], [47.057407379150391, 421.49798583984375, 303.53900146484375, 10.787994384765625], [350.59637451171875, 429.70599365234375, 0, 0], [350.59637451171875, 429.70599365234375, 0, 0], [47.297409057617188, 436.49798583984375, 303.57977294921875, 10.787994384765625], [350.87716674804688, 444.70599365234375, 0, 0], [350.87716674804688, 444.70599365234375, 0, 0], [47.609405517578125, 451.49798583984375, 44.86920166015625, 10.787994384765625], [92.478607177734375, 459.70599365234375, 0, 0], [92.478607177734375, 459.70599365234375, 0, 0], [61.577407836914062, 466.49798583984375, 289.39935302734375, 10.787994384765625], [350.97674560546875, 474.70599365234375, 0, 0], [350.97674560546875, 474.70599365234375, 0, 0], [47.10540771484375, 481.49798583984375, 303.55093383789062, 10.787994384765625], [350.65634155273438, 489.70599365234375, 0, 0], [350.65634155273438, 489.70599365234375, 0, 0], [47.189407348632812, 496.49798583984375, 193.45796203613281, 10.787994384765625]], "type": "pspdfkit/markup/highlight", "updatedAt": "2022-09-30T03:33:47Z", "v": 1},
// annotation=null,
// createdAt=null,
// updatedAt=2022-09-30T03:33:48.152Z,
// createdByMe=true),
//
//
//Highlight(id=4c720330-4ea3-41d4-9b7b-031c9b495312, shortId=dYGMMMbz, quote= So, you have your new puppy. Now what? Basically, you are at a fork in the road. The success of the relationship depends on your teaching your puppy the rules and regulations of domestic living. The most critical time in your dog's life is right now—puppyhood! First impressions are indelible and long-lasting. Consequently, prefix=null, suffix=null, patch={"bbox": [46.13800048828125, 194.449951171875, 303.64797973632812, 85.78802490234375], "blendMode": "multiply", "color": "#FEE832", "createdAt": "2022-10-03T15:35:50

View File

@ -1,7 +1,9 @@
package app.omnivore.omnivore.ui.reader
import android.util.Log
import app.omnivore.omnivore.models.Highlight
import app.omnivore.omnivore.models.LinkedItem
import com.google.gson.Gson
enum class WebFont(val displayText: String, val rawValue: String) {
INTER("Inter", "Inter"),
@ -26,11 +28,15 @@ enum class ArticleContentStatus(val rawValue: String) {
data class ArticleContent(
val title: String,
val htmlContent: String,
val highlightsJSONString: String,
val highlights: List<Highlight>,
val contentStatus: String, // ArticleContentStatus,
val objectID: String?, // whatever the Room Equivalent of objectID is
val labelsJSONString: String
)
) {
fun highlightsJSONString(): String {
return Gson().toJson(highlights)
}
}
data class WebReaderContent(
val textFontSize: Int,
@ -86,7 +92,7 @@ data class WebReaderContent(
readingProgressPercent: ${item.readingProgress},
readingProgressAnchorIndex: ${item.readingProgressAnchor},
labels: ${articleContent.labelsJSONString},
highlights: ${articleContent.highlightsJSONString},
highlights: ${articleContent.highlightsJSONString()},
}
window.fontSize = $textFontSize

View File

@ -39,7 +39,7 @@ class WebReaderViewModel @Inject constructor(
val articleContent = ArticleContent(
title = article.title,
htmlContent = article.content ?: "",
highlightsJSONString = Gson().toJson(articleQueryResult.highlights),
highlights = articleQueryResult.highlights,
contentStatus = "SUCCEEDED",
objectID = "",
labelsJSONString = Gson().toJson(articleQueryResult.labels)