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
Expand Up @@ -17,6 +17,7 @@ package io.getstream.feeds.android.client.api.model

import io.getstream.feeds.android.client.internal.model.addReaction
import io.getstream.feeds.android.client.internal.model.removeReaction
import io.getstream.feeds.android.client.internal.utils.updateIf
import io.getstream.feeds.android.client.internal.utils.upsert
import io.getstream.feeds.android.network.models.ActivityLocation
import io.getstream.feeds.android.network.models.ActivityResponse
Expand Down Expand Up @@ -199,9 +200,14 @@ internal fun ActivityResponse.Visibility.toModel(): ActivityDataVisibility =

/**
* Extension function to update the activity while preserving own bookmarks, reactions, and poll
* votes because "own" data from WS events is not reliable.
* votes because "own" data from WS events is not reliable. Optionally, different instances can be
* provided to be used instead of the current ones.
*/
internal fun ActivityData.update(updated: ActivityData): ActivityData =
internal fun ActivityData.update(
updated: ActivityData,
ownBookmarks: List<BookmarkData> = this.ownBookmarks,
ownReactions: List<FeedsReactionData> = this.ownReactions,
): ActivityData =
updated.copy(
ownBookmarks = ownBookmarks,
ownReactions = ownReactions,
Expand Down Expand Up @@ -236,46 +242,64 @@ internal fun ActivityData.removeComment(comment: CommentData): ActivityData {
return this.copy(comments = updatedComments, commentCount = max(0, this.commentCount - 1))
}

internal fun List<ActivityData>.deleteBookmark(
bookmark: BookmarkData,
currentUserId: String,
): List<ActivityData> =
updateIf({ it.id == bookmark.activity.id }) { activity ->
activity.deleteBookmark(bookmark, currentUserId)
}

internal fun List<ActivityData>.upsertBookmark(
bookmark: BookmarkData,
currentUserId: String,
): List<ActivityData> =
updateIf({ it.id == bookmark.activity.id }) { activity ->
activity.upsertBookmark(bookmark, currentUserId)
}

/**
* Adds a bookmark to the activity, updating the own bookmarks and bookmark count.
* Calls [changeBookmarks] with a [filter] operation to remove the bookmark.
*
* @param bookmark The bookmark to be added.
* @param currentUserId The ID of the current user, used to determine if the bookmark belongs to
* them.
* @return A new [ActivityData] instance with the updated own bookmarks and bookmark count.
* @see changeBookmarks
*/
internal fun ActivityData.addBookmark(bookmark: BookmarkData, currentUserId: String): ActivityData {
val updatedOwnBookmarks =
if (bookmark.user.id == currentUserId) {
this.ownBookmarks.upsert(bookmark, BookmarkData::id)
} else {
this.ownBookmarks
}
return this.copy(ownBookmarks = updatedOwnBookmarks, bookmarkCount = this.bookmarkCount + 1)
}
internal fun ActivityData.deleteBookmark(bookmark: BookmarkData, currentUserId: String) =
changeBookmarks(bookmark, currentUserId) { filter { it.id != bookmark.id } }

/**
* Calls [changeBookmarks] with an [upsert] operation.
*
* @see changeBookmarks
*/
internal fun ActivityData.upsertBookmark(
bookmark: BookmarkData,
currentUserId: String,
): ActivityData = changeBookmarks(bookmark, currentUserId) { upsert(bookmark, BookmarkData::id) }

/**
* Deletes a bookmark from the activity, updating the own bookmarks and bookmark count.
* Merges the receiver activity with [bookmark]'s [BookmarkData.activity] and updates own bookmarks
* using the provided [updateOwnBookmarks] function if the bookmark belongs to the current user.
*
* @param bookmark The bookmark to be deleted.
* @param bookmark The bookmark that was added or removed.
* @param currentUserId The ID of the current user, used to determine if the bookmark belongs to
* them.
* @return A new [ActivityData] instance with the updated own bookmarks and bookmark count.
* @param updateOwnBookmarks A function that takes the current list of own bookmarks and returns the
* updated list of own bookmarks.
* @return The updated [ActivityData] instance.
*/
internal fun ActivityData.deleteBookmark(
internal inline fun ActivityData.changeBookmarks(
bookmark: BookmarkData,
currentUserId: String,
updateOwnBookmarks: List<BookmarkData>.() -> List<BookmarkData>,
): ActivityData {
val updatedOwnBookmarks =
if (bookmark.user.id == currentUserId) {
this.ownBookmarks.filter { it.id != bookmark.id }
this.ownBookmarks.updateOwnBookmarks()
} else {
this.ownBookmarks
}
return this.copy(
ownBookmarks = updatedOwnBookmarks,
bookmarkCount = max(0, this.bookmarkCount - 1),
)

return update(updated = bookmark.activity, ownBookmarks = updatedOwnBookmarks)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import io.getstream.feeds.android.client.api.model.CommentData
import io.getstream.feeds.android.client.api.model.FeedsReactionData
import io.getstream.feeds.android.client.api.model.PaginationData
import io.getstream.feeds.android.client.api.model.PaginationResult
import io.getstream.feeds.android.client.api.model.addBookmark
import io.getstream.feeds.android.client.api.model.addComment
import io.getstream.feeds.android.client.api.model.addReaction
import io.getstream.feeds.android.client.api.model.deleteBookmark
import io.getstream.feeds.android.client.api.model.removeComment
import io.getstream.feeds.android.client.api.model.removeReaction
import io.getstream.feeds.android.client.api.model.upsertBookmark
import io.getstream.feeds.android.client.api.state.ActivityListState
import io.getstream.feeds.android.client.api.state.query.ActivitiesQuery
import io.getstream.feeds.android.client.api.state.query.ActivitiesQueryConfig
Expand Down Expand Up @@ -92,30 +92,12 @@ internal class ActivityListStateImpl(
}
}

override fun onBookmarkAdded(bookmark: BookmarkData) {
_activities.update { current ->
current.map { activity ->
if (activity.id == bookmark.activity.id) {
// If the activity matches the bookmark, add the bookmark to it
activity.addBookmark(bookmark, currentUserId)
} else {
activity
}
}
}
override fun onBookmarkRemoved(bookmark: BookmarkData) {
_activities.update { current -> current.deleteBookmark(bookmark, currentUserId) }
}

override fun onBookmarkRemoved(bookmark: BookmarkData) {
_activities.update { current ->
current.map { activity ->
if (activity.id == bookmark.activity.id) {
// If the activity matches the bookmark, remove the bookmark from it
activity.deleteBookmark(bookmark, currentUserId)
} else {
activity
}
}
}
override fun onBookmarkUpserted(bookmark: BookmarkData) {
_activities.update { current -> current.upsertBookmark(bookmark, currentUserId) }
}

override fun onCommentAdded(comment: CommentData) {
Expand Down Expand Up @@ -206,18 +188,18 @@ internal interface ActivityListStateUpdates {
fun onActivityUpdated(activity: ActivityData)

/**
* Called when a bookmark was added.
* Called when a bookmark was removed.
*
* @param bookmark The bookmark that was added.
* @param bookmark The bookmark that was removed.
*/
fun onBookmarkAdded(bookmark: BookmarkData)
fun onBookmarkRemoved(bookmark: BookmarkData)

/**
* Called when a bookmark was removed.
* Called when a bookmark was added or updated.
*
* @param bookmark The bookmark that was removed.
* @param bookmark The bookmark that was added or updated.
*/
fun onBookmarkRemoved(bookmark: BookmarkData)
fun onBookmarkUpserted(bookmark: BookmarkData)

/**
* Called when a comment is added to an activity.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import io.getstream.feeds.android.client.api.model.FeedsReactionData
import io.getstream.feeds.android.client.api.model.PollData
import io.getstream.feeds.android.client.api.model.PollVoteData
import io.getstream.feeds.android.client.api.model.ThreadedCommentData
import io.getstream.feeds.android.client.api.model.addBookmark
import io.getstream.feeds.android.client.api.model.addReaction
import io.getstream.feeds.android.client.api.model.castVote
import io.getstream.feeds.android.client.api.model.deleteBookmark
import io.getstream.feeds.android.client.api.model.removeReaction
import io.getstream.feeds.android.client.api.model.removeVote
import io.getstream.feeds.android.client.api.model.setClosed
import io.getstream.feeds.android.client.api.model.update
import io.getstream.feeds.android.client.api.model.upsertBookmark
import io.getstream.feeds.android.client.api.state.ActivityCommentListState
import io.getstream.feeds.android.client.api.state.ActivityState
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -82,14 +82,14 @@ internal class ActivityStateImpl(
_activity.update { current -> current?.removeReaction(reaction, currentUserId) }
}

override fun onBookmarkAdded(bookmark: BookmarkData) {
_activity.update { current -> current?.addBookmark(bookmark, currentUserId) }
}

override fun onBookmarkRemoved(bookmark: BookmarkData) {
_activity.update { current -> current?.deleteBookmark(bookmark, currentUserId) }
}

override fun onBookmarkUpserted(bookmark: BookmarkData) {
_activity.update { current -> current?.upsertBookmark(bookmark, currentUserId) }
}

override fun onPollClosed(poll: PollData) {
updatePoll(poll.id, PollData::setClosed)
}
Expand Down Expand Up @@ -162,18 +162,18 @@ internal interface ActivityStateUpdates {
fun onReactionRemoved(reaction: FeedsReactionData)

/**
* Called when a bookmark is added to the activity.
* Called when a bookmark is removed from the activity.
*
* @param bookmark The bookmark that was added.
* @param bookmark The bookmark that was deleted.
*/
fun onBookmarkAdded(bookmark: BookmarkData)
fun onBookmarkRemoved(bookmark: BookmarkData)

/**
* Called when a bookmark is removed from the activity.
* Called when a bookmark is added to or updated in an activity.
*
* @param bookmark The bookmark that was deleted.
* @param bookmark The bookmark that was added or updated.
*/
fun onBookmarkRemoved(bookmark: BookmarkData)
fun onBookmarkUpserted(bookmark: BookmarkData)

/**
* Called when the associated poll is closed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import io.getstream.feeds.android.client.api.state.query.BookmarksQuery
import io.getstream.feeds.android.client.api.state.query.BookmarksQueryConfig
import io.getstream.feeds.android.client.api.state.query.BookmarksSort
import io.getstream.feeds.android.client.internal.utils.mergeSorted
import io.getstream.feeds.android.client.internal.utils.upsertSorted
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand Down Expand Up @@ -96,22 +97,15 @@ internal class BookmarkListStateImpl(override val query: BookmarksQuery) :
}
}

override fun onBookmarkUpdated(bookmark: BookmarkData) {
_bookmarks.update { current ->
current.map {
if (it.id == bookmark.id) {
// Update the bookmark with the new data
bookmark
} else {
it
}
}
}
}

override fun onBookmarkRemoved(bookmark: BookmarkData) {
_bookmarks.update { current -> current.filter { it.id != bookmark.id } }
}

override fun onBookmarkUpserted(bookmark: BookmarkData) {
_bookmarks.update { current ->
current.upsertSorted(bookmark, BookmarkData::id, bookmarksSorting)
}
}
}

/**
Expand All @@ -134,7 +128,7 @@ internal interface BookmarkListStateUpdates {

fun onBookmarkFolderUpdated(folder: BookmarkFolderData)

fun onBookmarkUpdated(bookmark: BookmarkData)

fun onBookmarkRemoved(bookmark: BookmarkData)

fun onBookmarkUpserted(bookmark: BookmarkData)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import io.getstream.feeds.android.client.api.model.PaginationResult
import io.getstream.feeds.android.client.api.model.PollData
import io.getstream.feeds.android.client.api.model.PollVoteData
import io.getstream.feeds.android.client.api.model.QueryConfiguration
import io.getstream.feeds.android.client.api.model.addBookmark
import io.getstream.feeds.android.client.api.model.addComment
import io.getstream.feeds.android.client.api.model.addReaction
import io.getstream.feeds.android.client.api.model.castVote
Expand All @@ -42,6 +41,7 @@ import io.getstream.feeds.android.client.api.model.removeReaction
import io.getstream.feeds.android.client.api.model.removeVote
import io.getstream.feeds.android.client.api.model.setClosed
import io.getstream.feeds.android.client.api.model.update
import io.getstream.feeds.android.client.api.model.upsertBookmark
import io.getstream.feeds.android.client.api.state.FeedState
import io.getstream.feeds.android.client.api.state.query.ActivitiesQueryConfig
import io.getstream.feeds.android.client.api.state.query.ActivitiesSort
Expand Down Expand Up @@ -191,28 +191,12 @@ internal class FeedStateImpl(
_pinnedActivities.update { current -> current.filter { it.activity.id != activityId } }
}

override fun onBookmarkAdded(bookmark: BookmarkData) {
_activities.update { current ->
current.map {
if (it.id == bookmark.activity.id) {
it.addBookmark(bookmark, currentUserId)
} else {
it
}
}
}
override fun onBookmarkRemoved(bookmark: BookmarkData) {
_activities.update { current -> current.deleteBookmark(bookmark, currentUserId) }
}

override fun onBookmarkRemoved(bookmark: BookmarkData) {
_activities.update { current ->
current.map {
if (it.id == bookmark.activity.id) {
it.deleteBookmark(bookmark, currentUserId)
} else {
it
}
}
}
override fun onBookmarkUpserted(bookmark: BookmarkData) {
_activities.update { current -> current.upsertBookmark(bookmark, currentUserId) }
}

override fun onCommentAdded(comment: CommentData) {
Expand Down Expand Up @@ -438,12 +422,12 @@ internal interface FeedStateUpdates {
/** Handles updates to the feed state when an activity is unpinned. */
fun onActivityUnpinned(activityId: String)

/** Handles updates to the feed state when a bookmark is added or removed. */
fun onBookmarkAdded(bookmark: BookmarkData)

/** Handles updates to the feed state when a bookmark is removed. */
fun onBookmarkRemoved(bookmark: BookmarkData)

/** Handles updates to the feed state when a bookmark is added or updated. */
fun onBookmarkUpserted(bookmark: BookmarkData)

/** Handles updates to the feed state when a comment is added or removed. */
fun onCommentAdded(comment: CommentData)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ internal class ActivityEventHandler(
is StateUpdateEvent.BookmarkAdded -> {
val eventActivity = event.bookmark.activity
if (fid.rawValue !in eventActivity.feeds || eventActivity.id != activityId) return
state.onBookmarkAdded(event.bookmark)
state.onBookmarkUpserted(event.bookmark)
}

is StateUpdateEvent.BookmarkDeleted -> {
Expand All @@ -68,6 +68,12 @@ internal class ActivityEventHandler(
state.onBookmarkRemoved(event.bookmark)
}

is StateUpdateEvent.BookmarkUpdated -> {
val eventActivity = event.bookmark.activity
if (fid.rawValue !in eventActivity.feeds || eventActivity.id != activityId) return
state.onBookmarkUpserted(event.bookmark)
}

is StateUpdateEvent.PollClosed -> {
if (event.fid != fid.rawValue) return
state.onPollClosed(event.poll)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ internal class ActivityListEventHandler(private val state: ActivityListStateUpda
is StateUpdateEvent.ActivityDeleted -> state.onActivityRemoved(event.activityId)
is StateUpdateEvent.ActivityReactionAdded -> state.onReactionAdded(event.reaction)
is StateUpdateEvent.ActivityReactionDeleted -> state.onReactionRemoved(event.reaction)
is StateUpdateEvent.BookmarkAdded -> state.onBookmarkAdded(event.bookmark)
is StateUpdateEvent.BookmarkAdded -> state.onBookmarkUpserted(event.bookmark)
is StateUpdateEvent.BookmarkDeleted -> state.onBookmarkRemoved(event.bookmark)
is StateUpdateEvent.BookmarkUpdated -> state.onBookmarkUpserted(event.bookmark)
is StateUpdateEvent.CommentAdded -> state.onCommentAdded(event.comment)
is StateUpdateEvent.CommentDeleted -> state.onCommentRemoved(event.comment)
else -> {
Expand Down
Loading