emojireactions: Implement adding and removing on existing reactions
Based on 7bb0f1955d
by a1ba.
This commit is contained in:
parent
8d0a1f0927
commit
5d09d9a77c
|
@ -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
|
||||
|
|
|
@ -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!!
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in New Issue