Skip to content

Commit

Permalink
Update feed table to add unique feed ID column
Browse files Browse the repository at this point in the history
  • Loading branch information
msasikanth committed Apr 13, 2024
1 parent a90819a commit c371f7b
Show file tree
Hide file tree
Showing 27 changed files with 438 additions and 170 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import kotlinx.datetime.Instant

@Immutable
data class Feed(
val id: String,
val name: String,
val icon: String,
val description: String,
val link: String,
val homepageLink: String,
val createdAt: Instant,
val link: String,
val pinnedAt: Instant?,
val lastCleanUpAt: Instant? = null,
val numberOfUnreadPosts: Long = 0L,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ import kotlinx.datetime.Instant

data class Post(
val id: String,
val sourceId: String,
val title: String,
val description: String,
val rawContent: String?,
val imageUrl: String?,
val date: Instant,
val feedLink: String,
val link: String,
val bookmarked: Boolean,
val commentsLink: String?,
val bookmarked: Boolean,
val read: Boolean,
val rawContent: String?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ import kotlinx.datetime.Instant
@Immutable
data class PostWithMetadata(
val id: String,
val sourceId: String,
val title: String,
val description: String,
val imageUrl: String?,
val date: Instant,
val link: String,
val commentsLink: String?,
val bookmarked: Boolean,
val read: Boolean,
val feedName: String,
val feedIcon: String,
val feedLink: String,
val commentsLink: String?,
val read: Boolean,
)
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class AppPresenter(
is ModalConfig.FeedInfo -> {
Modals.FeedInfo(
presenter =
feedPresenter(modalConfig.feedLink, componentContext) { modalNavigation.dismiss() }
feedPresenter(modalConfig.feedId, componentContext) { modalNavigation.dismiss() }
)
}
}
Expand Down Expand Up @@ -220,6 +220,6 @@ class AppPresenter(

@Serializable
sealed interface ModalConfig {
@Serializable data class FeedInfo(val feedLink: String) : ModalConfig
@Serializable data class FeedInfo(val feedId: String) : ModalConfig
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class BookmarksPresenter(
) {
coroutineScope.launch {
val hasPost = rssRepository.hasPost(post.id)
val hasFeed = rssRepository.hasFeed(post.feedLink)
val hasFeed = rssRepository.hasFeed(post.sourceId)

if (hasPost && hasFeed) {
openReaderView(post)
Expand All @@ -137,7 +137,7 @@ class BookmarksPresenter(

private fun onPostBookmarkClicked(post: PostWithMetadata) {
coroutineScope.launch {
if (rssRepository.hasFeed(post.feedLink)) {
if (rssRepository.hasFeed(post.sourceId)) {
rssRepository.updateBookmarkStatus(bookmarked = !post.bookmarked, id = post.id)
} else {
rssRepository.deleteBookmark(id = post.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ import dev.sasikanth.rss.reader.utils.nameBasedUuidOf
object SQLCodeMigrations {

fun migrations(): Array<AfterVersion> {
return arrayOf(afterVersion12())
return arrayOf(afterVersion12(), afterVersion13())
}

private fun afterVersion13(): AfterVersion {
return AfterVersion(13) { driver ->
val feedIds = FeedsIdsQuery(driver).executeAsList()
feedIds.forEach { feedId -> migrateFeedsLinkIdsToUuid(feedId, driver) }
}
}

private fun afterVersion12(): AfterVersion {
Expand All @@ -36,6 +43,37 @@ object SQLCodeMigrations {
}
}

private fun migrateFeedsLinkIdsToUuid(oldFeedId: String, driver: SqlDriver) {
val newFeedId = nameBasedUuidOf(oldFeedId).toString()
driver.execute(
identifier = null,
sql = "UPDATE feed SET id = '$newFeedId' WHERE id = '$oldFeedId'",
parameters = 0,
binders = null
)

driver.execute(
identifier = null,
sql = "UPDATE feed_search SET id = '$newFeedId' WHERE id = '$oldFeedId'",
parameters = 0,
binders = null
)

driver.execute(
identifier = null,
sql = "UPDATE post SET sourceId = '$newFeedId' WHERE sourceId = '$oldFeedId'",
parameters = 0,
binders = null
)

driver.execute(
identifier = null,
sql = "UPDATE bookmark SET sourceId = '$newFeedId' WHERE sourceId = '$oldFeedId'",
parameters = 0,
binders = null
)
}

private fun migratePostLinkIdsToUuid(driver: SqlDriver, oldPostId: String) {
val newPostId = nameBasedUuidOf(oldPostId).toString()

Expand All @@ -62,6 +100,23 @@ object SQLCodeMigrations {
}
}

private class FeedsIdsQuery(
private val driver: SqlDriver,
) : Query<String>(mapper = { cursor -> cursor.getString(0)!! }) {
override fun addListener(listener: Listener) {
driver.addListener("feed", listener = listener)
}

override fun removeListener(listener: Listener) {
driver.removeListener("feed", listener = listener)
}

override fun <R> execute(mapper: (SqlCursor) -> QueryResult<R>): QueryResult<R> =
driver.executeQuery(null, "SELECT id FROM feed", mapper, 0, null)

override fun toString(): String = "Feed.sq:feedIds"
}

private class PostsIdsQuery(
private val driver: SqlDriver,
) : Query<String>(mapper = { cursor -> cursor.getString(0)!! }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ sealed interface FeedEvent {

data object RemoveFeedClicked : FeedEvent

data class OnFeedNameChanged(val newFeedName: String, val feedLink: String) : FeedEvent
data class OnFeedNameChanged(val newFeedName: String, val feedId: String) : FeedEvent

data object DismissSheet : FeedEvent

data class OnAlwaysFetchSourceArticleChanged(val newValue: Boolean, val feedLink: String) :
data class OnAlwaysFetchSourceArticleChanged(val newValue: Boolean, val feedId: String) :
FeedEvent

data class OnMarkPostsAsRead(val feedLink: String) : FeedEvent
data class OnMarkPostsAsRead(val feedId: String) : FeedEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import me.tatarka.inject.annotations.Inject

internal typealias FeedPresenterFactory =
(
feedLink: String,
feedId: String,
ComponentContext,
dismiss: () -> Unit,
) -> FeedPresenter
Expand All @@ -59,7 +59,7 @@ class FeedPresenter(
rssRepository: RssRepository,
settingsRepository: SettingsRepository,
private val observableSelectedFeed: ObservableSelectedFeed,
@Assisted feedLink: String,
@Assisted feedId: String,
@Assisted componentContext: ComponentContext,
@Assisted private val dismiss: () -> Unit
) : ComponentContext by componentContext {
Expand All @@ -70,7 +70,7 @@ class FeedPresenter(
dispatchersProvider = dispatchersProvider,
rssRepository = rssRepository,
settingsRepository = settingsRepository,
feedLink = feedLink,
feedId = feedId,
observableSelectedFeed = observableSelectedFeed,
)
}
Expand Down Expand Up @@ -98,7 +98,7 @@ class FeedPresenter(
private val dispatchersProvider: DispatchersProvider,
private val rssRepository: RssRepository,
private val settingsRepository: SettingsRepository,
private val feedLink: String,
private val feedId: String,
private val observableSelectedFeed: ObservableSelectedFeed,
) : InstanceKeeper.Instance {

Expand All @@ -122,14 +122,14 @@ class FeedPresenter(
// no-op
}
FeedEvent.RemoveFeedClicked -> removeFeed()
is FeedEvent.OnFeedNameChanged -> onFeedNameUpdated(event.newFeedName, event.feedLink)
is FeedEvent.OnFeedNameChanged -> onFeedNameUpdated(event.newFeedName, event.feedId)
is FeedEvent.OnAlwaysFetchSourceArticleChanged ->
onAlwaysFetchSourceArticleChanged(event.newValue, event.feedLink)
is FeedEvent.OnMarkPostsAsRead -> onMarkPostsAsRead(event.feedLink)
onAlwaysFetchSourceArticleChanged(event.newValue, event.feedId)
is FeedEvent.OnMarkPostsAsRead -> onMarkPostsAsRead(event.feedId)
}
}

private fun onMarkPostsAsRead(feedLink: String) {
private fun onMarkPostsAsRead(feedId: String) {
coroutineScope.launch {
val postsType = withContext(dispatchersProvider.io) { settingsRepository.postsType.first() }
val postsAfter =
Expand All @@ -144,21 +144,21 @@ class FeedPresenter(
}
}

rssRepository.markPostsInFeedAsRead(feedLink = feedLink, postsAfter = postsAfter)
rssRepository.markPostsInFeedAsRead(feedId = feedId, postsAfter = postsAfter)
}
}

private fun onAlwaysFetchSourceArticleChanged(newValue: Boolean, feedLink: String) {
coroutineScope.launch { rssRepository.updateFeedAlwaysFetchSource(feedLink, newValue) }
private fun onAlwaysFetchSourceArticleChanged(newValue: Boolean, feedId: String) {
coroutineScope.launch { rssRepository.updateFeedAlwaysFetchSource(feedId, newValue) }
}

private fun onFeedNameUpdated(newFeedName: String, feedLink: String) {
coroutineScope.launch { rssRepository.updateFeedName(newFeedName, feedLink) }
private fun onFeedNameUpdated(newFeedName: String, feedId: String) {
coroutineScope.launch { rssRepository.updateFeedName(newFeedName, feedId) }
}

private fun removeFeed() {
coroutineScope.launch {
rssRepository.removeFeed(feedLink)
rssRepository.removeFeed(feedId)
observableSelectedFeed.clearSelection()
effects.emit(FeedEffect.DismissSheet)
}
Expand All @@ -180,7 +180,7 @@ class FeedPresenter(
}

rssRepository
.feed(feedLink, postsAfter)
.feed(feedId, postsAfter)
.onEach { feed -> _state.update { it.copy(feed = feed) } }
.catch {
// no-op
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import androidx.compose.foundation.text.selection.LocalTextSelectionColors
import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.rounded.Check
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
Expand All @@ -54,7 +53,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -138,7 +136,7 @@ fun FeedInfoBottomSheet(
feed = feed,
onFeedNameChange = { newFeedName ->
feedPresenter.dispatch(
FeedEvent.OnFeedNameChanged(newFeedName = newFeedName, feedLink = feed.link)
FeedEvent.OnFeedNameChanged(newFeedName = newFeedName, feedId = feed.id)
)
}
)
Expand All @@ -148,15 +146,15 @@ fun FeedInfoBottomSheet(
FeedUnreadCount(
modifier = Modifier.fillMaxWidth().padding(horizontal = HORIZONTAL_PADDING),
numberOfUnreadPosts = feed.numberOfUnreadPosts,
onMarkPostsAsRead = { feedPresenter.dispatch(FeedEvent.OnMarkPostsAsRead(feed.link)) }
onMarkPostsAsRead = { feedPresenter.dispatch(FeedEvent.OnMarkPostsAsRead(feed.id)) }
)

Divider(horizontalInsets = HORIZONTAL_PADDING)

AlwaysFetchSourceArticleSwitch(
feed = feed,
onValueChanged = { newValue, feedLink ->
feedPresenter.dispatch(FeedEvent.OnAlwaysFetchSourceArticleChanged(newValue, feedLink))
onValueChanged = { newValue, feedId ->
feedPresenter.dispatch(FeedEvent.OnAlwaysFetchSourceArticleChanged(newValue, feedId))
}
)

Expand Down Expand Up @@ -354,7 +352,7 @@ private fun FeedOptions(feed: Feed, onRemoveFeedClick: () -> Unit, modifier: Mod
private fun AlwaysFetchSourceArticleSwitch(
feed: Feed,
modifier: Modifier = Modifier,
onValueChanged: (newValue: Boolean, feedLink: String) -> Unit
onValueChanged: (newValue: Boolean, feedId: String) -> Unit
) {
var checked by
remember(feed.alwaysFetchSourceArticle) { mutableStateOf(feed.alwaysFetchSourceArticle) }
Expand All @@ -363,7 +361,7 @@ private fun AlwaysFetchSourceArticleSwitch(
modifier =
Modifier.clickable {
checked = !checked
onValueChanged(checked, feed.link)
onValueChanged(checked, feed.id)
}
.padding(vertical = 16.dp, horizontal = HORIZONTAL_PADDING),
verticalAlignment = Alignment.CenterVertically
Expand All @@ -380,7 +378,7 @@ private fun AlwaysFetchSourceArticleSwitch(
Switch(
modifier = modifier,
checked = checked,
onCheckedChange = { newValue -> onValueChanged(newValue, feed.link) }
onCheckedChange = { newValue -> onValueChanged(newValue, feed.id) }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ sealed interface FeedsEvent {

data class OnToggleFeedSelection(val feed: Feed) : FeedsEvent

data class OnFeedNameUpdated(val newFeedName: String, val feedLink: String) : FeedsEvent
data class OnFeedNameUpdated(val newFeedName: String, val feedId: String) : FeedsEvent

data class OnFeedPinClicked(val feed: Feed) : FeedsEvent

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class FeedsPresenter(
FeedsEvent.OnGoBackClicked -> onGoBackClicked()
is FeedsEvent.OnDeleteFeed -> onDeleteFeed(event.feed)
is FeedsEvent.OnToggleFeedSelection -> onToggleFeedSelection(event.feed)
is FeedsEvent.OnFeedNameUpdated -> onFeedNameUpdated(event.newFeedName, event.feedLink)
is FeedsEvent.OnFeedNameUpdated -> onFeedNameUpdated(event.newFeedName, event.feedId)
is FeedsEvent.OnFeedPinClicked -> onFeedPinClicked(event.feed)
FeedsEvent.ClearSearchQuery -> clearSearchQuery()
is FeedsEvent.SearchQueryChanged -> onSearchQueryChanged(event.searchQuery)
Expand All @@ -156,7 +156,7 @@ class FeedsPresenter(

private fun onFeedClicked(feed: Feed) {
coroutineScope.launch {
if (_state.value.selectedFeed?.link != feed.link) {
if (_state.value.selectedFeed?.id != feed.id) {
observableSelectedFeed.selectFeed(feed)
}

Expand Down Expand Up @@ -229,14 +229,14 @@ class FeedsPresenter(
coroutineScope.launch { rssRepository.toggleFeedPinStatus(feed) }
}

private fun onFeedNameUpdated(newFeedName: String, feedLink: String) {
coroutineScope.launch { rssRepository.updateFeedName(newFeedName, feedLink) }
private fun onFeedNameUpdated(newFeedName: String, feedId: String) {
coroutineScope.launch { rssRepository.updateFeedName(newFeedName, feedId) }
}

private fun onDeleteFeed(feed: Feed) {
coroutineScope.launch {
rssRepository.removeFeed(feed.link)
if (_state.value.selectedFeed?.link == feed.link) {
rssRepository.removeFeed(feed.id)
if (_state.value.selectedFeed?.id == feed.id) {
observableSelectedFeed.clearSelection()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal fun BottomSheetCollapsedContent(
badgeCount = feed.numberOfUnreadPosts,
iconUrl = feed.icon,
canShowUnreadPostsCount = canShowUnreadPostsCount,
selected = selectedFeed?.link == feed.link,
selected = selectedFeed?.id == feed.id,
onClick = { onFeedClick(feed) }
)
}
Expand Down
Loading

0 comments on commit c371f7b

Please sign in to comment.