package com.example.dattingapp.homes import ChatScreen import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.ChatBubbleOutline import androidx.compose.material.icons.filled.Explore import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.SwapHoriz import androidx.compose.material3.AlertDialog import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.viewmodel.compose.viewModel import com.example.dattingapp.homes.networkandapi.MeetUiState import com.example.dattingapp.homes.networkandapi.MeetViewModel import com.example.dattingapp.homes.networkandapi.ProfileViewModel import com.example.dattingapp.homes.networkandapi.ProfileUiState import com.example.dattingapp.permission.PermissionHelper import com.example.dattingapp.ui.theme.DattingAPPTheme import kotlinx.coroutines.delay class HomeActivity : ComponentActivity() { private lateinit var permissionHelper: PermissionHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) permissionHelper = PermissionHelper(this) enableEdgeToEdge() setContent { DattingAPPTheme { var showDialog by remember { mutableStateOf(false) } var targetPermission by remember { mutableStateOf(null) } // Function to handle permission requests with state check fun checkAndRequestPermission(type: PermissionHelper.PermissionType) { val isAlreadyGranted = if (type == PermissionHelper.PermissionType.OVERLAY) { permissionHelper.isOverlayPermissionGranted() } else { permissionHelper.hasPermission(type) } if (isAlreadyGranted) { Toast.makeText(this, "${type.name} already granted!", Toast.LENGTH_SHORT).show() } else { targetPermission = type showDialog = true } } // 10-second delay trigger inside Compose lifecycle LaunchedEffect(Unit) { delay(10_000) // Wait 10 seconds checkAndRequestPermission(PermissionHelper.PermissionType.OVERLAY) } // Custom rationale dialog if (showDialog && targetPermission != null) { val (title, description) = when (targetPermission!!) { PermissionHelper.PermissionType.OVERLAY -> "Display Over Other Apps" to "This permission is needed to show floating call alerts over other apps." PermissionHelper.PermissionType.LOCATION -> "Location Access" to "We need location access to find matches near you." PermissionHelper.PermissionType.AUDIO -> "Microphone Access" to "Microphone access is required for voice calling." PermissionHelper.PermissionType.GALLERY -> "Photos Access" to "Access to photos is required to update your profile picture." PermissionHelper.PermissionType.NOTIFICATION -> "Notifications" to "Enable notifications so you don't miss new messages." } PermissionRationaleDialog( title = title, description = description, onConfirm = { showDialog = false val currentType = targetPermission!! if (currentType == PermissionHelper.PermissionType.OVERLAY) { permissionHelper.requestOverlayPermission { isGranted -> if (!isGranted) { Toast.makeText( this@HomeActivity, "Overlay Denied", Toast.LENGTH_SHORT ).show() } } } else { permissionHelper.requestPermissions(currentType) { isGranted -> val msg = if (isGranted) "${currentType.name} Granted" else "${currentType.name} Denied" Toast.makeText(this@HomeActivity, msg, Toast.LENGTH_SHORT).show() } } }, onDismiss = { showDialog = false } ) } HomeScreen() } } } } @Composable fun PermissionRationaleDialog( title: String, description: String, onConfirm: () -> Unit, onDismiss: () -> Unit ) { AlertDialog( onDismissRequest = onDismiss, title = { Text(text = title) }, text = { Text(text = description) }, confirmButton = { TextButton(onClick = onConfirm) { Text(text = "Allow") } }, dismissButton = { TextButton(onClick = onDismiss) { Text(text = "Cancel") } } ) } @Composable fun HomeScreen() { val appContext = LocalContext.current.applicationContext var selectedItem by remember { mutableIntStateOf(0) } Scaffold( bottomBar = { NavigationBar { // ========================================= // MEET // ========================================= NavigationBarItem( selected = selectedItem == 0, onClick = { selectedItem = 0 }, icon = { Icon( imageVector = Icons.Default.SwapHoriz, contentDescription = "Meet" ) }, label = { Text("Meet") } ) // ========================================= // EXPLORE // ========================================= NavigationBarItem( selected = selectedItem == 1, onClick = { selectedItem = 1 }, icon = { Icon( imageVector = Icons.Default.Explore, contentDescription = "Explore" ) }, label = { Text("Explore") } ) // ========================================= // POST // ========================================= NavigationBarItem( selected = selectedItem == 2, onClick = { selectedItem = 2 }, icon = { Icon( imageVector = Icons.Default.Add, contentDescription = "Post" ) }, label = { Text("Post") } ) // ========================================= // CHAT // ========================================= NavigationBarItem( selected = selectedItem == 3, onClick = { selectedItem = 3 }, icon = { Icon( imageVector = Icons.Default.ChatBubbleOutline, contentDescription = "Chat" ) }, label = { Text("Chat") } ) // ========================================= // PROFILE // ========================================= NavigationBarItem( selected = selectedItem == 4, onClick = { selectedItem = 4 }, icon = { Icon( imageVector = Icons.Default.Person, contentDescription = "Profile" ) }, label = { Text("Profile") } ) } } ) { innerPadding -> // ========================================= // CONTENT AREA // ========================================= val context = LocalContext.current // or via hiltViewModel() / factory Box(modifier = Modifier.padding(innerPadding)) { when (selectedItem) { // ========================================= // MEET // ========================================= 0 -> { // 1. Obtain instance of ViewModel and LocalContext val viewModel: MeetViewModel = viewModel() // 2. Collect state from ViewModel val uiState by viewModel.meetUiState.collectAsState() // 3. Trigger network call once when screen loads LaunchedEffect(Unit) { viewModel.meetUserResponse(context) } // 4. Map UI state to Composable parameters when (val state = uiState) { is MeetUiState.Loading, MeetUiState.Idle -> { MeetDiscoveryScreen( profiles = emptyList(), isLoading = true, errorMessage = null ) } is MeetUiState.Success -> { MeetDiscoveryScreen( profiles = state.response, isLoading = false, errorMessage = null ) } is MeetUiState.Error -> { MeetDiscoveryScreen( profiles = emptyList(), isLoading = false, errorMessage = state.message ) } } } // ========================================= // EXPLORE // ========================================= 1 -> { VibeCheckHomeScreen() } // ========================================= // CREATE POST // ========================================= 2 -> { CreateVibePostScreen() } // ========================================= // CHAT // ========================================= 3 -> { ChatScreen() } // ========================================= // PROFILE // ========================================= 4 -> { // 1. Obtain instance of ViewModel and LocalContext val profileViewModel: ProfileViewModel = viewModel() val context = LocalContext.current // 2. Collect state from ViewModel val uiState by profileViewModel.profileUiState.collectAsState() // 3. Trigger network call once when screen loads LaunchedEffect(Unit) { profileViewModel.profileResponse(context) } // 4. Map UI state to Composable parameters when (val state = uiState) { is ProfileUiState.Loading, ProfileUiState.Idle -> { MyProfileScreen( profileResponse = null, isLoading = true, errorMessage = null, // onRetry = { viewModel.meetUserResponse(context) } ) } is ProfileUiState.Success -> { MyProfileScreen( profileResponse = state.profileData, // or state.response depending on your data class naming isLoading = false, errorMessage = null, ) } is ProfileUiState.Error -> { MyProfileScreen( profileResponse = null, isLoading = false, errorMessage = state.message, onRetry = { profileViewModel.profileResponse(context) } ) } } } } } } }