mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-21 15:05:19 +00:00
SS-78 / SES-199 Mechanism required to limit emoji reaction rate
This commit is contained in:
parent
a8ee5c9f3b
commit
edd154d8e1
@ -1,7 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2
|
package org.thoughtcrime.securesms.conversation.v2
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.Manifest.permission.ACCESS_FINE_LOCATION
|
|
||||||
import android.animation.FloatEvaluator
|
import android.animation.FloatEvaluator
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
@ -183,6 +182,7 @@ import org.thoughtcrime.securesms.util.push
|
|||||||
import org.thoughtcrime.securesms.util.show
|
import org.thoughtcrime.securesms.util.show
|
||||||
import org.thoughtcrime.securesms.util.toPx
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
import java.util.LinkedList
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@ -194,7 +194,6 @@ import kotlin.math.min
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
|
||||||
private const val TAG = "ConversationActivityV2"
|
private const val TAG = "ConversationActivityV2"
|
||||||
|
|
||||||
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
||||||
@ -285,7 +284,12 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
var searchViewItem: MenuItem? = null
|
var searchViewItem: MenuItem? = null
|
||||||
|
|
||||||
private val bufferedLastSeenChannel = Channel<Long>(capacity = 512, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
private val bufferedLastSeenChannel = Channel<Long>(capacity = 512, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||||
|
|
||||||
private var emojiPickerVisible = false
|
private var emojiPickerVisible = false
|
||||||
|
private val emojiRateLimiterQueue = LinkedList<String>()
|
||||||
|
private val emojiRateLimiterQueueSize = 4 // Maximum number of emoji reactions allowed per 20 seconds (as removal delay is 5 secs)
|
||||||
|
private val emojiRateLimiterRemovalDelayMS = 5000L // Remove an emoji from the queue after this many milliseconds
|
||||||
|
private val emojiRateLimitHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
private val isScrolledToBottom: Boolean
|
private val isScrolledToBottom: Boolean
|
||||||
get() = binding.conversationRecyclerView.isScrolledToBottom
|
get() = binding.conversationRecyclerView.isScrolledToBottom
|
||||||
@ -1343,7 +1347,29 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method to add an emoji to a queue and remove it a short while later - this is used as a
|
||||||
|
// rate-limiting mechanism and is called from the `sendEmojiReaction` method, below.
|
||||||
|
private fun currentlyEmojiReactRateLimited(emoji: String): Boolean {
|
||||||
|
if (emojiRateLimiterQueue.size >= emojiRateLimiterQueueSize) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
// Add the emoji to the queue, then a little while later remove it
|
||||||
|
emojiRateLimiterQueue.add(emoji)
|
||||||
|
emojiRateLimitHandler.postDelayed({
|
||||||
|
emojiRateLimiterQueue.remove(emoji)
|
||||||
|
}, emojiRateLimiterRemovalDelayMS)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun sendEmojiReaction(emoji: String, originalMessage: MessageRecord) {
|
private fun sendEmojiReaction(emoji: String, originalMessage: MessageRecord) {
|
||||||
|
|
||||||
|
// Only allow the emoji reaction if we aren't currently rate limited
|
||||||
|
if (currentlyEmojiReactRateLimited(emoji)) {
|
||||||
|
Toast.makeText(this, getString(R.string.emojiReactsCoolDown), Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Create the message
|
// Create the message
|
||||||
val recipient = viewModel.recipient ?: return Log.w(TAG, "Could not locate recipient when sending emoji reaction")
|
val recipient = viewModel.recipient ?: return Log.w(TAG, "Could not locate recipient when sending emoji reaction")
|
||||||
val reactionMessage = VisibleMessage()
|
val reactionMessage = VisibleMessage()
|
||||||
@ -1389,6 +1415,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method to remove a emoji reaction from a message.
|
||||||
|
// Note: We do not count emoji removal towards the emojiRateLimiterQueue.
|
||||||
private fun sendEmojiRemoval(emoji: String, originalMessage: MessageRecord) {
|
private fun sendEmojiRemoval(emoji: String, originalMessage: MessageRecord) {
|
||||||
val recipient = viewModel.recipient ?: return
|
val recipient = viewModel.recipient ?: return
|
||||||
val message = VisibleMessage()
|
val message = VisibleMessage()
|
||||||
|
Loading…
Reference in New Issue
Block a user