Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b4020adf1 | |||
| f41a0d3a50 | |||
| 2aaea30468 |
@@ -22,7 +22,6 @@ google-services.json
|
|||||||
*.jks
|
*.jks
|
||||||
local.properties
|
local.properties
|
||||||
secrets.properties
|
secrets.properties
|
||||||
app/src/main/java/ru/kalinamall/seaca/ui/screens/DevConnectDefaults.kt
|
|
||||||
|
|
||||||
# Env
|
# Env
|
||||||
.env
|
.env
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ android {
|
|||||||
applicationId = "ru.kalinamall.seaca"
|
applicationId = "ru.kalinamall.seaca"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 21
|
versionCode = 19
|
||||||
versionName = "0.5.7"
|
versionName = "0.5.5"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -59,22 +59,16 @@ import ru.kalinamall.seaca.ui.screens.HostDetailScreen
|
|||||||
import ru.kalinamall.seaca.ui.screens.HostsScreen
|
import ru.kalinamall.seaca.ui.screens.HostsScreen
|
||||||
import ru.kalinamall.seaca.ui.screens.ProblemDetailScreen
|
import ru.kalinamall.seaca.ui.screens.ProblemDetailScreen
|
||||||
import ru.kalinamall.seaca.ui.screens.ProblemsScreen
|
import ru.kalinamall.seaca.ui.screens.ProblemsScreen
|
||||||
import ru.kalinamall.seaca.ui.ExternalPickerHost
|
|
||||||
import ru.kalinamall.seaca.ui.RingtonePicker
|
import ru.kalinamall.seaca.ui.RingtonePicker
|
||||||
import ru.kalinamall.seaca.ui.screens.ReportsScreen
|
import ru.kalinamall.seaca.ui.screens.ReportsScreen
|
||||||
import ru.kalinamall.seaca.ui.theme.SeacaTheme
|
import ru.kalinamall.seaca.ui.theme.SeacaTheme
|
||||||
|
|
||||||
class MainActivity : FragmentActivity(), ExternalPickerHost {
|
class MainActivity : FragmentActivity() {
|
||||||
private lateinit var repo: SacRepository
|
private lateinit var repo: SacRepository
|
||||||
private val biometricUnlocked = mutableStateOf(true)
|
private val biometricUnlocked = mutableStateOf(true)
|
||||||
private var pendingBiometric = false
|
private var pendingBiometric = false
|
||||||
private var externalPickerFlowActive = false
|
|
||||||
private val deepLinkState = composeMutableStateOf<String?>(null)
|
private val deepLinkState = composeMutableStateOf<String?>(null)
|
||||||
|
|
||||||
override fun beginExternalPickerFlow() {
|
|
||||||
externalPickerFlowActive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
repo = SacRepository(applicationContext)
|
repo = SacRepository(applicationContext)
|
||||||
@@ -105,12 +99,11 @@ class MainActivity : FragmentActivity(), ExternalPickerHost {
|
|||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
RingtonePicker.handleActivityResult(this, requestCode, resultCode, data)
|
RingtonePicker.handleActivityResult(requestCode, resultCode, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
if (externalPickerFlowActive) return
|
|
||||||
if (shouldRequireBiometric()) {
|
if (shouldRequireBiometric()) {
|
||||||
biometricUnlocked.value = false
|
biometricUnlocked.value = false
|
||||||
pendingBiometric = true
|
pendingBiometric = true
|
||||||
@@ -119,10 +112,6 @@ class MainActivity : FragmentActivity(), ExternalPickerHost {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (externalPickerFlowActive) {
|
|
||||||
externalPickerFlowActive = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (pendingBiometric && !biometricUnlocked.value && repo.session.getAccessToken() != null) {
|
if (pendingBiometric && !biometricUnlocked.value && repo.session.getAccessToken() != null) {
|
||||||
pendingBiometric = false
|
pendingBiometric = false
|
||||||
BiometricGate.authenticate(
|
BiometricGate.authenticate(
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package ru.kalinamall.seaca.push
|
package ru.kalinamall.seaca.push
|
||||||
|
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.media.RingtoneManager
|
import android.media.RingtoneManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import ru.kalinamall.seaca.data.NotificationSoundSettings
|
import ru.kalinamall.seaca.data.NotificationSoundSettings
|
||||||
@@ -29,16 +27,4 @@ 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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,15 @@ import android.media.RingtoneManager
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import ru.kalinamall.seaca.push.NotificationSoundResolver
|
import ru.kalinamall.seaca.push.NotificationSoundResolver
|
||||||
|
|
||||||
object RingtonePicker {
|
object RingtonePicker {
|
||||||
private const val REQUEST_CODE = 9001
|
private const val REQUEST_CODE = 9001
|
||||||
|
|
||||||
private var callback: (suspend (Uri?) -> Unit)? = null
|
private var callback: ((Uri?) -> Unit)? = null
|
||||||
|
|
||||||
fun launch(activity: FragmentActivity, currentUri: Uri, onResult: suspend (Uri?) -> Unit) {
|
fun launch(activity: FragmentActivity, currentUri: Uri, onResult: (Uri?) -> Unit) {
|
||||||
callback = onResult
|
callback = onResult
|
||||||
(activity as? ExternalPickerHost)?.beginExternalPickerFlow()
|
|
||||||
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
|
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
|
||||||
putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
|
putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
|
||||||
putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
|
putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
|
||||||
@@ -35,14 +32,12 @@ object RingtonePicker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleActivityResult(activity: FragmentActivity, requestCode: Int, resultCode: Int, data: Intent?) {
|
fun handleActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
if (requestCode != REQUEST_CODE) return
|
if (requestCode != REQUEST_CODE) return
|
||||||
val onResult = callback ?: return
|
val onResult = callback ?: return
|
||||||
callback = null
|
callback = null
|
||||||
val uri = if (resultCode == Activity.RESULT_OK) readResult(data) else null
|
val uri = if (resultCode == Activity.RESULT_OK) readResult(data) else null
|
||||||
activity.lifecycleScope.launch {
|
onResult(uri)
|
||||||
runCatching { onResult(uri) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readResult(data: Intent?): Uri? {
|
private fun readResult(data: Intent?): Uri? {
|
||||||
@@ -55,7 +50,3 @@ object RingtonePicker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExternalPickerHost {
|
|
||||||
fun beginExternalPickerFlow()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import ru.kalinamall.seaca.BuildConfig
|
||||||
import ru.kalinamall.seaca.data.SacRepository
|
import ru.kalinamall.seaca.data.SacRepository
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -29,11 +30,20 @@ fun ConnectScreen(
|
|||||||
repo: SacRepository,
|
repo: SacRepository,
|
||||||
onConnected: () -> Unit,
|
onConnected: () -> Unit,
|
||||||
) {
|
) {
|
||||||
var serverUrl by remember { mutableStateOf("") }
|
val devDefaults = BuildConfig.DEBUG
|
||||||
|
var serverUrl by remember {
|
||||||
|
mutableStateOf(if (devDefaults) DevConnectDefaults.SERVER_URL else "")
|
||||||
|
}
|
||||||
var enrollmentCode by remember { mutableStateOf("") }
|
var enrollmentCode by remember { mutableStateOf("") }
|
||||||
var username by remember { mutableStateOf("") }
|
var username by remember {
|
||||||
var password by remember { mutableStateOf("") }
|
mutableStateOf(if (devDefaults) DevConnectDefaults.USERNAME else "")
|
||||||
var displayName by remember { mutableStateOf(android.os.Build.MODEL) }
|
}
|
||||||
|
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 trustCert by remember { mutableStateOf(false) }
|
var trustCert by remember { mutableStateOf(false) }
|
||||||
var loading by remember { mutableStateOf(false) }
|
var loading by remember { mutableStateOf(false) }
|
||||||
var error by remember { mutableStateOf<String?>(null) }
|
var error by remember { mutableStateOf<String?>(null) }
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ fun DeviceScreen(repo: SacRepository, onLogout: () -> Unit) {
|
|||||||
val currentUri = NotificationSoundResolver.resolve(context, latestSoundSettings)
|
val currentUri = NotificationSoundResolver.resolve(context, latestSoundSettings)
|
||||||
try {
|
try {
|
||||||
RingtonePicker.launch(activity, currentUri) { uri ->
|
RingtonePicker.launch(activity, currentUri) { uri ->
|
||||||
NotificationSoundResolver.persistCustomUri(context, uri)
|
scope.launch {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
repo.session.setNotificationSound(NotificationSoundSource.SYSTEM, null)
|
repo.session.setNotificationSound(NotificationSoundSource.SYSTEM, null)
|
||||||
} else {
|
} else {
|
||||||
@@ -470,6 +470,7 @@ fun DeviceScreen(repo: SacRepository, onLogout: () -> Unit) {
|
|||||||
}
|
}
|
||||||
applySoundChannels(repo.session.getNotificationSoundSettings())
|
applySoundChannels(repo.session.getNotificationSoundSettings())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (_: ActivityNotFoundException) {
|
} catch (_: ActivityNotFoundException) {
|
||||||
Toast.makeText(context, "На устройстве нет выбора звука уведомлений", Toast.LENGTH_LONG).show()
|
Toast.makeText(context, "На устройстве нет выбора звука уведомлений", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package ru.kalinamall.seaca.ui.screens
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Временные значения для обкатки. Удалить перед релизом.
|
||||||
|
* Используются только в debug-сборке ([ru.kalinamall.seaca.BuildConfig.DEBUG]).
|
||||||
|
*/
|
||||||
|
internal object DevConnectDefaults {
|
||||||
|
const val SERVER_URL = "https://sac-api.kalinamall.ru"
|
||||||
|
const val USERNAME = "admin"
|
||||||
|
const val PASSWORD = "R3tt3tnatur"
|
||||||
|
const val DISPLAY_NAME = "papas s25"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user