feat: media upload quality override
This commit is contained in:
@@ -686,6 +686,24 @@
|
||||
"name": "Snapchat Plus",
|
||||
"description": "Enables Snapchat Plus features\nSome Server-sided features may not work"
|
||||
},
|
||||
"media_upload_quality": {
|
||||
"name": "Media Upload Quality",
|
||||
"description": "Overrides the media upload quality",
|
||||
"properties": {
|
||||
"force_video_upload_source_quality": {
|
||||
"name": "Force Video Upload Source Quality",
|
||||
"description": "Forces Snapchat to use the source quality when uploading videos\nPlease note that this may not remove metadata from media"
|
||||
},
|
||||
"disable_image_compression": {
|
||||
"name": "Disable Image Compression",
|
||||
"description": "Disables image compression when uploading media"
|
||||
},
|
||||
"custom_image_upload_format": {
|
||||
"name": "Custom Image Upload Format",
|
||||
"description": "Sets a custom image upload format\nSelect a lossless format (like PNG) for the best quality"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disable_confirmation_dialogs": {
|
||||
"name": "Disable Confirmation Dialogs",
|
||||
"description": "Automatically confirms selected actions"
|
||||
@@ -738,10 +756,6 @@
|
||||
"name": "Disable Google Play Services Dialogs",
|
||||
"description": "Prevent Google Play Services availability dialogs from being shown"
|
||||
},
|
||||
"force_upload_source_quality": {
|
||||
"name": "Force Upload Source Quality",
|
||||
"description": "Forces Snapchat to upload media in the original quality\nPlease note that this may not remove metadata from media"
|
||||
},
|
||||
"default_volume_controls": {
|
||||
"name": "Default Volume Controls",
|
||||
"description": "Forces Snapchat to use system volume controls"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.rhunk.snapenhance.common.config.impl
|
||||
|
||||
import me.rhunk.snapenhance.common.config.ConfigContainer
|
||||
import me.rhunk.snapenhance.common.config.ConfigFlag
|
||||
import me.rhunk.snapenhance.common.config.FeatureNotice
|
||||
|
||||
class Global : ConfigContainer() {
|
||||
@@ -27,8 +28,16 @@ class Global : ConfigContainer() {
|
||||
val spoofBatteryLevel = string("spoof_battery_level") { requireRestart(); inputCheck = { it.isEmpty() || it.toIntOrNull() in 0..100 } }
|
||||
val spoofHeadphones = boolean("spoof_headphones") { requireRestart() }
|
||||
}
|
||||
|
||||
inner class MediaUploadQualityConfig : ConfigContainer() {
|
||||
val forceVideoUploadSourceQuality = boolean("force_video_upload_source_quality") { requireRestart() }
|
||||
val disableImageCompression = boolean("disable_image_compression") { requireRestart() }
|
||||
val customUploadImageFormat = unique("custom_image_upload_format", "jpeg", "png", "webp") { requireRestart(); addFlags(ConfigFlag.NO_TRANSLATE) }
|
||||
}
|
||||
|
||||
val betterLocation = container("better_location", BetterLocation())
|
||||
val snapchatPlus = boolean("snapchat_plus") { requireRestart() }
|
||||
val mediaUploadQualityConfig = container("media_upload_quality", MediaUploadQualityConfig())
|
||||
val disableConfirmationDialogs = multiple("disable_confirmation_dialogs", "erase_message", "remove_friend", "block_friend", "ignore_friend", "hide_friend", "hide_conversation", "clear_conversation") { requireRestart() }
|
||||
val disableMetrics = boolean("disable_metrics") { requireRestart() }
|
||||
val disableStorySections = multiple("disable_story_sections", "friends", "following", "discover") { requireRestart(); requireCleanCache() }
|
||||
@@ -42,7 +51,6 @@ class Global : ConfigContainer() {
|
||||
val defaultVideoPlaybackRate = float("default_video_playback_rate", 1.0F) { requireRestart(); inputCheck = { (it.toFloatOrNull() ?: 1.0F) in 0.1F..4.0F} }
|
||||
val videoPlaybackRateSlider = boolean("video_playback_rate_slider") { requireRestart() }
|
||||
val disableGooglePlayDialogs = boolean("disable_google_play_dialogs") { requireRestart() }
|
||||
val forceUploadSourceQuality = boolean("force_upload_source_quality") { requireRestart() }
|
||||
val defaultVolumeControls = boolean("default_volume_controls") { requireRestart() }
|
||||
val hideActiveMusic = boolean("hide_active_music") { requireRestart() }
|
||||
val disableSnapSplitting = boolean("disable_snap_splitting") { addNotices(FeatureNotice.INTERNAL_BEHAVIOR) }
|
||||
|
||||
@@ -79,7 +79,7 @@ class FeatureManager(
|
||||
SendOverride(),
|
||||
UnlimitedSnapViewTime(),
|
||||
BypassVideoLengthRestriction(),
|
||||
MediaQualityLevelOverride(),
|
||||
MediaUploadQualityOverride(),
|
||||
MeoPasscodeBypass(),
|
||||
AppLock(),
|
||||
CameraTweaks(),
|
||||
|
||||
@@ -45,7 +45,7 @@ class ConfigurationOverride : Feature("Configuration Override", loadParams = Fea
|
||||
|
||||
overrideProperty("STREAK_EXPIRATION_INFO", { context.config.userInterface.streakExpirationInfo.get() },
|
||||
{ true })
|
||||
overrideProperty("TRANSCODING_MAX_QUALITY", { context.config.global.forceUploadSourceQuality.get() },
|
||||
overrideProperty("TRANSCODING_MAX_QUALITY", { context.config.global.mediaUploadQualityConfig.forceVideoUploadSourceQuality.get() },
|
||||
{ true }, isAppExperiment = true)
|
||||
|
||||
overrideProperty("CAMERA_ME_ENABLE_HEVC_RECORDING", { context.config.camera.hevcRecording.get() },
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package me.rhunk.snapenhance.core.features.impl.global
|
||||
|
||||
import me.rhunk.snapenhance.core.features.Feature
|
||||
import me.rhunk.snapenhance.core.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||
import me.rhunk.snapenhance.core.util.hook.hook
|
||||
import me.rhunk.snapenhance.mapper.impl.MediaQualityLevelProviderMapper
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class MediaQualityLevelOverride : Feature("MediaQualityLevelOverride", loadParams = FeatureLoadParams.INIT_SYNC) {
|
||||
override fun init() {
|
||||
if (!context.config.global.forceUploadSourceQuality.get()) return
|
||||
|
||||
context.mappings.useMapper(MediaQualityLevelProviderMapper::class) {
|
||||
mediaQualityLevelProvider.getAsClass()?.hook(
|
||||
mediaQualityLevelProviderMethod.getAsString()!!,
|
||||
HookStage.BEFORE
|
||||
) { param ->
|
||||
param.setResult((param.method() as Method).returnType.enumConstants.firstOrNull { it.toString() == "LEVEL_MAX" } )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package me.rhunk.snapenhance.core.features.impl.global
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import me.rhunk.snapenhance.core.features.Feature
|
||||
import me.rhunk.snapenhance.core.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||
import me.rhunk.snapenhance.core.util.hook.hook
|
||||
import me.rhunk.snapenhance.mapper.impl.MediaQualityLevelProviderMapper
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class MediaUploadQualityOverride : Feature("Media Upload Quality Override", loadParams = FeatureLoadParams.INIT_SYNC) {
|
||||
override fun init() {
|
||||
if (context.config.global.mediaUploadQualityConfig.forceVideoUploadSourceQuality.get()) {
|
||||
context.mappings.useMapper(MediaQualityLevelProviderMapper::class) {
|
||||
mediaQualityLevelProvider.getAsClass()?.hook(
|
||||
mediaQualityLevelProviderMethod.getAsString()!!,
|
||||
HookStage.BEFORE
|
||||
) { param ->
|
||||
param.setResult((param.method() as Method).returnType.enumConstants.firstOrNull { it.toString() == "LEVEL_MAX" } )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val disableImageCompression by context.config.global.mediaUploadQualityConfig.disableImageCompression
|
||||
val imageUploadFormat = context.config.global.mediaUploadQualityConfig.customUploadImageFormat.getNullable()
|
||||
|
||||
if (imageUploadFormat != null || disableImageCompression) {
|
||||
Bitmap::class.java.hook("compress", HookStage.BEFORE) { param ->
|
||||
if (param.arg<Int>(1) == 0) return@hook
|
||||
if (param.arg<Any>(0) == Bitmap.CompressFormat.JPEG) {
|
||||
@Suppress("DEPRECATION")
|
||||
param.setArg(0, when (imageUploadFormat) {
|
||||
"png" -> Bitmap.CompressFormat.PNG
|
||||
"webp" -> Bitmap.CompressFormat.WEBP
|
||||
"jpeg" -> Bitmap.CompressFormat.JPEG
|
||||
else -> Bitmap.CompressFormat.JPEG
|
||||
})
|
||||
if (disableImageCompression) {
|
||||
param.setArg(1, 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findClass("com.snap.camera.jni.SnapImageTranscoder").hook("nativeEncodeBitmapToJpeg", HookStage.BEFORE) {
|
||||
it.setResult(ByteArray(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user