commit 6fa79937124b4b2040631aec3b923ca0bd29d7ce
parent b120b6a27d198a8fbc03991db9c8d888016190ea
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Fri, 10 Nov 2023 21:24:05 +0100
feat(core/camera_tweaks): custom resolution
Diffstat:
5 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt
@@ -176,7 +176,7 @@ class AlertDialogs(
val focusRequester = remember { FocusRequester() }
DefaultDialogCard {
- val fieldValue = remember {
+ var fieldValue by remember {
mutableStateOf(property.value.get().toString().let {
TextFieldValue(
text = it,
@@ -193,10 +193,8 @@ class AlertDialogs(
focusRequester.requestFocus()
}
.focusRequester(focusRequester),
- value = fieldValue.value,
- onValueChange = {
- fieldValue.value = it
- },
+ value = fieldValue,
+ onValueChange = { fieldValue = it },
keyboardOptions = when (property.key.dataType.type) {
DataProcessors.Type.INTEGER -> KeyboardOptions(keyboardType = KeyboardType.Number)
DataProcessors.Type.FLOAT -> KeyboardOptions(keyboardType = KeyboardType.Decimal)
@@ -215,22 +213,27 @@ class AlertDialogs(
Text(text = translation["button.cancel"])
}
Button(onClick = {
+ if (fieldValue.text.isNotEmpty() && property.key.params.inputCheck?.invoke(fieldValue.text) == false) {
+ dismiss()
+ return@Button
+ }
+
when (property.key.dataType.type) {
DataProcessors.Type.INTEGER -> {
runCatching {
- property.value.setAny(fieldValue.value.text.toInt())
+ property.value.setAny(fieldValue.text.toInt())
}.onFailure {
property.value.setAny(0)
}
}
DataProcessors.Type.FLOAT -> {
runCatching {
- property.value.setAny(fieldValue.value.text.toFloat())
+ property.value.setAny(fieldValue.text.toFloat())
}.onFailure {
property.value.setAny(0f)
}
}
- else -> property.value.setAny(fieldValue.value.text)
+ else -> property.value.setAny(fieldValue.text)
}
dismiss()
}) {
diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json
@@ -454,6 +454,14 @@
"name": "Override Picture Resolution",
"description": "Overrides the picture resolution"
},
+ "custom_preview_resolution": {
+ "name": "Custom Preview Resolution",
+ "description": "Sets a custom camera preview resolution, width x height (e.g. 1920x1080).\nThe custom resolution must be supported by your device"
+ },
+ "custom_picture_resolution": {
+ "name": "Custom Picture Resolution",
+ "description": "Sets a custom picture resolution, width x height (e.g. 1920x1080).\nThe custom resolution must be supported by your device"
+ },
"custom_frame_rate": {
"name": "Custom Frame Rate",
"description": "Overrides the camera frame rate"
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigObjects.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/ConfigObjects.kt
@@ -38,7 +38,8 @@ class ConfigParams(
var icon: String? = null,
var disabledKey: String? = null,
var customTranslationPath: String? = null,
- var customOptionTranslationPath: String? = null
+ var customOptionTranslationPath: String? = null,
+ var inputCheck: ((String) -> Boolean)? = { true },
) {
val notices get() = _notices?.let { FeatureNotice.entries.filter { flag -> it and flag.id != 0 } } ?: emptyList()
val flags get() = _flags?.let { ConfigFlag.entries.filter { flag -> it and flag.id != 0 } } ?: emptyList()
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Camera.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/Camera.kt
@@ -41,10 +41,12 @@ class Camera : ConfigContainer() {
val disable = boolean("disable_camera")
val immersiveCameraPreview = boolean("immersive_camera_preview") { addNotices(FeatureNotice.UNSTABLE) }
val blackPhotos = boolean("black_photos")
- val overridePreviewResolution get() = _overridePreviewResolution
- val overridePictureResolution get() = _overridePictureResolution
val customFrameRate = unique("custom_frame_rate",
"5", "10", "20", "25", "30", "48", "60", "90", "120"
) { addNotices(FeatureNotice.UNSTABLE); addFlags(ConfigFlag.NO_TRANSLATE) }
val forceCameraSourceEncoding = boolean("force_camera_source_encoding")
+ val overridePreviewResolution get() = _overridePreviewResolution
+ val overridePictureResolution get() = _overridePictureResolution
+ val customPreviewResolution = string("custom_preview_resolution") { addNotices(FeatureNotice.UNSTABLE); inputCheck = { it.matches(Regex("\\d+x\\d+")) } }
+ val customPictureResolution = string("custom_picture_resolution") { addNotices(FeatureNotice.UNSTABLE); inputCheck = { it.matches(Regex("\\d+x\\d+")) } }
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/CameraTweaks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/tweaks/CameraTweaks.kt
@@ -22,13 +22,14 @@ import java.nio.ByteBuffer
class CameraTweaks : Feature("Camera Tweaks", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) {
- private fun parseResolution(resolution: String): IntArray {
- return resolution.split("x").map { it.toInt() }.toIntArray()
+ private fun parseResolution(resolution: String): IntArray? {
+ return runCatching { resolution.split("x").map { it.toInt() }.toIntArray() }.getOrNull()
}
@SuppressLint("MissingPermission", "DiscouragedApi")
override fun onActivityCreate() {
- if (context.config.camera.disable.get()) {
+ val config = context.config.camera
+ if (config.disable.get()) {
ContextWrapper::class.java.hook("checkPermission", HookStage.BEFORE) { param ->
val permission = param.arg<String>(0)
if (permission == Manifest.permission.CAMERA) {
@@ -41,10 +42,12 @@ class CameraTweaks : Feature("Camera Tweaks", loadParams = FeatureLoadParams.ACT
}
}
- val previewResolutionConfig = context.config.camera.overridePreviewResolution.getNullable()?.let { parseResolution(it) }
- val captureResolutionConfig = context.config.camera.overridePictureResolution.getNullable()?.let { parseResolution(it) }
+ val previewResolutionConfig = config.customPreviewResolution.getNullable()?.takeIf { it.isNotEmpty() }?.let { parseResolution(it) }
+ ?: config.overridePreviewResolution.getNullable()?.let { parseResolution(it) }
+ val captureResolutionConfig = config.customPictureResolution.getNullable()?.takeIf { it.isNotEmpty() }?.let { parseResolution(it) }
+ ?: config.overridePictureResolution.getNullable()?.let { parseResolution(it) }
- context.config.camera.customFrameRate.getNullable()?.also { value ->
+ config.customFrameRate.getNullable()?.also { value ->
val customFrameRate = value.toInt()
CameraCharacteristics::class.java.hook("get", HookStage.AFTER) { param ->
val key = param.arg<Key<*>>(0)
@@ -76,7 +79,7 @@ class CameraTweaks : Feature("Camera Tweaks", loadParams = FeatureLoadParams.ACT
}
}
- if (context.config.camera.blackPhotos.get()) {
+ if (config.blackPhotos.get()) {
findClass("android.media.ImageReader\$SurfaceImage").hook("getPlanes", HookStage.AFTER) { param ->
val image = param.thisObject() as? Image ?: return@hook
val planes = param.getResult() as? Array<*> ?: return@hook