Skip to content

Commit

Permalink
Added smarter thumbnail logic. App will try not to increase size of s…
Browse files Browse the repository at this point in the history
…mall images on Cards now
  • Loading branch information
spacecowboy committed Dec 2, 2023
1 parent 639eb88 commit 7d8369d
Show file tree
Hide file tree
Showing 25 changed files with 386 additions and 246 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ij_visual_guides = none
ij_wrap_on_typing = false

[*.{kt,kts}]
max_line_length = 200
ktlint_code_style = ktlint_official
ktlint_function_naming_ignore_when_annotated_with=Composable
twitter_compose_allowed_composition_locals = LocalTypographySettings,LocalDimens,LocalWindowSize,LocalFoldableHinge
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.kotlin.serialization)
}

android {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import com.nononsenseapps.feeder.db.room.AppDatabase
import com.nononsenseapps.feeder.db.room.FeedItem
import com.nononsenseapps.feeder.db.room.FeedItemCursor
import com.nononsenseapps.feeder.db.room.FeedItemDao
import com.nononsenseapps.feeder.db.room.FeedItemDao.Companion.feedItemsListOrderByAsc
import com.nononsenseapps.feeder.db.room.FeedItemDao.Companion.feedItemsListOrderByDesc
import com.nononsenseapps.feeder.db.room.FeedItemDao.Companion.FEED_ITEM_LIST_SORT_ORDER_ASC
import com.nononsenseapps.feeder.db.room.FeedItemDao.Companion.FEED_ITEM_LIST_SORT_ORDER_DESC
import com.nononsenseapps.feeder.db.room.FeedItemIdWithLink
import com.nononsenseapps.feeder.db.room.FeedItemWithFeed
import com.nononsenseapps.feeder.db.room.ID_SAVED_ARTICLES
import com.nononsenseapps.feeder.db.room.ID_UNSET
import com.nononsenseapps.feeder.db.room.upsertFeedItems
import com.nononsenseapps.feeder.model.PREVIEW_COLUMNS
import com.nononsenseapps.feeder.model.PreviewItem
import com.nononsenseapps.feeder.model.previewColumns
import com.nononsenseapps.feeder.ui.compose.feed.FeedListItem
import com.nononsenseapps.feeder.ui.compose.feedarticle.FeedListFilter
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -77,15 +77,15 @@ class FeedItemStore(override val di: DI) : DIAware {
val args = mutableListOf<Any?>()

queryString.apply {
append("SELECT $previewColumns FROM feed_items\n")
append("SELECT $PREVIEW_COLUMNS FROM feed_items\n")
append("LEFT JOIN feeds ON feed_items.feed_id = feeds.id\n")
append("WHERE\n")

rawQueryFilter(filter, args, minReadTime, feedId, tag)

when (newestFirst) {
true -> append("ORDER BY $feedItemsListOrderByDesc\n")
else -> append("ORDER BY $feedItemsListOrderByAsc\n")
true -> append("ORDER BY $FEED_ITEM_LIST_SORT_ORDER_DESC\n")
else -> append("ORDER BY $FEED_ITEM_LIST_SORT_ORDER_ASC\n")
}
}

Expand Down Expand Up @@ -276,8 +276,7 @@ class FeedItemStore(override val di: DI) : DIAware {
dao.markAllAsRead()
}

fun getFeedsItemsWithDefaultFullTextNeedingDownload(): Flow<List<FeedItemIdWithLink>> =
dao.getFeedsItemsWithDefaultFullTextNeedingDownload()
fun getFeedsItemsWithDefaultFullTextNeedingDownload(): Flow<List<FeedItemIdWithLink>> = dao.getFeedsItemsWithDefaultFullTextNeedingDownload()

suspend fun markAsFullTextDownloaded(feedItemId: Long) = dao.markAsFullTextDownloaded(feedItemId)

Expand Down Expand Up @@ -332,7 +331,7 @@ private fun PreviewItem.toFeedListItem() =
feedTitle = feedDisplayTitle,
unread = readTime == null,
pubDate = pubDate?.toLocalDateTime()?.formatDynamically() ?: "",
imageUrl = imageUrl,
image = image,
link = link,
bookmarked = bookmarked,
feedImageUrl = feedImageUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.nononsenseapps.feeder.db.room.ID_UNSET
import com.nononsenseapps.feeder.db.room.RemoteFeed
import com.nononsenseapps.feeder.db.room.SyncDevice
import com.nononsenseapps.feeder.db.room.SyncRemote
import com.nononsenseapps.feeder.model.ThumbnailImage
import com.nononsenseapps.feeder.model.workmanager.SyncServiceSendReadWorker
import com.nononsenseapps.feeder.model.workmanager.requestFeedSync
import com.nononsenseapps.feeder.sync.DeviceListResponse
Expand Down Expand Up @@ -510,8 +511,7 @@ class Repository(override val di: DI) : DIAware {

fun ensurePeriodicSyncConfigured() = settingsStore.configurePeriodicSync(replace = false)

fun getFeedsItemsWithDefaultFullTextNeedingDownload(): Flow<List<FeedItemIdWithLink>> =
feedItemStore.getFeedsItemsWithDefaultFullTextNeedingDownload()
fun getFeedsItemsWithDefaultFullTextNeedingDownload(): Flow<List<FeedItemIdWithLink>> = feedItemStore.getFeedsItemsWithDefaultFullTextNeedingDownload()

suspend fun markAsFullTextDownloaded(feedItemId: Long) = feedItemStore.markAsFullTextDownloaded(feedItemId)

Expand Down Expand Up @@ -796,8 +796,7 @@ data class Article(
val bookmarked: Boolean = item?.bookmarked ?: false
val wordCount: Int = item?.wordCount ?: 0
val wordCountFull: Int = item?.wordCountFull ?: 0
val image: String? = item?.imageUrl
val imageFromBody: Boolean = item?.imageFromBody ?: false
val image: ThumbnailImage? = item?.thumbnailImage
}

enum class TextToDisplay {
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/com/nononsenseapps/feeder/db/room/Converters.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.nononsenseapps.feeder.db.room

import androidx.room.TypeConverter
import com.nononsenseapps.feeder.model.ImageFromHTML
import com.nononsenseapps.feeder.model.ThumbnailImage
import com.nononsenseapps.feeder.util.sloppyLinkToStrictURLNoThrows
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.net.URL
import java.time.Instant
import java.time.ZonedDateTime
Expand Down Expand Up @@ -38,4 +42,27 @@ class Converters {

@TypeConverter
fun longFromInstant(value: Instant?): Long? = value?.toEpochMilli()

@TypeConverter
fun stringFromThumbnailImage(value: ThumbnailImage?): String? =
value?.let {
Json.encodeToString(it)
}

@TypeConverter
fun thumbnailImageFromString(value: String?): ThumbnailImage? =
value?.let {
try {
Json.decodeFromString<ThumbnailImage>(it)
} catch (_: Throwable) {
// Legacy values may be stored as just a URL
try {
val url = URL(it)
// But we don't know what type so we pick a conservative default
ImageFromHTML(url = url.toString(), width = null, height = null)
} catch (_: Throwable) {
null
}
}
}
}
13 changes: 9 additions & 4 deletions app/src/main/java/com/nononsenseapps/feeder/db/room/FeedItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.nononsenseapps.feeder.db.COL_WORD_COUNT_FULL
import com.nononsenseapps.feeder.db.FEED_ITEMS_TABLE_NAME
import com.nononsenseapps.feeder.model.ParsedArticle
import com.nononsenseapps.feeder.model.ParsedFeed
import com.nononsenseapps.feeder.model.ThumbnailImage
import com.nononsenseapps.feeder.model.host
import com.nononsenseapps.feeder.ui.text.HtmlToPlainTextConverter
import java.net.URI
Expand Down Expand Up @@ -74,8 +75,13 @@ data class FeedItem
var title: String = "",
@ColumnInfo(name = COL_PLAINTITLE) var plainTitle: String = "",
@ColumnInfo(name = COL_PLAINSNIPPET) var plainSnippet: String = "",
@ColumnInfo(name = COL_IMAGEURL) var imageUrl: String? = null,
@ColumnInfo(name = COL_IMAGE_FROM_BODY) var imageFromBody: Boolean = false,
@ColumnInfo(name = COL_IMAGEURL) var thumbnailImage: ThumbnailImage? = null,
@ColumnInfo(name = COL_IMAGE_FROM_BODY)
@Deprecated(
"This column has been 'removed' but sqlite doesn't support drop column.",
replaceWith = ReplaceWith("thumbnailImage?.fromBody ?: false"),
)
var imageFromBody: Boolean = false,
@ColumnInfo(name = COL_ENCLOSURELINK) var enclosureLink: String? = null,
@ColumnInfo(name = COL_ENCLOSURE_TYPE) var enclosureType: String? = null,
@ColumnInfo(name = COL_AUTHOR) var author: String? = null,
Expand Down Expand Up @@ -152,8 +158,7 @@ data class FeedItem
this.title = this.plainTitle
this.plainSnippet = summary

this.imageUrl = safeImage?.url
this.imageFromBody = safeImage?.fromBody ?: false
this.thumbnailImage = safeImage
val firstEnclosure = entry.attachments?.firstOrNull()
this.enclosureLink = firstEnclosure?.url
this.enclosureType = firstEnclosure?.mime_type?.lowercase()
Expand Down
40 changes: 20 additions & 20 deletions app/src/main/java/com/nononsenseapps/feeder/db/room/FeedItemDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import com.nononsenseapps.feeder.db.COL_PLAINSNIPPET
import com.nononsenseapps.feeder.db.COL_TITLE
import com.nononsenseapps.feeder.db.COL_URL
import com.nononsenseapps.feeder.db.FEEDS_TABLE_NAME
import com.nononsenseapps.feeder.model.PREVIEW_COLUMNS
import com.nononsenseapps.feeder.model.PreviewItem
import com.nononsenseapps.feeder.model.previewColumns
import kotlinx.coroutines.flow.Flow
import java.net.URL
import java.time.Instant
Expand Down Expand Up @@ -81,7 +81,7 @@ interface FeedItemDao {

@Query(
"""
SELECT $feedItemColumnsWithFeed
SELECT $FEED_ITEM_COLUMNS_WITH_FEED
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE feed_items.id IS :id
Expand Down Expand Up @@ -133,7 +133,7 @@ interface FeedItemDao {

@Query(
"""
SELECT $feedItemColumnsWithFeed
SELECT $FEED_ITEM_COLUMNS_WITH_FEED
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE feed_items.id IS :id
Expand All @@ -143,7 +143,7 @@ interface FeedItemDao {

@Query(
"""
SELECT $feedItemColumnsWithFeed
SELECT $FEED_ITEM_COLUMNS_WITH_FEED
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE feed_items.id IS :id
Expand All @@ -159,14 +159,14 @@ interface FeedItemDao {

@Query(
"""
SELECT $previewColumns
SELECT $PREVIEW_COLUMNS
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE feed_id IS :feedId
AND (read_time is null or read_time >= :minReadTime)
AND bookmarked in (1, :bookmarked)
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByDesc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_DESC
""",
)
fun pagingUnreadPreviewsDesc(
Expand All @@ -177,14 +177,14 @@ interface FeedItemDao {

@Query(
"""
SELECT $previewColumns
SELECT $PREVIEW_COLUMNS
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE tag IS :tag
AND (read_time is null or read_time >= :minReadTime)
AND bookmarked in (1, :bookmarked)
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByDesc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_DESC
""",
)
fun pagingUnreadPreviewsDesc(
Expand All @@ -195,13 +195,13 @@ interface FeedItemDao {

@Query(
"""
SELECT $previewColumns
SELECT $PREVIEW_COLUMNS
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE (read_time is null or read_time >= :minReadTime)
AND bookmarked in (1, :bookmarked)
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByDesc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_DESC
""",
)
fun pagingUnreadPreviewsDesc(
Expand All @@ -211,14 +211,14 @@ interface FeedItemDao {

@Query(
"""
SELECT $previewColumns
SELECT $PREVIEW_COLUMNS
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE feed_id IS :feedId
AND (read_time is null or read_time >= :minReadTime)
AND bookmarked in (1, :bookmarked)
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByAsc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_ASC
""",
)
fun pagingUnreadPreviewsAsc(
Expand All @@ -229,14 +229,14 @@ interface FeedItemDao {

@Query(
"""
SELECT $previewColumns
SELECT $PREVIEW_COLUMNS
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE tag IS :tag
AND (read_time is null or read_time >= :minReadTime)
AND bookmarked in (1, :bookmarked)
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByAsc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_ASC
""",
)
fun pagingUnreadPreviewsAsc(
Expand All @@ -247,13 +247,13 @@ interface FeedItemDao {

@Query(
"""
SELECT $previewColumns
SELECT $PREVIEW_COLUMNS
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE (read_time is null or read_time >= :minReadTime)
AND bookmarked in (1, :bookmarked)
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByAsc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_ASC
""",
)
fun pagingUnreadPreviewsAsc(
Expand All @@ -263,12 +263,12 @@ interface FeedItemDao {

@Query(
"""
SELECT $feedItemColumnsWithFeed
SELECT $FEED_ITEM_COLUMNS_WITH_FEED
FROM feed_items
LEFT JOIN feeds ON feed_items.feed_id = feeds.id
WHERE feed_id IN (:feedIds) AND notified IS 0 AND read_time is null
AND NOT EXISTS (SELECT 1 FROM blocklist WHERE lower(feed_items.plain_title) GLOB blocklist.glob_pattern)
ORDER BY $feedItemsListOrderByDesc
ORDER BY $FEED_ITEM_LIST_SORT_ORDER_DESC
LIMIT 20
""",
)
Expand Down Expand Up @@ -487,9 +487,9 @@ interface FeedItemDao {

companion object {
// These are backed by a database index
const val feedItemsListOrderByDesc =
const val FEED_ITEM_LIST_SORT_ORDER_DESC =
"primary_sort_time DESC, pub_date DESC, feed_items.id DESC"
const val feedItemsListOrderByAsc =
const val FEED_ITEM_LIST_SORT_ORDER_ASC =
"primary_sort_time ASC, pub_date ASC, feed_items.id ASC"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import com.nononsenseapps.feeder.db.COL_FULLTEXT_BY_DEFAULT
import com.nononsenseapps.feeder.db.COL_GUID
import com.nononsenseapps.feeder.db.COL_ID
import com.nononsenseapps.feeder.db.COL_IMAGEURL
import com.nononsenseapps.feeder.db.COL_IMAGE_FROM_BODY
import com.nononsenseapps.feeder.db.COL_LINK
import com.nononsenseapps.feeder.db.COL_PLAINSNIPPET
import com.nononsenseapps.feeder.db.COL_PLAINTITLE
Expand All @@ -28,14 +27,15 @@ import com.nononsenseapps.feeder.db.COL_WORD_COUNT
import com.nononsenseapps.feeder.db.COL_WORD_COUNT_FULL
import com.nononsenseapps.feeder.db.FEEDS_TABLE_NAME
import com.nononsenseapps.feeder.db.FEED_ITEMS_TABLE_NAME
import com.nononsenseapps.feeder.model.ThumbnailImage
import com.nononsenseapps.feeder.model.host
import com.nononsenseapps.feeder.util.sloppyLinkToStrictURLNoThrows
import java.net.URI
import java.net.URL
import java.time.Instant
import java.time.ZonedDateTime

const val feedItemColumnsWithFeed = """
const val FEED_ITEM_COLUMNS_WITH_FEED = """
$FEED_ITEMS_TABLE_NAME.$COL_ID AS $COL_ID, $COL_GUID, $FEED_ITEMS_TABLE_NAME.$COL_TITLE AS $COL_TITLE,
$COL_PLAINTITLE, $COL_PLAINSNIPPET, $FEED_ITEMS_TABLE_NAME.$COL_IMAGEURL, $COL_ENCLOSURELINK, $COL_ENCLOSURE_TYPE,
$COL_AUTHOR, $COL_PUBDATE, $COL_LINK, $COL_READ_TIME, $FEEDS_TABLE_NAME.$COL_TAG AS $COL_TAG, $FEEDS_TABLE_NAME.$COL_ID AS $COL_FEEDID,
Expand All @@ -45,8 +45,7 @@ const val feedItemColumnsWithFeed = """
$FEEDS_TABLE_NAME.$COL_FULLTEXT_BY_DEFAULT AS $COL_FULLTEXT_BY_DEFAULT,
$COL_BOOKMARKED,
$COL_WORD_COUNT,
$COL_WORD_COUNT_FULL,
$COL_IMAGE_FROM_BODY
$COL_WORD_COUNT_FULL
"""

data class FeedItemWithFeed
Expand All @@ -58,8 +57,7 @@ data class FeedItemWithFeed
var title: String = "",
@ColumnInfo(name = COL_PLAINTITLE) var plainTitle: String = "",
@ColumnInfo(name = COL_PLAINSNIPPET) var plainSnippet: String = "",
@ColumnInfo(name = COL_IMAGEURL) var imageUrl: String? = null,
@ColumnInfo(name = COL_IMAGE_FROM_BODY) var imageFromBody: Boolean = false,
@ColumnInfo(name = COL_IMAGEURL) var thumbnailImage: ThumbnailImage? = null,
@ColumnInfo(name = COL_ENCLOSURELINK) var enclosureLink: String? = null,
@ColumnInfo(name = COL_ENCLOSURE_TYPE) var enclosureType: String? = null,
var author: String? = null,
Expand Down
Loading

0 comments on commit 7d8369d

Please sign in to comment.