Skip to content

Commit

Permalink
Add article_statuses table
Browse files Browse the repository at this point in the history
  • Loading branch information
jocmp committed Dec 30, 2023
1 parent 9b08760 commit eba01ad
Show file tree
Hide file tree
Showing 23 changed files with 352 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import com.jocmp.basil.AccountManager
import com.jocmp.basil.Article
import com.jocmp.basil.Feed
import com.jocmp.basil.FeedFormEntry
import com.jocmp.basil.Filter
import com.jocmp.basil.Folder
import com.jocmp.basil.feedPagingSource
import com.jocmp.basil.buildPager
import com.jocmp.basilreader.selectAccount
import com.jocmp.basilreader.selectedAccount
import kotlinx.coroutines.flow.first
Expand All @@ -29,18 +30,22 @@ class AccountViewModel(
policy = neverEqualPolicy()
)

private val pager: MutableState<Pager<Int, Article>?> = mutableStateOf(null)

init {
viewModelScope.launch {
val accountID = settings.data.first().selectedAccount()

if (accountID != null) {
updateState(accountID)
selectAccount(accountID)
} else {
val firstID = accountManager.accountIDs().firstOrNull()
firstID?.let {
selectAccount(firstID)
selectSettingsAccount(firstID)
}
}

pager.value = account?.buildPager()
}
}

