Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package dev.dimension.flare.data.database.cache.mapper

import SnowflakeIdGenerator
import app.bsky.actor.ProfileView
import app.bsky.actor.ProfileViewBasic
import app.bsky.actor.ProfileViewDetailed
import app.bsky.bookmark.BookmarkView
import app.bsky.bookmark.BookmarkViewItemUnion
import app.bsky.feed.FeedViewPost
import app.bsky.feed.FeedViewPostReasonUnion
import app.bsky.feed.Like
import app.bsky.feed.PostView
import app.bsky.feed.ReplyRefParentUnion
import app.bsky.feed.Repost
import app.bsky.notification.ListNotificationsNotification
import app.bsky.notification.ListNotificationsReason
import app.bsky.notification.ListNotificationsNotificationReason
import chat.bsky.convo.ConvoView
import chat.bsky.convo.ConvoViewLastMessageUnion
import chat.bsky.convo.MessageView
Expand Down Expand Up @@ -149,6 +152,25 @@ internal object Bluesky {
}
}

internal suspend fun List<BookmarkView>.toDb(
accountKey: MicroBlogKey,
pagingKey: String,
sortIdProvider: suspend (BookmarkView) -> Long = {
it.createdAt?.toStdlibInstant()?.toEpochMilliseconds() ?: SnowflakeIdGenerator.nextId()
},
): List<DbPagingTimelineWithStatus> =
this.mapNotNull {
it.toDbStatusWithUser(accountKey)?.let { status ->
createDbPagingTimelineWithStatus(
accountKey = accountKey,
pagingKey = pagingKey,
sortId = sortIdProvider(it),
status = status,
references = mapOf(),
)
}
}

