commit bbfc0a835074a44f770ca85a9a3857e8b5a1f4c7
parent fd3e7e416e216cb41f0870c85a8d492523cba192
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Sun, 11 Jun 2023 01:04:35 +0200
feat: immersive camera preview
Diffstat:
5 files changed, 47 insertions(+), 11 deletions(-)
diff --git a/app/src/main/assets/lang/en_US.json b/app/src/main/assets/lang/en_US.json
@@ -61,6 +61,7 @@
"hide_ui_elements": "Hide UI Elements",
"auto_updater": "Auto Updater",
"disable_camera": "Disable Camera",
+ "immersive_camera_preview": "Immersive Camera Preview",
"infinite_story_boost": "Infinite Story Boost",
"enable_app_appearance": "Enable App Appearance Settings",
"disable_spotlight": "Disable Spotlight",
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt
@@ -183,6 +183,12 @@ enum class ConfigProperty(
ConfigCategory.UI_TWEAKS,
ConfigStateValue(false)
),
+ IMMERSIVE_CAMERA_PREVIEW(
+ "property.immersive_camera_preview",
+ "description.immersive_camera_preview",
+ ConfigCategory.UI_TWEAKS,
+ ConfigStateValue(false)
+ ),
HIDE_UI_ELEMENTS(
"property.hide_ui_elements",
"description.hide_ui_elements",
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt
@@ -15,10 +15,15 @@ import me.rhunk.snapenhance.hook.hook
class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) {
@SuppressLint("DiscouragedApi")
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 capriViewfinderDefaultCornerRadius = context.resources.getIdentifier("capri_viewfinder_default_corner_radius", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
- val ngsHovaNavLargerCameraButtonSize = context.resources.getIdentifier("ngs_hova_nav_larger_camera_button_size", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
+ val displayMetrics = context.resources.displayMetrics
+
+ 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 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 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 hiddenElements = context.config.options(ConfigProperty.HIDE_UI_ELEMENTS)
- Resources::class.java.methods.first { it.name == "getDimensionPixelSize"}.hook(HookStage.AFTER, {
- hiddenElements["remove_camera_borders"] == true
- }) { param ->
+ Resources::class.java.methods.first { it.name == "getDimensionPixelSize"}.hook(HookStage.AFTER,
+ { isImmersiveCamera }
+ ) { param ->
val id = param.arg<Int>(0)
if (id == capriViewfinderDefaultCornerRadius || id == ngsHovaNavLargerCameraButtonSize) {
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
- val addViewMethod = ViewGroup::class.java.getMethod(
+ ViewGroup::class.java.getMethod(
"addView",
View::class.java,
Int::class.javaPrimitiveType,
ViewGroup.LayoutParams::class.java
- )
- Hooker.hook(addViewMethod, HookStage.BEFORE) { param ->
+ ).hook(HookStage.BEFORE) { param ->
val view: View = param.arg(0)
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) {
view.isEnabled = false
view.setWillNotDraw(true)
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/hook/HookAdapter.kt b/app/src/main/kotlin/me/rhunk/snapenhance/hook/HookAdapter.kt
@@ -13,6 +13,10 @@ class HookAdapter(
return methodHookParam.thisObject as T
}
+ fun <T : Any> nullableThisObject(): T? {
+ return methodHookParam.thisObject as T?
+ }
+
fun method(): Member {
return methodHookParam.method
}
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/hook/Hooker.kt b/app/src/main/kotlin/me/rhunk/snapenhance/hook/Hooker.kt
@@ -75,6 +75,23 @@ object Hooker {
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(
clazz: Class<*>,
instance: Any,
@@ -84,7 +101,7 @@ object Hooker {
) {
val unhooks: MutableSet<XC_MethodHook.Unhook> = HashSet()
hook(clazz, methodName, stage) { param->
- if (param.thisObject<Any>() != instance) return@hook
+ if (param.nullableThisObject<Any>() != instance) return@hook
hookConsumer(param)
unhooks.forEach{ it.unhook() }
}.also { unhooks.addAll(it) }