hossain-khan / android-keep-alive

A simple app to keep alive specific apps
MIT License
4 stars 1 forks source link

[ADDED] Settings screen navigation #22

Closed hossain-khan closed 1 week ago

hossain-khan commented 1 week ago

Settings pseudo code with codegen

package dev.hossain.keepalive.ui.screen

import android.content.Context
import android.content.Intent
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.OutlinedTextField
import androidx.compose.material3.Slider
import androidx.compose.material3.Switch
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.rememberCoroutineScope
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.unit.dp
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.navigation.NavHostController
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

import android.content.pm.PackageManager
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

@Composable
fun SettingsScreen(navController: NavHostController) {
    val scope = rememberCoroutineScope()
    val dataStore = LocalContext.current.dataStore

    var username by remember { mutableStateOf("") }
    var age by remember { mutableStateOf(0) }
    var notificationsEnabled by remember { mutableStateOf(false) }

    LaunchedEffect(key1 = true) {
        // Load initial values from DataStore
        val preferences: Preferences = dataStore.data.first()
        username = preferences[stringPreferencesKey("username")] ?: ""
        age = preferences[intPreferencesKey("age")] ?: 0
        notificationsEnabled = preferences[booleanPreferencesKey("notifications_enabled")] ?: false
    }

    Column(
        modifier =
            Modifier
                .fillMaxSize()
                .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(16.dp),
    ) {
        OutlinedTextField(
            value = username,
            onValueChange = { username = it },
            label = { Text("Username") },
        )

        OutlinedTextField(
            value = age.toString(),
            onValueChange = { age = it.toIntOrNull() ?: 0 },
            label = { Text("Age") },
        )

        SliderPreference()

        AppSelectionSetting()

        Switch(
            checked = notificationsEnabled,
            onCheckedChange = { notificationsEnabled = it },
        )
        Text("Enable Notifications")

        Button(onClick = {
            scope.launch {
                dataStore.edit { preferences ->
                    preferences[stringPreferencesKey("username")] = username
                    preferences[intPreferencesKey("age")] = age
                    preferences[booleanPreferencesKey("notifications_enabled")] = notificationsEnabled
                }
            }
            navController.navigateUp()
        }) {
            Text("Save Settings")
        }
    }
}

@Composable
fun SliderPreference() {
    val sliderValue = remember { mutableStateOf(1f) }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        Text(text = "Select duration: ${sliderValue.value.toInt()} min")
        Slider(
            value = sliderValue.value,
            onValueChange = { sliderValue.value = it },
            valueRange = 1f..120f,
            steps = 119, // 120 - 1
            modifier = Modifier.fillMaxWidth()
        )
    }
}

@Composable
fun AppSelectionSetting() {
    val context = LocalContext.current
    val packageManager = context.packageManager

    var selectedAppName by remember { mutableStateOf<String?>(null) }
    var selectedAppPackageName by remember { mutableStateOf<String?>(null) }

    val launcher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult(),
        onResult = {
            it.data?.data?.let { uri ->
                val packageName = uri.encodedSchemeSpecificPart // Extract package name from URI
                selectedAppPackageName = packageName
                selectedAppName = packageManager.getApplicationLabel(
                    packageManager.getApplicationInfo(packageName, 0)
                ).toString()
            }
        }
    )

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        horizontalAlignment = Alignment.Start,
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text("Select an App")

        Button(onClick = {
            val intent = Intent(Intent.ACTION_MAIN).apply {
                addCategory(Intent.CATEGORY_LAUNCHER)
            }
            launcher.launch(intent)
        }) {
            Text(if (selectedAppName != null) "Selected: $selectedAppName" else "Choose App")
        }

        // Display other app details if needed
        selectedAppPackageName?.let {
            val appInfo = packageManager.getApplicationInfo(it, 0)
            Text("Package Name: $it")
            // You can access other app details using appInfo here
        }
    }
}