/* * Created by sweetbread * Copyright (c) 2025. All rights reserved. */ package ru.risdeveau.geotracker import android.Manifest import android.content.Context import android.content.pm.PackageManager import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Done import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.core.content.ContextCompat import kotlinx.coroutines.delay import kotlinx.coroutines.launch import ru.risdeveau.geotracker.ui.theme.GeoTrackerTheme import splitties.experimental.ExperimentalSplittiesApi import splitties.init.appCtx import splitties.resources.appStr class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { GeoTrackerTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Box( Modifier .padding(innerPadding) .fillMaxSize()) { var screen by remember { mutableStateOf(Screen.Loading) } when (screen) { Screen.Main -> { Text("Hello world") } Screen.Settings -> { Settings(Modifier.align(Alignment.Center)) { screen = Screen.Main } } Screen.Loading -> { var loading by remember { mutableStateOf(true) } if (loading) { CircularProgressIndicator(Modifier.align(Alignment.Center)) LaunchedEffect(true) { launch { screen = if (health(SettingsPreferences.url)) Screen.Main else Screen.Settings } } } } } } } } } } } sealed class Screen { object Main : Screen() object Settings : Screen() object Loading : Screen() } @OptIn(ExperimentalSplittiesApi::class) @Composable fun Settings(modifier: Modifier = Modifier, onConfirm: () -> Unit) { var username by remember { mutableStateOf("") } var url by remember { mutableStateOf("") } var urlIsValid by remember { mutableStateOf(false) } var loading by remember { mutableStateOf(false) } LaunchedEffect(url) { if (url.isNotEmpty()) { delay(1000) loading = true urlIsValid = health(url) loading = false } } Column (modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) { OutlinedTextField( value = username, onValueChange = { username = it }, label = { Text(appStr(R.string.username)) } ) OutlinedTextField( value = url, onValueChange = { url = it }, placeholder = { Text("https://geo.example.com", style = TextStyle(color = MaterialTheme.colorScheme.onSurfaceVariant) ) }, label = { Text(appStr(R.string.server_url)) }, trailingIcon = { if (loading) CircularProgressIndicator() else if (urlIsValid) Icon(Icons.Outlined.Done, "Done") } ) LocationPermissionScreen() Button({ SettingsPreferences.username = username.trim() SettingsPreferences.url = url onConfirm() }, enabled = urlIsValid && !loading && username.trim().isNotEmpty() && hasLocationPermissions(appCtx) ) { Text(appStr(R.string.apply)) } } } @Composable fun LocationPermissionScreen() { val context = LocalContext.current val locationPermissions = arrayOf( Manifest.permission.ACCESS_FINE_LOCATION ) val hasLocationPermissions = remember { mutableStateOf( locationPermissions.all { ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED } ) } val permissionLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestMultiplePermissions() ) { permissions -> hasLocationPermissions.value = permissions.all { it.value } } if (hasLocationPermissions.value) { Button({}, enabled = false) { Icon(Icons.Outlined.Done, "Done") Text("Разрешения получены") } } else { Button(onClick = { permissionLauncher.launch(locationPermissions) }) { Text("Получить разрешения") } } } fun hasLocationPermissions(context: Context): Boolean { return ContextCompat.checkSelfPermission( context, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( context, Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED }