diff --git a/android/Omnivore/app/src/main/AndroidManifest.xml b/android/Omnivore/app/src/main/AndroidManifest.xml
index dfdb231bc..0bbedccff 100644
--- a/android/Omnivore/app/src/main/AndroidManifest.xml
+++ b/android/Omnivore/app/src/main/AndroidManifest.xml
@@ -39,5 +39,15 @@
+
+
+
+
diff --git a/android/Omnivore/app/src/main/assets/test.pdf b/android/Omnivore/app/src/main/assets/test.pdf
new file mode 100644
index 000000000..2887e5b76
Binary files /dev/null and b/android/Omnivore/app/src/main/assets/test.pdf differ
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt
index 2a07a427b..ff2d4f155 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt
@@ -16,6 +16,7 @@ import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import app.omnivore.omnivore.ui.auth.LoginViewModel
import app.omnivore.omnivore.ui.home.HomeViewModel
+import app.omnivore.omnivore.ui.reader.PDFReaderViewModel
import app.omnivore.omnivore.ui.reader.WebReaderViewModel
import app.omnivore.omnivore.ui.root.RootView
import dagger.hilt.android.AndroidEntryPoint
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/models/LinkedItem.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/models/LinkedItem.kt
index 0d5a75efd..960348b8b 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/models/LinkedItem.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/models/LinkedItem.kt
@@ -26,4 +26,9 @@ data class LinkedItem(
fun publisherDisplayName(): String? {
return publisherURLString?.toUri()?.host
}
+
+ fun isPDF(): Boolean {
+ val hasPDFSuffix = pageURLString.endsWith("pdf")
+ return contentReader == "PDF" || hasPDFSuffix
+ }
}
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt
index ed17d858a..54e6ab667 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt
@@ -1,5 +1,6 @@
package app.omnivore.omnivore.ui.home
+import android.content.Intent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
@@ -11,10 +12,12 @@ import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import app.omnivore.omnivore.Routes
import app.omnivore.omnivore.models.LinkedItem
+import app.omnivore.omnivore.ui.reader.PDFReaderActivity
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -53,6 +56,7 @@ fun HomeViewContent(
navController: NavHostController,
modifier: Modifier
) {
+ val context = LocalContext.current
val listState = rememberLazyListState()
val linkedItems: List by homeViewModel.itemsLiveData.observeAsState(listOf())
@@ -69,7 +73,13 @@ fun HomeViewContent(
LinkedItemCard(
item = item,
onClickHandler = {
- navController.navigate("WebReader/${item.slug}")
+ if (item.isPDF()) {
+ val intent = Intent(context, PDFReaderActivity::class.java)
+ intent.putExtra("LINKED_ITEM_SLUG", item.slug)
+ context.startActivity(intent)
+ } else {
+ navController.navigate("WebReader/${item.slug}")
+ }
}
)
}
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt
index e07e2c09d..6fc76e977 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt
@@ -24,7 +24,7 @@ class HomeViewModel @Inject constructor(
private var receivedIdx = 0
// Live Data
- val searchTextLiveData = MutableLiveData("")
+ val searchTextLiveData = MutableLiveData("")
val itemsLiveData = MutableLiveData>(listOf())
fun updateSearchText(text: String) {
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/PDFReader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/PDFReader.kt
new file mode 100644
index 000000000..91a134234
--- /dev/null
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/PDFReader.kt
@@ -0,0 +1,76 @@
+package app.omnivore.omnivore.ui.reader
+
+import android.net.Uri
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import com.pspdfkit.configuration.activity.PdfActivityConfiguration
+import com.pspdfkit.configuration.activity.UserInterfaceViewMode
+import com.pspdfkit.jetpack.compose.DocumentView
+import com.pspdfkit.jetpack.compose.ExperimentalPSPDFKitApi
+import com.pspdfkit.jetpack.compose.rememberDocumentState
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class PDFReaderActivity: AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ val viewModel: PDFReaderViewModel by viewModels()
+
+ super.onCreate(savedInstanceState)
+
+ val slug = intent.getStringExtra("LINKED_ITEM_SLUG") ?: ""
+
+ setContent {
+ PDFReaderLoadingContainer(slug = slug, pdfReaderViewModel = viewModel)
+ }
+ }
+}
+
+@Composable
+fun PDFReaderLoadingContainer(slug: String, pdfReaderViewModel: PDFReaderViewModel) {
+ val pdfReaderParams: PDFReaderParams? by pdfReaderViewModel.pdfReaderParamsLiveData.observeAsState(null)
+
+ if (pdfReaderParams == null) {
+ pdfReaderViewModel.loadItem(slug = slug)
+ }
+
+ if (pdfReaderParams != null) {
+ PDFDocumentView(urlString = pdfReaderParams!!.item.pageURLString)
+ } else {
+ // TODO: add a proper loading view
+ Text("Loading...")
+ }
+}
+
+@OptIn(ExperimentalPSPDFKitApi::class)
+@Composable
+fun PDFDocumentView(urlString: String) {
+ val context = LocalContext.current
+
+ val pdfActivityConfiguration = remember {
+ PdfActivityConfiguration
+ .Builder(context)
+ .setUserInterfaceViewMode(UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_HIDDEN)
+ .build()
+ }
+
+ val pdfDocumentState = rememberDocumentState(
+ documentUri = Uri.parse("file:///android_asset/test.pdf"),
+// documentUri = Uri.parse(urlString),
+ configuration = pdfActivityConfiguration
+ )
+
+ DocumentView(
+ documentState = pdfDocumentState,
+ modifier = Modifier.fillMaxSize()
+ )
+}
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/PDFReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/PDFReaderViewModel.kt
new file mode 100644
index 000000000..b5c1370ad
--- /dev/null
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/PDFReaderViewModel.kt
@@ -0,0 +1,49 @@
+package app.omnivore.omnivore.ui.reader
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import app.omnivore.omnivore.DatastoreRepository
+import app.omnivore.omnivore.models.LinkedItem
+import app.omnivore.omnivore.networking.Networker
+import app.omnivore.omnivore.networking.linkedItem
+import com.google.gson.Gson
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+data class PDFReaderParams(
+ val item: LinkedItem,
+ val articleContent: ArticleContent
+)
+
+@HiltViewModel
+class PDFReaderViewModel @Inject constructor(
+ private val datastoreRepo: DatastoreRepository,
+ private val networker: Networker
+): ViewModel() {
+ val pdfReaderParamsLiveData = MutableLiveData(null)
+
+ fun loadItem(slug: String) {
+ viewModelScope.launch {
+ val articleQueryResult = networker.linkedItem(slug)
+
+ val article = articleQueryResult.item ?: return@launch
+
+ val articleContent = ArticleContent(
+ title = article.title,
+ htmlContent = article.content ?: "",
+ highlightsJSONString = Gson().toJson(articleQueryResult.highlights),
+ contentStatus = "SUCCEEDED",
+ objectID = "",
+ labelsJSONString = Gson().toJson(articleQueryResult.labels)
+ )
+
+ pdfReaderParamsLiveData.value = PDFReaderParams(article, articleContent)
+ }
+ }
+
+ fun reset() {
+ pdfReaderParamsLiveData.value = null
+ }
+}
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt
index c141a78ef..20e3e0439 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt
@@ -17,9 +17,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.viewinterop.AndroidView
import app.omnivore.omnivore.R
-import app.omnivore.omnivore.networking.ReadingProgressParams
import com.google.gson.Gson
-import org.json.JSONObject
@Composable
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt
index 60619015c..c669be8b6 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/root/RootView.kt
@@ -18,10 +18,7 @@ import app.omnivore.omnivore.ui.auth.LoginViewModel
import app.omnivore.omnivore.ui.auth.WelcomeScreen
import app.omnivore.omnivore.ui.home.HomeView
import app.omnivore.omnivore.ui.home.HomeViewModel
-import app.omnivore.omnivore.ui.reader.ArticleWebView
-import app.omnivore.omnivore.ui.reader.WebReader
-import app.omnivore.omnivore.ui.reader.WebReaderLoadingContainer
-import app.omnivore.omnivore.ui.reader.WebReaderViewModel
+import app.omnivore.omnivore.ui.reader.*
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@Composable