feat: immersive camera preview

This commit is contained in:
rhunk 2023-06-11 01:04:35 +02:00
parent fd3e7e416e
commit bbfc0a8350
5 changed files with 47 additions and 11 deletions

View File

@ -61,6 +61,7 @@
"hide_ui_elements": "Hide UI Elements", "hide_ui_elements": "Hide UI Elements",
"auto_updater": "Auto Updater", "auto_updater": "Auto Updater",
"disable_camera": "Disable Camera", "disable_camera": "Disable Camera",
"immersive_camera_preview": "Immersive Camera Preview",
"infinite_story_boost": "Infinite Story Boost", "infinite_story_boost": "Infinite Story Boost",
"enable_app_appearance": "Enable App Appearance Settings", "enable_app_appearance": "Enable App Appearance Settings",
"disable_spotlight": "Disable Spotlight", "disable_spotlight": "Disable Spotlight",

View File

@ -183,6 +183,12 @@ enum class ConfigProperty(
ConfigCategory.UI_TWEAKS, ConfigCategory.UI_TWEAKS,
ConfigStateValue(false) ConfigStateValue(false)
), ),
IMMERSIVE_CAMERA_PREVIEW(
"property.immersive_camera_preview",
"description.immersive_camera_preview",
ConfigCategory.UI_TWEAKS,
ConfigStateValue(false)
),
HIDE_UI_ELEMENTS( HIDE_UI_ELEMENTS(
"property.hide_ui_elements", "property.hide_ui_elements",
"description.hide_ui_elements", "description.hide_ui_elements",

View File

@ -15,10 +15,15 @@ import me.rhunk.snapenhance.hook.hook
class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) { class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) {
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
override fun onActivityCreate() { override fun onActivityCreate() {
val hiddenElements = context.config.options(ConfigProperty.HIDE_UI_ELEMENTS)
val isImmersiveCamera = context.config.bool(ConfigProperty.IMMERSIVE_CAMERA_PREVIEW)
val resources = context.resources val resources = context.resources
val capriViewfinderDefaultCornerRadius = context.resources.getIdentifier("capri_viewfinder_default_corner_radius", "dimen", Constants.SNAPCHAT_PACKAGE_NAME) val displayMetrics = context.resources.displayMetrics
val ngsHovaNavLargerCameraButtonSize = context.resources.getIdentifier("ngs_hova_nav_larger_camera_button_size", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
val capriViewfinderDefaultCornerRadius = resources.getIdentifier("capri_viewfinder_default_corner_radius", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
val ngsHovaNavLargerCameraButtonSize = resources.getIdentifier("ngs_hova_nav_larger_camera_button_size", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
val fullScreenSurfaceView = resources.getIdentifier("full_screen_surface_view", "id", Constants.SNAPCHAT_PACKAGE_NAME)
val callButtonsStub = resources.getIdentifier("call_buttons_stub", "id", Constants.SNAPCHAT_PACKAGE_NAME) val callButtonsStub = resources.getIdentifier("call_buttons_stub", "id", Constants.SNAPCHAT_PACKAGE_NAME)
val callButton1 = resources.getIdentifier("friend_action_button3", "id", Constants.SNAPCHAT_PACKAGE_NAME) val callButton1 = resources.getIdentifier("friend_action_button3", "id", Constants.SNAPCHAT_PACKAGE_NAME)
@ -27,11 +32,10 @@ class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CRE
val chatNoteRecordButton = resources.getIdentifier("chat_note_record_button", "id", Constants.SNAPCHAT_PACKAGE_NAME) val chatNoteRecordButton = resources.getIdentifier("chat_note_record_button", "id", Constants.SNAPCHAT_PACKAGE_NAME)
val chatInputBarSticker = resources.getIdentifier("chat_input_bar_sticker", "id", Constants.SNAPCHAT_PACKAGE_NAME) val chatInputBarSticker = resources.getIdentifier("chat_input_bar_sticker", "id", Constants.SNAPCHAT_PACKAGE_NAME)
val chatInputBarCognac = resources.getIdentifier("chat_input_bar_cognac", "id", Constants.SNAPCHAT_PACKAGE_NAME) val chatInputBarCognac = resources.getIdentifier("chat_input_bar_cognac", "id", Constants.SNAPCHAT_PACKAGE_NAME)
val hiddenElements = context.config.options(ConfigProperty.HIDE_UI_ELEMENTS)
Resources::class.java.methods.first { it.name == "getDimensionPixelSize"}.hook(HookStage.AFTER, { Resources::class.java.methods.first { it.name == "getDimensionPixelSize"}.hook(HookStage.AFTER,
hiddenElements["remove_camera_borders"] == true { isImmersiveCamera }
}) { param -> ) { param ->
val id = param.arg<Int>(0) val id = param.arg<Int>(0)
if (id == capriViewfinderDefaultCornerRadius || id == ngsHovaNavLargerCameraButtonSize) { if (id == capriViewfinderDefaultCornerRadius || id == ngsHovaNavLargerCameraButtonSize) {
param.setResult(0) param.setResult(0)
@ -49,17 +53,21 @@ class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CRE
} }
} }
//TODO: use the event bus to dispatch a addView event ViewGroup::class.java.getMethod(
val addViewMethod = ViewGroup::class.java.getMethod(
"addView", "addView",
View::class.java, View::class.java,
Int::class.javaPrimitiveType, Int::class.javaPrimitiveType,
ViewGroup.LayoutParams::class.java ViewGroup.LayoutParams::class.java
) ).hook(HookStage.BEFORE) { param ->
Hooker.hook(addViewMethod, HookStage.BEFORE) { param ->
val view: View = param.arg(0) val view: View = param.arg(0)
val viewId = view.id val viewId = view.id
if (isImmersiveCamera && view.id == fullScreenSurfaceView) {
Hooker.hookObjectMethod(View::class.java, view, "layout", HookStage.BEFORE) { param ->
param.setArg(3, displayMetrics.heightPixels)
}
}
if (viewId == chatNoteRecordButton && hiddenElements["remove_voice_record_button"] == true) { if (viewId == chatNoteRecordButton && hiddenElements["remove_voice_record_button"] == true) {
view.isEnabled = false view.isEnabled = false
view.setWillNotDraw(true) view.setWillNotDraw(true)

View File

@ -13,6 +13,10 @@ class HookAdapter(
return methodHookParam.thisObject as T return methodHookParam.thisObject as T
} }
fun <T : Any> nullableThisObject(): T? {
return methodHookParam.thisObject as T?
}
fun method(): Member { fun method(): Member {
return methodHookParam.method return methodHookParam.method
} }

View File

@ -75,6 +75,23 @@ object Hooker {
XposedBridge.hookAllConstructors(clazz, newMethodHook(stage, consumer, filter)) XposedBridge.hookAllConstructors(clazz, newMethodHook(stage, consumer, filter))
} }
fun hookObjectMethod(
clazz: Class<*>,
instance: Any,
methodName: String,
stage: HookStage,
hookConsumer: (HookAdapter) -> Unit
) {
val unhooks: MutableSet<XC_MethodHook.Unhook> = HashSet()
hook(clazz, methodName, stage) { param->
if (param.nullableThisObject<Any>().let {
if (it == null) unhooks.forEach { u -> u.unhook() }
it != instance
}) return@hook
hookConsumer(param)
}.also { unhooks.addAll(it) }
}
fun ephemeralHookObjectMethod( fun ephemeralHookObjectMethod(
clazz: Class<*>, clazz: Class<*>,
instance: Any, instance: Any,
@ -84,7 +101,7 @@ object Hooker {
) { ) {
val unhooks: MutableSet<XC_MethodHook.Unhook> = HashSet() val unhooks: MutableSet<XC_MethodHook.Unhook> = HashSet()
hook(clazz, methodName, stage) { param-> hook(clazz, methodName, stage) { param->
if (param.thisObject<Any>() != instance) return@hook if (param.nullableThisObject<Any>() != instance) return@hook
hookConsumer(param) hookConsumer(param)
unhooks.forEach{ it.unhook() } unhooks.forEach{ it.unhook() }
}.also { unhooks.addAll(it) } }.also { unhooks.addAll(it) }