load highlights when pdf is loaded
This commit is contained in:
@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user