diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/LibrarySync.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/LibrarySync.kt index 07a1f08434..7e246f2a42 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/LibrarySync.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/LibrarySync.kt @@ -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, @@ -151,6 +164,7 @@ data class SavedItemSyncResult( hasMoreItems = true, cursor = null, count = 0, + errorString = null, savedItemSlugs = listOf() ) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/LibraryRepository.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/LibraryRepository.kt index 67091e73cf..5b335a3589 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/LibraryRepository.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/LibraryRepository.kt @@ -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 - suspend fun fetchSavedItemContent(slug: String) + suspend fun fetchSavedItemContent(context: Context, slug: String) suspend fun insertAllLabels(labels: List) @@ -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 } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/impl/LibraryRepositoryImpl.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/impl/LibraryRepositoryImpl.kt index 6d3f709bdc..5e4fbc1be0 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/impl/LibraryRepositoryImpl.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/data/repository/impl/LibraryRepositoryImpl.kt @@ -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 } + ) } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SavedItemQuery.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SavedItemQuery.kt index b54fa2b6a5..b124338c41 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SavedItemQuery.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SavedItemQuery.kt @@ -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, diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SearchQuery.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SearchQuery.kt index 2943e85cf5..00322da520 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SearchQuery.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/network/SearchQuery.kt @@ -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 @@ -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 diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/following/FollowingViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/following/FollowingViewModel.kt index a3639d034f..76b4c3cae1 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/following/FollowingViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/following/FollowingViewModel.kt @@ -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) { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt index b2c0c0b379..4357371bd4 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt @@ -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( diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryViewModel.kt index d2b27fc816..6a2bff0448 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryViewModel.kt @@ -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, diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/SearchViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/SearchViewModel.kt index 6a0240a270..fda56889d8 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/SearchViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/SearchViewModel.kt @@ -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(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) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/profile/about/AboutScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/profile/about/AboutScreen.kt index 014eaf8bbf..23e1161642 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/profile/about/AboutScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/profile/about/AboutScreen.kt @@ -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), diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/PDFReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/PDFReaderViewModel.kt index 1d82f0aaff..3ad22f8242 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/PDFReaderViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/PDFReaderViewModel.kt @@ -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(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) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt index 477def25df..6a84f8fcaa 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/reader/WebReaderViewModel.kt @@ -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 = 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, diff --git a/packages/web/next.config.js b/packages/web/next.config.js index 5e6314214f..e556c8223c 100644 --- a/packages/web/next.config.js +++ b/packages/web/next.config.js @@ -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, }, {