Rework Feed table columns

This commit is contained in:
Shinokuni 2024-08-04 18:04:55 +02:00
parent 5247d878c4
commit 3af1220666
15 changed files with 109 additions and 70 deletions

View File

@ -130,8 +130,8 @@ class ItemScreen(
val itemWithFeed = state.itemWithFeed!!
val item = itemWithFeed.item
val accentColor = if (itemWithFeed.bgColor != 0) {
Color(itemWithFeed.bgColor)
val accentColor = if (itemWithFeed.color != 0) {
Color(itemWithFeed.color)
} else {
primaryColor
}
@ -203,8 +203,8 @@ class ItemScreen(
if (item.imageLink != null) {
BackgroundTitle(itemWithFeed = itemWithFeed)
} else {
val tintColor = if (itemWithFeed.bgColor != 0) {
Color(itemWithFeed.bgColor)
val tintColor = if (itemWithFeed.color != 0) {
Color(itemWithFeed.color)
} else {
MaterialTheme.colorScheme.onBackground
}
@ -249,8 +249,8 @@ fun BackgroundTitle(
itemWithFeed: ItemWithFeed,
) {
val onScrimColor = Color.White.copy(alpha = 0.85f)
val accentColor = if (itemWithFeed.bgColor != 0) {
Color(itemWithFeed.bgColor)
val accentColor = if (itemWithFeed.color != 0) {
Color(itemWithFeed.color)
} else {
onScrimColor
}

View File

@ -124,7 +124,7 @@ class LocalRSSRepository(
try {
iconUrl = HtmlParser.getFaviconLink(siteUrl!!, get()).also { feedUrl ->
feedUrl?.let { backgroundColor = FeedColors.getFeedColor(it) }
feedUrl?.let { color = FeedColors.getFeedColor(it) }
}
} catch (e: Exception) {
Log.d("LocalRSSRepository", "insertFeed: ${e.message}")

View File

@ -119,7 +119,7 @@ class SyncAnalyzer(
text = text,
largeIcon = icon,
item = item,
color = feed.backgroundColor,
color = feed.color,
accountId = account.id
)
}

View File

@ -67,7 +67,6 @@ private val itemWithFeed = ItemWithFeed(
),
feedName = "feed name",
color = 0,
bgColor = 0,
feedId = 0,
feedIconUrl = "",
websiteUrl = "",

View File

@ -62,7 +62,7 @@ fun RegularTimelineItem(
TimelineItemHeader(
feedName = itemWithFeed.feedName,
feedIconUrl = itemWithFeed.feedIconUrl,
feedColor = itemWithFeed.bgColor,
feedColor = itemWithFeed.color,
folderName = itemWithFeed.folder?.name,
date = itemWithFeed.item.pubDate!!,
duration = itemWithFeed.item.readTime,
@ -80,7 +80,7 @@ fun RegularTimelineItem(
TimelineItemBadge(
date = itemWithFeed.item.pubDate!!,
duration = itemWithFeed.item.readTime,
color = itemWithFeed.bgColor
color = itemWithFeed.color
)
}
}
@ -111,7 +111,7 @@ fun CompactTimelineItem(
TimelineItemHeader(
feedName = itemWithFeed.feedName,
feedIconUrl = itemWithFeed.feedIconUrl,
feedColor = itemWithFeed.bgColor,
feedColor = itemWithFeed.color,
folderName = itemWithFeed.folder?.name,
onFavorite = onFavorite,
onShare = onShare,
@ -162,7 +162,7 @@ fun LargeTimelineItem(
TimelineItemHeader(
feedName = itemWithFeed.feedName,
feedIconUrl = itemWithFeed.feedIconUrl,
feedColor = itemWithFeed.bgColor,
feedColor = itemWithFeed.color,
folderName = itemWithFeed.folder?.name,
date = itemWithFeed.item.pubDate!!,
duration = itemWithFeed.item.readTime,
@ -176,7 +176,7 @@ fun LargeTimelineItem(
TimelineItemBadge(
date = itemWithFeed.item.pubDate!!,
duration = itemWithFeed.item.readTime,
color = itemWithFeed.bgColor
color = itemWithFeed.color
)
ShortSpacer()

View File

@ -3,6 +3,7 @@ package com.readrops.app.util
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
@ -54,9 +55,17 @@ class CrashActivity : ComponentActivity() {
val throwable = intent.getSerializableExtra(THROWABLE_KEY) as Throwable?
val stackTrace = try {
throwable?.stackTraceToString()
} catch (e: Exception) {
Log.e("CrashActivity", "Unable to get crash exception")
null
}
setContent {
ReadropsTheme {
CrashScreen(throwable?.stackTraceToString().orEmpty())
CrashScreen(stackTrace.orEmpty())
}
}
}

View File

@ -2,11 +2,11 @@
"formatVersion": 1,
"database": {
"version": 4,
"identityHash": "6a1403979efe044075bf2f30a47a9e08",
"identityHash": "1cd84a05829477201803f5f27275fe29",
"entities": [
{
"tableName": "Feed",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `description` TEXT, `url` TEXT, `siteUrl` TEXT, `lastUpdated` TEXT, `text_color` INTEGER NOT NULL, `background_color` INTEGER NOT NULL, `icon_url` TEXT, `etag` TEXT, `last_modified` TEXT, `folder_id` INTEGER, `remoteId` TEXT, `account_id` INTEGER NOT NULL, `notification_enabled` INTEGER NOT NULL DEFAULT 1, FOREIGN KEY(`folder_id`) REFERENCES `Folder`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`account_id`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `description` TEXT, `url` TEXT, `siteUrl` TEXT, `last_updated` TEXT, `color` INTEGER NOT NULL, `icon_url` TEXT, `etag` TEXT, `last_modified` TEXT, `folder_id` INTEGER, `remote_id` TEXT, `account_id` INTEGER NOT NULL, `notification_enabled` INTEGER NOT NULL DEFAULT 1, FOREIGN KEY(`folder_id`) REFERENCES `Folder`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`account_id`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
@ -40,19 +40,13 @@
},
{
"fieldPath": "lastUpdated",
"columnName": "lastUpdated",
"columnName": "last_updated",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "textColor",
"columnName": "text_color",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "backgroundColor",
"columnName": "background_color",
"fieldPath": "color",
"columnName": "color",
"affinity": "INTEGER",
"notNull": true
},
@ -82,7 +76,7 @@
},
{
"fieldPath": "remoteId",
"columnName": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT",
"notNull": false
},
@ -526,7 +520,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6a1403979efe044075bf2f30a47a9e08')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1cd84a05829477201803f5f27275fe29')"
]
}
}

View File

@ -3,7 +3,7 @@ package com.readrops.db
import androidx.room.testing.MigrationTestHelper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import junit.framework.Assert.assertEquals
import junit.framework.TestCase.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

View File

@ -83,6 +83,17 @@ object MigrationFrom3To4 : Migration(3, 4) {
db.execSQL("DROP TABLE IF EXISTS `Item`")
db.execSQL("ALTER TABLE `_new_Item` RENAME TO `Item`")
db.execSQL("CREATE INDEX IF NOT EXISTS `index_Item_feed_id` ON `Item` (`feed_id`)")
// remove text_color
// rename background_color to color
// rename remoteId to remote_id
// rename lastUpdated to last_updated
db.execSQL("CREATE TABLE IF NOT EXISTS `_new_Feed` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `description` TEXT, `url` TEXT, `siteUrl` TEXT, `last_updated` TEXT, `color` INTEGER NOT NULL, `icon_url` TEXT, `etag` TEXT, `last_modified` TEXT, `folder_id` INTEGER, `remote_id` TEXT, `account_id` INTEGER NOT NULL, `notification_enabled` INTEGER NOT NULL DEFAULT 1, FOREIGN KEY(`folder_id`) REFERENCES `Folder`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`account_id`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )")
db.execSQL("INSERT INTO `_new_Feed` (`id`, `name`, `description`, `url`, `siteUrl`, `last_updated`, `color`, `icon_url`, `etag`, `last_modified`, `folder_id`, `remote_id`, `account_id`, `notification_enabled`) SELECT `id`, `name`, `description`, `url`, `siteUrl`, `lastUpdated`, `background_color`, `icon_url`, `etag`, `last_modified`, `folder_id`, `remoteId`, `account_id`, `notification_enabled` FROM `Feed`")
db.execSQL("DROP TABLE IF EXISTS `Feed`")
db.execSQL("ALTER TABLE `_new_Feed` RENAME TO `Feed`")
db.execSQL("CREATE INDEX IF NOT EXISTS `index_Feed_folder_id` ON `Feed` (`folder_id`)")
db.execSQL("CREATE INDEX IF NOT EXISTS `index_Feed_account_id` ON `Feed` (`account_id`)")
}
}

View File

@ -39,22 +39,22 @@ abstract class FeedDao : BaseDao<Feed> {
@Query("Select count(*) from Feed Where account_id = :accountId")
abstract suspend fun selectFeedCount(accountId: Int): Int
@Query("Select remoteId From Feed Where account_id = :accountId")
@Query("Select remote_id From Feed Where account_id = :accountId")
abstract suspend fun selectFeedRemoteIds(accountId: Int): MutableList<String>
@Query("Select id From Folder Where remoteId = :remoteId And account_id = :accountId")
abstract suspend fun selectRemoteFolderLocalId(remoteId: String, accountId: Int): Int
@Query("Select id From Feed Where remoteId = :remoteId And account_id = :accountId")
@Query("Select id From Feed Where remote_id = :remoteId And account_id = :accountId")
abstract suspend fun selectRemoteFeedLocalId(remoteId: String, accountId: Int): Int
@Query("Update Feed set name = :name, folder_id = :folderId Where remoteId = :remoteFeedId And account_id = :accountId")
@Query("Update Feed set name = :name, folder_id = :folderId Where remote_id = :remoteFeedId And account_id = :accountId")
abstract fun updateFeedNameAndFolder(remoteFeedId: String, accountId: Int, name: String, folderId: Int?)
@Query("Delete from Feed Where remoteId in (:ids) And account_id = :accountId")
@Query("Delete from Feed Where remote_id in (:ids) And account_id = :accountId")
abstract fun deleteByIds(ids: List<String>, accountId: Int)
@Query("Update Feed set background_color = :color Where id = :feedId")
@Query("Update Feed set color = :color Where id = :feedId")
abstract fun updateFeedColor(feedId: Int, color: Int)
@Query("""Select Feed.*, Folder.name as folder_name From Feed Left Join Folder On Feed.folder_id = Folder.id

View File

@ -8,25 +8,39 @@ import androidx.room.Ignore
import androidx.room.PrimaryKey
import com.readrops.db.entities.account.Account
@Entity(foreignKeys = [ForeignKey(entity = Folder::class, parentColumns = ["id"], childColumns = ["folder_id"],
onDelete = ForeignKey.SET_NULL), ForeignKey(entity = Account::class, parentColumns = ["id"],
childColumns = ["account_id"], onDelete = ForeignKey.CASCADE)])
@Entity(
foreignKeys = [
ForeignKey(
entity = Folder::class,
parentColumns = ["id"],
childColumns = ["folder_id"],
onDelete = ForeignKey.SET_NULL
), ForeignKey(
entity = Account::class,
parentColumns = ["id"],
childColumns = ["account_id"],
onDelete = ForeignKey.CASCADE
)
]
)
data class Feed(
@PrimaryKey(autoGenerate = true) var id: Int = 0,
var name: String? = null,
var description: String? = null,
var url: String? = null,
var siteUrl: String? = null,
var lastUpdated: String? = null,
@ColumnInfo(name = "text_color") @ColorInt var textColor: Int = 0,
@ColumnInfo(name = "background_color") @ColorInt var backgroundColor: Int = 0,
@ColumnInfo("last_updated") var lastUpdated: String? = null,
@ColorInt var color: Int = 0,
@ColumnInfo(name = "icon_url") var iconUrl: String? = null,
var etag: String? = null,
@ColumnInfo(name = "last_modified") var lastModified: String? = null,
@ColumnInfo(name = "folder_id", index = true) var folderId: Int? = null,
var remoteId: String? = null,
@ColumnInfo("remote_id") var remoteId: String? = null,
@ColumnInfo(name = "account_id", index = true) var accountId: Int = 0,
@ColumnInfo(name = "notification_enabled", defaultValue = "1") var isNotificationEnabled: Boolean = true,
@ColumnInfo(
name = "notification_enabled",
defaultValue = "1"
) var isNotificationEnabled: Boolean = true,
@Ignore var unreadCount: Int = 0,
@Ignore var remoteFolderId: String? = null,
)

View File

@ -10,9 +10,8 @@ data class ItemWithFeed(
@Embedded val item: Item,
@ColumnInfo(name = "name") val feedName: String,
@ColumnInfo(name = "feedId") val feedId: Int,
@ColumnInfo(name = "text_color") @ColorInt val color: Int,
@ColumnInfo(name = "background_color") @ColorInt val bgColor: Int,
@ColumnInfo(name = "color") @ColorInt val color: Int,
@ColumnInfo(name = "icon_url") val feedIconUrl: String?,
@ColumnInfo(name = "siteUrl") val websiteUrl: String?,
@Embedded(prefix = "folder_") val folder: Folder?,
@Embedded(prefix = "folder_") val folder: Folder?
)

View File

@ -13,7 +13,7 @@ object FoldersAndFeedsQueryBuilder {
"Feed.url As feedUrl",
"Feed.siteUrl As feedSiteUrl",
"Feed.description as feedDescription",
"Feed.remoteId as feedRemoteId",
"Feed.remote_id as feedRemoteId",
"Folder.id As folderId",
"Folder.name As folderName",
"Feed.account_id as accountId",

View File

@ -6,10 +6,24 @@ import androidx.sqlite.db.SupportSQLiteQueryBuilder
object ItemSelectionQueryBuilder {
private val COLUMNS = arrayOf(
"Item.id", "Item.remoteId", "title", "Item.description", "content",
"link", "pub_date", "image_link", "author", "Item.read", "text_color", "icon_url",
"background_color", "read_time", "Feed.name", "Feed.id as feedId", "siteUrl",
"Folder.id as folder_id", "Folder.name as folder_name"
"Item.id",
"Item.remote_id",
"title",
"Item.description",
"content",
"link",
"pub_date",
"image_link",
"author",
"Item.read",
"icon_url",
"color",
"read_time",
"Feed.name",
"Feed.id as feedId",
"siteUrl",
"Folder.id as folder_id",
"Folder.name as folder_name"
)
private val SEPARATE_STATE_COLUMNS =
@ -19,7 +33,7 @@ object ItemSelectionQueryBuilder {
"Item Inner Join Feed On Item.feed_id = Feed.id Left Join Folder on Folder.id = Feed.folder_id"
private const val SEPARATE_STATE_JOIN =
" Left Join ItemState On ItemState.remote_id = Item.remoteId"
" Left Join ItemState On ItemState.remote_id = Item.remote_id"
/**
* @param separateState Indicates if item state must be retrieved from ItemState table

View File

@ -17,8 +17,7 @@ object ItemsQueryBuilder {
"pub_date",
"link",
"Feed.name",
"text_color",
"background_color",
"color",
"icon_url",
"read_time",
"Feed.id as feedId",