Add NTFY configuration settings and persistence using SharedPreferences
Komit ini mengimplementasikan fitur konfigurasi endpoint NTFY yang dinamis dan menyimpannya menggunakan SharedPreferences. Ini mencakup penambahan layar pengaturan (SettingsScreen), perbaikan navigasi kembali menggunakan BackHandler, dan pembaruan fungsi sendNotification agar membaca URL dari konfigurasi yang disimpan.
This commit is contained in:
parent
9807c900dd
commit
e2bd34be8a
@ -63,5 +63,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.11.0")
|
implementation("com.squareup.okhttp3:okhttp:4.11.0")
|
||||||
implementation("androidx.compose.material3:material3:1.1.1")
|
implementation("androidx.compose.material3:material3:1.1.1")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.compose.BackHandler // ⬅️ Tambahkan impor ini
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
@ -27,6 +28,47 @@ import okhttp3.MediaType.Companion.toMediaType
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Settings
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// 1. CONSTANTS & HELPER FUNCTIONS FOR SHAREDPREFERENCES
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
const val PREFS_NAME = "AppPrefs"
|
||||||
|
const val KEY_NTFY_SERVER = "ntfyServer"
|
||||||
|
const val KEY_NTFY_TOPIC = "ntfyTopic"
|
||||||
|
|
||||||
|
const val DEFAULT_NTFY_SERVER = "https://ntfy.ubharajaya.ac.id"
|
||||||
|
const val DEFAULT_NTFY_TOPIC = "panic-button"
|
||||||
|
|
||||||
|
|
||||||
|
fun getPrefs(context: Context) = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
fun saveNtfyConfig(context: Context, server: String, topic: String) {
|
||||||
|
getPrefs(context).edit().apply {
|
||||||
|
putString(KEY_NTFY_SERVER, server)
|
||||||
|
putString(KEY_NTFY_TOPIC, topic)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNtfyUrl(context: Context): String {
|
||||||
|
val prefs = getPrefs(context)
|
||||||
|
val server = prefs.getString(KEY_NTFY_SERVER, DEFAULT_NTFY_SERVER)
|
||||||
|
val topic = prefs.getString(KEY_NTFY_TOPIC, DEFAULT_NTFY_TOPIC)
|
||||||
|
|
||||||
|
val cleanServer = server?.trimEnd('/') ?: DEFAULT_NTFY_SERVER.trimEnd('/')
|
||||||
|
val cleanTopic = topic?.trimStart('/') ?: DEFAULT_NTFY_TOPIC.trimStart('/')
|
||||||
|
|
||||||
|
return "$cleanServer/$cleanTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// 2. MAIN ACTIVITY CLASS
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -37,133 +79,96 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// 3. MY APP (NAVIGATOR)
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
sealed class ScreenState {
|
||||||
|
object Main : ScreenState()
|
||||||
|
object Settings : ScreenState()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun MyApp() {
|
fun MyApp() {
|
||||||
val focusManager = LocalFocusManager.current
|
var currentScreen by remember { mutableStateOf<ScreenState>(ScreenState.Main) }
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val sharedPreferences = context.getSharedPreferences("PanicButtonPrefs", Context.MODE_PRIVATE)
|
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text("Panic Button") },
|
||||||
|
// Logika TopBar hanya muncul jika di MainScreen,
|
||||||
|
// SettingsScreen memiliki TopBar sendiri
|
||||||
|
actions = {
|
||||||
|
if (currentScreen is ScreenState.Main) {
|
||||||
|
IconButton(onClick = {
|
||||||
|
currentScreen = ScreenState.Settings
|
||||||
|
}) {
|
||||||
|
Icon(Icons.Filled.Settings, contentDescription = "Settings")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
when (currentScreen) {
|
||||||
|
is ScreenState.Main -> MainScreen(
|
||||||
|
paddingValues = paddingValues,
|
||||||
|
onSendNotification = { conditions, report, onResult ->
|
||||||
|
sendNotification(context, conditions, report, onResult)
|
||||||
|
},
|
||||||
|
onNavigateEvakuasi = {
|
||||||
|
val intent = Intent(context, JalurEvakuasiActivity::class.java)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
is ScreenState.Settings -> SettingsScreen(
|
||||||
|
// Melewatkan fungsi untuk kembali
|
||||||
|
onBack = { currentScreen = ScreenState.Main }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// 4. MAIN SCREEN
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MainScreen(
|
||||||
|
paddingValues: PaddingValues,
|
||||||
|
onSendNotification: (String, String, (String) -> Unit) -> Unit,
|
||||||
|
onNavigateEvakuasi: () -> Unit
|
||||||
|
) {
|
||||||
|
val focusManager = LocalFocusManager.current
|
||||||
var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") }
|
var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") }
|
||||||
var selectedConditions by remember { mutableStateOf(mutableSetOf<String>()) }
|
var selectedConditions by remember { mutableStateOf(mutableSetOf<String>()) }
|
||||||
var additionalNotes by remember { mutableStateOf(TextFieldValue("")) }
|
var additionalNotes by remember { mutableStateOf(TextFieldValue("")) }
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
|
||||||
var dialogMessage by remember { mutableStateOf("") }
|
|
||||||
var showSettingsDialog by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
// Load saved configuration
|
|
||||||
var ntfyServer by remember {
|
|
||||||
mutableStateOf(sharedPreferences.getString("ntfyServer", "https://ntfy.sh") ?: "https://ntfy.sh")
|
|
||||||
}
|
|
||||||
var ntfyTopic by remember {
|
|
||||||
mutableStateOf(sharedPreferences.getString("ntfyTopic", "ubahara-panic-button") ?: "ubahara-panic-button")
|
|
||||||
}
|
|
||||||
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
// Dialog konfirmasi
|
|
||||||
if (showDialog) {
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = { showDialog = false },
|
|
||||||
title = { Text("Konfirmasi") },
|
|
||||||
text = { Text(dialogMessage) },
|
|
||||||
confirmButton = {
|
|
||||||
Button(onClick = { showDialog = false }) {
|
|
||||||
Text("OK")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dialog Settings
|
|
||||||
if (showSettingsDialog) {
|
|
||||||
var tempServer by remember { mutableStateOf(ntfyServer) }
|
|
||||||
var tempTopic by remember { mutableStateOf(ntfyTopic) }
|
|
||||||
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = { showSettingsDialog = false },
|
|
||||||
title = { Text("Pengaturan NTFY") },
|
|
||||||
text = {
|
|
||||||
Column {
|
|
||||||
Text("Server NTFY:")
|
|
||||||
OutlinedTextField(
|
|
||||||
value = tempServer,
|
|
||||||
onValueChange = { tempServer = it },
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
Text("Topic:")
|
|
||||||
OutlinedTextField(
|
|
||||||
value = tempTopic,
|
|
||||||
onValueChange = { tempTopic = it },
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
confirmButton = {
|
|
||||||
Button(onClick = {
|
|
||||||
ntfyServer = tempServer
|
|
||||||
ntfyTopic = tempTopic
|
|
||||||
// Save to SharedPreferences
|
|
||||||
with(sharedPreferences.edit()) {
|
|
||||||
putString("ntfyServer", tempServer)
|
|
||||||
putString("ntfyTopic", tempTopic)
|
|
||||||
// Gabungkan untuk kompatibilitas dengan AlertActivity
|
|
||||||
putString("urlKey", "$tempServer/$tempTopic")
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
showSettingsDialog = false
|
|
||||||
message = "Pengaturan berhasil disimpan"
|
|
||||||
}) {
|
|
||||||
Text("Simpan")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = { showSettingsDialog = false }) {
|
|
||||||
Text("Batal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(scrollState)
|
.verticalScroll(scrollState)
|
||||||
|
.padding(paddingValues)
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.Top,
|
verticalArrangement = Arrangement.Top,
|
||||||
horizontalAlignment = Alignment.Start
|
horizontalAlignment = Alignment.Start
|
||||||
) {
|
) {
|
||||||
// Header dengan tombol settings
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "Terjadi Kondisi Darurat",
|
|
||||||
fontSize = 20.sp,
|
|
||||||
color = Color.Red
|
|
||||||
)
|
|
||||||
Button(
|
|
||||||
onClick = { showSettingsDialog = true },
|
|
||||||
colors = ButtonDefaults.buttonColors(containerColor = Color.Gray)
|
|
||||||
) {
|
|
||||||
Text("⚙️", fontSize = 18.sp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = "Server: $ntfyServer\nTopic: $ntfyTopic",
|
text = "Terjadi Kondisi Darurat",
|
||||||
fontSize = 12.sp,
|
fontSize = 20.sp,
|
||||||
color = Color.Gray,
|
color = Color.Red,
|
||||||
modifier = Modifier.padding(bottom = 16.dp)
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
listOf(
|
listOf(
|
||||||
"🔥 Kebakaran", "⛈️ Banjir", "🌊 Tsunami", "🌋 Gunung Meletus",
|
"\uD83D\uDD25 Kebakaran", "⛈\uFE0F Banjir", "\uD83C\uDF0A Tsunami", "\uD83C\uDF0B Gunung Meletus",
|
||||||
"🌏 Gempa Bumi", "👿 Huru hara", "🐍 Binatang Buas",
|
"\uD83C\uDF0F Gempa Bumi", "\uD83D\uDC7F Huru hara", "\uD83D\uDC0D Binatang Buas",
|
||||||
"☢️ Radiasi Nuklir", "☣️ Biohazard"
|
"☢\uFE0F Radiasi Nuklir", "☣\uFE0F Biohazard"
|
||||||
).forEach { condition ->
|
).forEach { condition ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -212,23 +217,18 @@ fun MyApp() {
|
|||||||
val notes = additionalNotes.text
|
val notes = additionalNotes.text
|
||||||
val conditions = selectedConditions.joinToString(", ")
|
val conditions = selectedConditions.joinToString(", ")
|
||||||
val report = "Kondisi: $conditions\nCatatan: $notes"
|
val report = "Kondisi: $conditions\nCatatan: $notes"
|
||||||
val fullUrl = "$ntfyServer/$ntfyTopic"
|
onSendNotification(conditions, report) { response ->
|
||||||
|
|
||||||
sendNotification(fullUrl, conditions, report) { response ->
|
|
||||||
message = response
|
message = response
|
||||||
dialogMessage = response
|
|
||||||
showDialog = true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(containerColor = Color.Red),
|
colors = ButtonDefaults.buttonColors(containerColor = Color.Red)
|
||||||
enabled = selectedConditions.isNotEmpty()
|
|
||||||
) {
|
) {
|
||||||
Text(text = "Kirim Laporan", color = Color.White)
|
Text(text = "Kirim Laporan", color = Color.White)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "JANGAN PANIK! SEGERA EVAKUASI\nDIRI ANDA KE TITIK KUMPUL",
|
text = "“JANGAN PANIK! SEGERA EVAKUASI\nDIRI ANDA KE TITIK KUMPUL”",
|
||||||
color = Color.Red,
|
color = Color.Red,
|
||||||
fontSize = 15.sp
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
@ -236,10 +236,7 @@ fun MyApp() {
|
|||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(text = message, Modifier.padding(top = 16.dp))
|
Text(text = message, Modifier.padding(top = 16.dp))
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = onNavigateEvakuasi,
|
||||||
val intent = Intent(context, JalurEvakuasiActivity::class.java)
|
|
||||||
context.startActivity(intent)
|
|
||||||
},
|
|
||||||
colors = ButtonDefaults.buttonColors(containerColor = Color.Green)
|
colors = ButtonDefaults.buttonColors(containerColor = Color.Green)
|
||||||
) {
|
) {
|
||||||
Text(text = "Lihat Jalur Evakuasi", color = Color.White)
|
Text(text = "Lihat Jalur Evakuasi", color = Color.White)
|
||||||
@ -247,19 +244,122 @@ fun MyApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendNotification(url: String, condition: String, report: String, onResult: (String) -> Unit) {
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// 5. SETTINGS SCREEN (DIPERBAIKI)
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun SettingsScreen(onBack: () -> Unit) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val prefs = remember { getPrefs(context) }
|
||||||
|
|
||||||
|
// Inisialisasi state dari SharedPreferences
|
||||||
|
var serverText by remember {
|
||||||
|
mutableStateOf(TextFieldValue(prefs.getString(KEY_NTFY_SERVER, DEFAULT_NTFY_SERVER) ?: DEFAULT_NTFY_SERVER))
|
||||||
|
}
|
||||||
|
var topicText by remember {
|
||||||
|
mutableStateOf(TextFieldValue(prefs.getString(KEY_NTFY_TOPIC, DEFAULT_NTFY_TOPIC) ?: DEFAULT_NTFY_TOPIC))
|
||||||
|
}
|
||||||
|
|
||||||
|
var saveMessage by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
// ⬅️ TAMBAHAN: Menangani tombol kembali pada perangkat
|
||||||
|
BackHandler(onBack = onBack)
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text("Pengaturan NTFY Endpoint") },
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = onBack) { // ⬅️ onBack menangani navigasi kembali ke MainScreen
|
||||||
|
Icon(Icons.Filled.ArrowBack, contentDescription = "Kembali")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(innerPadding)
|
||||||
|
.padding(16.dp)
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
horizontalAlignment = Alignment.Start
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Konfigurasi Server Notifikasi",
|
||||||
|
fontSize = 18.sp,
|
||||||
|
modifier = Modifier.padding(bottom = 16.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = serverText,
|
||||||
|
onValueChange = { serverText = it },
|
||||||
|
label = { Text("Server NTFY (contoh: https://ntfy.sh)") },
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = topicText,
|
||||||
|
onValueChange = { topicText = it },
|
||||||
|
label = { Text("Topic (contoh: panic-button)") },
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
saveNtfyConfig(
|
||||||
|
context,
|
||||||
|
serverText.text.trim(),
|
||||||
|
topicText.text.trim()
|
||||||
|
)
|
||||||
|
saveMessage = "Konfigurasi berhasil disimpan! URL: ${getNtfyUrl(context)}"
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text("Simpan Konfigurasi")
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = saveMessage,
|
||||||
|
color = if (saveMessage.contains("berhasil")) Color.Green else Color.Black,
|
||||||
|
modifier = Modifier.padding(top = 16.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(
|
||||||
|
text = "URL saat ini: ${getNtfyUrl(context)}",
|
||||||
|
style = TextStyle(color = Color.Gray, fontSize = 12.sp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// 6. SEND NOTIFICATION FUNCTION
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
fun sendNotification(context: Context, condition: String, report: String, onResult: (String) -> Unit) {
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
val url = getNtfyUrl(context)
|
||||||
|
|
||||||
val tagMapping = mapOf(
|
val tagMapping = mapOf(
|
||||||
"🔥 Kebakaran" to "fire",
|
"\uD83D\uDD25 Kebakaran" to "fire",
|
||||||
"⛈️ Banjir" to "cloud_with_lightning_and_rain",
|
"⛈\uFE0F Banjir" to "cloud_with_lightning_and_rain",
|
||||||
"🌊 Tsunami" to "ocean",
|
"\uD83C\uDF0A Tsunami" to "ocean",
|
||||||
"🌋 Gunung Meletus" to "volcano",
|
"\uD83C\uDF0B Gunung Meletus" to "volcano",
|
||||||
"🌏 Gempa Bumi" to "earth_asia",
|
"\uD83C\uDF0F Gempa Bumi" to "earth_asia",
|
||||||
"👿 Huru hara" to "imp",
|
"\uD83D\uDC7F Huru hara" to "imp",
|
||||||
"🐍 Binatang Buas" to "snake",
|
"\uD83D\uDC0D Binatang Buas" to "snake",
|
||||||
"☢️ Radiasi Nuklir" to "radioactive",
|
"☢\uFE0F Radiasi Nuklir" to "radioactive",
|
||||||
"☣️ Biohazard" to "biohazard"
|
"☣\uFE0F Biohazard" to "biohazard"
|
||||||
)
|
)
|
||||||
|
|
||||||
val selectedList = condition
|
val selectedList = condition
|
||||||
@ -269,7 +369,8 @@ fun sendNotification(url: String, condition: String, report: String, onResult: (
|
|||||||
|
|
||||||
val cleanConditionText = selectedList.joinToString(", ")
|
val cleanConditionText = selectedList.joinToString(", ")
|
||||||
val emojiTags = selectedList.mapNotNull { tagMapping[it] }
|
val emojiTags = selectedList.mapNotNull { tagMapping[it] }
|
||||||
val finalTags = listOf("alert", "warning") + emojiTags
|
|
||||||
|
val finalTags = listOf("Alert") + emojiTags
|
||||||
val finalReport = "Kondisi: $cleanConditionText\nCatatan: ${report.substringAfter("Catatan:")}"
|
val finalReport = "Kondisi: $cleanConditionText\nCatatan: ${report.substringAfter("Catatan:")}"
|
||||||
|
|
||||||
val requestBody = RequestBody.create(
|
val requestBody = RequestBody.create(
|
||||||
@ -278,7 +379,7 @@ fun sendNotification(url: String, condition: String, report: String, onResult: (
|
|||||||
)
|
)
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.addHeader("Title", "⚠️ ALERT - Kondisi Darurat")
|
.addHeader("Title", "Alert")
|
||||||
.addHeader("Priority", "urgent")
|
.addHeader("Priority", "urgent")
|
||||||
.addHeader("Tags", finalTags.joinToString(","))
|
.addHeader("Tags", finalTags.joinToString(","))
|
||||||
.post(requestBody)
|
.post(requestBody)
|
||||||
@ -288,12 +389,12 @@ fun sendNotification(url: String, condition: String, report: String, onResult: (
|
|||||||
try {
|
try {
|
||||||
val response = client.newCall(request).execute()
|
val response = client.newCall(request).execute()
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
onResult("✅ Notifikasi berhasil dikirim!\nLaporan telah terkirim ke sistem.")
|
onResult("Notifikasi berhasil dikirim ke $url!")
|
||||||
} else {
|
} else {
|
||||||
onResult("❌ Gagal mengirim notifikasi\nKode error: ${response.code}")
|
onResult("Gagal mengirim notifikasi ke $url: ${response.code}")
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
onResult("❌ Error: ${e.message}")
|
onResult("Error: ${e.message}")
|
||||||
}
|
}
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user