Expand All @@ -54,8 +59,6 @@ class AccountViewModel(

private val articleState = mutableStateOf<Article?>(null)

private val pager = mutableStateOf<Pager<Int, Article>?>(null)

val feeds: List<Feed>
get() = account?.feeds?.toList() ?: emptyList()

Expand All @@ -65,9 +68,16 @@ class AccountViewModel(
fun articles(): Pager<Int, Article>? = pager.value

fun selectFeed(feedID: String, onComplete: () -> Unit) {
this.feedID.value = feedID
val feed = account?.findFeed(feedID)

this.feedID.value = feed?.id

if (feed != null) {
pager.value = account?.buildPager(
filter = Filter.Feeds(feed = feed, status = Filter.Status.ALL),
)
}

pager.value = account?.feedPagingSource(this.feedID.value)
clearArticle()

onComplete()
Expand All @@ -80,20 +90,20 @@ class AccountViewModel(
}

fun selectArticle(articleID: String) {
articleState.value = account?.findArticle(articleID.toLong(), feedID.value?.toLongOrNull())
articleState.value = account?.findArticle(articleID.toLong())
}

fun clearArticle() {
articleState.value = null
}

private fun selectAccount(accountID: String) {
private fun selectSettingsAccount(accountID: String) {
viewModelScope.launch {
settings.selectAccount(accountID)
}
}

private fun updateState(accountID: String) {
private fun selectAccount(accountID: String) {
accountState.value = accountManager.findByID(accountID)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.paging.Pager
import androidx.paging.compose.collectAsLazyPagingItems
import com.jocmp.basil.Article
import kotlinx.coroutines.launch
import java.time.format.DateTimeFormatter

@OptIn(ExperimentalMaterialApi::class)
@Composable
Expand Down Expand Up @@ -61,7 +62,10 @@ fun ArticleList(
}
}
) {
Text(item?.title ?: "No title", fontSize = 20.sp)
item?.let { article ->
Text(article.title, fontSize = 20.sp)
Text(article.arrivedAt.format(DateTimeFormatter.BASIC_ISO_DATE))
}
}
}
}
Expand Down
53 changes: 27 additions & 26 deletions basil/src/main/java/com/jocmp/basil/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package com.jocmp.basil

import com.jocmp.basil.accounts.AccountDelegate
import com.jocmp.basil.accounts.LocalAccountDelegate
import com.jocmp.basil.articles.articleMapper
import com.jocmp.basil.db.Articles
import com.jocmp.basil.accounts.ParsedItem
import com.jocmp.basil.accounts.asOPML
import com.jocmp.basil.db.Database
import com.jocmp.basil.feeds.FeedRecords
import com.jocmp.basil.opml.Outline
import com.jocmp.basil.opml.asFeed
import com.jocmp.basil.opml.asFolder
import com.jocmp.basil.persistence.FeedRecords
import com.jocmp.basil.persistence.articleMapper
import com.jocmp.basil.shared.nowUTC
import com.jocmp.feedfinder.FeedFinder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
Expand Down Expand Up @@ -52,6 +54,10 @@ data class Account(
addAll(folders.flatMap { it.feeds })
}

fun findFeed(feedID: String): Feed? {
return flattenedFeeds.find { it.id == feedID }
}

suspend fun addFolder(title: String): Folder {
val folder = Folder(title = title)

Expand Down Expand Up @@ -87,18 +93,7 @@ data class Account(
launch {
val items = delegate.fetchAll(feed)

items.forEach { item ->
database.articlesQueries.create(
feed_id = feed.primaryKey,
external_id = item.externalID,
title = item.title,
content_html = item.contentHTML,
url = item.url,
summary = item.summary,
image_url = item.imageURL,
published_at = item.publishedAt?.toEpochSecond()
)
}
updateArticles(feed, items)
}
}

Expand Down Expand Up @@ -129,7 +124,22 @@ data class Account(

val items = delegate.fetchAll(feed)

updateArticles(feed, items)
}

fun findArticle(articleID: Long?): Article? {
articleID ?: return null

return database.articlesQueries.findBy(
articleID = articleID,
mapper = ::articleMapper
).executeAsOneOrNull()
}

private fun updateArticles(feed: Feed, items: List<ParsedItem>) {
items.forEach { item ->
val publishedAt = item.publishedAt?.toEpochSecond()

database.articlesQueries.create(
feed_id = feed.primaryKey,
external_id = item.externalID,
Expand All @@ -138,21 +148,12 @@ data class Account(
url = item.url,
summary = item.summary,
image_url = item.imageURL,
published_at = item.publishedAt?.toEpochSecond()
published_at = publishedAt,
arrived_at = publishedAt ?: nowUTC()
)
}
}

fun findArticle(articleID: Long?, feedID: Long?): Article? {
articleID ?: return null

return database.articlesQueries.findBy(
articleID = articleID,
feedID = feedID,
mapper = ::articleMapper
).executeAsOneOrNull()
}

private fun entrySiteURL(url: URL?): String {
return url?.toString() ?: ""
}
Expand Down
19 changes: 19 additions & 0 deletions basil/src/main/java/com/jocmp/basil/AccountPager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.jocmp.basil

import androidx.paging.Pager
import androidx.paging.PagingConfig
import com.jocmp.basil.persistence.ArticlePagerFactory

fun Account.buildPager(
filter: Filter = Filter.Articles(status = Filter.Status.ALL)
): Pager<Int, Article> {
val pagerFactory = ArticlePagerFactory(
database = database,
filter = filter
)

return Pager(
config = PagingConfig(pageSize = 10),
pagingSourceFactory = { pagerFactory.find() }
)
}
4 changes: 3 additions & 1 deletion basil/src/main/java/com/jocmp/basil/Article.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.jocmp.basil

import java.net.URL
import java.time.ZonedDateTime

data class Article(
val id: String,
Expand All @@ -10,5 +11,6 @@ data class Article(
val contentHTML: String,
val url: URL?,
val summary: String,
val imageURL: URL?
val imageURL: URL?,
val arrivedAt: ZonedDateTime
)
28 changes: 0 additions & 28 deletions basil/src/main/java/com/jocmp/basil/ArticlesPagerExt.kt

This file was deleted.

6 changes: 0 additions & 6 deletions basil/src/main/java/com/jocmp/basil/Feed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,3 @@ data class Feed(
return id.hashCode()
}
}

fun Feed.asOPML(indentLevel: Int): String {
val opml =
"<outline text=\"${name}\" title=\"${name}\" description=\"\" type=\"rss\" version=\"RSS\" htmlUrl=\"${siteURL}\" xmlUrl=\"${feedURL}\" basil_id=\"${id}\"/>\n"
return opml.prepending(tabCount = indentLevel)
}
15 changes: 15 additions & 0 deletions basil/src/main/java/com/jocmp/basil/Filter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.jocmp.basil

sealed class Filter(val status: Status) {
enum class Status(value: String) {
ALL("all"),
READ("read"),
STARRED("starred")
}

class Articles(status: Status) : Filter(status)

class Feeds(val feed: Feed, status: Status) : Filter(status)

class Folders(val folder: Folder, status: Status) : Filter(status)
}
18 changes: 0 additions & 18 deletions basil/src/main/java/com/jocmp/basil/Folder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,3 @@ data class Folder(
return 31 * result
}
}

fun Folder.asOPML(indentLevel: Int = 0): String {
if (feeds.isEmpty()) {
val opml = "<outline text=\"${title}\" title=\"${title}\"/>\n"
return opml.prepending(tabCount = indentLevel)
}

var opml = "<outline text=\"${title}\" title=\"${title}\">\n"
opml = opml.prepending(tabCount = indentLevel)

feeds.forEach { feed ->
opml += feed.asOPML(indentLevel = indentLevel + 1)
}

opml = opml + repeatTab(tabCount = indentLevel) + "</outline>\n"

return opml
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.jocmp.basil.accounts

import com.jocmp.basil.Feed
import com.jocmp.basil.feeds.ExternalFeed
import java.net.URL

internal interface AccountDelegate {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jocmp.basil.feeds
package com.jocmp.basil.accounts

internal data class ExternalFeed(
val externalID: String,
Expand Down
10 changes: 10 additions & 0 deletions basil/src/main/java/com/jocmp/basil/accounts/FeedOPMLExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.jocmp.basil.accounts

import com.jocmp.basil.Feed
import com.jocmp.basil.shared.prepending

fun Feed.asOPML(indentLevel: Int): String {
val opml =
"<outline text=\"${name}\" title=\"${name}\" description=\"\" type=\"rss\" version=\"RSS\" htmlUrl=\"${siteURL}\" xmlUrl=\"${feedURL}\" basil_id=\"${id}\"/>\n"
return opml.prepending(tabCount = indentLevel)
}
23 changes: 23 additions & 0 deletions basil/src/main/java/com/jocmp/basil/accounts/FolderOPMLExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.jocmp.basil.accounts

import com.jocmp.basil.Folder
import com.jocmp.basil.shared.prepending
import com.jocmp.basil.shared.repeatTab

internal fun Folder.asOPML(indentLevel: Int = 0): String {
if (feeds.isEmpty()) {
val opml = "<outline text=\"${title}\" title=\"${title}\"/>\n"
return opml.prepending(tabCount = indentLevel)
}

var opml = "<outline text=\"${title}\" title=\"${title}\">\n"
opml = opml.prepending(tabCount = indentLevel)

feeds.forEach { feed ->
opml += feed.asOPML(indentLevel = indentLevel + 1)
}

opml = opml + repeatTab(tabCount = indentLevel) + "</outline>\n"

return opml
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package com.jocmp.basil.accounts

import com.jocmp.basil.Account
import com.jocmp.basil.Feed
import com.jocmp.basil.feeds.ExternalFeed
import com.jocmp.basil.shared.parseISODate
import com.prof18.rssparser.RssParser
import com.prof18.rssparser.model.RssItem
import java.net.URL
import java.time.ZonedDateTime

internal class LocalAccountDelegate(private val account: Account) : AccountDelegate {
override suspend fun createFeed(feedURL: URL): ExternalFeed {
Expand Down
Loading

0 comments on commit eba01ad

Please sign in to comment.