mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-29 21:10:20 +02:00
perf: bridge objects
- bridge oneway methods - scope sync
This commit is contained in:
parent
0994b8f36d
commit
8c71e4af27
@ -8,6 +8,7 @@ import java.io.ByteArrayOutputStream
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication)
|
||||
alias(libs.plugins.kotlinAndroid)
|
||||
id("kotlin-parcelize")
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -12,9 +12,8 @@ import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper
|
||||
import me.rhunk.snapenhance.common.data.MessagingFriendInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingGroupInfo
|
||||
import me.rhunk.snapenhance.common.data.SocialScope
|
||||
import me.rhunk.snapenhance.common.database.impl.FriendInfo
|
||||
import me.rhunk.snapenhance.common.logger.LogLevel
|
||||
import me.rhunk.snapenhance.common.util.SerializableDataObject
|
||||
import me.rhunk.snapenhance.common.util.toParcelable
|
||||
import me.rhunk.snapenhance.download.DownloadProcessor
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
@ -61,12 +60,12 @@ class BridgeService : Service() {
|
||||
|
||||
when (scope) {
|
||||
SocialScope.FRIEND -> {
|
||||
SerializableDataObject.fromJson<FriendInfo>(syncedObject).let {
|
||||
toParcelable<MessagingFriendInfo>(syncedObject)?.let {
|
||||
modDatabase.syncFriend(it)
|
||||
}
|
||||
}
|
||||
SocialScope.GROUP -> {
|
||||
SerializableDataObject.fromJson<MessagingGroupInfo>(syncedObject).let {
|
||||
toParcelable<MessagingGroupInfo>(syncedObject)?.let {
|
||||
modDatabase.syncGroupInfo(it)
|
||||
}
|
||||
}
|
||||
@ -169,8 +168,8 @@ class BridgeService : Service() {
|
||||
) {
|
||||
remoteSideContext.log.verbose("Received ${groups.size} groups and ${friends.size} friends")
|
||||
remoteSideContext.modDatabase.receiveMessagingDataCallback(
|
||||
friends.map { SerializableDataObject.fromJson<MessagingFriendInfo>(it) },
|
||||
groups.map { SerializableDataObject.fromJson<MessagingGroupInfo>(it) }
|
||||
friends.mapNotNull { toParcelable<MessagingFriendInfo>(it) },
|
||||
groups.mapNotNull { toParcelable<MessagingGroupInfo>(it) }
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import me.rhunk.snapenhance.common.data.FriendStreaks
|
||||
import me.rhunk.snapenhance.common.data.MessagingFriendInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingGroupInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingRuleType
|
||||
import me.rhunk.snapenhance.common.database.impl.FriendInfo
|
||||
import me.rhunk.snapenhance.common.scripting.type.ModuleInfo
|
||||
import me.rhunk.snapenhance.common.util.SQLiteDatabaseHelper
|
||||
import me.rhunk.snapenhance.common.util.ktx.getInteger
|
||||
@ -56,7 +55,7 @@ class ModDatabase(
|
||||
"targetUuid VARCHAR"
|
||||
),
|
||||
"streaks" to listOf(
|
||||
"userId VARCHAR PRIMARY KEY",
|
||||
"id VARCHAR PRIMARY KEY",
|
||||
"notify BOOLEAN",
|
||||
"expirationTimestamp BIGINT",
|
||||
"length INTEGER"
|
||||
@ -89,7 +88,7 @@ class ModDatabase(
|
||||
}
|
||||
|
||||
fun getFriends(descOrder: Boolean = false): List<MessagingFriendInfo> {
|
||||
return database.rawQuery("SELECT * FROM friends ORDER BY id ${if (descOrder) "DESC" else "ASC"}", null).use { cursor ->
|
||||
return database.rawQuery("SELECT * FROM friends LEFT OUTER JOIN streaks ON friends.userId = streaks.id ORDER BY id ${if (descOrder) "DESC" else "ASC"}", null).use { cursor ->
|
||||
val friends = mutableListOf<MessagingFriendInfo>()
|
||||
while (cursor.moveToNext()) {
|
||||
runCatching {
|
||||
@ -99,7 +98,14 @@ class ModDatabase(
|
||||
displayName = cursor.getStringOrNull("displayName"),
|
||||
mutableUsername = cursor.getStringOrNull("mutableUsername")!!,
|
||||
bitmojiId = cursor.getStringOrNull("bitmojiId"),
|
||||
selfieId = cursor.getStringOrNull("selfieId")
|
||||
selfieId = cursor.getStringOrNull("selfieId"),
|
||||
streaks = cursor.getLongOrNull("expirationTimestamp")?.let {
|
||||
FriendStreaks(
|
||||
notify = cursor.getInteger("notify") == 1,
|
||||
expirationTimestamp = it,
|
||||
length = cursor.getInteger("length")
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}.onFailure {
|
||||
@ -125,7 +131,7 @@ class ModDatabase(
|
||||
}
|
||||
}
|
||||
|
||||
fun syncFriend(friend: FriendInfo) {
|
||||
fun syncFriend(friend: MessagingFriendInfo) {
|
||||
executeAsync {
|
||||
try {
|
||||
database.execSQL(
|
||||
@ -133,24 +139,22 @@ class ModDatabase(
|
||||
arrayOf(
|
||||
friend.userId,
|
||||
friend.displayName,
|
||||
friend.usernameForSorting!!,
|
||||
friend.bitmojiAvatarId,
|
||||
friend.bitmojiSelfieId
|
||||
friend.mutableUsername,
|
||||
friend.bitmojiId,
|
||||
friend.selfieId
|
||||
)
|
||||
)
|
||||
//sync streaks
|
||||
if (friend.streakLength > 0) {
|
||||
val streaks = getFriendStreaks(friend.userId!!)
|
||||
friend.streaks?.takeIf { it.length > 0 }?.let {
|
||||
val streaks = getFriendStreaks(friend.userId)
|
||||
|
||||
database.execSQL("INSERT OR REPLACE INTO streaks (userId, notify, expirationTimestamp, length) VALUES (?, ?, ?, ?)", arrayOf(
|
||||
database.execSQL("INSERT OR REPLACE INTO streaks (id, notify, expirationTimestamp, length) VALUES (?, ?, ?, ?)", arrayOf(
|
||||
friend.userId,
|
||||
streaks?.notify ?: true,
|
||||
friend.streakExpirationTimestamp,
|
||||
friend.streakLength
|
||||
it.expirationTimestamp,
|
||||
it.length
|
||||
))
|
||||
} else {
|
||||
database.execSQL("DELETE FROM streaks WHERE userId = ?", arrayOf(friend.userId))
|
||||
}
|
||||
} ?: database.execSQL("DELETE FROM streaks WHERE id = ?", arrayOf(friend.userId))
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
@ -190,14 +194,21 @@ class ModDatabase(
|
||||
}
|
||||
|
||||
fun getFriendInfo(userId: String): MessagingFriendInfo? {
|
||||
return database.rawQuery("SELECT * FROM friends WHERE userId = ?", arrayOf(userId)).use { cursor ->
|
||||
return database.rawQuery("SELECT * FROM friends LEFT OUTER JOIN streaks ON friends.userId = streaks.id WHERE userId = ?", arrayOf(userId)).use { cursor ->
|
||||
if (!cursor.moveToFirst()) return@use null
|
||||
MessagingFriendInfo(
|
||||
userId = cursor.getStringOrNull("userId")!!,
|
||||
displayName = cursor.getStringOrNull("displayName"),
|
||||
mutableUsername = cursor.getStringOrNull("mutableUsername")!!,
|
||||
bitmojiId = cursor.getStringOrNull("bitmojiId"),
|
||||
selfieId = cursor.getStringOrNull("selfieId")
|
||||
selfieId = cursor.getStringOrNull("selfieId"),
|
||||
streaks = cursor.getLongOrNull("expirationTimestamp")?.let {
|
||||
FriendStreaks(
|
||||
notify = cursor.getInteger("notify") == 1,
|
||||
expirationTimestamp = it,
|
||||
length = cursor.getInteger("length")
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -205,7 +216,7 @@ class ModDatabase(
|
||||
fun deleteFriend(userId: String) {
|
||||
executeAsync {
|
||||
database.execSQL("DELETE FROM friends WHERE userId = ?", arrayOf(userId))
|
||||
database.execSQL("DELETE FROM streaks WHERE userId = ?", arrayOf(userId))
|
||||
database.execSQL("DELETE FROM streaks WHERE id = ?", arrayOf(userId))
|
||||
database.execSQL("DELETE FROM rules WHERE targetUuid = ?", arrayOf(userId))
|
||||
}
|
||||
}
|
||||
@ -229,10 +240,9 @@ class ModDatabase(
|
||||
}
|
||||
|
||||
fun getFriendStreaks(userId: String): FriendStreaks? {
|
||||
return database.rawQuery("SELECT * FROM streaks WHERE userId = ?", arrayOf(userId)).use { cursor ->
|
||||
return database.rawQuery("SELECT * FROM streaks WHERE id = ?", arrayOf(userId)).use { cursor ->
|
||||
if (!cursor.moveToFirst()) return@use null
|
||||
FriendStreaks(
|
||||
userId = cursor.getStringOrNull("userId")!!,
|
||||
notify = cursor.getInteger("notify") == 1,
|
||||
expirationTimestamp = cursor.getLongOrNull("expirationTimestamp") ?: 0L,
|
||||
length = cursor.getInteger("length")
|
||||
@ -242,7 +252,7 @@ class ModDatabase(
|
||||
|
||||
fun setFriendStreaksNotify(userId: String, notify: Boolean) {
|
||||
executeAsync {
|
||||
database.execSQL("UPDATE streaks SET notify = ? WHERE userId = ?", arrayOf(
|
||||
database.execSQL("UPDATE streaks SET notify = ? WHERE id = ?", arrayOf(
|
||||
if (notify) 1 else 0,
|
||||
userId
|
||||
))
|
||||
|
@ -26,7 +26,9 @@ import androidx.compose.ui.window.Dialog
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navigation
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import me.rhunk.snapenhance.R
|
||||
import me.rhunk.snapenhance.common.data.MessagingFriendInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingGroupInfo
|
||||
@ -214,8 +216,13 @@ class SocialSection : Section() {
|
||||
|
||||
SocialScope.FRIEND -> {
|
||||
val friend = friendList[index]
|
||||
val streaks =
|
||||
remember { context.modDatabase.getFriendStreaks(friend.userId) }
|
||||
var streaks by remember { mutableStateOf(friend.streaks) }
|
||||
|
||||
LaunchedEffect(friend.userId) {
|
||||
withContext(Dispatchers.IO) {
|
||||
streaks = context.modDatabase.getFriendStreaks(friend.userId)
|
||||
}
|
||||
}
|
||||
|
||||
BitmojiImage(
|
||||
context = context,
|
||||
@ -244,7 +251,7 @@ class SocialSection : Section() {
|
||||
)
|
||||
}
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
if (streaks != null && streaks.notify) {
|
||||
streaks?.takeIf { it.notify }?.let { streaks ->
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = R.drawable.streak_icon),
|
||||
contentDescription = null,
|
||||
@ -256,7 +263,7 @@ class SocialSection : Section() {
|
||||
Text(
|
||||
text = context.translation.format(
|
||||
"manager.sections.social.streaks_expiration_short",
|
||||
"hours" to ((streaks.expirationTimestamp - System.currentTimeMillis()) / 3600000).toInt()
|
||||
"hours" to (((streaks.expirationTimestamp - System.currentTimeMillis()) / 3600000).toInt().takeIf { it > 0 } ?: 0)
|
||||
.toString()
|
||||
),
|
||||
maxLines = 1,
|
||||
|
@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
alias(libs.plugins.androidLibrary)
|
||||
alias(libs.plugins.kotlinAndroid)
|
||||
id("kotlin-parcelize")
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -13,7 +13,7 @@ interface BridgeInterface {
|
||||
/**
|
||||
* broadcast a log message
|
||||
*/
|
||||
void broadcastLog(String tag, String level, String message);
|
||||
oneway void broadcastLog(String tag, String level, String message);
|
||||
|
||||
/**
|
||||
* Execute a file operation
|
||||
@ -36,7 +36,7 @@ interface BridgeInterface {
|
||||
/**
|
||||
* Enqueue a download
|
||||
*/
|
||||
void enqueueDownload(in Intent intent, DownloadCallback callback);
|
||||
oneway void enqueueDownload(in Intent intent, DownloadCallback callback);
|
||||
|
||||
/**
|
||||
* Get rules for a given user or conversation
|
||||
@ -56,7 +56,7 @@ interface BridgeInterface {
|
||||
*
|
||||
* @param type rule type (MessagingRuleType)
|
||||
*/
|
||||
void setRule(String uuid, String type, boolean state);
|
||||
oneway void setRule(String uuid, String type, boolean state);
|
||||
|
||||
/**
|
||||
* Sync groups and friends
|
||||
@ -66,12 +66,12 @@ interface BridgeInterface {
|
||||
/**
|
||||
* Trigger sync for an id
|
||||
*/
|
||||
void triggerSync(String scope, String id);
|
||||
oneway void triggerSync(String scope, String id);
|
||||
|
||||
/**
|
||||
* Pass all groups and friends to be able to add them to the database
|
||||
* @param groups list of groups (MessagingGroupInfo as json string)
|
||||
* @param friends list of friends (MessagingFriendInfo as json string)
|
||||
* @param groups list of groups (MessagingGroupInfo as parcelable)
|
||||
* @param friends list of friends (MessagingFriendInfo as parcelable)
|
||||
*/
|
||||
oneway void passGroupsAndFriends(in List<String> groups, in List<String> friends);
|
||||
|
||||
@ -81,11 +81,11 @@ interface BridgeInterface {
|
||||
|
||||
MessageLoggerInterface getMessageLogger();
|
||||
|
||||
void registerMessagingBridge(MessagingBridge bridge);
|
||||
oneway void registerMessagingBridge(MessagingBridge bridge);
|
||||
|
||||
void openSettingsOverlay();
|
||||
oneway void openSettingsOverlay();
|
||||
|
||||
void closeSettingsOverlay();
|
||||
oneway void closeSettingsOverlay();
|
||||
|
||||
void registerConfigStateListener(in ConfigStateListener listener);
|
||||
oneway void registerConfigStateListener(in ConfigStateListener listener);
|
||||
}
|
@ -8,11 +8,11 @@ interface IScripting {
|
||||
|
||||
@nullable String getScriptContent(String path);
|
||||
|
||||
void registerIPCListener(String channel, String eventName, IPCListener listener);
|
||||
oneway void registerIPCListener(String channel, String eventName, IPCListener listener);
|
||||
|
||||
void sendIPCMessage(String channel, String eventName, in String[] args);
|
||||
oneway void sendIPCMessage(String channel, String eventName, in String[] args);
|
||||
|
||||
@nullable String configTransaction(String module, String action, @nullable String key, @nullable String value, boolean save);
|
||||
|
||||
void registerAutoReloadListener(in AutoReloadListener listener);
|
||||
oneway void registerAutoReloadListener(in AutoReloadListener listener);
|
||||
}
|
@ -33,7 +33,7 @@ class ModConfig(
|
||||
private fun load() {
|
||||
root = createRootConfig()
|
||||
wasPresent = file.isFileExists()
|
||||
if (!file.isFileExists()) {
|
||||
if (!wasPresent) {
|
||||
writeConfig()
|
||||
return
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
package me.rhunk.snapenhance.common.data
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import me.rhunk.snapenhance.common.config.FeatureNotice
|
||||
import me.rhunk.snapenhance.common.util.SerializableDataObject
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
|
||||
|
||||
@ -52,12 +53,12 @@ enum class MessagingRuleType(
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class FriendStreaks(
|
||||
val userId: String,
|
||||
val notify: Boolean,
|
||||
val notify: Boolean = true,
|
||||
val expirationTimestamp: Long,
|
||||
val length: Int
|
||||
) : SerializableDataObject() {
|
||||
): Parcelable {
|
||||
fun hoursLeft() = (expirationTimestamp - System.currentTimeMillis()) / 1000 / 60 / 60
|
||||
|
||||
fun isAboutToExpire(expireHours: Int) = (expirationTimestamp - System.currentTimeMillis()).let {
|
||||
@ -65,20 +66,22 @@ data class FriendStreaks(
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class MessagingGroupInfo(
|
||||
val conversationId: String,
|
||||
val name: String,
|
||||
val participantsCount: Int
|
||||
) : SerializableDataObject()
|
||||
): Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class MessagingFriendInfo(
|
||||
val userId: String,
|
||||
val displayName: String?,
|
||||
val mutableUsername: String,
|
||||
val bitmojiId: String?,
|
||||
val selfieId: String?
|
||||
) : SerializableDataObject()
|
||||
|
||||
val selfieId: String?,
|
||||
var streaks: FriendStreaks?,
|
||||
): Parcelable
|
||||
|
||||
class StoryData(
|
||||
val url: String,
|
||||
@ -86,4 +89,4 @@ class StoryData(
|
||||
val createdAt: Long,
|
||||
val key: ByteArray?,
|
||||
val iv: ByteArray?
|
||||
) : SerializableDataObject()
|
||||
)
|
@ -3,7 +3,6 @@ package me.rhunk.snapenhance.common.database.impl
|
||||
import android.annotation.SuppressLint
|
||||
import android.database.Cursor
|
||||
import me.rhunk.snapenhance.common.database.DatabaseObject
|
||||
import me.rhunk.snapenhance.common.util.SerializableDataObject
|
||||
import me.rhunk.snapenhance.common.util.ktx.getInteger
|
||||
import me.rhunk.snapenhance.common.util.ktx.getLong
|
||||
import me.rhunk.snapenhance.common.util.ktx.getStringOrNull
|
||||
@ -33,7 +32,7 @@ data class FriendInfo(
|
||||
var usernameForSorting: String? = null,
|
||||
var friendLinkType: Int = 0,
|
||||
var postViewEmoji: String? = null,
|
||||
) : DatabaseObject, SerializableDataObject() {
|
||||
) : DatabaseObject {
|
||||
val mutableUsername get() = username?.split("|")?.last()
|
||||
val firstCreatedUsername get() = username?.split("|")?.first()
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
package me.rhunk.snapenhance.common.util
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.parcelableCreator
|
||||
import kotlin.io.encoding.Base64
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
|
||||
@OptIn(ExperimentalEncodingApi::class)
|
||||
fun Parcelable.toSerialized(): String? {
|
||||
val parcel = android.os.Parcel.obtain()
|
||||
return try {
|
||||
writeToParcel(parcel, 0)
|
||||
parcel.marshall()?.let {
|
||||
Base64.encode(it)
|
||||
}
|
||||
} finally {
|
||||
parcel.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalEncodingApi::class)
|
||||
inline fun <reified T : Parcelable> toParcelable(serialized: String): T? {
|
||||
val parcel = android.os.Parcel.obtain()
|
||||
return try {
|
||||
Base64.decode(serialized).let {
|
||||
parcel.unmarshall(it, 0, it.size)
|
||||
}
|
||||
parcel.setDataPosition(0)
|
||||
parcelableCreator<T>().createFromParcel(parcel)
|
||||
} finally {
|
||||
parcel.recycle()
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package me.rhunk.snapenhance.common.util
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
|
||||
open class SerializableDataObject {
|
||||
companion object {
|
||||
val gson: Gson = GsonBuilder().create()
|
||||
|
||||
inline fun <reified T : SerializableDataObject> fromJson(json: String): T {
|
||||
return gson.fromJson(json, T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : SerializableDataObject> fromJson(json: String, type: Class<T>): T {
|
||||
return gson.fromJson(json, type)
|
||||
}
|
||||
}
|
||||
|
||||
fun toJson(): String {
|
||||
return gson.toJson(this)
|
||||
}
|
||||
}
|
@ -13,8 +13,10 @@ import me.rhunk.snapenhance.bridge.SyncCallback
|
||||
import me.rhunk.snapenhance.common.Constants
|
||||
import me.rhunk.snapenhance.common.ReceiversConfig
|
||||
import me.rhunk.snapenhance.common.action.EnumAction
|
||||
import me.rhunk.snapenhance.common.data.FriendStreaks
|
||||
import me.rhunk.snapenhance.common.data.MessagingFriendInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingGroupInfo
|
||||
import me.rhunk.snapenhance.common.util.toSerialized
|
||||
import me.rhunk.snapenhance.core.bridge.BridgeClient
|
||||
import me.rhunk.snapenhance.core.bridge.loadFromBridge
|
||||
import me.rhunk.snapenhance.core.data.SnapClassCache
|
||||
@ -151,7 +153,6 @@ class SnapEnhance {
|
||||
features.init()
|
||||
scriptRuntime.connect(bridgeClient.getScriptingInterface())
|
||||
scriptRuntime.eachModule { callFunction("module.onSnapApplicationLoad", androidContext) }
|
||||
syncRemote()
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +196,7 @@ class SnapEnhance {
|
||||
}
|
||||
}
|
||||
|
||||
appContext.apply {
|
||||
appContext.executeAsync {
|
||||
bridgeClient.registerConfigStateListener(object: ConfigStateListener.Stub() {
|
||||
override fun onConfigChanged() {
|
||||
log.verbose("onConfigChanged")
|
||||
@ -227,7 +228,21 @@ class SnapEnhance {
|
||||
appContext.executeAsync {
|
||||
bridgeClient.sync(object : SyncCallback.Stub() {
|
||||
override fun syncFriend(uuid: String): String? {
|
||||
return database.getFriendInfo(uuid)?.toJson()
|
||||
return database.getFriendInfo(uuid)?.let {
|
||||
MessagingFriendInfo(
|
||||
userId = it.userId!!,
|
||||
displayName = it.displayName,
|
||||
mutableUsername = it.mutableUsername!!,
|
||||
bitmojiId = it.bitmojiAvatarId,
|
||||
selfieId = it.bitmojiSelfieId,
|
||||
streaks = if (it.streakLength > 0) {
|
||||
FriendStreaks(
|
||||
expirationTimestamp = it.streakExpirationTimestamp,
|
||||
length = it.streakLength
|
||||
)
|
||||
} else null
|
||||
).toSerialized()
|
||||
}
|
||||
}
|
||||
|
||||
override fun syncGroup(uuid: String): String? {
|
||||
@ -236,7 +251,7 @@ class SnapEnhance {
|
||||
it.key!!,
|
||||
it.feedDisplayName!!,
|
||||
it.participantsSize
|
||||
).toJson()
|
||||
).toSerialized()
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -260,14 +275,12 @@ class SnapEnhance {
|
||||
it.friendDisplayName,
|
||||
it.friendDisplayUsername!!.split("|")[1],
|
||||
it.bitmojiAvatarId,
|
||||
it.bitmojiSelfieId
|
||||
it.bitmojiSelfieId,
|
||||
streaks = null
|
||||
)
|
||||
}
|
||||
|
||||
bridgeClient.passGroupsAndFriends(
|
||||
groups.map { it.toJson() },
|
||||
friends.map { it.toJson() }
|
||||
)
|
||||
bridgeClient.passGroupsAndFriends(groups, friends)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,11 @@ import me.rhunk.snapenhance.common.bridge.FileLoaderWrapper
|
||||
import me.rhunk.snapenhance.common.bridge.types.BridgeFileType
|
||||
import me.rhunk.snapenhance.common.bridge.types.FileActionType
|
||||
import me.rhunk.snapenhance.common.bridge.types.LocalePair
|
||||
import me.rhunk.snapenhance.common.data.MessagingFriendInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingGroupInfo
|
||||
import me.rhunk.snapenhance.common.data.MessagingRuleType
|
||||
import me.rhunk.snapenhance.common.data.SocialScope
|
||||
import me.rhunk.snapenhance.common.util.toSerialized
|
||||
import me.rhunk.snapenhance.core.ModContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.Executors
|
||||
@ -136,7 +139,10 @@ class BridgeClient(
|
||||
|
||||
fun triggerSync(scope: SocialScope, id: String) = service.triggerSync(scope.key, id)
|
||||
|
||||
fun passGroupsAndFriends(groups: List<String>, friends: List<String>) = service.passGroupsAndFriends(groups, friends)
|
||||
fun passGroupsAndFriends(groups: List<MessagingGroupInfo>, friends: List<MessagingFriendInfo>) = service.passGroupsAndFriends(
|
||||
groups.mapNotNull { it.toSerialized() },
|
||||
friends.mapNotNull { it.toSerialized() }
|
||||
)
|
||||
|
||||
fun getRules(targetUuid: String): List<MessagingRuleType> {
|
||||
return service.getRules(targetUuid).mapNotNull { MessagingRuleType.getByName(it) }
|
||||
|
@ -15,12 +15,12 @@ class ActionManager(
|
||||
|
||||
private val actions by lazy {
|
||||
mapOf(
|
||||
EnumAction.CLEAN_CACHE to CleanCache::class,
|
||||
EnumAction.EXPORT_CHAT_MESSAGES to ExportChatMessages::class,
|
||||
EnumAction.BULK_MESSAGING_ACTION to BulkMessagingAction::class,
|
||||
EnumAction.EXPORT_MEMORIES to ExportMemories::class,
|
||||
EnumAction.CLEAN_CACHE to CleanCache(),
|
||||
EnumAction.EXPORT_CHAT_MESSAGES to ExportChatMessages(),
|
||||
EnumAction.BULK_MESSAGING_ACTION to BulkMessagingAction(),
|
||||
EnumAction.EXPORT_MEMORIES to ExportMemories(),
|
||||
).map {
|
||||
it.key to it.value.java.getConstructor().newInstance().apply {
|
||||
it.key to it.value.apply {
|
||||
this.context = modContext
|
||||
}
|
||||
}.toMap().toMutableMap()
|
||||
|
@ -8,17 +8,15 @@ import me.rhunk.snapenhance.core.features.Feature
|
||||
import me.rhunk.snapenhance.core.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.core.features.MessagingRuleFeature
|
||||
import me.rhunk.snapenhance.core.features.impl.ConfigurationOverride
|
||||
import me.rhunk.snapenhance.core.features.impl.MixerStories
|
||||
import me.rhunk.snapenhance.core.features.impl.OperaViewerParamsOverride
|
||||
import me.rhunk.snapenhance.core.features.impl.ScopeSync
|
||||
import me.rhunk.snapenhance.core.features.impl.MixerStories
|
||||
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
|
||||
import me.rhunk.snapenhance.core.features.impl.downloader.ProfilePictureDownloader
|
||||
import me.rhunk.snapenhance.core.features.impl.experiments.*
|
||||
import me.rhunk.snapenhance.core.features.impl.global.*
|
||||
import me.rhunk.snapenhance.core.features.impl.messaging.*
|
||||
import me.rhunk.snapenhance.core.features.impl.spying.HalfSwipeNotifier
|
||||
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
|
||||
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
|
||||
import me.rhunk.snapenhance.core.features.impl.spying.*
|
||||
import me.rhunk.snapenhance.core.features.impl.tweaks.BypassScreenshotDetection
|
||||
import me.rhunk.snapenhance.core.features.impl.tweaks.CameraTweaks
|
||||
import me.rhunk.snapenhance.core.features.impl.tweaks.PreventMessageListAutoScroll
|
||||
@ -33,23 +31,19 @@ import kotlin.system.measureTimeMillis
|
||||
class FeatureManager(
|
||||
private val context: ModContext
|
||||
) : Manager {
|
||||
private val features = mutableListOf<Feature>()
|
||||
private val features = mutableMapOf<KClass<out Feature>, Feature>()
|
||||
|
||||
private fun register(vararg featureClasses: KClass<out Feature>) {
|
||||
private fun register(vararg featureList: Feature) {
|
||||
runBlocking {
|
||||
featureClasses.forEach { clazz ->
|
||||
featureList.forEach { feature ->
|
||||
launch(Dispatchers.IO) {
|
||||
runCatching {
|
||||
clazz.java.constructors.first().newInstance()
|
||||
.let { it as Feature }
|
||||
.also {
|
||||
it.context = context
|
||||
feature.context = context
|
||||
synchronized(features) {
|
||||
features.add(it)
|
||||
}
|
||||
features[feature::class] = feature
|
||||
}
|
||||
}.onFailure {
|
||||
CoreLogger.xposedLog("Failed to register feature ${clazz.simpleName}", it)
|
||||
CoreLogger.xposedLog("Failed to register feature ${feature.featureKey}", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,82 +52,76 @@ class FeatureManager(
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Feature> get(featureClass: KClass<T>): T? {
|
||||
return features.find { it::class == featureClass } as? T
|
||||
return features[featureClass] as? T
|
||||
}
|
||||
|
||||
fun getRuleFeatures() = features.filterIsInstance<MessagingRuleFeature>().sortedBy { it.ruleType.ordinal }
|
||||
fun getRuleFeatures() = features.values.filterIsInstance<MessagingRuleFeature>().sortedBy { it.ruleType.ordinal }
|
||||
|
||||
override fun init() {
|
||||
register(
|
||||
EndToEndEncryption::class,
|
||||
ScopeSync::class,
|
||||
PreventMessageListAutoScroll::class,
|
||||
Messaging::class,
|
||||
MediaDownloader::class,
|
||||
StealthMode::class,
|
||||
MenuViewInjector::class,
|
||||
PreventReadReceipts::class,
|
||||
MessageLogger::class,
|
||||
ConvertMessageLocally::class,
|
||||
SnapchatPlus::class,
|
||||
DisableMetrics::class,
|
||||
PreventMessageSending::class,
|
||||
Notifications::class,
|
||||
AutoSave::class,
|
||||
UITweaks::class,
|
||||
ConfigurationOverride::class,
|
||||
UnsaveableMessages::class,
|
||||
SendOverride::class,
|
||||
UnlimitedSnapViewTime::class,
|
||||
BypassVideoLengthRestriction::class,
|
||||
MediaQualityLevelOverride::class,
|
||||
MeoPasscodeBypass::class,
|
||||
AppPasscode::class,
|
||||
LocationSpoofer::class,
|
||||
CameraTweaks::class,
|
||||
InfiniteStoryBoost::class,
|
||||
AmoledDarkMode::class,
|
||||
PinConversations::class,
|
||||
UnlimitedMultiSnap::class,
|
||||
DeviceSpooferHook::class,
|
||||
ClientBootstrapOverride::class,
|
||||
GooglePlayServicesDialogs::class,
|
||||
NoFriendScoreDelay::class,
|
||||
ProfilePictureDownloader::class,
|
||||
AddFriendSourceSpoof::class,
|
||||
DisableReplayInFF::class,
|
||||
OldBitmojiSelfie::class,
|
||||
FriendFeedMessagePreview::class,
|
||||
HideStreakRestore::class,
|
||||
HideFriendFeedEntry::class,
|
||||
HideQuickAddFriendFeed::class,
|
||||
CallStartConfirmation::class,
|
||||
SnapPreview::class,
|
||||
InstantDelete::class,
|
||||
BypassScreenshotDetection::class,
|
||||
HalfSwipeNotifier::class,
|
||||
DisableConfirmationDialogs::class,
|
||||
MixerStories::class,
|
||||
DisableComposerModules::class,
|
||||
FideliusIndicator::class,
|
||||
EditTextOverride::class,
|
||||
PreventForcedLogout::class,
|
||||
SuspendLocationUpdates::class,
|
||||
ConversationToolbox::class,
|
||||
SpotlightCommentsUsername::class,
|
||||
OperaViewerParamsOverride::class,
|
||||
EndToEndEncryption(),
|
||||
ScopeSync(),
|
||||
PreventMessageListAutoScroll(),
|
||||
Messaging(),
|
||||
MediaDownloader(),
|
||||
StealthMode(),
|
||||
MenuViewInjector(),
|
||||
PreventReadReceipts(),
|
||||
MessageLogger(),
|
||||
ConvertMessageLocally(),
|
||||
SnapchatPlus(),
|
||||
DisableMetrics(),
|
||||
PreventMessageSending(),
|
||||
Notifications(),
|
||||
AutoSave(),
|
||||
UITweaks(),
|
||||
ConfigurationOverride(),
|
||||
UnsaveableMessages(),
|
||||
SendOverride(),
|
||||
UnlimitedSnapViewTime(),
|
||||
BypassVideoLengthRestriction(),
|
||||
MediaQualityLevelOverride(),
|
||||
MeoPasscodeBypass(),
|
||||
AppPasscode(),
|
||||
LocationSpoofer(),
|
||||
CameraTweaks(),
|
||||
InfiniteStoryBoost(),
|
||||
AmoledDarkMode(),
|
||||
PinConversations(),
|
||||
UnlimitedMultiSnap(),
|
||||
DeviceSpooferHook(),
|
||||
ClientBootstrapOverride(),
|
||||
GooglePlayServicesDialogs(),
|
||||
NoFriendScoreDelay(),
|
||||
ProfilePictureDownloader(),
|
||||
AddFriendSourceSpoof(),
|
||||
DisableReplayInFF(),
|
||||
OldBitmojiSelfie(),
|
||||
FriendFeedMessagePreview(),
|
||||
HideStreakRestore(),
|
||||
HideFriendFeedEntry(),
|
||||
HideQuickAddFriendFeed(),
|
||||
CallStartConfirmation(),
|
||||
SnapPreview(),
|
||||
InstantDelete(),
|
||||
BypassScreenshotDetection(),
|
||||
HalfSwipeNotifier(),
|
||||
DisableConfirmationDialogs(),
|
||||
MixerStories(),
|
||||
DisableComposerModules(),
|
||||
FideliusIndicator(),
|
||||
EditTextOverride(),
|
||||
PreventForcedLogout(),
|
||||
SuspendLocationUpdates(),
|
||||
ConversationToolbox(),
|
||||
SpotlightCommentsUsername(),
|
||||
OperaViewerParamsOverride(),
|
||||
)
|
||||
|
||||
initializeFeatures()
|
||||
}
|
||||
|
||||
private fun initFeatures(
|
||||
syncParam: Int,
|
||||
asyncParam: Int,
|
||||
syncAction: (Feature) -> Unit,
|
||||
asyncAction: (Feature) -> Unit
|
||||
) {
|
||||
fun tryInit(feature: Feature, block: () -> Unit) {
|
||||
private inline fun tryInit(feature: Feature, crossinline block: () -> Unit) {
|
||||
runCatching {
|
||||
block()
|
||||
}.onFailure {
|
||||
@ -142,7 +130,14 @@ class FeatureManager(
|
||||
}
|
||||
}
|
||||
|
||||
features.toList().forEach { feature ->
|
||||
private fun initFeatures(
|
||||
syncParam: Int,
|
||||
asyncParam: Int,
|
||||
syncAction: (Feature) -> Unit,
|
||||
asyncAction: (Feature) -> Unit
|
||||
) {
|
||||
|
||||
features.values.toList().forEach { feature ->
|
||||
if (feature.loadParams and syncParam != 0) {
|
||||
tryInit(feature) {
|
||||
syncAction(feature)
|
||||
|
Loading…
x
Reference in New Issue
Block a user