diff --git a/android/Omnivore/app/src/main/AndroidManifest.xml b/android/Omnivore/app/src/main/AndroidManifest.xml
index a78d2d2f0..8e8ed979a 100644
--- a/android/Omnivore/app/src/main/AndroidManifest.xml
+++ b/android/Omnivore/app/src/main/AndroidManifest.xml
@@ -51,5 +51,11 @@
android:name=".ui.reader.PDFReaderActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"
android:windowSoftInputMode="adjustNothing" />
+
+
+
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 ededf42ad..2d38bcef9 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
@@ -41,123 +41,6 @@ import kotlinx.coroutines.launch
import java.util.*
import kotlin.math.roundToInt
-
-@Composable
-fun WebReaderLoadingContainer(slug: String, webReaderViewModel: WebReaderViewModel) {
- val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
-
- var isMenuExpanded by remember { mutableStateOf(false) }
- var showWebPreferencesDialog by remember { mutableStateOf(false ) }
-
- val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsLiveData.observeAsState(null)
- val annotation: String? by webReaderViewModel.annotationLiveData.observeAsState(null)
- val shouldPopView: Boolean by webReaderViewModel.shouldPopViewLiveData.observeAsState(false)
-
- val maxToolbarHeight = 48.dp
- val maxToolbarHeightPx = with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() }
- val toolbarHeightPx = remember { mutableStateOf(maxToolbarHeightPx) }
-
- // Create a connection to the nested scroll system and listen to the scroll happening inside child Column
- val nestedScrollConnection = remember {
- object : NestedScrollConnection {
- override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
- val delta = available.y
- val newHeight = toolbarHeightPx.value + delta
- toolbarHeightPx.value = newHeight.coerceIn(0f, maxToolbarHeightPx)
- return Offset.Zero
- }
- }
- }
-
- if (webReaderParams == null) {
- webReaderViewModel.loadItem(slug = slug)
- }
-
- if (webReaderParams != null) {
- Box(
- modifier = Modifier
- .fillMaxSize()
- .nestedScroll(nestedScrollConnection)
- ) {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .verticalScroll(webReaderViewModel.scrollState)
-
- ) {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .requiredHeight(height = maxToolbarHeight)
- ) {
- }
- WebReader(webReaderParams!!, webReaderViewModel.storedWebPreferences(isSystemInDarkTheme()), webReaderViewModel)
- }
-
- TopAppBar(
- modifier = Modifier
- .height(height = with(LocalDensity.current) {
- webReaderViewModel.currentToolbarHeight = toolbarHeightPx.value.toInt()
- toolbarHeightPx.value.roundToInt().toDp()
- } ),
- backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
- title = {},
- actions = {
- // Disabling menu until we implement local persistence
- IconButton(onClick = { isMenuExpanded = true }) {
- Icon(
- imageVector = Icons.Filled.Menu,
- contentDescription = null
- )
- }
- IconButton(onClick = { showWebPreferencesDialog = true }) {
- Icon(
- imageVector = Icons.Filled.Settings, // TODO: set a better icon
- contentDescription = null
- )
- }
- SavedItemContextMenu(
- isExpanded = isMenuExpanded,
- isArchived = webReaderParams!!.item.isArchived,
- onDismiss = { isMenuExpanded = false },
- actionHandler = { webReaderViewModel.handleSavedItemAction(webReaderParams!!.item.savedItemId, it) }
- )
- }
- )
-
- if (showWebPreferencesDialog) {
- WebPreferencesDialog(
- onDismiss = {
- showWebPreferencesDialog = false
- },
- webReaderViewModel = webReaderViewModel
- )
- }
-
- if (annotation != null) {
- AnnotationEditView(
- initialAnnotation = annotation!!,
- onSave = {
- webReaderViewModel.saveAnnotation(it)
- },
- onCancel = {
- webReaderViewModel.cancelAnnotationEdit()
- }
- )
- }
- }
-
- LaunchedEffect(shouldPopView) {
- if (shouldPopView) {
- onBackPressedDispatcher?.onBackPressed()
- }
- }
- } else {
- // TODO: add a proper loading view
- Text("Loading...")
- }
-}
-
@SuppressLint("SetJavaScriptEnabled")
@Composable
fun WebReader(
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt
new file mode 100644
index 000000000..8313adb39
--- /dev/null
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt
@@ -0,0 +1,200 @@
+package app.omnivore.omnivore.ui.reader
+
+import android.graphics.PointF
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
+import androidx.activity.compose.setContent
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.foundation.background
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.TopAppBar
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Menu
+import androidx.compose.material.icons.filled.Settings
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.*
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.dp
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import app.omnivore.omnivore.R
+import app.omnivore.omnivore.ui.root.RootView
+import app.omnivore.omnivore.ui.savedItemViews.SavedItemContextMenu
+import app.omnivore.omnivore.ui.theme.OmnivoreTheme
+import com.pspdfkit.annotations.Annotation
+import com.pspdfkit.annotations.HighlightAnnotation
+import com.pspdfkit.configuration.PdfConfiguration
+import com.pspdfkit.configuration.page.PageScrollDirection
+import com.pspdfkit.listeners.DocumentListener
+import com.pspdfkit.listeners.OnPreparePopupToolbarListener
+import com.pspdfkit.ui.PdfFragment
+import com.pspdfkit.ui.PdfThumbnailBar
+import com.pspdfkit.ui.search.PdfSearchViewModular
+import com.pspdfkit.ui.special_mode.controller.TextSelectionController
+import com.pspdfkit.ui.special_mode.manager.TextSelectionManager
+import dagger.hilt.android.AndroidEntryPoint
+import kotlin.math.roundToInt
+
+
+@AndroidEntryPoint
+class WebReaderLoadingContainerActivity: AppCompatActivity() {
+ val viewModel: WebReaderViewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val requestID = intent.getStringExtra("SAVED_ITEM_REQUEST_ID") ?: ""
+
+ setContent {
+ OmnivoreTheme {
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(color = Color.Black)
+ ) {
+ WebReaderLoadingContainer(requestID = requestID, webReaderViewModel = viewModel)
+ }
+ }
+ }
+
+ // animate the view up when keyboard appears
+ WindowCompat.setDecorFitsSystemWindows(window, false)
+ val rootView = findViewById(android.R.id.content).rootView
+ ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, insets ->
+ val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
+ rootView.setPadding(0, 0, 0, imeHeight)
+ insets
+ }
+ }
+}
+
+@Composable
+fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, webReaderViewModel: WebReaderViewModel) {
+ val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
+
+ var isMenuExpanded by remember { mutableStateOf(false) }
+ var showWebPreferencesDialog by remember { mutableStateOf(false ) }
+
+ val webReaderParams: WebReaderParams? by webReaderViewModel.webReaderParamsLiveData.observeAsState(null)
+ val annotation: String? by webReaderViewModel.annotationLiveData.observeAsState(null)
+ val shouldPopView: Boolean by webReaderViewModel.shouldPopViewLiveData.observeAsState(false)
+
+ val maxToolbarHeight = 48.dp
+ val maxToolbarHeightPx = with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() }
+ val toolbarHeightPx = remember { mutableStateOf(maxToolbarHeightPx) }
+
+ // Create a connection to the nested scroll system and listen to the scroll happening inside child Column
+ val nestedScrollConnection = remember {
+ object : NestedScrollConnection {
+ override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
+ val delta = available.y
+ val newHeight = toolbarHeightPx.value + delta
+ toolbarHeightPx.value = newHeight.coerceIn(0f, maxToolbarHeightPx)
+ return Offset.Zero
+ }
+ }
+ }
+
+ if (webReaderParams == null) {
+ webReaderViewModel.loadItem(slug = slug, requestID = requestID)
+ }
+
+ if (webReaderParams != null) {
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .nestedScroll(nestedScrollConnection)
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .verticalScroll(webReaderViewModel.scrollState)
+
+ ) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .requiredHeight(height = maxToolbarHeight)
+ ) {
+ }
+ WebReader(webReaderParams!!, webReaderViewModel.storedWebPreferences(isSystemInDarkTheme()), webReaderViewModel)
+ }
+
+ TopAppBar(
+ modifier = Modifier
+ .height(height = with(LocalDensity.current) {
+ webReaderViewModel.currentToolbarHeight = toolbarHeightPx.value.toInt()
+ toolbarHeightPx.value.roundToInt().toDp()
+ } ),
+ backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
+ title = {},
+ actions = {
+ // Disabling menu until we implement local persistence
+ IconButton(onClick = { isMenuExpanded = true }) {
+ Icon(
+ imageVector = Icons.Filled.Menu,
+ contentDescription = null
+ )
+ }
+ IconButton(onClick = { showWebPreferencesDialog = true }) {
+ Icon(
+ imageVector = Icons.Filled.Settings, // TODO: set a better icon
+ contentDescription = null
+ )
+ }
+ SavedItemContextMenu(
+ isExpanded = isMenuExpanded,
+ isArchived = webReaderParams!!.item.isArchived,
+ onDismiss = { isMenuExpanded = false },
+ actionHandler = { webReaderViewModel.handleSavedItemAction(webReaderParams!!.item.savedItemId, it) }
+ )
+ }
+ )
+
+ if (showWebPreferencesDialog) {
+ WebPreferencesDialog(
+ onDismiss = {
+ showWebPreferencesDialog = false
+ },
+ webReaderViewModel = webReaderViewModel
+ )
+ }
+
+ if (annotation != null) {
+ AnnotationEditView(
+ initialAnnotation = annotation!!,
+ onSave = {
+ webReaderViewModel.saveAnnotation(it)
+ },
+ onCancel = {
+ webReaderViewModel.cancelAnnotationEdit()
+ }
+ )
+ }
+ }
+
+ LaunchedEffect(shouldPopView) {
+ if (shouldPopView) {
+ onBackPressedDispatcher?.onBackPressed()
+ }
+ }
+ } else {
+ // TODO: add a proper loading view
+ Text("Loading...")
+ }
+}
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt
index affa6166d..eca884c8b 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt
@@ -45,7 +45,12 @@ class WebReaderViewModel @Inject constructor(
var hasTappedExistingHighlight = false
var lastTapCoordinates: TapCoordinates? = null
- fun loadItem(slug: String) {
+ fun loadItem(slug: String?, requestID: String?) {
+ slug?.let { loadItemUsingSlug(it) }
+ requestID?.let { loadItemUsingRequestID(it) }
+ }
+
+ private fun loadItemUsingSlug(slug: String) {
viewModelScope.launch {
val webReaderParams = loadItemFromServer(slug)
@@ -58,6 +63,10 @@ class WebReaderViewModel @Inject constructor(
}
}
+ private fun loadItemUsingRequestID(requestID: String) {
+ // TODO: implement
+ }
+
private suspend fun loadItemFromDB(slug: String) {
withContext(Dispatchers.IO) {
val persistedItem = dataService.db.savedItemDao().getSavedItemWithLabelsAndHighlights(slug)
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt
index ee37a0f52..e0818befe 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveContent.kt
@@ -1,5 +1,7 @@
package app.omnivore.omnivore.ui.save
+import android.content.Intent
+import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
@@ -11,13 +13,18 @@ import androidx.compose.material.*
import androidx.compose.material.ButtonDefaults
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
+import app.omnivore.omnivore.MainActivity
+import app.omnivore.omnivore.ui.reader.PDFReaderActivity
+import app.omnivore.omnivore.ui.reader.WebReaderLoadingContainerActivity
import kotlinx.coroutines.launch
@Composable
@OptIn(ExperimentalMaterialApi::class)
fun SaveContent(viewModel: SaveViewModel, modalBottomSheetState: ModalBottomSheetState, modifier: Modifier) {
val coroutineScope = rememberCoroutineScope()
+ val context = LocalContext.current
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
Column(
@@ -34,7 +41,11 @@ fun SaveContent(viewModel: SaveViewModel, modalBottomSheetState: ModalBottomShee
onClick = {
coroutineScope.launch {
modalBottomSheetState.hide()
- // TODO: open app
+ viewModel.clientRequestID?.let {
+ val intent = Intent(context, WebReaderLoadingContainerActivity::class.java)
+ intent.putExtra("SAVED_ITEM_REQUEST_ID", it)
+ context.startActivity(intent)
+ }
}
},
colors = ButtonDefaults.buttonColors(
diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt
index 0dbdc7222..b02e92f59 100644
--- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt
+++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt
@@ -29,6 +29,9 @@ class SaveViewModel @Inject constructor(
var message by mutableStateOf(null)
private set
+ var clientRequestID by mutableStateOf(null)
+ private set
+
private fun getAuthToken(): String? = runBlocking {
datastoreRepo.getString(DatastoreKeys.omnivoreAuthToken)
}
@@ -52,10 +55,12 @@ class SaveViewModel @Inject constructor(
.build()
try {
+ clientRequestID = UUID.randomUUID().toString()
+
val response = apolloClient.mutation(
SaveUrlMutation(
SaveUrlInput(
- clientRequestId = UUID.randomUUID().toString(),
+ clientRequestId = clientRequestID!!,
source = "android",
url = url
)