commit e7ccaf312e0b7be206adcab703579ce1965eee4b
parent de1a676084eaf25f94a674e1c4db7444530d6744
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Fri, 26 May 2023 20:47:22 +0200

feat: media quality level override

Diffstat:
Mapp/src/main/assets/lang/en_US.json | 8++++++--
Mapp/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt | 40++++++++++++++++++++++++++++------------
Aapp/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/MediaQualityLevelOverride.kt | 33+++++++++++++++++++++++++++++++++
Mapp/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt | 3+++
Mapp/src/main/kotlin/me/rhunk/snapenhance/mapping/impl/EnumMapper.kt | 25+++++++++++++++++++++++++
5 files changed, 95 insertions(+), 14 deletions(-)

diff --git a/app/src/main/assets/lang/en_US.json b/app/src/main/assets/lang/en_US.json @@ -12,7 +12,8 @@ "action": { "clean_cache": "Clean Cache", - "clear_message_logger": "Clear Message Logger" + "clear_message_logger": "Clear Message Logger", + "refresh_mappings": "Refresh Mappings" }, "property": { @@ -41,11 +42,14 @@ "auto_save": "Auto Save", "anti_auto_save": "Anti Auto Save Button", "snapchat_plus": "Snapchat Plus", + "disable_snap_splitting": "Disable Snap Splitting", + "disable_video_length_restriction": "Disable Video Length Restriction", + "override_media_quality": "Override Media Quality", + "media_quality_level": "Media Quality Level", "remove_voice_record_button": "Remove Voice Record Button", "remove_stickers_button": "Remove Stickers Button", "remove_cognac_button": "Remove Cognac Button", "remove_call_buttons": "Remove Call Buttons", - "disable_snap_splitting": "Disable Snap Splitting", "block_ads": "Block Ads", "streak_expiration_info": "Show Streak Expiration Info", "new_map_ui": "New Map UI", diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt @@ -3,6 +3,7 @@ package me.rhunk.snapenhance.config import android.os.Environment import me.rhunk.snapenhance.config.impl.ConfigIntegerValue import me.rhunk.snapenhance.config.impl.ConfigStateListValue +import me.rhunk.snapenhance.config.impl.ConfigStateSelection import me.rhunk.snapenhance.config.impl.ConfigStateValue import me.rhunk.snapenhance.config.impl.ConfigStringValue import java.io.File @@ -143,6 +144,33 @@ enum class ConfigProperty( ANTI_AUTO_SAVE("property.anti_auto_save", "description.anti_auto_save", ConfigCategory.EXTRAS, ConfigStateValue(false)), SNAPCHAT_PLUS("property.snapchat_plus", "description.snapchat_plus", ConfigCategory.EXTRAS, ConfigStateValue(false)), + DISABLE_SNAP_SPLITTING( + "property.disable_snap_splitting", + "description.disable_snap_splitting", + ConfigCategory.TWEAKS, + ConfigStateValue(false) + ), + DISABLE_VIDEO_LENGTH_RESTRICTION( + "property.disable_video_length_restriction", + "description.disable_video_length_restriction", + ConfigCategory.TWEAKS, + ConfigStateValue(false) + ), + OVERRIDE_MEDIA_QUALITY( + "property.override_media_quality", + "description.override_media_quality", + ConfigCategory.TWEAKS, + ConfigStateValue(false) + ), + MEDIA_QUALITY_LEVEL( + "property.media_quality_level", + "description.media_quality_level", + ConfigCategory.TWEAKS, + ConfigStateSelection( + listOf("LEVEL_NONE", "LEVEL_1", "LEVEL_2", "LEVEL_3", "LEVEL_4", "LEVEL_5", "LEVEL_6", "LEVEL_7", "LEVEL_MAX"), + "LEVEL_NONE" + ) + ), REMOVE_VOICE_RECORD_BUTTON( "property.remove_voice_record_button", "description.remove_voice_record_button", @@ -167,18 +195,6 @@ enum class ConfigProperty( ConfigCategory.TWEAKS, ConfigStateValue(false) ), - DISABLE_SNAP_SPLITTING( - "property.disable_snap_splitting", - "description.disable_snap_splitting", - ConfigCategory.TWEAKS, - ConfigStateValue(false) - ), - DISABLE_VIDEO_LENGTH_RESTRICTION( - "property.disable_video_length_restriction", - "description.disable_video_length_restriction", - ConfigCategory.TWEAKS, - ConfigStateValue(false) - ), BLOCK_ADS("property.block_ads", "description.block_ads", ConfigCategory.TWEAKS, ConfigStateValue(false)), STREAK_EXPIRATION_INFO( "property.streak_expiration_info", diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/MediaQualityLevelOverride.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/MediaQualityLevelOverride.kt @@ -0,0 +1,32 @@ +package me.rhunk.snapenhance.features.impl.extras + +import me.rhunk.snapenhance.Logger +import me.rhunk.snapenhance.config.ConfigProperty +import me.rhunk.snapenhance.features.Feature +import me.rhunk.snapenhance.features.FeatureLoadParams +import me.rhunk.snapenhance.hook.HookStage +import me.rhunk.snapenhance.hook.Hooker + +class MediaQualityLevelOverride : Feature("MediaQualityLevelOverride", loadParams = FeatureLoadParams.INIT_SYNC) { + override fun init() { + val enumQualityLevel = context.mappings.getMappedClass("enums", "QualityLevel") + + Hooker.hookConstructor(context.androidContext.classLoader.loadClass("hfj"), HookStage.AFTER) { + Logger.log(it.thisObject()) + } + + Hooker.hook(context.mappings.getMappedClass("MediaQualityLevelProvider"), + context.mappings.getMappedValue("MediaQualityLevelProviderMethod"), + HookStage.BEFORE, + {context.config.bool(ConfigProperty.OVERRIDE_MEDIA_QUALITY)} + ) { param -> + val currentCompressionLevel = enumQualityLevel.enumConstants + .firstOrNull { it.toString() == context.config.state(ConfigProperty.MEDIA_QUALITY_LEVEL)} ?: run { + context.longToast("Invalid media quality level: ${context.config.state(ConfigProperty.MEDIA_QUALITY_LEVEL)}") + return@hook + } + Logger.debug("set media compression level to $currentCompressionLevel") + param.setResult(currentCompressionLevel) + } + } +}+ \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt @@ -10,6 +10,7 @@ import me.rhunk.snapenhance.features.impl.downloader.AntiAutoDownload import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.features.impl.extras.AntiAutoSave import me.rhunk.snapenhance.features.impl.extras.AutoSave +import me.rhunk.snapenhance.features.impl.extras.MediaQualityLevelOverride import me.rhunk.snapenhance.features.impl.extras.DisableVideoLengthRestriction import me.rhunk.snapenhance.features.impl.extras.ExternalMediaAsSnap import me.rhunk.snapenhance.features.impl.extras.Notifications @@ -68,6 +69,7 @@ class FeatureManager(private val context: ModContext) : Manager { register(AntiAutoSave::class) register(UnlimitedSnapViewTime::class) register(DisableVideoLengthRestriction::class) + register(MediaQualityLevelOverride::class) initializeFeatures() } @@ -80,6 +82,7 @@ class FeatureManager(private val context: ModContext) : Manager { action(feature) }.onFailure { Logger.xposedLog("Failed to init feature ${feature.nameKey}", it) + context.longToast("Failed to init feature ${feature.nameKey}") } } if (!isAsync) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/mapping/impl/EnumMapper.kt b/app/src/main/kotlin/me/rhunk/snapenhance/mapping/impl/EnumMapper.kt @@ -1,8 +1,10 @@ package me.rhunk.snapenhance.mapping.impl +import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.Logger.debug import me.rhunk.snapenhance.mapping.Mapper import java.lang.reflect.Method +import java.lang.reflect.Modifier import java.util.Objects @@ -13,11 +15,22 @@ class EnumMapper : Mapper() { mappings: MutableMap<String, Any> ) { val enumMappings = HashMap<String, String>() + var enumQualityLevel: Class<*>? = null + //settings classes have an interface that extends Serializable and contains the getName method //this enum classes are used to store the settings values //Setting enum class -> implements an interface -> getName method classes.forEach { clazz -> if (!clazz.isEnum) return@forEach + + //quality level enum + if (enumQualityLevel == null) { + if (clazz.enumConstants.any { it.toString().startsWith("LEVEL_NONE") }) { + enumMappings["QualityLevel"] = clazz.name + enumQualityLevel = clazz + } + } + if (clazz.interfaces.isEmpty()) return@forEach val serializableInterfaceClass = clazz.interfaces[0] if (serializableInterfaceClass.methods @@ -35,6 +48,18 @@ class EnumMapper : Mapper() { } } } + + //find the media quality level provider + for (clazz in classes) { + if (!Modifier.isAbstract(clazz.modifiers)) continue + if (clazz.fields.none { Modifier.isTransient(it.modifiers) }) continue + clazz.methods.firstOrNull { it.returnType == enumQualityLevel }?.let { + mappings["MediaQualityLevelProvider"] = clazz.name + mappings["MediaQualityLevelProviderMethod"] = it.name + Logger.debug("found MediaQualityLevelProvider: ${clazz.name}.${it.name}") + } + } + debug("found " + enumMappings.size + " enums") mappings["enums"] = enumMappings }