commit 2aac63ef7a1a18635ece0a79145c1419d218ad37
parent bcaa7b78ae52cbceb91d3b4897469dbb92ead34e
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun, 28 May 2023 09:11:01 +0200

feat: app passcode

Diffstat:
Mapp/src/main/assets/lang/en_US.json | 2++
Mapp/src/main/kotlin/me/rhunk/snapenhance/bridge/service/MainActivity.kt | 4----
Mapp/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt | 12++++++++++++
Aapp/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/AppPasscode.kt | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt | 2++
5 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/app/src/main/assets/lang/en_US.json b/app/src/main/assets/lang/en_US.json @@ -54,6 +54,8 @@ "streak_expiration_info": "Show Streak Expiration Info", "new_map_ui": "New Map UI", "use_download_manager": "Use Android Download Manager", + "app_passcode": "Set App Passcode", + "app_lock_on_resume": "App Lock On Resume", "meo_passcode_bypass": "My Eyes Only Passcode Bypass" }, diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/MainActivity.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/MainActivity.kt @@ -8,10 +8,6 @@ import me.rhunk.snapenhance.Constants class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (intent.getBooleanExtra("is_from_bridge", false)) { - finish() - return - } packageManager.getLaunchIntentForPackage(Constants.SNAPCHAT_PACKAGE_NAME)?.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(this) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt @@ -213,6 +213,18 @@ enum class ConfigProperty( ConfigCategory.EXPERIMENTAL, ConfigStateValue(false) ), + APP_PASSCODE( + "property.app_passcode", + "description.app_passcode", + ConfigCategory.EXPERIMENTAL, + ConfigStringValue("") + ), + APP_LOCK_ON_RESUME( + "property.app_lock_on_resume", + "description.app_lock_on_resume", + ConfigCategory.EXPERIMENTAL, + ConfigStateValue(false) + ), MEO_PASSCODE_BYPASS( "property.meo_passcode_bypass", "description.meo_passcode_bypass", diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/AppPasscode.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/extras/AppPasscode.kt @@ -0,0 +1,101 @@ +package me.rhunk.snapenhance.features.impl.extras + +import android.annotation.SuppressLint +import android.app.AlertDialog +import android.content.Context +import android.os.Build +import android.text.Editable +import android.text.InputType +import android.text.TextWatcher +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import me.rhunk.snapenhance.config.ConfigProperty +import me.rhunk.snapenhance.features.Feature +import me.rhunk.snapenhance.features.FeatureLoadParams + +//TODO: fingerprint unlock +class AppPasscode : Feature("App Passcode", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) { + private var isLocked = false + + private fun setActivityVisibility(isVisible: Boolean) { + context.mainActivity?.let { + it.window.attributes = it.window.attributes.apply { alpha = if (isVisible) 1.0F else 0.0F } + } + } + + fun lock() { + if (isLocked) return + isLocked = true + val passcode = context.config.string(ConfigProperty.APP_PASSCODE).also { if (it.isEmpty()) return } + val isDigitPasscode = passcode.all { it.isDigit() } + + val mainActivity = context.mainActivity!! + setActivityVisibility(false) + + val prompt = AlertDialog.Builder(mainActivity) + val createPrompt = { + val alertDialog = prompt.create() + val textView = EditText(mainActivity) + textView.setSingleLine() + textView.inputType = if (isDigitPasscode) InputType.TYPE_CLASS_NUMBER else InputType.TYPE_CLASS_TEXT + textView.hint = "Code :" + textView.setPadding(100, 100, 100, 100) + + textView.addTextChangedListener(object: TextWatcher { + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + if (s.contentEquals(passcode)) { + alertDialog.dismiss() + isLocked = false + setActivityVisibility(true) + } + } + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + override fun afterTextChanged(s: Editable?) {} + }) + + alertDialog.setView(textView) + + textView.viewTreeObserver.addOnWindowFocusChangeListener { hasFocus -> + if (!hasFocus) return@addOnWindowFocusChangeListener + val imm = mainActivity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.showSoftInput(textView, InputMethodManager.SHOW_IMPLICIT) + } + + alertDialog.window?.let { + it.attributes.verticalMargin = -0.18F + } + + alertDialog.show() + textView.requestFocus() + } + + prompt.setOnCancelListener { + createPrompt() + } + + createPrompt() + } + + @SuppressLint("MissingPermission") + override fun onActivityCreate() { + if (!context.database.hasArroyo()) return + + context.runOnUiThread { + lock() + } + + if (!context.config.bool(ConfigProperty.APP_LOCK_ON_RESUME)) return + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + context.mainActivity?.registerActivityLifecycleCallbacks(object: android.app.Application.ActivityLifecycleCallbacks { + override fun onActivityPaused(activity: android.app.Activity) { lock() } + override fun onActivityResumed(activity: android.app.Activity) {} + override fun onActivityStarted(activity: android.app.Activity) {} + override fun onActivityDestroyed(activity: android.app.Activity) {} + override fun onActivitySaveInstanceState(activity: android.app.Activity, outState: android.os.Bundle) {} + override fun onActivityStopped(activity: android.app.Activity) {} + override fun onActivityCreated(activity: android.app.Activity, savedInstanceState: android.os.Bundle?) {} + }) + } + } +}+ \ 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.Messaging 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.AppPasscode import me.rhunk.snapenhance.features.impl.extras.AutoSave import me.rhunk.snapenhance.features.impl.extras.DisableVideoLengthRestriction import me.rhunk.snapenhance.features.impl.extras.GalleryMediaSendOverride @@ -72,6 +73,7 @@ class FeatureManager(private val context: ModContext) : Manager { register(DisableVideoLengthRestriction::class) register(MediaQualityLevelOverride::class) register(MeoPasscodeBypass::class) + register(AppPasscode::class) initializeFeatures() }