Modified the database structure and Updated version name

This commit is contained in:
Ash 2022-04-06 18:14:22 +08:00
parent 1ba149368b
commit aca2e9c41b
9 changed files with 58 additions and 48 deletions

View File

@ -14,7 +14,7 @@ android {
minSdk 26 minSdk 26
targetSdk 32 targetSdk 32
versionCode 1 versionCode 1
versionName "1.0" versionName "0.6.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {

View File

@ -12,7 +12,7 @@
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 1, "versionCode": 1,
"versionName": "1.0", "versionName": "0.6.1",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],

View File

@ -219,7 +219,7 @@ interface ArticleDao {
""" """
SELECT a.id, a.date, a.title, a.author, a.rawDescription, SELECT a.id, a.date, a.title, a.author, a.rawDescription,
a.shortDescription, a.fullContent, a.link, a.feedId, a.shortDescription, a.fullContent, a.link, a.feedId,
a.accountId, a.isUnread, a.isStarred a.accountId, a.isUnread, a.isStarred, a.isReadLater
FROM article AS a FROM article AS a
LEFT JOIN feed AS b ON b.id = a.feedId LEFT JOIN feed AS b ON b.id = a.feedId
LEFT JOIN `group` AS c ON c.id = b.groupId LEFT JOIN `group` AS c ON c.id = b.groupId
@ -239,7 +239,7 @@ interface ArticleDao {
""" """
SELECT a.id, a.date, a.title, a.author, a.rawDescription, SELECT a.id, a.date, a.title, a.author, a.rawDescription,
a.shortDescription, a.fullContent, a.link, a.feedId, a.shortDescription, a.fullContent, a.link, a.feedId,
a.accountId, a.isUnread, a.isStarred a.accountId, a.isUnread, a.isStarred, a.isReadLater
FROM article AS a FROM article AS a
LEFT JOIN feed AS b ON b.id = a.feedId LEFT JOIN feed AS b ON b.id = a.feedId
LEFT JOIN `group` AS c ON c.id = b.groupId LEFT JOIN `group` AS c ON c.id = b.groupId
@ -261,7 +261,7 @@ interface ArticleDao {
""" """
SELECT a.id, a.date, a.title, a.author, a.rawDescription, SELECT a.id, a.date, a.title, a.author, a.rawDescription,
a.shortDescription, a.fullContent, a.link, a.feedId, a.shortDescription, a.fullContent, a.link, a.feedId,
a.accountId, a.isUnread, a.isStarred a.accountId, a.isUnread, a.isStarred, a.isReadLater
FROM article AS a FROM article AS a
LEFT JOIN feed AS b ON b.id = a.feedId LEFT JOIN feed AS b ON b.id = a.feedId
LEFT JOIN `group` AS c ON c.id = b.groupId LEFT JOIN `group` AS c ON c.id = b.groupId
@ -325,7 +325,7 @@ interface ArticleDao {
""" """
SELECT a.id, a.date, a.title, a.author, a.rawDescription, SELECT a.id, a.date, a.title, a.author, a.rawDescription,
a.shortDescription, a.fullContent, a.link, a.feedId, a.shortDescription, a.fullContent, a.link, a.feedId,
a.accountId, a.isUnread, a.isStarred a.accountId, a.isUnread, a.isStarred, a.isReadLater
FROM article AS a LEFT JOIN feed AS b FROM article AS a LEFT JOIN feed AS b
ON a.feedId = b.id ON a.feedId = b.id
WHERE a.feedId = :feedId WHERE a.feedId = :feedId

View File

@ -41,4 +41,6 @@ data class Article(
var isUnread: Boolean = true, var isUnread: Boolean = true,
@ColumnInfo(defaultValue = "false") @ColumnInfo(defaultValue = "false")
var isStarred: Boolean = false, var isStarred: Boolean = false,
@ColumnInfo(defaultValue = "false")
var isReadLater: Boolean = false,
) )

View File

@ -18,7 +18,7 @@ data class Feed(
@ColumnInfo @ColumnInfo
val name: String, val name: String,
@ColumnInfo @ColumnInfo
var icon: ByteArray? = null, var icon: String? = null,
@ColumnInfo @ColumnInfo
val url: String, val url: String,
@ColumnInfo(index = true) @ColumnInfo(index = true)
@ -32,6 +32,7 @@ data class Feed(
) { ) {
@Ignore @Ignore
var important: Int? = 0 var important: Int? = 0
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false
@ -40,10 +41,7 @@ data class Feed(
if (id != other.id) return false if (id != other.id) return false
if (name != other.name) return false if (name != other.name) return false
if (icon != null) { if (icon != other.icon) return false
if (other.icon == null) return false
if (!icon.contentEquals(other.icon)) return false
} else if (other.icon != null) return false
if (url != other.url) return false if (url != other.url) return false
if (groupId != other.groupId) return false if (groupId != other.groupId) return false
if (accountId != other.accountId) return false if (accountId != other.accountId) return false
@ -57,7 +55,7 @@ data class Feed(
override fun hashCode(): Int { override fun hashCode(): Int {
var result = id.hashCode() var result = id.hashCode()
result = 31 * result + name.hashCode() result = 31 * result + name.hashCode()
result = 31 * result + (icon?.contentHashCode() ?: 0) result = 31 * result + (icon?.hashCode() ?: 0)
result = 31 * result + url.hashCode() result = 31 * result + url.hashCode()
result = 31 * result + groupId.hashCode() result = 31 * result + groupId.hashCode()
result = 31 * result + accountId result = 31 * result + accountId

View File

@ -119,10 +119,11 @@ class RssHelper @Inject constructor(
articleLink: String, articleLink: String,
) { ) {
withContext(dispatcherIO) { withContext(dispatcherIO) {
val execute = OkHttpClient() val domainRegex = Regex("(http|https)://(www.)?(\\w+(\\.)?)+")
val request = OkHttpClient()
.newCall(Request.Builder().url(articleLink).build()) .newCall(Request.Builder().url(articleLink).build())
.execute() .execute()
val content = execute.body!!.string() val content = request.body!!.string()
val regex = val regex =
Regex("""<link(.+?)rel="shortcut icon"(.+?)href="(.+?)"""") Regex("""<link(.+?)rel="shortcut icon"(.+?)href="(.+?)"""")
var iconLink = regex var iconLink = regex
@ -135,31 +136,30 @@ class RssHelper @Inject constructor(
iconLink = "http:$iconLink" iconLink = "http:$iconLink"
} }
if (iconLink.startsWith("/")) { if (iconLink.startsWith("/")) {
val domainRegex = iconLink = "${domainRegex.find(articleLink)?.value}$iconLink"
Regex("""http(s)?://(([\w-]+\.)+\w+(:\d{1,5})?)""")
iconLink =
"http://${domainRegex.find(articleLink)?.groups?.get(2)?.value}$iconLink"
} }
saveRssIcon(feedDao, feed, iconLink) saveRssIcon(feedDao, feed, iconLink)
} else { } else {
// saveRssIcon(feedDao, feed, "") domainRegex.find(articleLink)?.value?.let {
Log.i("RLog", "favicon: ${it}")
val request = OkHttpClient()
.newCall(Request.Builder().url("$it/favicon.ico").build())
.execute()
if (request.isSuccessful) {
saveRssIcon(feedDao, feed, it)
}
}
} }
} }
} }
@Throws(Exception::class) private suspend fun saveRssIcon(feedDao: FeedDao, feed: Feed, iconLink: String) {
suspend fun saveRssIcon(feedDao: FeedDao, feed: Feed, iconLink: String) {
withContext(dispatcherIO) {
val response = OkHttpClient()
.newCall(Request.Builder().url(iconLink).build())
.execute()
feedDao.update( feedDao.update(
feed.apply { feed.apply {
icon = response.body!!.bytes() icon = iconLink
} }
) )
} }
}
private fun parseDate( private fun parseDate(
inputDate: String, patterns: Array<String?> = arrayOf( inputDate: String, patterns: Array<String?> = arrayOf(

View File

@ -10,6 +10,7 @@ import me.ash.reader.data.entity.Group
import me.ash.reader.data.entity.GroupWithFeed import me.ash.reader.data.entity.GroupWithFeed
import me.ash.reader.data.module.DispatcherIO import me.ash.reader.data.module.DispatcherIO
import me.ash.reader.ui.ext.currentAccountId import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.spacerDollar
import java.io.InputStream import java.io.InputStream
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -40,7 +41,9 @@ class OpmlLocalDataSource @Inject constructor(
if (!it.attributes["isDefault"].toBoolean()) { if (!it.attributes["isDefault"].toBoolean()) {
groupWithFeedList.addGroup( groupWithFeedList.addGroup(
Group( Group(
id = UUID.randomUUID().toString(), id = context.currentAccountId.spacerDollar(
UUID.randomUUID().toString()
),
name = it.attributes["title"] ?: it.text!!, name = it.attributes["title"] ?: it.text!!,
accountId = accountId, accountId = accountId,
) )
@ -49,7 +52,9 @@ class OpmlLocalDataSource @Inject constructor(
} else { } else {
groupWithFeedList.addFeedToDefault( groupWithFeedList.addFeedToDefault(
Feed( Feed(
id = UUID.randomUUID().toString(), id = context.currentAccountId.spacerDollar(
UUID.randomUUID().toString()
),
name = it.attributes["title"] ?: it.text!!, name = it.attributes["title"] ?: it.text!!,
url = it.attributes["xmlUrl"]!!, url = it.attributes["xmlUrl"]!!,
groupId = defaultGroup.id, groupId = defaultGroup.id,
@ -62,7 +67,8 @@ class OpmlLocalDataSource @Inject constructor(
} else { } else {
var groupId = defaultGroup.id var groupId = defaultGroup.id
if (!it.attributes["isDefault"].toBoolean()) { if (!it.attributes["isDefault"].toBoolean()) {
groupId = UUID.randomUUID().toString() groupId =
context.currentAccountId.spacerDollar(UUID.randomUUID().toString())
groupWithFeedList.addGroup( groupWithFeedList.addGroup(
Group( Group(
id = groupId, id = groupId,
@ -74,7 +80,9 @@ class OpmlLocalDataSource @Inject constructor(
it.subElements.forEach { outline -> it.subElements.forEach { outline ->
groupWithFeedList.addFeed( groupWithFeedList.addFeed(
Feed( Feed(
id = UUID.randomUUID().toString(), id = context.currentAccountId.spacerDollar(
UUID.randomUUID().toString()
),
name = outline.attributes["title"] ?: outline.text!!, name = outline.attributes["title"] ?: outline.text!!,
url = outline.attributes["xmlUrl"]!!, url = outline.attributes["xmlUrl"]!!,
groupId = groupId, groupId = groupId,

View File

@ -93,9 +93,13 @@ fun FeedsPage(
} }
LaunchedEffect(filterState) { LaunchedEffect(filterState) {
feedsViewModel.dispatch( feedsViewModel.dispatch(FeedsViewAction.FetchData(filterState))
FeedsViewAction.FetchData(filterState) }
)
LaunchedEffect(isSyncing) {
if (!isSyncing) {
feedsViewModel.dispatch(FeedsViewAction.FetchData(filterState))
}
} }
Scaffold( Scaffold(

View File

@ -60,19 +60,17 @@ fun ReadPage(
} }
} }
LaunchedEffect(readViewModel.viewState) { LaunchedEffect(viewState.articleWithFeed?.article?.id) {
readViewModel.viewState.collect {
isScrollDown = false isScrollDown = false
if (it.articleWithFeed != null) { viewState.articleWithFeed?.let {
if (it.articleWithFeed.article.isUnread) { if (it.article.isUnread) {
readViewModel.dispatch(ReadViewAction.MarkUnread(false)) readViewModel.dispatch(ReadViewAction.MarkUnread(false))
} }
if (it.articleWithFeed.feed.isFullContent) { if (it.feed.isFullContent) {
readViewModel.dispatch(ReadViewAction.RenderFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
} }
} }
} }
}
Scaffold( Scaffold(
modifier = Modifier.background(MaterialTheme.colorScheme.surface), modifier = Modifier.background(MaterialTheme.colorScheme.surface),