package com.example.dattingapp.registration import android.content.Context import android.net.Uri import android.os.Bundle import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.FileUpload import androidx.compose.material.icons.filled.PhotoCamera import androidx.compose.material.icons.filled.Videocam import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.content.FileProvider import androidx.media3.common.MediaItem import androidx.media3.exoplayer.ExoPlayer import androidx.media3.ui.PlayerView import coil.compose.rememberAsyncImagePainter import com.example.dattingapp.ui.theme.DattingAPPTheme import java.io.File enum class DisplayMode { IMAGE, VIDEO, BIO } class UploadIntroVideoActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() // Retrieve Profile Image URI string val profileImageUriString = intent.getStringExtra("EXTRA_PROFILE_IMAGE_URI") val profileImageUri: Uri? = profileImageUriString?.let { Uri.parse(it) } setContent { DattingAPPTheme { UploadIntroVideoScreen( profileImageUri = profileImageUri, onBackClick = { finish() }, onSkipClick = { /* Handle skip */ }, onSubmit = { videoUri, bioText -> // Final registration submission logic Toast.makeText(this, "Registration Data Ready!", Toast.LENGTH_SHORT).show() } ) } } } } @Composable fun UploadIntroVideoScreen( profileImageUri: Uri?, onBackClick: () -> Unit = {}, onSkipClick: () -> Unit = {}, onSubmit: (videoUri: Uri?, bioText: String) -> Unit ) { val context = LocalContext.current var displayMode by remember { mutableStateOf(DisplayMode.IMAGE) } var recordedVideoUri by remember { mutableStateOf(null) } var bioText by remember { mutableStateOf("") } // Launchers remain the same... val videoPickerLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.GetContent() ) { uri: Uri? -> if (uri != null) { recordedVideoUri = uri displayMode = DisplayMode.VIDEO } } val recordVideoLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.CaptureVideo() ) { success -> if (success && recordedVideoUri != null) { displayMode = DisplayMode.VIDEO } } var tempCameraPhotoUri by remember { mutableStateOf(null) } var capturedPhotoUri by remember { mutableStateOf(null) } val takePhotoLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.TakePicture() ) { success -> if (success && tempCameraPhotoUri != null) { capturedPhotoUri = tempCameraPhotoUri displayMode = DisplayMode.IMAGE } } val buttonGradient = Brush.horizontalGradient( colors = listOf(Color(0xFFB70054), Color(0xFF6700C7)) ) Column( modifier = Modifier .fillMaxSize() .background(Color(0xFFF9F9F9)) .systemBarsPadding() // 👇 ADD imePadding() HERE TO RESIZE WHEN KEYBOARD OPENS 👇 .imePadding() .padding(horizontal = 20.dp, vertical = 12.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceBetween ) { // --- Header Section --- Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { IconButton(onClick = onBackClick) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", tint = Color.Black) } Text( text = "VibeCheck", fontSize = 22.sp, fontWeight = FontWeight.Bold, color = Color(0xFF9C27B0) ) TextButton(onClick = onSkipClick) { Text(text = "SKIP", color = Color.Gray, fontWeight = FontWeight.Bold, fontSize = 12.sp) } } // --- Header Title --- Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( text = if (displayMode == DisplayMode.BIO) "Your Bio" else "Video Introduction", fontSize = 22.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1E293B) ) Spacer(modifier = Modifier.height(4.dp)) Text( text = if (displayMode == DisplayMode.BIO) "Write a short intro about yourself (up to 200 words)." else "Say hello! Share a bit about yourself in 60 seconds.", fontSize = 13.sp, color = Color.Gray ) } // --- Central Media / Text Container --- Box( modifier = Modifier .fillMaxWidth() .weight(1f) .padding(vertical = 12.dp) .clip(RoundedCornerShape(20.dp)) .background(Color.LightGray), contentAlignment = Alignment.Center ) { when (displayMode) { DisplayMode.IMAGE -> { if (capturedPhotoUri != null || profileImageUri != null) { Image( painter = rememberAsyncImagePainter(model = capturedPhotoUri ?: profileImageUri), contentDescription = "Profile Image Preview", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop ) } } DisplayMode.VIDEO -> { recordedVideoUri?.let { uri -> VideoPlayer(videoUri = uri) } } DisplayMode.BIO -> { OutlinedTextField( value = bioText, onValueChange = { input -> val words = input.trim().split("\\s+".toRegex()) if (input.isEmpty() || words.size <= 200) bioText = input }, modifier = Modifier .fillMaxSize() .background(Color.White) .padding(12.dp), placeholder = { Text("Write something about yourself (max 200 words)...") }, colors = TextFieldDefaults.colors( unfocusedContainerColor = Color.White, focusedContainerColor = Color.White ) ) } } // Overlay timer & action icons (hidden during Bio input) if (displayMode != DisplayMode.BIO) { Box( modifier = Modifier .padding(12.dp) .align(Alignment.TopEnd) .clip(RoundedCornerShape(12.dp)) .background(Color.Black.copy(alpha = 0.5f)) .padding(horizontal = 10.dp, vertical = 4.dp) ) { Text( text = "00:00 / 01:00", color = Color.White, fontSize = 11.sp, fontWeight = FontWeight.SemiBold ) } Row( modifier = Modifier .align(Alignment.BottomCenter) .padding(bottom = 20.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier .size(48.dp) .clip(CircleShape) .background(Color.White.copy(alpha = 0.85f)) .clickable { videoPickerLauncher.launch("video/*") }, contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.FileUpload, contentDescription = "Upload Gallery Video", tint = Color(0xFF475569), modifier = Modifier.size(24.dp) ) } Box( modifier = Modifier .size(64.dp) .clip(CircleShape) .background(Color.White.copy(alpha = 0.9f)) .border(2.dp, Color(0xFFE11D48), CircleShape) .clickable { val tempUri = createVideoUri(context) recordedVideoUri = tempUri recordVideoLauncher.launch(tempUri) }, contentAlignment = Alignment.Center ) { Box( modifier = Modifier .size(48.dp) .clip(CircleShape) .background(Color(0xFFE11D48)), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Videocam, contentDescription = "Record Video", tint = Color.White, modifier = Modifier.size(26.dp) ) } } Box( modifier = Modifier .size(48.dp) .clip(CircleShape) .background(Color.White.copy(alpha = 0.85f)) .clickable { val tempUri = createImageUri(context) tempCameraPhotoUri = tempUri takePhotoLauncher.launch(tempUri) }, contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.PhotoCamera, contentDescription = "Take Photo", tint = Color(0xFF475569), modifier = Modifier.size(24.dp) ) } } } } // --- Bottom Buttons --- Column( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(10.dp) ) { Button( onClick = { onSubmit(recordedVideoUri, bioText) }, modifier = Modifier .fillMaxWidth() .height(50.dp) .background(buttonGradient, shape = RoundedCornerShape(12.dp)), colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent), shape = RoundedCornerShape(12.dp) ) { Text(text = "UPLOAD", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 16.sp) } OutlinedButton( onClick = { displayMode = if (displayMode == DisplayMode.BIO) { if (recordedVideoUri != null) DisplayMode.VIDEO else DisplayMode.IMAGE } else { DisplayMode.BIO } }, modifier = Modifier .fillMaxWidth() .height(50.dp), shape = RoundedCornerShape(12.dp), border = ButtonDefaults.outlinedButtonBorder.copy( brush = Brush.horizontalGradient(listOf(Color(0xFFE11D48), Color(0xFFE11D48))) ) ) { Text( text = if (displayMode == DisplayMode.BIO) "VIDEO INTRO" else "ADD BIO", color = Color(0xFFE11D48), fontWeight = FontWeight.Bold, fontSize = 14.sp ) } } } } // Media3 ExoPlayer composable @Composable fun VideoPlayer(videoUri: Uri) { val context = LocalContext.current val exoPlayer = remember(videoUri) { ExoPlayer.Builder(context).build().apply { setMediaItem(MediaItem.fromUri(videoUri)) prepare() playWhenReady = true } } DisposableEffect(Unit) { onDispose { exoPlayer.release() } } AndroidView( factory = { ctx -> PlayerView(ctx).apply { player = exoPlayer useController = true } }, modifier = Modifier.fillMaxSize() ) } // Helper functions to create temporary File Uris for Video and Image captures fun createVideoUri(context: Context): Uri { val tempFile = File.createTempFile("intro_video_", ".mp4", context.cacheDir).apply { createNewFile() deleteOnExit() } return FileProvider.getUriForFile( context, "${context.packageName}.provider", tempFile ) } fun createImageUrl(context: Context): Uri { val tempFile = File.createTempFile("intro_photo_", ".jpg", context.cacheDir).apply { createNewFile() deleteOnExit() } return FileProvider.getUriForFile( context, "${context.packageName}.provider", tempFile ) } // --- Composable Previews --- @Preview( name = "Upload Intro Screen - Full Preview", showBackground = true, showSystemUi = true ) @Composable fun UploadIntroVideoScreenPreview() { DattingAPPTheme { UploadIntroVideoScreen( profileImageUri = null, onSubmit = { _, _ -> } ) } }