mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
add logic to display items based on split preference
This commit is contained in:
parent
21bece00c4
commit
3e5f65b430
15 changed files with 273 additions and 235 deletions
|
|
@ -21,6 +21,7 @@ query GetArticle($slug: String!) {
|
|||
fragment ArticleFields on Article {
|
||||
id
|
||||
title
|
||||
folder
|
||||
url
|
||||
author
|
||||
image
|
||||
|
|
|
|||
|
|
@ -1,56 +1,57 @@
|
|||
query Search($after: String, $first: Int, $query: String) {
|
||||
search(first: $first, after: $after, query: $query, includeContent: true) {
|
||||
... on SearchSuccess {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
url
|
||||
pageType
|
||||
contentReader
|
||||
createdAt
|
||||
isArchived
|
||||
readingProgressPercent
|
||||
readingProgressAnchorIndex
|
||||
author
|
||||
image
|
||||
description
|
||||
publishedAt
|
||||
ownedByViewer
|
||||
originalArticleUrl
|
||||
uploadFileId
|
||||
labels {
|
||||
...LabelFields
|
||||
}
|
||||
highlights {
|
||||
...HighlightFields
|
||||
}
|
||||
pageId
|
||||
shortId
|
||||
quote
|
||||
annotation
|
||||
state
|
||||
siteName
|
||||
subscription
|
||||
readAt
|
||||
savedAt
|
||||
updatedAt
|
||||
wordsCount
|
||||
content
|
||||
search(first: $first, after: $after, query: $query, includeContent: true) {
|
||||
... on SearchSuccess {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
url
|
||||
folder
|
||||
pageType
|
||||
contentReader
|
||||
createdAt
|
||||
isArchived
|
||||
readingProgressPercent
|
||||
readingProgressAnchorIndex
|
||||
author
|
||||
image
|
||||
description
|
||||
publishedAt
|
||||
ownedByViewer
|
||||
originalArticleUrl
|
||||
uploadFileId
|
||||
labels {
|
||||
...LabelFields
|
||||
}
|
||||
highlights {
|
||||
...HighlightFields
|
||||
}
|
||||
pageId
|
||||
shortId
|
||||
quote
|
||||
annotation
|
||||
state
|
||||
siteName
|
||||
subscription
|
||||
readAt
|
||||
savedAt
|
||||
updatedAt
|
||||
wordsCount
|
||||
content
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
... on SearchError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
... on SearchError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ query UpdatesSince(
|
|||
node {
|
||||
id
|
||||
title
|
||||
folder
|
||||
slug
|
||||
url
|
||||
pageType
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ suspend fun DataService.sync(since: String, cursor: String?, limit: Int = 20): S
|
|||
val savedItem = SavedItem(
|
||||
savedItemId = it.id,
|
||||
title = it.title,
|
||||
folder = it.folder,
|
||||
createdAt = it.createdAt as String,
|
||||
savedAt = it.savedAt as String,
|
||||
readAt = it.readAt as String?,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package app.omnivore.omnivore.core.data.model
|
||||
|
||||
data class LibraryQuery(
|
||||
val folders: List<String>,
|
||||
val allowedArchiveStates: List<Int>,
|
||||
val sortKey: String,
|
||||
val requiredLabels: List<String>,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class LibraryRepositoryImpl @Inject constructor(
|
|||
|
||||
override fun getSavedItems(query: LibraryQuery): Flow<List<SavedItemWithLabelsAndHighlights>> =
|
||||
savedItemDao.filteredLibraryData(
|
||||
folders = query.folders,
|
||||
query.allowedArchiveStates,
|
||||
query.sortKey,
|
||||
hasRequiredLabels = query.requiredLabels.size,
|
||||
|
|
@ -418,6 +419,7 @@ class LibraryRepositoryImpl @Inject constructor(
|
|||
val savedItem = SavedItem(
|
||||
savedItemId = it.id,
|
||||
title = it.title,
|
||||
folder = it.folder,
|
||||
createdAt = it.createdAt as String,
|
||||
savedAt = it.savedAt as String,
|
||||
readAt = it.readAt as String?,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import app.omnivore.omnivore.core.database.entities.ViewerDao
|
|||
HighlightChange::class,
|
||||
SavedItemAndSavedItemLabelCrossRef::class,
|
||||
SavedItemAndHighlightCrossRef::class],
|
||||
version = 26,
|
||||
version = 27,
|
||||
exportSchema = true
|
||||
)
|
||||
abstract class OmnivoreDatabase : RoomDatabase() {
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ interface SavedItemDao {
|
|||
"LEFT OUTER JOIN Highlight on highlight.highlightId = SavedItemAndHighlightCrossRef.highlightId " +
|
||||
|
||||
"WHERE SavedItem.serverSyncStatus != 2 " +
|
||||
"AND SavedItem.folder IN (:folders) " +
|
||||
"AND SavedItem.isArchived IN (:allowedArchiveStates) " +
|
||||
"AND SavedItem.contentReader IN (:allowedContentReaders) " +
|
||||
"AND CASE WHEN :hasRequiredLabels THEN SavedItemLabel.name in (:requiredLabels) ELSE 1 END " +
|
||||
|
|
@ -97,6 +98,7 @@ interface SavedItemDao {
|
|||
"CASE WHEN :sortKey = 'recentlyPublished' THEN SavedItem.publishDate END DESC"
|
||||
)
|
||||
fun filteredLibraryData(
|
||||
folders: List<String>,
|
||||
allowedArchiveStates: List<Int>,
|
||||
sortKey: String,
|
||||
hasRequiredLabels: Int,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.room.PrimaryKey
|
|||
data class SavedItem(
|
||||
@PrimaryKey val savedItemId: String,
|
||||
val title: String,
|
||||
val folder: String,
|
||||
val createdAt: String,
|
||||
val savedAt: String,
|
||||
val readAt: String?,
|
||||
|
|
@ -71,12 +72,10 @@ data class TypeaheadCardData(
|
|||
)
|
||||
|
||||
object SavedItemQueryConstants {
|
||||
const val columns =
|
||||
"savedItemId, slug, publisherURLString, title, author, descriptionText, imageURLString, isArchived, pageURLString, contentReader, savedAt, readingProgress, wordsCount"
|
||||
const val libraryColumns = "SavedItem.savedItemId, " +
|
||||
"SavedItem.slug, " +
|
||||
"SavedItem.createdAt, " +
|
||||
|
||||
"SavedItem.folder, " +
|
||||
"SavedItem.publisherURLString, " +
|
||||
"SavedItem.title, " +
|
||||
"SavedItem.author, " +
|
||||
|
|
|
|||
|
|
@ -1,110 +1,117 @@
|
|||
package app.omnivore.omnivore.core.network
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.graphql.generated.GetArticleQuery
|
||||
import app.omnivore.omnivore.graphql.generated.type.ContentReader
|
||||
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.core.database.entities.Highlight
|
||||
import app.omnivore.omnivore.graphql.generated.GetArticleQuery
|
||||
import app.omnivore.omnivore.graphql.generated.type.ContentReader
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
|
||||
data class SavedItemQueryResponse(
|
||||
val item: SavedItem?,
|
||||
val highlights: List<Highlight>,
|
||||
val labels: List<SavedItemLabel>,
|
||||
val state: String
|
||||
val item: SavedItem?,
|
||||
val highlights: List<Highlight>,
|
||||
val labels: List<SavedItemLabel>,
|
||||
val state: String
|
||||
) {
|
||||
companion object {
|
||||
fun emptyResponse(): SavedItemQueryResponse {
|
||||
return SavedItemQueryResponse(null, listOf(), listOf(), state = "")
|
||||
companion object {
|
||||
fun emptyResponse(): SavedItemQueryResponse {
|
||||
return SavedItemQueryResponse(null, listOf(), listOf(), state = "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun Networker.savedItem(slug: String): SavedItemQueryResponse {
|
||||
try {
|
||||
val result = authenticatedApolloClient().query(
|
||||
GetArticleQuery(slug = slug)
|
||||
).execute()
|
||||
try {
|
||||
val result = authenticatedApolloClient().query(
|
||||
GetArticleQuery(slug = slug)
|
||||
).execute()
|
||||
|
||||
val article = result.data?.article?.onArticleSuccess?.article
|
||||
?: return SavedItemQueryResponse.emptyResponse()
|
||||
val article = result.data?.article?.onArticleSuccess?.article
|
||||
?: return SavedItemQueryResponse.emptyResponse()
|
||||
|
||||
val labels = article.labels ?: listOf()
|
||||
val labels = article.labels ?: listOf()
|
||||
|
||||
val savedItemLabels = labels.map {
|
||||
SavedItemLabel(
|
||||
savedItemLabelId = it.labelFields.id,
|
||||
name = it.labelFields.name,
|
||||
color = it.labelFields.color,
|
||||
createdAt = it.labelFields.createdAt as String?,
|
||||
labelDescription = it.labelFields.description
|
||||
)
|
||||
}
|
||||
val savedItemLabels = labels.map {
|
||||
SavedItemLabel(
|
||||
savedItemLabelId = it.labelFields.id,
|
||||
name = it.labelFields.name,
|
||||
color = it.labelFields.color,
|
||||
createdAt = it.labelFields.createdAt as String?,
|
||||
labelDescription = it.labelFields.description
|
||||
)
|
||||
}
|
||||
|
||||
val highlights = article.highlights.map {
|
||||
val highlights = article.highlights.map {
|
||||
// val updatedAtString = it.highlightFields.updatedAt as? String
|
||||
|
||||
Highlight(
|
||||
highlightId = it.highlightFields.id,
|
||||
type = it.highlightFields.type.toString(),
|
||||
shortId = it.highlightFields.shortId,
|
||||
quote = it.highlightFields.quote,
|
||||
prefix = it.highlightFields.prefix,
|
||||
suffix = it.highlightFields.suffix,
|
||||
patch = it.highlightFields.patch,
|
||||
annotation = it.highlightFields.annotation,
|
||||
createdAt = it.highlightFields.createdAt as String?,
|
||||
updatedAt = it.highlightFields.updatedAt as String?,
|
||||
createdByMe = it.highlightFields.createdByMe,
|
||||
color = it.highlightFields.color,
|
||||
highlightPositionPercent = it.highlightFields.highlightPositionPercent,
|
||||
highlightPositionAnchorIndex = it.highlightFields.highlightPositionAnchorIndex
|
||||
)
|
||||
Highlight(
|
||||
highlightId = it.highlightFields.id,
|
||||
type = it.highlightFields.type.toString(),
|
||||
shortId = it.highlightFields.shortId,
|
||||
quote = it.highlightFields.quote,
|
||||
prefix = it.highlightFields.prefix,
|
||||
suffix = it.highlightFields.suffix,
|
||||
patch = it.highlightFields.patch,
|
||||
annotation = it.highlightFields.annotation,
|
||||
createdAt = it.highlightFields.createdAt as String?,
|
||||
updatedAt = it.highlightFields.updatedAt as String?,
|
||||
createdByMe = it.highlightFields.createdByMe,
|
||||
color = it.highlightFields.color,
|
||||
highlightPositionPercent = it.highlightFields.highlightPositionPercent,
|
||||
highlightPositionAnchorIndex = it.highlightFields.highlightPositionAnchorIndex
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
title = article.articleFields.title,
|
||||
folder = article.articleFields.folder,
|
||||
createdAt = article.articleFields.createdAt as String,
|
||||
savedAt = article.articleFields.savedAt as String,
|
||||
readAt = article.articleFields.readAt as String?,
|
||||
updatedAt = article.articleFields.updatedAt as String?,
|
||||
readingProgress = article.articleFields.readingProgressPercent,
|
||||
readingProgressAnchor = article.articleFields.readingProgressAnchorIndex,
|
||||
imageURLString = article.articleFields.image,
|
||||
pageURLString = article.articleFields.url,
|
||||
descriptionText = article.articleFields.description,
|
||||
publisherURLString = article.articleFields.originalArticleUrl,
|
||||
siteName = article.articleFields.siteName,
|
||||
author = article.articleFields.author,
|
||||
publishDate = article.articleFields.publishedAt as String?,
|
||||
slug = article.articleFields.slug,
|
||||
isArchived = article.articleFields.isArchived,
|
||||
contentReader = article.articleFields.contentReader.rawValue,
|
||||
content = article.articleFields.content,
|
||||
wordsCount = article.articleFields.wordsCount,
|
||||
localPDFPath = localPDFPath
|
||||
)
|
||||
|
||||
return SavedItemQueryResponse(
|
||||
item = savedItem,
|
||||
highlights,
|
||||
labels = savedItemLabels,
|
||||
state = article.articleFields.state?.rawValue ?: ""
|
||||
)
|
||||
} catch (e: java.lang.Exception) {
|
||||
return SavedItemQueryResponse(item = null, listOf(), labels = listOf(), state = "")
|
||||
}
|
||||
|
||||
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,
|
||||
title = article.articleFields.title,
|
||||
createdAt = article.articleFields.createdAt as String,
|
||||
savedAt = article.articleFields.savedAt as String,
|
||||
readAt = article.articleFields.readAt as String?,
|
||||
updatedAt = article.articleFields.updatedAt as String?,
|
||||
readingProgress = article.articleFields.readingProgressPercent,
|
||||
readingProgressAnchor = article.articleFields.readingProgressAnchorIndex,
|
||||
imageURLString = article.articleFields.image,
|
||||
pageURLString = article.articleFields.url,
|
||||
descriptionText = article.articleFields.description,
|
||||
publisherURLString = article.articleFields.originalArticleUrl,
|
||||
siteName = article.articleFields.siteName,
|
||||
author = article.articleFields.author,
|
||||
publishDate = article.articleFields.publishedAt as String?,
|
||||
slug = article.articleFields.slug,
|
||||
isArchived = article.articleFields.isArchived,
|
||||
contentReader = article.articleFields.contentReader.rawValue,
|
||||
content = article.articleFields.content,
|
||||
wordsCount = article.articleFields.wordsCount,
|
||||
localPDFPath = localPDFPath
|
||||
)
|
||||
|
||||
return SavedItemQueryResponse(item = savedItem, highlights, labels = savedItemLabels, state = article.articleFields.state?.rawValue ?: "")
|
||||
} catch (e: java.lang.Exception) {
|
||||
return SavedItemQueryResponse(item = null, listOf(), labels = listOf(), state = "")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,100 +1,91 @@
|
|||
package app.omnivore.omnivore.core.network
|
||||
|
||||
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 app.omnivore.omnivore.core.data.model.ServerSyncStatus
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
|
||||
data class LibrarySearchQueryResponse(
|
||||
val cursor: String?,
|
||||
val items: List<LibrarySearchItem>
|
||||
val cursor: String?, val items: List<LibrarySearchItem>
|
||||
)
|
||||
|
||||
data class LibrarySearchItem(
|
||||
val item: SavedItem,
|
||||
val labels: List<SavedItemLabel>,
|
||||
val highlights: List<Highlight>
|
||||
val item: SavedItem, val labels: List<SavedItemLabel>, val highlights: List<Highlight>
|
||||
)
|
||||
|
||||
suspend fun Networker.search(
|
||||
cursor: String? = null,
|
||||
limit: Int = 15,
|
||||
query: String
|
||||
cursor: String? = null, limit: Int = 15, query: String
|
||||
): LibrarySearchQueryResponse {
|
||||
try {
|
||||
val result = authenticatedApolloClient().query(
|
||||
SearchQuery(
|
||||
after = Optional.presentIfNotNull(cursor),
|
||||
first = Optional.presentIfNotNull(limit),
|
||||
query = Optional.presentIfNotNull(query)
|
||||
)
|
||||
).execute()
|
||||
try {
|
||||
val result = authenticatedApolloClient().query(
|
||||
SearchQuery(
|
||||
after = Optional.presentIfNotNull(cursor),
|
||||
first = Optional.presentIfNotNull(limit),
|
||||
query = Optional.presentIfNotNull(query)
|
||||
)
|
||||
).execute()
|
||||
|
||||
val newCursor = result.data?.search?.onSearchSuccess?.pageInfo?.endCursor
|
||||
val itemList = result.data?.search?.onSearchSuccess?.edges ?: listOf()
|
||||
val newCursor = result.data?.search?.onSearchSuccess?.pageInfo?.endCursor
|
||||
val itemList = result.data?.search?.onSearchSuccess?.edges ?: listOf()
|
||||
|
||||
val searchItems = itemList.map {
|
||||
LibrarySearchItem(
|
||||
item = SavedItem(
|
||||
savedItemId = it.node.id,
|
||||
title = it.node.title,
|
||||
createdAt = it.node.createdAt as String,
|
||||
savedAt = it.node.savedAt as String,
|
||||
readAt = it.node.readAt as String?,
|
||||
updatedAt = it.node.updatedAt as String?,
|
||||
readingProgress = it.node.readingProgressPercent,
|
||||
readingProgressAnchor = it.node.readingProgressAnchorIndex,
|
||||
imageURLString = it.node.image,
|
||||
pageURLString = it.node.url,
|
||||
descriptionText = it.node.description,
|
||||
publisherURLString = it.node.originalArticleUrl,
|
||||
siteName = it.node.siteName,
|
||||
author = it.node.author,
|
||||
publishDate = it.node.publishedAt as String?,
|
||||
slug = it.node.slug,
|
||||
isArchived = it.node.isArchived,
|
||||
contentReader = it.node.contentReader.rawValue,
|
||||
content = it.node.content,
|
||||
wordsCount = it.node.wordsCount,
|
||||
),
|
||||
labels = (it.node.labels ?: listOf()).map { label ->
|
||||
SavedItemLabel(
|
||||
savedItemLabelId = label.labelFields.id,
|
||||
name = label.labelFields.name,
|
||||
color = label.labelFields.color,
|
||||
createdAt = label.labelFields.createdAt as String?,
|
||||
labelDescription = null
|
||||
)
|
||||
},
|
||||
highlights = (it.node.highlights ?: listOf()).map { highlight ->
|
||||
Highlight(
|
||||
highlightId = highlight.highlightFields.id,
|
||||
type = highlight.highlightFields.type.toString(),
|
||||
annotation = highlight.highlightFields.annotation,
|
||||
createdByMe = highlight.highlightFields.createdByMe,
|
||||
patch = highlight.highlightFields.patch,
|
||||
prefix = highlight.highlightFields.prefix,
|
||||
quote = highlight.highlightFields.quote,
|
||||
serverSyncStatus = ServerSyncStatus.IS_SYNCED.rawValue,
|
||||
shortId = highlight.highlightFields.shortId,
|
||||
suffix = highlight.highlightFields.suffix,
|
||||
updatedAt = highlight.highlightFields.updatedAt as String?,
|
||||
createdAt = highlight.highlightFields.createdAt as String?,
|
||||
color = highlight.highlightFields.color,
|
||||
highlightPositionPercent = highlight.highlightFields.highlightPositionPercent,
|
||||
highlightPositionAnchorIndex = highlight.highlightFields.highlightPositionAnchorIndex
|
||||
)
|
||||
val searchItems = itemList.map {
|
||||
LibrarySearchItem(item = SavedItem(
|
||||
savedItemId = it.node.id,
|
||||
title = it.node.title,
|
||||
folder = it.node.folder,
|
||||
createdAt = it.node.createdAt as String,
|
||||
savedAt = it.node.savedAt as String,
|
||||
readAt = it.node.readAt as String?,
|
||||
updatedAt = it.node.updatedAt as String?,
|
||||
readingProgress = it.node.readingProgressPercent,
|
||||
readingProgressAnchor = it.node.readingProgressAnchorIndex,
|
||||
imageURLString = it.node.image,
|
||||
pageURLString = it.node.url,
|
||||
descriptionText = it.node.description,
|
||||
publisherURLString = it.node.originalArticleUrl,
|
||||
siteName = it.node.siteName,
|
||||
author = it.node.author,
|
||||
publishDate = it.node.publishedAt as String?,
|
||||
slug = it.node.slug,
|
||||
isArchived = it.node.isArchived,
|
||||
contentReader = it.node.contentReader.rawValue,
|
||||
content = it.node.content,
|
||||
wordsCount = it.node.wordsCount
|
||||
), labels = (it.node.labels ?: listOf()).map { label ->
|
||||
SavedItemLabel(
|
||||
savedItemLabelId = label.labelFields.id,
|
||||
name = label.labelFields.name,
|
||||
color = label.labelFields.color,
|
||||
createdAt = label.labelFields.createdAt as String?,
|
||||
labelDescription = null
|
||||
)
|
||||
}, highlights = (it.node.highlights ?: listOf()).map { highlight ->
|
||||
Highlight(
|
||||
highlightId = highlight.highlightFields.id,
|
||||
type = highlight.highlightFields.type.toString(),
|
||||
annotation = highlight.highlightFields.annotation,
|
||||
createdByMe = highlight.highlightFields.createdByMe,
|
||||
patch = highlight.highlightFields.patch,
|
||||
prefix = highlight.highlightFields.prefix,
|
||||
quote = highlight.highlightFields.quote,
|
||||
serverSyncStatus = ServerSyncStatus.IS_SYNCED.rawValue,
|
||||
shortId = highlight.highlightFields.shortId,
|
||||
suffix = highlight.highlightFields.suffix,
|
||||
updatedAt = highlight.highlightFields.updatedAt as String?,
|
||||
createdAt = highlight.highlightFields.createdAt as String?,
|
||||
color = highlight.highlightFields.color,
|
||||
highlightPositionPercent = highlight.highlightFields.highlightPositionPercent,
|
||||
highlightPositionAnchorIndex = highlight.highlightFields.highlightPositionAnchorIndex
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return LibrarySearchQueryResponse(
|
||||
cursor = newCursor,
|
||||
items = searchItems
|
||||
)
|
||||
} catch (e: java.lang.Exception) {
|
||||
return LibrarySearchQueryResponse(null, listOf())
|
||||
}
|
||||
return LibrarySearchQueryResponse(
|
||||
cursor = newCursor, items = searchItems
|
||||
)
|
||||
} catch (e: java.lang.Exception) {
|
||||
return LibrarySearchQueryResponse(null, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,9 +55,10 @@ class FollowingViewModel @Inject constructor(
|
|||
|
||||
private val _libraryQuery = MutableStateFlow(
|
||||
LibraryQuery(
|
||||
folders = listOf("following"),
|
||||
allowedArchiveStates = listOf(0),
|
||||
sortKey = "newest",
|
||||
requiredLabels = listOf("Newsletter", "RSS"),
|
||||
requiredLabels = listOf(),
|
||||
excludedLabels = listOf(),
|
||||
allowedContentReaders = listOf("WEB", "PDF", "EPUB")
|
||||
)
|
||||
|
|
@ -148,7 +149,8 @@ class FollowingViewModel @Inject constructor(
|
|||
fun loadUsingSearchAPI() {
|
||||
viewModelScope.launch {
|
||||
val result = libraryRepository.librarySearch(
|
||||
cursor = librarySearchCursor, query = searchQueryString()
|
||||
cursor = librarySearchCursor,
|
||||
query = searchQueryString()
|
||||
)
|
||||
result.cursor?.let {
|
||||
librarySearchCursor = it
|
||||
|
|
@ -225,6 +227,7 @@ class FollowingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
_libraryQuery.value = LibraryQuery(
|
||||
folders = listOf("following"),
|
||||
allowedArchiveStates = allowedArchiveStates,
|
||||
sortKey = sortKey,
|
||||
requiredLabels = requiredLabels,
|
||||
|
|
@ -367,7 +370,7 @@ class FollowingViewModel @Inject constructor(
|
|||
|
||||
private fun searchQueryString(): String {
|
||||
var query =
|
||||
"${appliedFilterState.value?.queryString} ${appliedSortFilterLiveData.value?.queryString}"
|
||||
"${appliedFilterState.value.queryString} ${appliedSortFilterLiveData.value.queryString}"
|
||||
|
||||
activeLabels.value.let {
|
||||
if (it.isNotEmpty()) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import app.omnivore.omnivore.core.data.repository.LibraryRepository
|
|||
import app.omnivore.omnivore.core.database.entities.SavedItemLabel
|
||||
import app.omnivore.omnivore.core.database.entities.SavedItemWithLabelsAndHighlights
|
||||
import app.omnivore.omnivore.core.datastore.DatastoreRepository
|
||||
import app.omnivore.omnivore.core.datastore.followingTabActive
|
||||
import app.omnivore.omnivore.core.datastore.lastUsedSavedItemFilter
|
||||
import app.omnivore.omnivore.core.datastore.lastUsedSavedItemSortFilter
|
||||
import app.omnivore.omnivore.core.datastore.libraryLastSyncTimestamp
|
||||
|
|
@ -37,7 +38,7 @@ import javax.inject.Inject
|
|||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@HiltViewModel
|
||||
class LibraryViewModel @Inject constructor(
|
||||
private val datastoreRepo: DatastoreRepository,
|
||||
private val datastoreRepository: DatastoreRepository,
|
||||
private val libraryRepository: LibraryRepository,
|
||||
@ApplicationContext private val applicationContext: Context
|
||||
) : ViewModel(), SavedItemViewModel {
|
||||
|
|
@ -48,16 +49,42 @@ class LibraryViewModel @Inject constructor(
|
|||
var snackbarMessage by mutableStateOf<String?>(null)
|
||||
private set
|
||||
|
||||
private val folders = MutableStateFlow(listOf<String>())
|
||||
|
||||
private val _libraryQuery = MutableStateFlow(
|
||||
LibraryQuery(
|
||||
folders = folders.value,
|
||||
allowedArchiveStates = listOf(0),
|
||||
sortKey = "newest",
|
||||
requiredLabels = listOf(),
|
||||
excludedLabels = listOf("Newsletter", "RSS"),
|
||||
excludedLabels = listOf(),
|
||||
allowedContentReaders = listOf("WEB", "PDF", "EPUB")
|
||||
)
|
||||
)
|
||||
|
||||
private val followingTabActiveState: StateFlow<Boolean> = datastoreRepository.getBoolean(followingTabActive).stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
initialValue = false
|
||||
)
|
||||
|
||||
private fun updateLibraryQuery() {
|
||||
_libraryQuery.value = _libraryQuery.value.copy(folders = folders.value)
|
||||
}
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
followingTabActiveState.collect { tabActive ->
|
||||
if (tabActive) {
|
||||
folders.value = listOf("inbox")
|
||||
} else {
|
||||
folders.value = listOf("inbox","following")
|
||||
}
|
||||
updateLibraryQuery()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val uiState: StateFlow<LibraryUiState> = _libraryQuery.flatMapLatest { query ->
|
||||
libraryRepository.getSavedItems(query)
|
||||
}.map(LibraryUiState::Success).stateIn(
|
||||
|
|
@ -114,7 +141,7 @@ class LibraryViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getLastSyncTime(): Instant? = runBlocking {
|
||||
datastoreRepo.getString(libraryLastSyncTimestamp)?.let {
|
||||
datastoreRepository.getString(libraryLastSyncTimestamp)?.let {
|
||||
try {
|
||||
return@let Instant.parse(it)
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -142,7 +169,8 @@ class LibraryViewModel @Inject constructor(
|
|||
fun loadUsingSearchAPI() {
|
||||
viewModelScope.launch {
|
||||
val result = libraryRepository.librarySearch(
|
||||
cursor = librarySearchCursor, query = searchQueryString()
|
||||
cursor = librarySearchCursor,
|
||||
query = searchQueryString()
|
||||
)
|
||||
result.cursor?.let {
|
||||
librarySearchCursor = it
|
||||
|
|
@ -160,7 +188,7 @@ class LibraryViewModel @Inject constructor(
|
|||
|
||||
fun updateSavedItemFilter(filter: SavedItemFilter) {
|
||||
viewModelScope.launch {
|
||||
datastoreRepo.putString(lastUsedSavedItemFilter, filter.rawValue)
|
||||
datastoreRepository.putString(lastUsedSavedItemFilter, filter.rawValue)
|
||||
appliedFilterState.value = filter
|
||||
handleFilterChanges()
|
||||
}
|
||||
|
|
@ -168,7 +196,7 @@ class LibraryViewModel @Inject constructor(
|
|||
|
||||
fun updateSavedItemSortFilter(filter: SavedItemSortFilter) {
|
||||
viewModelScope.launch {
|
||||
datastoreRepo.putString(lastUsedSavedItemSortFilter, filter.rawValue)
|
||||
datastoreRepository.putString(lastUsedSavedItemSortFilter, filter.rawValue)
|
||||
appliedSortFilterLiveData.value = filter
|
||||
handleFilterChanges()
|
||||
}
|
||||
|
|
@ -214,10 +242,11 @@ class LibraryViewModel @Inject constructor(
|
|||
|
||||
val excludeLabels = when (appliedFilterState.value) {
|
||||
SavedItemFilter.NON_FEED -> listOf("Newsletter", "RSS")
|
||||
else -> listOf("Newsletter", "RSS")
|
||||
else -> listOf()
|
||||
}
|
||||
|
||||
_libraryQuery.value = LibraryQuery(
|
||||
folders = folders.value,
|
||||
allowedArchiveStates = allowedArchiveStates,
|
||||
sortKey = sortKey,
|
||||
requiredLabels = requiredLabels,
|
||||
|
|
@ -269,7 +298,7 @@ class LibraryViewModel @Inject constructor(
|
|||
isInitialBatch = false
|
||||
)
|
||||
} else {
|
||||
datastoreRepo.putString(libraryLastSyncTimestamp, startTime)
|
||||
datastoreRepository.putString(libraryLastSyncTimestamp, startTime)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ internal fun FiltersScreen(
|
|||
|
||||
SwitchPreferenceWidget(
|
||||
title = stringResource(R.string.hide_following_tab),
|
||||
checked = followingTabActive,
|
||||
onCheckedChanged = { filtersViewModel.setFollowingTabActiveState(it) },
|
||||
checked = !followingTabActive,
|
||||
onCheckedChanged = { filtersViewModel.setFollowingTabActiveState(!it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ fun RootView(
|
|||
val navController = rememberNavController()
|
||||
val followingTabActive by loginViewModel.followingTabActiveState.collectAsStateWithLifecycle()
|
||||
|
||||
val destinations = if (!followingTabActive) {
|
||||
val destinations = if (followingTabActive) {
|
||||
TopLevelDestination.entries
|
||||
} else {
|
||||
TopLevelDestination.entries.filter { it.route != Routes.Following.route }
|
||||
|
|
|
|||
Loading…
Reference in a new issue