emojireactions: Implement adding and removing on existing reactions

Based on 7bb0f1955d by a1ba.
This commit is contained in:
fruye 2022-11-09 19:39:15 +01:00
parent 8d0a1f0927
commit 5d09d9a77c
9 changed files with 62 additions and 0 deletions

View File

@ -23,3 +23,4 @@ data class PollVoteEvent(val statusId: String, val poll: Poll) : Event
data class DomainMuteEvent(val instance: String) : Event
data class AnnouncementReadEvent(val announcementId: String) : Event
data class PinEvent(val statusId: String, val pinned: Boolean) : Event
data class EmojiReactEvent(val newStatus: Status) : Event

View File

@ -28,6 +28,7 @@ import androidx.paging.map
import androidx.room.withTransaction
import com.google.gson.Gson
import com.keylesspalace.tusky.appstore.BookmarkEvent
import com.keylesspalace.tusky.appstore.EmojiReactEvent
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FavoriteEvent
import com.keylesspalace.tusky.appstore.PinEvent
@ -269,6 +270,10 @@ class CachedTimelineViewModel @Inject constructor(
// handled by CacheUpdater
}
override fun handleEmojiReactEvent(emojiReactionEvent: EmojiReactEvent) {
// handled by CacheUpdater
}
override fun fullReload() {
viewModelScope.launch {
val activeAccount = accountManager.activeAccount!!

View File

@ -24,6 +24,7 @@ import androidx.paging.PagingConfig
import androidx.paging.cachedIn
import androidx.paging.filter
import com.keylesspalace.tusky.appstore.BookmarkEvent
import com.keylesspalace.tusky.appstore.EmojiReactEvent
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FavoriteEvent
import com.keylesspalace.tusky.appstore.PinEvent
@ -243,6 +244,12 @@ class NetworkTimelineViewModel @Inject constructor(
}
}
override fun handleEmojiReactEvent(emojiReactionEvent: EmojiReactEvent) {
updateActionableStatusById(emojiReactionEvent.newStatus.actionableId) {
it.copy(pleroma = emojiReactionEvent.newStatus.actionableStatus.pleroma)
}
}
override fun fullReload() {
nextKey = statusData.firstOrNull { it is StatusViewData.Concrete }?.asStatusOrNull()?.id
statusData.clear()

View File

@ -26,6 +26,7 @@ import at.connyduck.calladapter.networkresult.getOrThrow
import com.keylesspalace.tusky.appstore.BlockEvent
import com.keylesspalace.tusky.appstore.BookmarkEvent
import com.keylesspalace.tusky.appstore.DomainMuteEvent
import com.keylesspalace.tusky.appstore.EmojiReactEvent
import com.keylesspalace.tusky.appstore.Event
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FavoriteEvent
@ -178,6 +179,8 @@ abstract class TimelineViewModel(
abstract fun handlePinEvent(pinEvent: PinEvent)
abstract fun handleEmojiReactEvent(emojiReactionEvent: EmojiReactEvent)
abstract fun fullReload()
abstract fun clearWarning(status: StatusViewData.Concrete)
@ -241,6 +244,7 @@ abstract class TimelineViewModel(
is ReblogEvent -> handleReblogEvent(event)
is BookmarkEvent -> handleBookmarkEvent(event)
is PinEvent -> handlePinEvent(event)
is EmojiReactEvent -> handleEmojiReactEvent(event)
is MuteConversationEvent -> fullReload()
is UnfollowEvent -> {
if (kind == Kind.HOME) {

View File

@ -24,6 +24,7 @@ import at.connyduck.calladapter.networkresult.getOrThrow
import com.google.gson.Gson
import com.keylesspalace.tusky.appstore.BlockEvent
import com.keylesspalace.tusky.appstore.BookmarkEvent
import com.keylesspalace.tusky.appstore.EmojiReactEvent
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FavoriteEvent
import com.keylesspalace.tusky.appstore.PinEvent
@ -94,6 +95,7 @@ class ViewThreadViewModel @Inject constructor(
is StatusComposedEvent -> handleStatusComposedEvent(event)
is StatusDeletedEvent -> handleStatusDeletedEvent(event)
is StatusEditedEvent -> handleStatusEditedEvent(event)
is EmojiReactEvent -> handleEmojiReactEvent(event)
}
}
}
@ -301,6 +303,12 @@ class ViewThreadViewModel @Inject constructor(
}
}
private fun handleEmojiReactEvent(event: EmojiReactEvent) {
updateStatus(event.newStatus.id) { status ->
status.copy(pleroma = event.newStatus.pleroma)
}
}
private fun removeAllByAccountId(accountId: String) {
updateSuccess { uiState ->
uiState.copy(

View File

@ -145,6 +145,14 @@ abstract class SFragment : Fragment(), Injectable {
popup.inflate(R.menu.emoji_reaction_more)
popup.setOnMenuItemClickListener { item: MenuItem ->
when (item.itemId) {
R.id.emoji_react -> {
onEmojiReact(statusId, reaction.name, true)
return@setOnMenuItemClickListener true
}
R.id.emoji_unreact -> {
onEmojiReact(statusId, reaction.name, false)
return@setOnMenuItemClickListener true
}
R.id.emoji_reacted_by -> {
val intent = newIntent(requireContext(), AccountListActivity.Type.REACTED, statusId, false /* FIXME */, reaction.name)
(requireActivity() as BaseActivity).startActivityWithSlideInAnimation(intent)
@ -426,6 +434,16 @@ abstract class SFragment : Fragment(), Injectable {
.show()
}
open fun onEmojiReact(id: String, emoji: String, react: Boolean) {
lifecycleScope.launch {
val result = timelineCases.react(id, emoji, react).exceptionOrNull()
if (result != null) {
Log.w("SFragment", "error reacting status", result)
Toast.makeText(context, R.string.error_generic, Toast.LENGTH_SHORT).show()
}
}
}
private fun editStatus(id: String, status: Status) {
lifecycleScope.launch {
mastodonApi.statusSource(id).fold(

View File

@ -22,6 +22,7 @@ import at.connyduck.calladapter.networkresult.onFailure
import at.connyduck.calladapter.networkresult.onSuccess
import com.keylesspalace.tusky.appstore.BlockEvent
import com.keylesspalace.tusky.appstore.BookmarkEvent
import com.keylesspalace.tusky.appstore.EmojiReactEvent
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FavoriteEvent
import com.keylesspalace.tusky.appstore.MuteConversationEvent
@ -68,6 +69,16 @@ class TimelineCases @Inject constructor(
}
}
suspend fun react(statusId: String, emoji: String, react: Boolean): NetworkResult<Status> {
return if (react) {
mastodonApi.reactWithEmoji(statusId, emoji)
} else {
mastodonApi.unreactWithEmoji(statusId, emoji)
}.onSuccess {
eventHub.dispatch(EmojiReactEvent(it))
}
}
suspend fun bookmark(statusId: String, bookmark: Boolean): NetworkResult<Status> {
return if (bookmark) {
mastodonApi.bookmarkStatus(statusId)

View File

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/emoji_react"
android:title="@string/action_emoji_react" />
<item
android:id="@+id/emoji_unreact"
android:title="@string/action_emoji_unreact" />
<item
android:id="@+id/emoji_reacted_by"
android:title="@string/action_emoji_reacted_by" />

View File

@ -6,6 +6,8 @@
<string name="admin">Admin</string>
<string name="moderator">Moderator</string>
<string name="action_emoji_react">Add reaction</string>
<string name="action_emoji_unreact">Remove reaction</string>
<string name="action_emoji_reacted_by">Who reacted</string>
<string name="title_emoji_reacted_by">%s reacted by</string>