internal fun List<PostView>.toDb(
accountKey: MicroBlogKey,
pagingKey: String,
Expand All @@ -173,10 +195,10 @@ internal fun List<ListNotificationsNotification>.toDb(
val grouped = this.groupBy { it.reason }.filter { it.value.any() }
return grouped.flatMap { (reason, items) ->
when (reason) {
is ListNotificationsReason.Unknown,
ListNotificationsReason.StarterpackJoined,
ListNotificationsReason.Verified,
ListNotificationsReason.Unverified,
is ListNotificationsNotificationReason.Unknown,
ListNotificationsNotificationReason.StarterpackJoined,
ListNotificationsNotificationReason.Verified,
ListNotificationsNotificationReason.Unverified,
->
items.map {
createDbPagingTimelineWithStatus(
Expand All @@ -188,15 +210,15 @@ internal fun List<ListNotificationsNotification>.toDb(
)
}

ListNotificationsReason.Repost, ListNotificationsReason.Like -> {
ListNotificationsNotificationReason.Repost, ListNotificationsNotificationReason.Like -> {
val post =
items
.first()
.record
.let {
when (reason) {
ListNotificationsReason.Repost -> it.decodeAs<Repost>().subject
ListNotificationsReason.Like -> it.decodeAs<Like>().subject
ListNotificationsNotificationReason.Repost -> it.decodeAs<Repost>().subject
ListNotificationsNotificationReason.Like -> it.decodeAs<Like>().subject
else -> null
}
}?.uri
Expand All @@ -210,8 +232,8 @@ internal fun List<ListNotificationsNotification>.toDb(
)
val idSuffix =
when (reason) {
ListNotificationsReason.Repost -> "_repost"
ListNotificationsReason.Like -> "_like"
ListNotificationsNotificationReason.Repost -> "_repost"
ListNotificationsNotificationReason.Like -> "_like"
else -> ""
}
val data =
Expand Down Expand Up @@ -246,13 +268,18 @@ internal fun List<ListNotificationsNotification>.toDb(
listOfNotNull(
post,
).associate {
ReferenceType.Notification to listOfNotNull(it.toDbStatusWithUser(accountKey = accountKey))
ReferenceType.Notification to
listOfNotNull(
it.toDbStatusWithUser(
accountKey = accountKey,
),
)
},
),
)
}

ListNotificationsReason.Follow -> {
ListNotificationsNotificationReason.Follow -> {
val content = UserList(data = items, post = null)
val data =
DbStatusWithUser(
Expand Down Expand Up @@ -287,7 +314,10 @@ internal fun List<ListNotificationsNotification>.toDb(
)
}

ListNotificationsReason.Mention, ListNotificationsReason.Reply, ListNotificationsReason.Quote -> {
ListNotificationsNotificationReason.Mention,
ListNotificationsNotificationReason.Reply,
ListNotificationsNotificationReason.Quote,
-> {
items.mapNotNull {
val post = references[it.uri] ?: return@mapNotNull null
val content = Post(post = post)
Expand Down Expand Up @@ -316,13 +346,18 @@ internal fun List<ListNotificationsNotification>.toDb(
status = data,
references =
mapOf(
ReferenceType.Notification to listOfNotNull(post.toDbStatusWithUser(accountKey)),
ReferenceType.Notification to
listOfNotNull(
post.toDbStatusWithUser(
accountKey,
),
),
),
)
}
}

ListNotificationsReason.LikeViaRepost ->
ListNotificationsNotificationReason.LikeViaRepost ->
items.mapNotNull {
val post = references[it.uri] ?: return@mapNotNull null
val content = Post(post = post)
Expand Down Expand Up @@ -351,12 +386,17 @@ internal fun List<ListNotificationsNotification>.toDb(
status = data,
references =
mapOf(
ReferenceType.Notification to listOfNotNull(post.toDbStatusWithUser(accountKey)),
ReferenceType.Notification to
listOfNotNull(
post.toDbStatusWithUser(
accountKey,
),
),
),
)
}

ListNotificationsReason.RepostViaRepost ->
ListNotificationsNotificationReason.RepostViaRepost ->
items.mapNotNull {
val post = references[it.uri] ?: return@mapNotNull null
val content = Post(post = post)
Expand Down Expand Up @@ -385,12 +425,17 @@ internal fun List<ListNotificationsNotification>.toDb(
status = data,
references =
mapOf(
ReferenceType.Notification to listOfNotNull(post.toDbStatusWithUser(accountKey)),
ReferenceType.Notification to
listOfNotNull(
post.toDbStatusWithUser(
accountKey,
),
),
),
)
}

ListNotificationsReason.SubscribedPost -> {
ListNotificationsNotificationReason.SubscribedPost -> {
items.mapNotNull {
val post = references[it.uri] ?: return@mapNotNull null
val content = Post(post = post)
Expand Down Expand Up @@ -419,7 +464,12 @@ internal fun List<ListNotificationsNotification>.toDb(
status = data,
references =
mapOf(
ReferenceType.Notification to listOfNotNull(post.toDbStatusWithUser(accountKey)),
ReferenceType.Notification to
listOfNotNull(
post.toDbStatusWithUser(
accountKey,
),
),
),
)
}
Expand All @@ -428,6 +478,14 @@ internal fun List<ListNotificationsNotification>.toDb(
}
}

private fun BookmarkView.toDbStatusWithUser(accountKey: MicroBlogKey): DbStatusWithUser? =
when (val content = item) {
is BookmarkViewItemUnion.BlockedPost -> null
is BookmarkViewItemUnion.NotFoundPost -> null
is BookmarkViewItemUnion.PostView -> content.value.toDbStatusWithUser(accountKey)
is BookmarkViewItemUnion.Unknown -> null
}

private fun ListNotificationsNotification.toDbStatusWithUser(accountKey: MicroBlogKey): DbStatusWithUser {
val user = this.author.toDbUser(accountKey.host)
val status = this.toDbStatus(accountKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import app.bsky.actor.GetProfileQueryParams
import app.bsky.actor.PreferencesUnion
import app.bsky.actor.PutPreferencesRequest
import app.bsky.actor.SavedFeed
import app.bsky.actor.Type
import app.bsky.actor.SavedFeedType
import app.bsky.embed.Images
import app.bsky.embed.ImagesImage
import app.bsky.embed.Record
Expand Down Expand Up @@ -1190,7 +1190,7 @@ internal class BlueskyDataSource(
?.value
?.items
?.filter {
it.type == Type.Feed
it.type == SavedFeedType.Feed
}.orEmpty()
service
.getFeedGenerators(
Expand Down Expand Up @@ -1325,7 +1325,7 @@ internal class BlueskyDataSource(
(
pref.value.items +
SavedFeed(
type = Type.Feed,
type = SavedFeedType.Feed,
value = feedInfo.view.uri.atUri,
pinned = true,
id = Uuid.random().toString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package dev.dimension.flare.data.datasource.bluesky

import androidx.paging.ExperimentalPagingApi
import app.bsky.bookmark.GetBookmarksQueryParams
import dev.dimension.flare.common.BaseTimelineRemoteMediator
import dev.dimension.flare.data.database.cache.CacheDatabase
import dev.dimension.flare.data.database.cache.mapper.toDb
import dev.dimension.flare.data.network.bluesky.BlueskyService
import dev.dimension.flare.model.MicroBlogKey

@OptIn(ExperimentalPagingApi::class)
internal class BookmarkTimelineRemoteMediator(
private val service: BlueskyService,
database: CacheDatabase,
private val accountKey: MicroBlogKey,
) : BaseTimelineRemoteMediator(
database = database,
) {
override val pagingKey: String = "bookmark_$accountKey"

override suspend fun timeline(
pageSize: Int,
request: Request,
): Result {
val response =
when (request) {
Request.Refresh -> {
service
.getBookmarks(
GetBookmarksQueryParams(
limit = pageSize.toLong(),
),
).requireResponse()
}

is Request.Prepend -> {
return Result(
endOfPaginationReached = true,
)
}

is Request.Append -> {
service
.getBookmarks(
GetBookmarksQueryParams(
limit = pageSize.toLong(),
cursor = request.nextKey,
),
).requireResponse()
}
}

return Result(
endOfPaginationReached = response.bookmarks.isEmpty() || response.cursor == null,
data =
response.bookmarks.toDb(
accountKey = accountKey,
pagingKey = pagingKey,
),
nextKey = response.cursor,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import androidx.paging.ExperimentalPagingApi
import app.bsky.feed.GetPostsQueryParams
import app.bsky.feed.Like
import app.bsky.feed.Repost
import app.bsky.notification.ListNotificationsNotificationReason
import app.bsky.notification.ListNotificationsQueryParams
import app.bsky.notification.ListNotificationsReason
import app.bsky.notification.UpdateSeenRequest
import dev.dimension.flare.common.BaseTimelineRemoteMediator
import dev.dimension.flare.data.database.cache.CacheDatabase
Expand Down Expand Up @@ -79,27 +79,27 @@ internal class NotificationRemoteMediator(
response.notifications
.mapNotNull {
when (it.reason) {
is ListNotificationsReason.Unknown -> null
ListNotificationsReason.Like ->
is ListNotificationsNotificationReason.Unknown -> null
ListNotificationsNotificationReason.Like ->
it.record
.decodeAs<Like>()
.subject.uri

ListNotificationsReason.Repost ->
ListNotificationsNotificationReason.Repost ->
it.record
.decodeAs<Repost>()
.subject.uri

ListNotificationsReason.Follow -> null
ListNotificationsReason.Mention -> it.uri
ListNotificationsReason.Reply -> it.uri
ListNotificationsReason.Quote -> it.uri
ListNotificationsReason.StarterpackJoined -> null
ListNotificationsReason.Unverified -> null
ListNotificationsReason.Verified -> null
ListNotificationsReason.LikeViaRepost -> it.uri
ListNotificationsReason.RepostViaRepost -> it.uri
ListNotificationsReason.SubscribedPost -> it.uri
ListNotificationsNotificationReason.Follow -> null
ListNotificationsNotificationReason.Mention -> it.uri
ListNotificationsNotificationReason.Reply -> it.uri
ListNotificationsNotificationReason.Quote -> it.uri
ListNotificationsNotificationReason.StarterpackJoined -> null
ListNotificationsNotificationReason.Unverified -> null
ListNotificationsNotificationReason.Verified -> null
ListNotificationsNotificationReason.LikeViaRepost -> it.uri
ListNotificationsNotificationReason.RepostViaRepost -> it.uri
ListNotificationsNotificationReason.SubscribedPost -> it.uri
}
}.distinct()
.toImmutableList()
Expand Down
Loading
Loading