diff --git a/.idea/copilot.data.migration.agent.xml b/.idea/copilot.data.migration.agent.xml
index 51eb2bc..a1ee19c 100644
--- a/.idea/copilot.data.migration.agent.xml
+++ b/.idea/copilot.data.migration.agent.xml
@@ -24,6 +24,10 @@
+
+
+
+
@@ -84,6 +88,9 @@
+
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ace9e6e..013d055 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,10 @@
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt b/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt
index 822ffb8..3d79fb0 100644
--- a/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt
+++ b/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt
@@ -1,6 +1,7 @@
package id.ac.ubharajaya.panicbutton
import android.Manifest
+import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
@@ -11,16 +12,20 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.compose.material3.MaterialTheme
import com.google.android.gms.location.LocationServices
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
private lateinit var viewModel: MainViewModel
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
- // result handled inline when requesting
+ // Inform user about permission result
+ if (isGranted) {
+ // User granted permission
+ // Ask user to press the panic button again to include location
+ if (::viewModel.isInitialized) viewModel.dialogMessage = "Izin lokasi diberikan. Tekan kembali untuk menyertakan koordinat."
+ } else {
+ if (::viewModel.isInitialized) viewModel.dialogMessage = "Izin lokasi ditolak. Laporan akan dikirim tanpa koordinat."
+ }
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -33,8 +38,8 @@ class MainActivity : ComponentActivity() {
startActivity(Intent(this, EvacuationMapsActivity::class.java))
}
- // onSendAlert will try to get location (if permission granted) and then call viewModel.sendAlert
- val onSendAlert = {
+ @SuppressLint("MissingPermission")
+ fun handleSendAlert() {
// Check permission
val fineGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
val coarseGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
@@ -44,28 +49,28 @@ class MainActivity : ComponentActivity() {
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
// After permission flow, user will need to press the button again to actually send with location
viewModel.dialogMessage = "Izin lokasi dibutuhkan untuk menyertakan koordinat. Silakan tekan lagi setelah mengizinkan lokasi."
- return@let
+ return
}
- // Try get last location asynchronously
- CoroutineScope(Dispatchers.Main).launch {
- try {
- val loc = fusedClient.lastLocation.await() // need extension await - we'll handle fallback
+ // Try get last location asynchronously via Task listeners
+ fusedClient.lastLocation
+ .addOnSuccessListener { loc ->
if (loc != null) {
viewModel.sendAlert(loc.latitude, loc.longitude)
} else {
// fallback: send without coordinates
viewModel.sendAlert()
}
- } catch (e: Exception) {
+ }
+ .addOnFailureListener {
+ // If obtaining location fails, send without coordinates
viewModel.sendAlert()
}
- }
}
setContent {
MaterialTheme {
- MainScreen(viewModel = viewModel, onOpenEvacMaps = openEvacMaps)
+ MainScreen(viewModel = viewModel, onOpenEvacMaps = openEvacMaps, onSendAlert = ::handleSendAlert)
}
}
}
diff --git a/app/src/main/java/id/ac/ubharajaya/panicbutton/MainScreen.kt b/app/src/main/java/id/ac/ubharajaya/panicbutton/MainScreen.kt
index 1608514..698ab25 100644
--- a/app/src/main/java/id/ac/ubharajaya/panicbutton/MainScreen.kt
+++ b/app/src/main/java/id/ac/ubharajaya/panicbutton/MainScreen.kt
@@ -12,7 +12,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@@ -22,9 +22,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.ui.draw.shadow
-import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.foundation.layout.IntrinsicSize
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -91,17 +89,18 @@ fun MainScreen(viewModel: MainViewModel, onOpenEvacMaps: () -> Unit, onSendAlert
}
// Dialog
- val dialogMessage = viewModel.dialogMessage
- if (!dialogMessage.isNullOrBlank()) {
- AlertDialog(
- onDismissRequest = { viewModel.clearDialog() },
- confirmButton = {
- TextButton(onClick = { viewModel.clearDialog() }) { Text("OK") }
- },
- title = { Text("🚨 Notifikasi", style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)) },
- text = { Text(dialogMessage ?: "") }
- )
- }
+ viewModel.dialogMessage
+ ?.takeIf { it.isNotBlank() }
+ ?.let { msg ->
+ AlertDialog(
+ onDismissRequest = { viewModel.clearDialog() },
+ confirmButton = {
+ TextButton(onClick = { viewModel.clearDialog() }) { Text("OK") }
+ },
+ title = { Text("🚨 Notifikasi", style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)) },
+ text = { Text(msg) }
+ )
+ }
}
}