Improve PDF downloading on Android

This commit is contained in:
Jackson Harper
2023-10-24 12:36:54 +08:00
parent 9a1ccd46bc
commit 6bce5b5e19
6 changed files with 80 additions and 30 deletions

View File

@ -17,8 +17,8 @@ android {
applicationId "app.omnivore.omnivore"
minSdk 26
targetSdk 33
versionCode 118
versionName "0.0.118"
versionCode 122
versionName "0.0.122"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@ -1,9 +1,15 @@
package app.omnivore.omnivore.networking
import android.util.Log
import app.omnivore.omnivore.graphql.generated.GetArticleQuery
import app.omnivore.omnivore.graphql.generated.type.ContentReader
import app.omnivore.omnivore.persistence.entities.SavedItem
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
import app.omnivore.omnivore.persistence.entities.Highlight
import java.io.File
import java.net.URL
import java.nio.file.Files
import java.nio.file.StandardCopyOption
data class SavedItemQueryResponse(
val item: SavedItem?,
@ -60,7 +66,18 @@ suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
)
}
// TODO: handle errors
var localPDFPath: String? = null
if (article.articleFields.contentReader == ContentReader.PDF) {
// download the PDF and save it locally
// article.articleFields.url
val localFile = File.createTempFile("pdf-" + article.articleFields.id, ".pdf", )
val url = URL(article.articleFields.url)
Log.d("pdf", "creating local file: $localFile")
url.openStream().use { Files.copy(it, localFile.toPath(), StandardCopyOption.REPLACE_EXISTING) }
localPDFPath = localFile.toPath().toString()
}
val savedItem = SavedItem(
savedItemId = article.articleFields.id,
@ -82,7 +99,8 @@ suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
isArchived = article.articleFields.isArchived,
contentReader = article.articleFields.contentReader.rawValue,
content = article.articleFields.content,
wordsCount = article.articleFields.wordsCount
wordsCount = article.articleFields.wordsCount,
localPDFPath = localPDFPath
)
return SavedItemQueryResponse(item = savedItem, highlights, labels = savedItemLabels, state = article.articleFields.state?.rawValue ?: "")

View File

@ -13,7 +13,7 @@ import app.omnivore.omnivore.persistence.entities.*
SavedItemAndSavedItemLabelCrossRef::class,
SavedItemAndHighlightCrossRef::class
],
version = 11
version = 12
)
abstract class AppDatabase : RoomDatabase() {
abstract fun viewerDao(): ViewerDao

View File

@ -40,7 +40,8 @@ data class SavedItem(
@ColumnInfo(typeAffinity = ColumnInfo.BLOB) val pdfData: ByteArray? = null,
var serverSyncStatus: Int = 0,
val tempPDFURL: String? = null,
val wordsCount: Int? = null
val wordsCount: Int? = null,
val localPDFPath: String? = null
// hasMany highlights
// hasMany labels

View File

@ -7,7 +7,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.omnivore.omnivore.DatastoreRepository
import app.omnivore.omnivore.EventTracker
import app.omnivore.omnivore.dataService.DataService
import app.omnivore.omnivore.graphql.generated.type.CreateHighlightInput
import app.omnivore.omnivore.graphql.generated.type.MergeHighlightInput
import app.omnivore.omnivore.graphql.generated.type.UpdateHighlightInput
@ -21,11 +21,16 @@ import com.pspdfkit.document.download.DownloadJob
import com.pspdfkit.document.download.DownloadRequest
import com.pspdfkit.document.download.Progress
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.io.File
import java.lang.Double.max
import java.lang.Double.min
import java.lang.Exception
import java.net.URLEncoder
import java.nio.file.FileSystem
import java.util.*
import javax.inject.Inject
@ -38,8 +43,8 @@ data class PDFReaderParams(
@HiltViewModel
class PDFReaderViewModel @Inject constructor(
private val datastoreRepo: DatastoreRepository,
private val networker: Networker,
private val eventTracker: EventTracker,
private val dataService: DataService,
private val networker: Networker
): ViewModel() {
var annotationUnderNoteEdit: Annotation? = null
val pdfReaderParamsLiveData = MutableLiveData<PDFReaderParams?>(null)
@ -47,21 +52,51 @@ class PDFReaderViewModel @Inject constructor(
fun loadItem(slug: String, context: Context) {
viewModelScope.launch {
loadItemFromDB(slug)
loadItemFromNetwork(slug, context)
}
}
private suspend fun loadItemFromDB(slug: String) {
withContext(Dispatchers.IO) {
val persistedItem = dataService.db.savedItemDao().getSavedItemWithLabelsAndHighlights(slug)
persistedItem?.let { persistedItem ->
persistedItem?.savedItem?.localPDF?.let { localPDF ->
val localFile = File(localPDF)
if (localFile.exists()) {
val articleContent = ArticleContent(
title = persistedItem.savedItem.title,
htmlContent = "",
highlights = persistedItem.highlights,
contentStatus = "SUCCEEDED",
objectID = "",
labelsJSONString = Gson().toJson(persistedItem.labels)
)
pdfReaderParamsLiveData.postValue(
PDFReaderParams(
persistedItem.savedItem,
articleContent,
Uri.fromFile(localFile)
)
)
}
}
}
}
}
private suspend fun loadItemFromNetwork(slug: String, context: Context) {
withContext(Dispatchers.IO) {
val articleQueryResult = networker.savedItem(slug)
val article = articleQueryResult.item ?: return@launch
val article = articleQueryResult.item ?: return@withContext
val request = DownloadRequest.Builder(context)
.uri(article.pageURLString)
.build()
val job = DownloadJob.startDownload(request)
job.setProgressListener(object : DownloadJob.ProgressListenerAdapter() {
override fun onProgress(progress: Progress) {
// progressBar.setProgress((100f * progress.bytesReceived / progress.totalBytes).toInt())
}
override fun onComplete(output: File) {
val articleContent = ArticleContent(
title = article.title,
@ -72,22 +107,18 @@ class PDFReaderViewModel @Inject constructor(
labelsJSONString = Gson().toJson(articleQueryResult.labels)
)
val pdfReaderParams = PDFReaderParams(article, articleContent, Uri.fromFile(output))
eventTracker.track("link_read",
com.posthog.android.Properties()
.putValue("linkID", pdfReaderParams.item.savedItemId)
.putValue("slug", pdfReaderParams.item.slug)
.putValue("originalArticleURL", pdfReaderParams.item.pageURLString)
.putValue("loaded_from", "network")
)
currentReadingProgress = article.readingProgress
pdfReaderParamsLiveData.postValue(pdfReaderParams)
pdfReaderParamsLiveData.postValue(
PDFReaderParams(
article,
articleContent,
Uri.fromFile(output)
)
)
}
override fun onError(exception: Throwable) {
// handleDownloadError(exception)
// handleDownloadError(exception)
}
})
}

View File

@ -91,7 +91,7 @@ data class WebReaderContent(
url: `${item.pageURLString}`,
title: `${articleContent.title.replace("`", "\\`")}`,
content: document.getElementById('_omnivore-htmlContent').innerHTML,
originalArticleUrl: "${item.pageURLString}",
originalArticleUrl: "${item.publisherURLString}",
contentReader: "WEB",
readingProgressPercent: ${item.readingProgress},
readingProgressAnchorIndex: ${item.readingProgressAnchor},