Merge pull request #3974 from omnivore-app/fix/android-content-display
Use internal storage for content files
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
package app.omnivore.omnivore.core.data
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.core.data.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
@ -12,8 +13,8 @@ import app.omnivore.omnivore.core.network.savedItem
|
||||
import app.omnivore.omnivore.core.network.savedItemUpdates
|
||||
import app.omnivore.omnivore.core.network.search
|
||||
|
||||
suspend fun DataService.librarySearch(cursor: String?, query: String): SearchResult {
|
||||
val searchResult = networker.search(cursor = cursor, limit = 10, query = query)
|
||||
suspend fun DataService.librarySearch(context: Context, cursor: String?, query: String): SearchResult {
|
||||
val searchResult = networker.search(context, cursor = cursor, limit = 10, query = query)
|
||||
|
||||
val savedItems = searchResult.items.map {
|
||||
SavedItemWithLabelsAndHighlights(
|
||||
@ -39,7 +40,7 @@ suspend fun DataService.librarySearch(cursor: String?, query: String): SearchRes
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun DataService.sync(since: String, cursor: String?, limit: Int = 20): SavedItemSyncResult {
|
||||
suspend fun DataService.sync(context: Context, since: String, cursor: String?, limit: Int = 20): SavedItemSyncResult {
|
||||
val syncResult = networker.savedItemUpdates(cursor = cursor, limit = limit, since = since)
|
||||
?: return SavedItemSyncResult.errorResult
|
||||
|
||||
@ -48,7 +49,16 @@ suspend fun DataService.sync(since: String, cursor: String?, limit: Int = 20): S
|
||||
}
|
||||
|
||||
val savedItems = syncResult.items.map {
|
||||
saveLibraryItemContentToFile(it.id, it.content)
|
||||
if (!saveLibraryItemContentToFile(context, it.id, it.content)) {
|
||||
return SavedItemSyncResult(
|
||||
hasError = true,
|
||||
errorString = "Error saving page content",
|
||||
hasMoreItems = false,
|
||||
count = 0,
|
||||
cursor = null,
|
||||
savedItemSlugs = listOf()
|
||||
)
|
||||
}
|
||||
val savedItem = SavedItem(
|
||||
savedItemId = it.id,
|
||||
title = it.title,
|
||||
@ -109,25 +119,27 @@ suspend fun DataService.sync(since: String, cursor: String?, limit: Int = 20): S
|
||||
|
||||
Log.d("sync", "found ${syncResult.items.size} items with sync api. Since: $since")
|
||||
|
||||
return SavedItemSyncResult(hasError = false,
|
||||
return SavedItemSyncResult(
|
||||
hasError = false,
|
||||
errorString = null,
|
||||
hasMoreItems = syncResult.hasMoreItems,
|
||||
cursor = syncResult.cursor,
|
||||
count = syncResult.items.size,
|
||||
savedItemSlugs = syncResult.items.map { it.slug })
|
||||
savedItemSlugs = syncResult.items.map { it.slug }
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun DataService.isSavedItemContentStoredInDB(slug: String): Boolean {
|
||||
suspend fun DataService.isSavedItemContentStoredInDB(context: Context, slug: String): Boolean {
|
||||
val existingItem = db.savedItemDao().getSavedItemWithLabelsAndHighlights(slug)
|
||||
existingItem?.savedItem?.savedItemId?.let { savedItemId ->
|
||||
val htmlContent = loadLibraryItemContent(savedItemId)
|
||||
val htmlContent = loadLibraryItemContent(context, savedItemId)
|
||||
return (htmlContent ?: "").length > 10
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
suspend fun DataService.fetchSavedItemContent(slug: String) {
|
||||
val syncResult = networker.savedItem(slug)
|
||||
|
||||
suspend fun DataService.fetchSavedItemContent(context: Context, slug: String) {
|
||||
val syncResult = networker.savedItem(context, slug)
|
||||
val savedItem = syncResult.item
|
||||
savedItem?.let {
|
||||
val item = SavedItemWithLabelsAndHighlights(
|
||||
@ -140,6 +152,7 @@ suspend fun DataService.fetchSavedItemContent(slug: String) {
|
||||
|
||||
data class SavedItemSyncResult(
|
||||
val hasError: Boolean,
|
||||
val errorString: String?,
|
||||
val hasMoreItems: Boolean,
|
||||
val count: Int,
|
||||
val savedItemSlugs: List<String>,
|
||||
@ -151,6 +164,7 @@ data class SavedItemSyncResult(
|
||||
hasMoreItems = true,
|
||||
cursor = null,
|
||||
count = 0,
|
||||
errorString = null,
|
||||
savedItemSlugs = listOf()
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package app.omnivore.omnivore.core.data.repository
|
||||
|
||||
import android.content.Context
|
||||
import app.omnivore.omnivore.core.data.SavedItemSyncResult
|
||||
import app.omnivore.omnivore.core.data.SearchResult
|
||||
import app.omnivore.omnivore.core.data.model.LibraryQuery
|
||||
@ -16,7 +17,7 @@ interface LibraryRepository {
|
||||
|
||||
suspend fun getLabels(): List<SavedItemLabel>
|
||||
|
||||
suspend fun fetchSavedItemContent(slug: String)
|
||||
suspend fun fetchSavedItemContent(context: Context, slug: String)
|
||||
|
||||
suspend fun insertAllLabels(labels: List<SavedItemLabel>)
|
||||
|
||||
@ -30,9 +31,9 @@ interface LibraryRepository {
|
||||
|
||||
suspend fun createNewSavedItemLabel(labelName: String, hexColorValue: String)
|
||||
|
||||
suspend fun librarySearch(cursor: String?, query: String): SearchResult
|
||||
suspend fun librarySearch(context: Context, cursor: String?, query: String): SearchResult
|
||||
|
||||
suspend fun isSavedItemContentStoredInDB(slug: String): Boolean
|
||||
suspend fun isSavedItemContentStoredInDB(context: Context, slug: String): Boolean
|
||||
|
||||
suspend fun deleteSavedItem(itemID: String)
|
||||
|
||||
@ -44,5 +45,5 @@ interface LibraryRepository {
|
||||
|
||||
suspend fun syncHighlightChange(highlightChange: HighlightChange): Boolean
|
||||
|
||||
suspend fun sync(since: String, cursor: String?, limit: Int = 20): SavedItemSyncResult
|
||||
suspend fun sync(context: Context, since: String, cursor: String?, limit: Int = 20): SavedItemSyncResult
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package app.omnivore.omnivore.core.data.repository.impl
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.core.data.DataService
|
||||
import app.omnivore.omnivore.core.data.SavedItemSyncResult
|
||||
@ -81,8 +82,8 @@ class LibraryRepositoryImpl @Inject constructor(
|
||||
savedItemLabelDao.insertAll(labels)
|
||||
}
|
||||
|
||||
override suspend fun fetchSavedItemContent(slug: String) {
|
||||
val syncResult = networker.savedItem(slug)
|
||||
override suspend fun fetchSavedItemContent(context: Context, slug: String) {
|
||||
val syncResult = networker.savedItem(context, slug)
|
||||
|
||||
val savedItem = syncResult.item
|
||||
savedItem?.let {
|
||||
@ -192,9 +193,8 @@ class LibraryRepositoryImpl @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun librarySearch(cursor: String?, query: String): SearchResult {
|
||||
val searchResult = networker.search(cursor = cursor, limit = 10, query = query)
|
||||
|
||||
override suspend fun librarySearch(context: Context, cursor: String?, query: String): SearchResult {
|
||||
val searchResult = networker.search(context = context, cursor = cursor, limit = 10, query = query)
|
||||
val savedItems = searchResult.items.map {
|
||||
SavedItemWithLabelsAndHighlights(
|
||||
savedItem = it.item,
|
||||
@ -219,10 +219,10 @@ class LibraryRepositoryImpl @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun isSavedItemContentStoredInDB(slug: String): Boolean {
|
||||
override suspend fun isSavedItemContentStoredInDB(context: Context, slug: String): Boolean {
|
||||
val existingItem = savedItemDao.getSavedItemWithLabelsAndHighlights(slug)
|
||||
existingItem?.savedItem?.savedItemId?.let { savedItemId ->
|
||||
val htmlContent = loadLibraryItemContent(savedItemId)
|
||||
val htmlContent = loadLibraryItemContent(context, savedItemId)
|
||||
return (htmlContent ?: "").length > 10
|
||||
}
|
||||
return false
|
||||
@ -412,7 +412,7 @@ class LibraryRepositoryImpl @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sync(since: String, cursor: String?, limit: Int): SavedItemSyncResult {
|
||||
override suspend fun sync(context: Context, since: String, cursor: String?, limit: Int): SavedItemSyncResult {
|
||||
val syncResult = networker.savedItemUpdates(cursor = cursor, limit = limit, since = since)
|
||||
?: return SavedItemSyncResult.errorResult
|
||||
|
||||
@ -421,7 +421,7 @@ class LibraryRepositoryImpl @Inject constructor(
|
||||
}
|
||||
|
||||
val savedItems = syncResult.items.map {
|
||||
saveLibraryItemContentToFile(it.id, it.content)
|
||||
saveLibraryItemContentToFile(context, it.id, it.content)
|
||||
val savedItem = SavedItem(
|
||||
savedItemId = it.id,
|
||||
title = it.title,
|
||||
@ -482,10 +482,13 @@ class LibraryRepositoryImpl @Inject constructor(
|
||||
|
||||
Log.d("sync", "found ${syncResult.items.size} items with sync api. Since: $since")
|
||||
|
||||
return SavedItemSyncResult(hasError = false,
|
||||
return SavedItemSyncResult(
|
||||
hasError = false,
|
||||
errorString = null,
|
||||
hasMoreItems = syncResult.hasMoreItems,
|
||||
cursor = syncResult.cursor,
|
||||
count = syncResult.items.size,
|
||||
savedItemSlugs = syncResult.items.map { it.slug })
|
||||
savedItemSlugs = syncResult.items.map { it.slug }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
@ -24,7 +25,7 @@ data class SavedItemQueryResponse(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
|
||||
suspend fun Networker.savedItem(context: Context, slug: String): SavedItemQueryResponse {
|
||||
try {
|
||||
val result = authenticatedApolloClient().query(
|
||||
GetArticleQuery(slug = slug)
|
||||
@ -80,7 +81,7 @@ suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
|
||||
localPDFPath = localFile.toPath().toString()
|
||||
}
|
||||
|
||||
saveLibraryItemContentToFile(article.articleFields.id, article.articleFields.content)
|
||||
saveLibraryItemContentToFile(context, article.articleFields.id, article.articleFields.content)
|
||||
|
||||
val savedItem = SavedItem(
|
||||
savedItemId = article.articleFields.id,
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import android.os.Environment
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.ActivityCompat
|
||||
import app.omnivore.omnivore.core.data.model.ServerSyncStatus
|
||||
import app.omnivore.omnivore.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItem
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.graphql.generated.SearchQuery
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import androidx.core.content.ContextCompat
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Context.MODE_PRIVATE
|
||||
import android.util.Log
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
data class LibrarySearchQueryResponse(
|
||||
val cursor: String?, val items: List<LibrarySearchItem>
|
||||
@ -21,6 +27,7 @@ data class LibrarySearchItem(
|
||||
)
|
||||
|
||||
suspend fun Networker.search(
|
||||
context: Context,
|
||||
cursor: String? = null, limit: Int = 15, query: String
|
||||
): LibrarySearchQueryResponse {
|
||||
try {
|
||||
@ -36,7 +43,7 @@ suspend fun Networker.search(
|
||||
val itemList = result.data?.search?.onSearchSuccess?.edges ?: listOf()
|
||||
|
||||
val searchItems = itemList.map {
|
||||
saveLibraryItemContentToFile(it.node.id, it.node.content)
|
||||
saveLibraryItemContentToFile(context, it.node.id, it.node.content)
|
||||
LibrarySearchItem(item = SavedItem(
|
||||
savedItemId = it.node.id,
|
||||
title = it.node.title,
|
||||
@ -95,12 +102,38 @@ suspend fun Networker.search(
|
||||
}
|
||||
}
|
||||
|
||||
fun saveLibraryItemContentToFile(libraryItemId: String, content: String?): Boolean {
|
||||
//
|
||||
private fun writeToInternalStorage(context: Context, content: String, fileName: String) {
|
||||
try {
|
||||
context.openFileOutput(fileName, MODE_PRIVATE).use { outputStream ->
|
||||
outputStream.write(content.toByteArray())
|
||||
outputStream.flush()
|
||||
Log.d("FileWrite", "File written successfully to internal storage.")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("FileWrite", "Error writing file", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun readFromInternalStorage(context: Context, fileName: String): String? {
|
||||
return try {
|
||||
context.openFileInput(fileName).bufferedReader().useLines { lines ->
|
||||
lines.fold("") { some, text ->
|
||||
"$some\n$text"
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("FileRead", "Error reading file", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun saveLibraryItemContentToFile(context: Context, libraryItemId: String, content: String?): Boolean {
|
||||
return try {
|
||||
content?.let { content ->
|
||||
val directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
|
||||
val file = File(directory, "${libraryItemId}.html")
|
||||
FileOutputStream(file).use { it.write(content.toByteArray()) }
|
||||
writeToInternalStorage(context, content = content, fileName = "${libraryItemId}.html", )
|
||||
return false
|
||||
}
|
||||
false
|
||||
@ -110,15 +143,9 @@ fun saveLibraryItemContentToFile(libraryItemId: String, content: String?): Boole
|
||||
}
|
||||
}
|
||||
|
||||
fun loadLibraryItemContent(libraryItemId: String): String? {
|
||||
fun loadLibraryItemContent(context: Context, libraryItemId: String): String? {
|
||||
return try {
|
||||
val directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
|
||||
val file = File(directory, "${libraryItemId}.html")
|
||||
if (file.exists()) {
|
||||
return FileInputStream(file).bufferedReader().use { it.readText() }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return readFromInternalStorage(context = context, fileName = "${libraryItemId}.html")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@ -91,9 +92,10 @@ class FollowingViewModel @Inject constructor(
|
||||
syncLabels()
|
||||
|
||||
viewModelScope.launch {
|
||||
val context = applicationContext
|
||||
handleFilterChanges()
|
||||
for (slug in contentRequestChannel) {
|
||||
libraryRepository.fetchSavedItemContent(slug)
|
||||
libraryRepository.fetchSavedItemContent(context, slug)
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,7 +150,9 @@ class FollowingViewModel @Inject constructor(
|
||||
|
||||
fun loadUsingSearchAPI() {
|
||||
viewModelScope.launch {
|
||||
val context = applicationContext
|
||||
val result = libraryRepository.librarySearch(
|
||||
context = context,
|
||||
cursor = librarySearchCursor,
|
||||
query = searchQueryString()
|
||||
)
|
||||
@ -156,7 +160,7 @@ class FollowingViewModel @Inject constructor(
|
||||
librarySearchCursor = it
|
||||
}
|
||||
result.savedItems.map {
|
||||
val isSavedInDB = libraryRepository.isSavedItemContentStoredInDB(it.savedItem.slug)
|
||||
val isSavedInDB = libraryRepository.isSavedItemContentStoredInDB(context = applicationContext, it.savedItem.slug)
|
||||
|
||||
if (!isSavedInDB) {
|
||||
delay(2000)
|
||||
@ -257,7 +261,7 @@ class FollowingViewModel @Inject constructor(
|
||||
startTime: String,
|
||||
) {
|
||||
libraryRepository.syncOfflineItemsWithServerIfNeeded()
|
||||
val result = libraryRepository.sync(since = since, cursor = cursor, limit = 20)
|
||||
val result = libraryRepository.sync(context = this.applicationContext, since = since, cursor = cursor, limit = 20)
|
||||
val totalCount = count + result.count
|
||||
|
||||
if (!result.hasError && result.hasMoreItems && result.cursor != null) {
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.FloatTweenSpec
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
@ -56,6 +58,8 @@ import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavHostController
|
||||
@ -76,6 +80,7 @@ import app.omnivore.omnivore.navigation.TopLevelDestination
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.jar.Manifest
|
||||
|
||||
@Composable
|
||||
internal fun LibraryView(
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.*
|
||||
import android.widget.Toast
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@ -33,6 +39,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.time.Instant
|
||||
import java.util.jar.Manifest
|
||||
import javax.inject.Inject
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@ -113,7 +120,8 @@ class LibraryViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
handleFilterChanges()
|
||||
for (slug in contentRequestChannel) {
|
||||
libraryRepository.fetchSavedItemContent(slug)
|
||||
val context = applicationContext
|
||||
libraryRepository.fetchSavedItemContent(context, slug)
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,8 +175,10 @@ class LibraryViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun loadUsingSearchAPI() {
|
||||
val context = applicationContext
|
||||
viewModelScope.launch {
|
||||
val result = libraryRepository.librarySearch(
|
||||
context = context,
|
||||
cursor = librarySearchCursor,
|
||||
query = searchQueryString()
|
||||
)
|
||||
@ -176,7 +186,7 @@ class LibraryViewModel @Inject constructor(
|
||||
librarySearchCursor = it
|
||||
}
|
||||
result.savedItems.map {
|
||||
val isSavedInDB = libraryRepository.isSavedItemContentStoredInDB(it.savedItem.slug)
|
||||
val isSavedInDB = libraryRepository.isSavedItemContentStoredInDB(context, it.savedItem.slug)
|
||||
|
||||
if (!isSavedInDB) {
|
||||
delay(2000)
|
||||
@ -277,9 +287,15 @@ class LibraryViewModel @Inject constructor(
|
||||
) {
|
||||
libraryRepository.syncOfflineItemsWithServerIfNeeded()
|
||||
|
||||
val result = libraryRepository.sync(since = since, cursor = cursor, limit = 20)
|
||||
val result = libraryRepository.sync(context = this.applicationContext, since = since, cursor = cursor, limit = 10)
|
||||
val totalCount = count + result.count
|
||||
|
||||
if (result.hasError) {
|
||||
result.errorString?.let { errorString ->
|
||||
System.out.println("SYNC ERROR: ${errorString}")
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.hasError && result.hasMoreItems && result.cursor != null) {
|
||||
performItemSync(
|
||||
cursor = result.cursor,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package app.omnivore.omnivore.feature.library
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
@ -17,6 +18,7 @@ import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.core.network.Networker
|
||||
import app.omnivore.omnivore.core.network.typeaheadSearch
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
@ -28,7 +30,8 @@ import javax.inject.Inject
|
||||
class SearchViewModel @Inject constructor(
|
||||
private val networker: Networker,
|
||||
private val dataService: DataService,
|
||||
private val datastoreRepo: DatastoreRepository
|
||||
private val datastoreRepo: DatastoreRepository,
|
||||
@ApplicationContext private val applicationContext: Context
|
||||
) : ViewModel(), SavedItemViewModel {
|
||||
private val contentRequestChannel = Channel<String>(capacity = Channel.UNLIMITED)
|
||||
|
||||
@ -76,8 +79,10 @@ class SearchViewModel @Inject constructor(
|
||||
|
||||
private fun loadUsingSearchAPI() {
|
||||
viewModelScope.launch {
|
||||
val context = applicationContext
|
||||
withContext(Dispatchers.IO) {
|
||||
val result = dataService.librarySearch(
|
||||
context = applicationContext,
|
||||
cursor = librarySearchCursor,
|
||||
query = searchQueryString()
|
||||
)
|
||||
@ -86,7 +91,7 @@ class SearchViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
result.savedItems.map {
|
||||
val isSavedInDB = dataService.isSavedItemContentStoredInDB(it.savedItem.slug)
|
||||
val isSavedInDB = dataService.isSavedItemContentStoredInDB(applicationContext, it.savedItem.slug)
|
||||
|
||||
if (!isSavedInDB) {
|
||||
delay(2000)
|
||||
|
||||
@ -132,7 +132,6 @@ internal fun AboutScreen(
|
||||
icon = ImageVector.vectorResource(R.drawable.ic_x),
|
||||
url = "https://x.com/omnivoreapp",
|
||||
)
|
||||
|
||||
LinkIcon(
|
||||
label = "GitHub",
|
||||
icon = ImageVector.vectorResource(R.drawable.ic_github),
|
||||
|
||||
@ -27,6 +27,7 @@ import com.pspdfkit.annotations.HighlightAnnotation
|
||||
import com.pspdfkit.document.download.DownloadJob
|
||||
import com.pspdfkit.document.download.DownloadRequest
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -46,7 +47,8 @@ data class PDFReaderParams(
|
||||
@HiltViewModel
|
||||
class PDFReaderViewModel @Inject constructor(
|
||||
private val dataService: DataService,
|
||||
private val networker: Networker
|
||||
private val networker: Networker,
|
||||
@ApplicationContext private val applicationContext: Context
|
||||
): ViewModel() {
|
||||
var annotationUnderNoteEdit: Annotation? = null
|
||||
val pdfReaderParamsLiveData = MutableLiveData<PDFReaderParams?>(null)
|
||||
@ -91,7 +93,7 @@ class PDFReaderViewModel @Inject constructor(
|
||||
|
||||
private suspend fun loadItemFromNetwork(slug: String, context: Context) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val articleQueryResult = networker.savedItem(slug)
|
||||
val articleQueryResult = networker.savedItem(context = applicationContext, slug)
|
||||
val article = articleQueryResult.item ?: return@withContext
|
||||
val request = DownloadRequest.Builder(context)
|
||||
.uri(article.pageURLString)
|
||||
|
||||
@ -48,6 +48,7 @@ import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
|
||||
import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
@ -92,7 +93,8 @@ class WebReaderViewModel @Inject constructor(
|
||||
private val dataService: DataService,
|
||||
private val networker: Networker,
|
||||
private val eventTracker: EventTracker,
|
||||
private val savedItemDao: SavedItemDao // TODO - Use repo
|
||||
private val savedItemDao: SavedItemDao,
|
||||
@ApplicationContext private val applicationContext: Context
|
||||
) : ViewModel() {
|
||||
var lastJavascriptActionLoopUUID: UUID = UUID.randomUUID()
|
||||
var javascriptDispatchQueue: MutableList<String> = mutableListOf()
|
||||
@ -267,7 +269,7 @@ class WebReaderViewModel @Inject constructor(
|
||||
val persistedItem = dataService.db.savedItemDao().getSavedItemWithLabelsAndHighlights(slug)
|
||||
val savedItemId = persistedItem?.savedItem?.savedItemId
|
||||
if (savedItemId != null) {
|
||||
val htmlContent = loadLibraryItemContent(savedItemId)
|
||||
val htmlContent = loadLibraryItemContent(applicationContext, savedItemId)
|
||||
if (htmlContent != null) {
|
||||
val articleContent = ArticleContent(
|
||||
title = persistedItem.savedItem.title,
|
||||
@ -300,10 +302,10 @@ class WebReaderViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private suspend fun loadItemFromServer(slug: String): WebReaderParams? {
|
||||
val articleQueryResult = networker.savedItem(slug)
|
||||
val articleQueryResult = networker.savedItem(context = applicationContext, slug)
|
||||
|
||||
val article = articleQueryResult.item ?: return null
|
||||
val htmlContent = loadLibraryItemContent(article.savedItemId)
|
||||
val htmlContent = loadLibraryItemContent(applicationContext, article.savedItemId)
|
||||
|
||||
val articleContent = ArticleContent(
|
||||
title = article.title,
|
||||
|
||||
@ -159,7 +159,7 @@ const moduleExports = {
|
||||
{
|
||||
source: '/install/chrome',
|
||||
destination:
|
||||
'https://chrome.google.com/webstore/detail/omnivore/blkggjdmcfjdbmmmlfcpplkchpeaiiab/',
|
||||
'https://chromewebstore.google.com/detail/omnivore/blkggjdmcfjdbmmmlfcpplkchpeaiiab',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user