From af92cf5a7dece693fe59462b78285f8e7048da3c Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:12:19 +0800 Subject: [PATCH] Refactor activity helpers into HelperBaseActivity --- .../java/com/v2ray/ang/ui/BackupActivity.kt | 2 +- .../java/com/v2ray/ang/ui/BaseActivity.kt | 68 -------------- .../com/v2ray/ang/ui/HelperBaseActivity.kt | 90 +++++++++++++++++++ .../java/com/v2ray/ang/ui/MainActivity.kt | 4 +- .../v2ray/ang/ui/RoutingSettingActivity.kt | 3 +- .../com/v2ray/ang/ui/ScScannerActivity.kt | 2 +- .../java/com/v2ray/ang/ui/ScannerActivity.kt | 4 +- .../com/v2ray/ang/ui/UserAssetActivity.kt | 3 +- 8 files changed, 97 insertions(+), 79 deletions(-) create mode 100644 V2rayNG/app/src/main/java/com/v2ray/ang/ui/HelperBaseActivity.kt diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt index 77fd5d06..4f29b5d4 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt @@ -27,7 +27,7 @@ import java.io.File import java.text.SimpleDateFormat import java.util.Locale -class BackupActivity : BaseActivity() { +class BackupActivity : HelperBaseActivity() { private val binding by lazy { ActivityBackupBinding.inflate(layoutInflater) } private val config_backup_options: Array by lazy { diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt index c7117a11..cf975694 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BaseActivity.kt @@ -1,7 +1,6 @@ package com.v2ray.ang.ui import android.content.Context -import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem @@ -20,10 +19,6 @@ import com.v2ray.ang.R import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.helper.CustomDividerItemDecoration import com.v2ray.ang.util.MyContextWrapper -import com.v2ray.ang.dto.PermissionType -import com.v2ray.ang.helper.FileChooserHelper -import com.v2ray.ang.helper.PermissionHelper -import com.v2ray.ang.helper.QRCodeScannerHelper import com.v2ray.ang.util.Utils @@ -41,15 +36,9 @@ import com.v2ray.ang.util.Utils abstract class BaseActivity : AppCompatActivity() { // Progress indicator that sits at the bottom of the toolbar private var progressBar: LinearProgressIndicator? = null - private lateinit var fileChooser : FileChooserHelper - private lateinit var permissionRequester : PermissionHelper - private lateinit var qrCodeScanner : QRCodeScannerHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - fileChooser = FileChooserHelper(this) - permissionRequester = PermissionHelper(this) - qrCodeScanner = QRCodeScannerHelper(this) supportActionBar?.setDisplayHomeAsUpEnabled(true) if (!Utils.getDarkModeStatus(this)) { @@ -224,61 +213,4 @@ abstract class BaseActivity : AppCompatActivity() { protected fun isLoadingVisible(): Boolean { return progressBar?.visibility == View.VISIBLE } - - /** - * Check if permission is granted and request it if not. - * Convenience method that delegates to permissionRequester. - * - * @param permissionType The type of permission to check and request - * @param onGranted Callback to execute when permission is granted - */ - protected fun checkAndRequestPermission( - permissionType: PermissionType, - onGranted: () -> Unit - ) { - permissionRequester.request(permissionType, onGranted) - } - - /** - * Launch file chooser with ACTION_GET_CONTENT intent. - * Convenience method that delegates to fileChooser helper. - * - * @param mimeType MIME type filter for files - * @param onResult Callback invoked with the selected file URI (null if cancelled) - */ - protected fun launchFileChooser( - mimeType: String = "*/*", - onResult: (Uri?) -> Unit - ) { - checkAndRequestPermission(PermissionType.READ_STORAGE) { - fileChooser.launch(mimeType, onResult) - } - } - - /** - * Launch document creator to create a new file at user-selected location. - * Convenience method that delegates to fileChooser helper. - * Note: No permission check needed as CreateDocument uses Storage Access Framework. - * - * @param fileName Default file name for the new document - * @param onResult Callback invoked with the created file URI (null if cancelled) - */ - protected fun launchCreateDocument( - fileName: String, - onResult: (Uri?) -> Unit - ) { - fileChooser.createDocument(fileName, onResult) - } - - /** - * Launch QR code scanner with camera permission check. - * Convenience method that delegates to qrCodeScanner helper. - * - * @param onResult Callback invoked with the scan result string (null if cancelled or failed) - */ - protected fun launchQRCodeScanner(onResult: (String?) -> Unit) { - checkAndRequestPermission(PermissionType.CAMERA) { - qrCodeScanner.launch(onResult) - } - } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/HelperBaseActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/HelperBaseActivity.kt new file mode 100644 index 00000000..95a28d60 --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/HelperBaseActivity.kt @@ -0,0 +1,90 @@ +package com.v2ray.ang.ui + +import android.net.Uri +import android.os.Bundle +import com.v2ray.ang.dto.PermissionType +import com.v2ray.ang.helper.FileChooserHelper +import com.v2ray.ang.helper.PermissionHelper +import com.v2ray.ang.helper.QRCodeScannerHelper + +/** + * HelperBaseActivity extends BaseActivity and provides additional helpers for + * activities that need file chooser, permission requesting, or QR code scanning functionality. + * + * Activities that don't need these features should extend BaseActivity directly. + * Activities that need file selection, permissions, or QR code scanning should extend this class. + * + * Additional Responsibilities: + * - Provide file chooser helpers for selecting and creating files. + * - Provide permission request helpers with callbacks. + * - Provide QR code scanning helpers with camera permission handling. + */ +abstract class HelperBaseActivity : BaseActivity() { + private lateinit var fileChooser : FileChooserHelper + private lateinit var permissionRequester : PermissionHelper + private lateinit var qrCodeScanner : QRCodeScannerHelper + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + fileChooser = FileChooserHelper(this) + permissionRequester = PermissionHelper(this) + qrCodeScanner = QRCodeScannerHelper(this) + } + + /** + * Check if permission is granted and request it if not. + * Convenience method that delegates to permissionRequester. + * + * @param permissionType The type of permission to check and request + * @param onGranted Callback to execute when permission is granted + */ + protected fun checkAndRequestPermission( + permissionType: PermissionType, + onGranted: () -> Unit + ) { + permissionRequester.request(permissionType, onGranted) + } + + /** + * Launch file chooser with ACTION_GET_CONTENT intent. + * Convenience method that delegates to fileChooser helper. + * + * @param mimeType MIME type filter for files + * @param onResult Callback invoked with the selected file URI (null if cancelled) + */ + protected fun launchFileChooser( + mimeType: String = "*/*", + onResult: (Uri?) -> Unit + ) { + checkAndRequestPermission(PermissionType.READ_STORAGE) { + fileChooser.launch(mimeType, onResult) + } + } + + /** + * Launch document creator to create a new file at user-selected location. + * Convenience method that delegates to fileChooser helper. + * Note: No permission check needed as CreateDocument uses Storage Access Framework. + * + * @param fileName Default file name for the new document + * @param onResult Callback invoked with the created file URI (null if cancelled) + */ + protected fun launchCreateDocument( + fileName: String, + onResult: (Uri?) -> Unit + ) { + fileChooser.createDocument(fileName, onResult) + } + + /** + * Launch QR code scanner with camera permission check. + * Convenience method that delegates to qrCodeScanner helper. + * + * @param onResult Callback invoked with the scan result string (null if cancelled or failed) + */ + protected fun launchQRCodeScanner(onResult: (String?) -> Unit) { + checkAndRequestPermission(PermissionType.CAMERA) { + qrCodeScanner.launch(onResult) + } + } +} diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt index 3b8f5565..5462b9e2 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt @@ -25,6 +25,7 @@ import com.v2ray.ang.AppConfig import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivityMainBinding import com.v2ray.ang.dto.EConfigType +import com.v2ray.ang.dto.PermissionType import com.v2ray.ang.extension.toast import com.v2ray.ang.extension.toastError import com.v2ray.ang.handler.AngConfigManager @@ -32,7 +33,6 @@ import com.v2ray.ang.handler.MmkvManager import com.v2ray.ang.handler.SettingsChangeManager import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.handler.V2RayServiceManager -import com.v2ray.ang.dto.PermissionType import com.v2ray.ang.util.Utils import com.v2ray.ang.viewmodel.MainViewModel import kotlinx.coroutines.Dispatchers @@ -40,7 +40,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener { +class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelectedListener { private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt index fc6a8a14..f8017900 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt @@ -20,14 +20,13 @@ import com.v2ray.ang.handler.MmkvManager import com.v2ray.ang.handler.SettingsManager import com.v2ray.ang.helper.SimpleItemTouchHelperCallback import com.v2ray.ang.util.JsonUtil -import com.v2ray.ang.dto.PermissionType import com.v2ray.ang.util.Utils import com.v2ray.ang.viewmodel.RoutingSettingsViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -class RoutingSettingActivity : BaseActivity() { +class RoutingSettingActivity : HelperBaseActivity() { private val binding by lazy { ActivityRoutingSettingBinding.inflate(layoutInflater) } private val ownerActivity: RoutingSettingActivity get() = this diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScScannerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScScannerActivity.kt index f9e9cbfa..5bd1e4b4 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScScannerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScScannerActivity.kt @@ -7,7 +7,7 @@ import com.v2ray.ang.extension.toastError import com.v2ray.ang.extension.toastSuccess import com.v2ray.ang.handler.AngConfigManager -class ScScannerActivity : BaseActivity() { +class ScScannerActivity : HelperBaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt index c95f912e..7ed97650 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ScannerActivity.kt @@ -11,15 +11,13 @@ import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivityNoneBinding import com.v2ray.ang.extension.toast import com.v2ray.ang.handler.MmkvManager -import com.v2ray.ang.dto.PermissionType -import com.v2ray.ang.extension.toastError import com.v2ray.ang.util.QRCodeDecoder import io.github.g00fy2.quickie.QRResult import io.github.g00fy2.quickie.ScanCustomCode import io.github.g00fy2.quickie.config.BarcodeFormat import io.github.g00fy2.quickie.config.ScannerConfig -class ScannerActivity : BaseActivity() { +class ScannerActivity : HelperBaseActivity() { private val binding by lazy { ActivityNoneBinding.inflate(layoutInflater) } private val scanQrCode = registerForActivityResult(ScanCustomCode(), ::handleResult) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt index 7cf66b69..b1e2b22d 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/UserAssetActivity.kt @@ -21,7 +21,6 @@ import com.v2ray.ang.extension.toastError import com.v2ray.ang.extension.toastSuccess import com.v2ray.ang.handler.MmkvManager import com.v2ray.ang.handler.SettingsManager -import com.v2ray.ang.dto.PermissionType import com.v2ray.ang.util.Utils import com.v2ray.ang.viewmodel.UserAssetViewModel import kotlinx.coroutines.Dispatchers @@ -29,7 +28,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File -class UserAssetActivity : BaseActivity() { +class UserAssetActivity : HelperBaseActivity() { private val binding by lazy { ActivityUserAssetBinding.inflate(layoutInflater) } private val ownerActivity: UserAssetActivity get() = this