From 642d468005346151a64793691cadd2395fb60334 Mon Sep 17 00:00:00 2001 From: PTah Date: Sun, 14 Jun 2026 18:38:08 +1000 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0?= =?UTF-8?q?=D1=82=20=D0=B8=D0=B7=20picker=20=D0=B7=D0=B2=D1=83=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B1=D0=B5=D0=B7=20=D0=BA=D1=80=D0=B0=D1=88=D0=B0,=20?= =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BD=D1=8B=20dev-credentials=20(0.5.7?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Не блокировать биометрией при выборе звука. Удалён DevConnectDefaults.kt с паролем из репозитория. --- .gitignore | 1 + app/build.gradle.kts | 4 ++-- .../java/ru/kalinamall/seaca/MainActivity.kt | 15 +++++++++++++-- .../seaca/push/NotificationSoundResolver.kt | 14 ++++++++++++++ .../ru/kalinamall/seaca/ui/RingtonePicker.kt | 17 +++++++++++++---- .../seaca/ui/screens/ConnectScreen.kt | 18 ++++-------------- .../seaca/ui/screens/DetailScreens.kt | 13 ++++++------- 7 files changed, 53 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index a649a34..c82221a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ google-services.json *.jks local.properties secrets.properties +app/src/main/java/ru/kalinamall/seaca/ui/screens/DevConnectDefaults.kt # Env .env diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0bd9760..9b9121c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { applicationId = "ru.kalinamall.seaca" minSdk = 26 targetSdk = 35 - versionCode = 19 - versionName = "0.5.5" + versionCode = 21 + versionName = "0.5.7" } buildTypes { diff --git a/app/src/main/java/ru/kalinamall/seaca/MainActivity.kt b/app/src/main/java/ru/kalinamall/seaca/MainActivity.kt index 694fdd1..770cfe5 100644 --- a/app/src/main/java/ru/kalinamall/seaca/MainActivity.kt +++ b/app/src/main/java/ru/kalinamall/seaca/MainActivity.kt @@ -59,16 +59,22 @@ import ru.kalinamall.seaca.ui.screens.HostDetailScreen import ru.kalinamall.seaca.ui.screens.HostsScreen import ru.kalinamall.seaca.ui.screens.ProblemDetailScreen import ru.kalinamall.seaca.ui.screens.ProblemsScreen +import ru.kalinamall.seaca.ui.ExternalPickerHost import ru.kalinamall.seaca.ui.RingtonePicker import ru.kalinamall.seaca.ui.screens.ReportsScreen import ru.kalinamall.seaca.ui.theme.SeacaTheme -class MainActivity : FragmentActivity() { +class MainActivity : FragmentActivity(), ExternalPickerHost { private lateinit var repo: SacRepository private val biometricUnlocked = mutableStateOf(true) private var pendingBiometric = false + private var externalPickerFlowActive = false private val deepLinkState = composeMutableStateOf(null) + override fun beginExternalPickerFlow() { + externalPickerFlowActive = true + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) repo = SacRepository(applicationContext) @@ -99,11 +105,12 @@ class MainActivity : FragmentActivity() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @Suppress("DEPRECATION") super.onActivityResult(requestCode, resultCode, data) - RingtonePicker.handleActivityResult(requestCode, resultCode, data) + RingtonePicker.handleActivityResult(this, requestCode, resultCode, data) } override fun onStop() { super.onStop() + if (externalPickerFlowActive) return if (shouldRequireBiometric()) { biometricUnlocked.value = false pendingBiometric = true @@ -112,6 +119,10 @@ class MainActivity : FragmentActivity() { override fun onResume() { super.onResume() + if (externalPickerFlowActive) { + externalPickerFlowActive = false + return + } if (pendingBiometric && !biometricUnlocked.value && repo.session.getAccessToken() != null) { pendingBiometric = false BiometricGate.authenticate( diff --git a/app/src/main/java/ru/kalinamall/seaca/push/NotificationSoundResolver.kt b/app/src/main/java/ru/kalinamall/seaca/push/NotificationSoundResolver.kt index fbb7966..cdae605 100644 --- a/app/src/main/java/ru/kalinamall/seaca/push/NotificationSoundResolver.kt +++ b/app/src/main/java/ru/kalinamall/seaca/push/NotificationSoundResolver.kt @@ -1,6 +1,8 @@ package ru.kalinamall.seaca.push +import android.content.ContentResolver import android.content.Context +import android.content.Intent import android.media.RingtoneManager import android.net.Uri import ru.kalinamall.seaca.data.NotificationSoundSettings @@ -27,4 +29,16 @@ object NotificationSoundResolver { "—" } } + + fun persistCustomUri(context: Context, uri: Uri?) { + if (uri == null || uri.scheme != ContentResolver.SCHEME_CONTENT) return + try { + context.contentResolver.takePersistableUriPermission( + uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION, + ) + } catch (_: SecurityException) { + // Picker may not grant persistable permission for some URIs. + } + } } diff --git a/app/src/main/java/ru/kalinamall/seaca/ui/RingtonePicker.kt b/app/src/main/java/ru/kalinamall/seaca/ui/RingtonePicker.kt index 934c9e9..4bf2a2e 100644 --- a/app/src/main/java/ru/kalinamall/seaca/ui/RingtonePicker.kt +++ b/app/src/main/java/ru/kalinamall/seaca/ui/RingtonePicker.kt @@ -7,15 +7,18 @@ import android.media.RingtoneManager import android.net.Uri import android.os.Build import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.launch import ru.kalinamall.seaca.push.NotificationSoundResolver object RingtonePicker { private const val REQUEST_CODE = 9001 - private var callback: ((Uri?) -> Unit)? = null + private var callback: (suspend (Uri?) -> Unit)? = null - fun launch(activity: FragmentActivity, currentUri: Uri, onResult: (Uri?) -> Unit) { + fun launch(activity: FragmentActivity, currentUri: Uri, onResult: suspend (Uri?) -> Unit) { callback = onResult + (activity as? ExternalPickerHost)?.beginExternalPickerFlow() val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply { putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION) putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) @@ -32,12 +35,14 @@ object RingtonePicker { } } - fun handleActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + fun handleActivityResult(activity: FragmentActivity, requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode != REQUEST_CODE) return val onResult = callback ?: return callback = null val uri = if (resultCode == Activity.RESULT_OK) readResult(data) else null - onResult(uri) + activity.lifecycleScope.launch { + runCatching { onResult(uri) } + } } private fun readResult(data: Intent?): Uri? { @@ -50,3 +55,7 @@ object RingtonePicker { } } } + +interface ExternalPickerHost { + fun beginExternalPickerFlow() +} diff --git a/app/src/main/java/ru/kalinamall/seaca/ui/screens/ConnectScreen.kt b/app/src/main/java/ru/kalinamall/seaca/ui/screens/ConnectScreen.kt index 39a84ce..6ba30af 100644 --- a/app/src/main/java/ru/kalinamall/seaca/ui/screens/ConnectScreen.kt +++ b/app/src/main/java/ru/kalinamall/seaca/ui/screens/ConnectScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch -import ru.kalinamall.seaca.BuildConfig import ru.kalinamall.seaca.data.SacRepository @Composable @@ -30,20 +29,11 @@ fun ConnectScreen( repo: SacRepository, onConnected: () -> Unit, ) { - val devDefaults = BuildConfig.DEBUG - var serverUrl by remember { - mutableStateOf(if (devDefaults) DevConnectDefaults.SERVER_URL else "") - } + var serverUrl by remember { mutableStateOf("") } var enrollmentCode by remember { mutableStateOf("") } - var username by remember { - mutableStateOf(if (devDefaults) DevConnectDefaults.USERNAME else "") - } - var password by remember { - mutableStateOf(if (devDefaults) DevConnectDefaults.PASSWORD else "") - } - var displayName by remember { - mutableStateOf(if (devDefaults) DevConnectDefaults.DISPLAY_NAME else android.os.Build.MODEL) - } + var username by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + var displayName by remember { mutableStateOf(android.os.Build.MODEL) } var trustCert by remember { mutableStateOf(false) } var loading by remember { mutableStateOf(false) } var error by remember { mutableStateOf(null) } diff --git a/app/src/main/java/ru/kalinamall/seaca/ui/screens/DetailScreens.kt b/app/src/main/java/ru/kalinamall/seaca/ui/screens/DetailScreens.kt index 2b2a59c..358f089 100644 --- a/app/src/main/java/ru/kalinamall/seaca/ui/screens/DetailScreens.kt +++ b/app/src/main/java/ru/kalinamall/seaca/ui/screens/DetailScreens.kt @@ -462,14 +462,13 @@ fun DeviceScreen(repo: SacRepository, onLogout: () -> Unit) { val currentUri = NotificationSoundResolver.resolve(context, latestSoundSettings) try { RingtonePicker.launch(activity, currentUri) { uri -> - scope.launch { - if (uri == null) { - repo.session.setNotificationSound(NotificationSoundSource.SYSTEM, null) - } else { - repo.session.setNotificationSound(NotificationSoundSource.CUSTOM, uri.toString()) - } - applySoundChannels(repo.session.getNotificationSoundSettings()) + NotificationSoundResolver.persistCustomUri(context, uri) + if (uri == null) { + repo.session.setNotificationSound(NotificationSoundSource.SYSTEM, null) + } else { + repo.session.setNotificationSound(NotificationSoundSource.CUSTOM, uri.toString()) } + applySoundChannels(repo.session.getNotificationSoundSettings()) } } catch (_: ActivityNotFoundException) { Toast.makeText(context, "На устройстве нет выбора звука уведомлений", Toast.LENGTH_LONG).show()