mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-02 07:34:25 +02:00
feat(experimental): auto open snaps
This commit is contained in:
parent
785fb49aa9
commit
68c61a0b73
@ -199,6 +199,14 @@
|
||||
"whitelist": "Unsaveable Messages"
|
||||
}
|
||||
},
|
||||
"auto_open_snaps": {
|
||||
"name": "Auto Open Snaps",
|
||||
"description": "Automatically opens Snaps when receiving them",
|
||||
"options": {
|
||||
"blacklist": "Exclude from Auto Open Snaps",
|
||||
"whitelist": "Auto Open Snaps"
|
||||
}
|
||||
},
|
||||
"hide_friend_feed": {
|
||||
"name": "Hide from Friend Feed"
|
||||
},
|
||||
@ -945,6 +953,7 @@
|
||||
"auto_download": "\u2B07\uFE0F Auto Download",
|
||||
"auto_save": "\uD83D\uDCAC Auto Save Messages",
|
||||
"unsaveable_messages": "\u2B07\uFE0F Unsaveable Messages",
|
||||
"auto_open_snaps": "\uD83D\uDCF7 Auto Open Snaps",
|
||||
"stealth": "\uD83D\uDC7B Stealth Mode",
|
||||
"mark_snaps_as_seen": "\uD83D\uDC40 Mark Snaps as seen",
|
||||
"mark_stories_as_seen_locally": "\uD83D\uDC40 Mark Stories as seen locally",
|
||||
@ -1357,6 +1366,11 @@
|
||||
"incoming_secret_message": "Your friend just accepted your public key. Click below to accept the secret."
|
||||
},
|
||||
|
||||
"auto_open_snaps": {
|
||||
"title": "Auto Open Snaps",
|
||||
"notification_content": "{count} Snaps opened"
|
||||
},
|
||||
|
||||
"suspend_location_updates": {
|
||||
"switch_text": "Suspend Location Updates"
|
||||
},
|
||||
|
@ -45,6 +45,7 @@ enum class MessagingRuleType(
|
||||
STEALTH("stealth", true),
|
||||
AUTO_DOWNLOAD("auto_download", true),
|
||||
AUTO_SAVE("auto_save", true, defaultValue = "blacklist"),
|
||||
AUTO_OPEN_SNAPS("auto_open_snaps", true, configNotices = arrayOf(FeatureNotice.BAN_RISK, FeatureNotice.UNSTABLE), defaultValue = null),
|
||||
UNSAVEABLE_MESSAGES("unsaveable_messages", true, configNotices = arrayOf(FeatureNotice.REQUIRE_NATIVE_HOOKS), defaultValue = null),
|
||||
HIDE_FRIEND_FEED("hide_friend_feed", false, showInFriendMenu = false),
|
||||
E2E_ENCRYPTION("e2e_encryption", false),
|
||||
|
@ -128,6 +128,7 @@ class FeatureManager(
|
||||
BetterLocation(),
|
||||
MediaFilePicker(),
|
||||
HideActiveMusic(),
|
||||
AutoOpenSnaps(),
|
||||
)
|
||||
|
||||
initializeFeatures()
|
||||
|
@ -0,0 +1,121 @@
|
||||
package me.rhunk.snapenhance.core.features.impl.experiments
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import me.rhunk.snapenhance.common.data.ContentType
|
||||
import me.rhunk.snapenhance.common.data.MessageUpdate
|
||||
import me.rhunk.snapenhance.common.data.MessagingRuleType
|
||||
import me.rhunk.snapenhance.core.event.events.impl.BuildMessageEvent
|
||||
import me.rhunk.snapenhance.core.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.core.features.MessagingRuleFeature
|
||||
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlin.random.Random
|
||||
|
||||
class AutoOpenSnaps: MessagingRuleFeature("Auto Open Snaps", MessagingRuleType.AUTO_OPEN_SNAPS, loadParams = FeatureLoadParams.INIT_SYNC) {
|
||||
private val snapQueue = MutableSharedFlow<Pair<String, Long>>()
|
||||
private var snapQueueSize = AtomicInteger(0)
|
||||
private val openedSnaps = mutableListOf<Long>()
|
||||
|
||||
private val notificationManager by lazy {
|
||||
context.androidContext.getSystemService(NotificationManager::class.java)
|
||||
}
|
||||
|
||||
private val notificationId by lazy { Random.nextInt() }
|
||||
|
||||
private val channelId by lazy {
|
||||
"auto_open_snaps".also {
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(it, context.translation["auto_open_snaps.title"], NotificationManager.IMPORTANCE_LOW)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendStatusNotification(count: Int) {
|
||||
notificationManager.notify(
|
||||
notificationId,
|
||||
Notification.Builder(context.androidContext, channelId)
|
||||
.setContentTitle(context.translation["auto_open_snaps.title"])
|
||||
.setContentText(context.translation.format("auto_open_snaps.notification_content", "count" to count.toString()))
|
||||
.setSmallIcon(android.R.drawable.ic_menu_view)
|
||||
.setProgress(0, 0, true)
|
||||
.build().apply {
|
||||
flags = flags or Notification.FLAG_ONLY_ALERT_ONCE
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
if (getRuleState() == null) return
|
||||
val messaging = context.feature(Messaging::class)
|
||||
|
||||
context.coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
|
||||
snapQueue.collect { (conversationId, messageId) ->
|
||||
snapQueueSize.addAndGet(-1)
|
||||
delay(Random.nextLong(50, 100))
|
||||
var result: String?
|
||||
|
||||
for (i in 0..5) {
|
||||
while (context.isMainActivityPaused || messaging.conversationManager == null) {
|
||||
delay(2000)
|
||||
}
|
||||
|
||||
result = suspendCoroutine { continuation ->
|
||||
runCatching {
|
||||
messaging.conversationManager?.updateMessage(conversationId, messageId, MessageUpdate.READ) { result ->
|
||||
continuation.resume(result)
|
||||
}
|
||||
}.getOrNull() ?: continuation.resume("ConversationManager is null")
|
||||
}
|
||||
|
||||
if (result != null && result != "DUPLICATEREQUEST") {
|
||||
context.log.warn("Failed to mark snap as read, retrying in 3 second")
|
||||
delay(3000)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if (snapQueueSize.get() <= 5) {
|
||||
notificationManager.cancel(notificationId)
|
||||
synchronized(openedSnaps) {
|
||||
openedSnaps.clear()
|
||||
}
|
||||
} else {
|
||||
sendStatusNotification(openedSnaps.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.event.subscribe(BuildMessageEvent::class, priority = 103) { event ->
|
||||
val conversationId = event.message.messageDescriptor?.conversationId?.toString() ?: return@subscribe
|
||||
val clientMessageId = event.message.messageDescriptor?.messageId ?: return@subscribe
|
||||
|
||||
if (
|
||||
event.message.messageContent?.contentType != ContentType.SNAP ||
|
||||
event.message.messageMetadata?.openedBy?.any { it.toString() == context.database.myUserId } == true
|
||||
) {
|
||||
return@subscribe
|
||||
}
|
||||
|
||||
context.coroutineScope.launch {
|
||||
if (!canUseRule(conversationId)) return@launch
|
||||
synchronized(openedSnaps) {
|
||||
if (openedSnaps.contains(clientMessageId)) {
|
||||
return@launch
|
||||
}
|
||||
openedSnaps.add(clientMessageId)
|
||||
}
|
||||
snapQueueSize.addAndGet(1)
|
||||
snapQueue.emit(conversationId to clientMessageId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user