package ru.officialdakari.fmd import android.content.Context import android.os.Bundle import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import ru.officialdakari.fmd.dialogs.NewPinDialog import ru.officialdakari.fmd.dialogs.SelectAppsDialog import ru.officialdakari.fmd.ui.theme.FindMyDeviceTheme import java.io.File import java.io.FileInputStream import java.io.FileOutputStream class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { FindMyDeviceTheme { Scaffold(topBar = { Titlebar() }, modifier = Modifier.fillMaxSize()) { innerPadding -> Column( modifier = Modifier .fillMaxWidth() .padding(innerPadding), verticalArrangement = Arrangement.Center, ) { SetPinButton(context = this@MainActivity) SetAppsButton(context = this@MainActivity) } } } } } } @Composable fun SetPinButton(context: Context) { val deviceProtectedContext: Context = context.createDeviceProtectedStorageContext() var showDialog by remember { mutableStateOf(false) } if (showDialog) { NewPinDialog( onDismissRequest = { showDialog = false }, onConfirm = { pass -> var pinFile = File("${deviceProtectedContext.filesDir.path}/pin.txt") val pinInputStream = FileOutputStream(pinFile) var hashedPin = Utils.sha256(pass) pinInputStream.write(hashedPin.toByteArray(Charsets.US_ASCII)) } ) } Text( text = "FMD is operating through notifications and SMS. To prevent malicious usage, you need to set PIN and remember it. It is required to trigger FMD remotely.", modifier = Modifier.padding(10.dp) ) Button( onClick = { showDialog = true }, modifier = Modifier.fillMaxWidth().padding(10.dp) ) { Text("Set PIN") } } @Composable fun SetAppsButton(context: Context) { var showDialog by remember { mutableStateOf(false) } val initialState = mutableListOf>() for (app in Utils.getAllowedApps(context)) { initialState.add(Pair(app, true)) } if (showDialog) { SelectAppsDialog( onDismissRequest = { showDialog = false }, onConfirm = { state -> var l = mutableListOf() for (pair in state) { if (pair.second) { l.add(pair.first) } } Utils.setAllowedApps(context, l.toTypedArray()) Toast.makeText(context, "App list saved", Toast.LENGTH_SHORT) }, initialState = initialState, context = context, ) } Text( text = "Choose which apps' notifications are allowed to control FMD.", modifier = Modifier.padding(10.dp) ) Button( onClick = { showDialog = true }, modifier = Modifier.fillMaxWidth().padding(10.dp) ) { Text("Choose apps") } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun Titlebar() { TopAppBar( colors = TopAppBarDefaults.topAppBarColors( containerColor = MaterialTheme.colorScheme.primaryContainer, titleContentColor = MaterialTheme.colorScheme.primary, ), title = { Text(text = "FindMyDevice") } ) }