mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-03 07:54:30 +02:00
feat(experimental): auto open snaps
This commit is contained in:
parent
785fb49aa9
commit
68c61a0b73
@ -199,6 +199,14 @@
|
|||||||
"whitelist": "Unsaveable Messages"
|
"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": {
|
"hide_friend_feed": {
|
||||||
"name": "Hide from Friend Feed"
|
"name": "Hide from Friend Feed"
|
||||||
},
|
},
|
||||||
@ -945,6 +953,7 @@
|
|||||||
"auto_download": "\u2B07\uFE0F Auto Download",
|
"auto_download": "\u2B07\uFE0F Auto Download",
|
||||||
"auto_save": "\uD83D\uDCAC Auto Save Messages",
|
"auto_save": "\uD83D\uDCAC Auto Save Messages",
|
||||||
"unsaveable_messages": "\u2B07\uFE0F Unsaveable Messages",
|
"unsaveable_messages": "\u2B07\uFE0F Unsaveable Messages",
|
||||||
|
"auto_open_snaps": "\uD83D\uDCF7 Auto Open Snaps",
|
||||||
"stealth": "\uD83D\uDC7B Stealth Mode",
|
"stealth": "\uD83D\uDC7B Stealth Mode",
|
||||||
"mark_snaps_as_seen": "\uD83D\uDC40 Mark Snaps as seen",
|
"mark_snaps_as_seen": "\uD83D\uDC40 Mark Snaps as seen",
|
||||||
"mark_stories_as_seen_locally": "\uD83D\uDC40 Mark Stories as seen locally",
|
"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."
|
"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": {
|
"suspend_location_updates": {
|
||||||
"switch_text": "Suspend Location Updates"
|
"switch_text": "Suspend Location Updates"
|
||||||
},
|
},
|
||||||
|
@ -45,6 +45,7 @@ enum class MessagingRuleType(
|
|||||||
STEALTH("stealth", true),
|
STEALTH("stealth", true),
|
||||||
AUTO_DOWNLOAD("auto_download", true),
|
AUTO_DOWNLOAD("auto_download", true),
|
||||||
AUTO_SAVE("auto_save", true, defaultValue = "blacklist"),
|
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),
|
UNSAVEABLE_MESSAGES("unsaveable_messages", true, configNotices = arrayOf(FeatureNotice.REQUIRE_NATIVE_HOOKS), defaultValue = null),
|
||||||
HIDE_FRIEND_FEED("hide_friend_feed", false, showInFriendMenu = false),
|
HIDE_FRIEND_FEED("hide_friend_feed", false, showInFriendMenu = false),
|
||||||
E2E_ENCRYPTION("e2e_encryption", false),
|
E2E_ENCRYPTION("e2e_encryption", false),
|
||||||
|
@ -128,6 +128,7 @@ class FeatureManager(
|
|||||||
BetterLocation(),
|
BetterLocation(),
|
||||||
MediaFilePicker(),
|
MediaFilePicker(),
|
||||||
HideActiveMusic(),
|
HideActiveMusic(),
|
||||||
|
AutoOpenSnaps(),
|
||||||
)
|
)
|
||||||
|
|
||||||
initializeFeatures()
|
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