Android: ChatGPT-style menu with Camera/Photos/Files
- Top row of attachment buttons: Camera | Photos | Files - Dark menu background (0xFF1E1E2E) for contrast - Styled menu items with icons and trailing values - Session and Thinking level show current value on right - Dividers between sections - TODO: Implement camera capture and file picker
This commit is contained in:
parent
40a5b0ce1e
commit
fbf18d55b8
@ -28,6 +28,8 @@ import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowUpward
|
||||
import androidx.compose.material.icons.filled.AttachFile
|
||||
import androidx.compose.material.icons.filled.CameraAlt
|
||||
import androidx.compose.material.icons.filled.Image
|
||||
import androidx.compose.material.icons.filled.Menu
|
||||
import androidx.compose.material.icons.filled.Mic
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
@ -75,7 +77,9 @@ fun ChatComposer(
|
||||
attachments: List<PendingImageAttachment>,
|
||||
seamColor: Color = Color(0xFF3B82F6),
|
||||
talkEnabled: Boolean = false,
|
||||
onOpenCamera: () -> Unit = {},
|
||||
onPickImages: () -> Unit,
|
||||
onPickFiles: () -> Unit = {},
|
||||
onRemoveAttachment: (id: String) -> Unit,
|
||||
onSetThinkingLevel: (level: String) -> Unit,
|
||||
onSelectSession: (sessionKey: String) -> Unit,
|
||||
@ -143,20 +147,63 @@ fun ChatComposer(
|
||||
DropdownMenu(
|
||||
expanded = showMenu,
|
||||
onDismissRequest = { showMenu = false },
|
||||
modifier = Modifier.background(Color(0xFF1E1E2E)), // Darker shade
|
||||
) {
|
||||
// Attachment buttons row: Camera | Photos | Files
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
AttachmentButton(
|
||||
icon = Icons.Default.CameraAlt,
|
||||
label = "Camera",
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onOpenCamera()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
AttachmentButton(
|
||||
icon = Icons.Default.Image,
|
||||
label = "Photos",
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onPickImages()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
AttachmentButton(
|
||||
icon = Icons.Default.AttachFile,
|
||||
label = "Files",
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onPickFiles()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
color = Color.White.copy(alpha = 0.1f),
|
||||
)
|
||||
|
||||
// Session selector
|
||||
DropdownMenuItem(
|
||||
text = { Text("Session: $currentSessionLabel") },
|
||||
text = { Text("Session", color = Color.White) },
|
||||
onClick = {
|
||||
showMenu = false
|
||||
showSessionMenu = true
|
||||
},
|
||||
leadingIcon = { Icon(Icons.Default.Settings, contentDescription = null) },
|
||||
leadingIcon = { Icon(Icons.Default.Settings, contentDescription = null, tint = Color.White.copy(alpha = 0.7f)) },
|
||||
trailingIcon = { Text(currentSessionLabel, color = Color.White.copy(alpha = 0.5f), style = MaterialTheme.typography.bodySmall) },
|
||||
)
|
||||
|
||||
// Thinking level
|
||||
DropdownMenuItem(
|
||||
text = { Text("Thinking: ${thinkingLabel(thinkingLevel)}") },
|
||||
text = { Text("Thinking", color = Color.White) },
|
||||
onClick = {
|
||||
showMenu = false
|
||||
showThinkingMenu = true
|
||||
@ -164,28 +211,22 @@ fun ChatComposer(
|
||||
leadingIcon = {
|
||||
Text("🧠", style = MaterialTheme.typography.bodyLarge)
|
||||
},
|
||||
trailingIcon = { Text(thinkingLabel(thinkingLevel), color = Color.White.copy(alpha = 0.5f), style = MaterialTheme.typography.bodySmall) },
|
||||
)
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
// Attach file
|
||||
DropdownMenuItem(
|
||||
text = { Text("Attach image") },
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onPickImages()
|
||||
},
|
||||
leadingIcon = { Icon(Icons.Default.AttachFile, contentDescription = null) },
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
color = Color.White.copy(alpha = 0.1f),
|
||||
)
|
||||
|
||||
// Refresh
|
||||
DropdownMenuItem(
|
||||
text = { Text("Refresh") },
|
||||
text = { Text("Refresh", color = Color.White) },
|
||||
onClick = {
|
||||
showMenu = false
|
||||
onRefresh()
|
||||
},
|
||||
leadingIcon = { Icon(Icons.Default.Refresh, contentDescription = null) },
|
||||
leadingIcon = { Icon(Icons.Default.Refresh, contentDescription = null, tint = Color.White.copy(alpha = 0.7f)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -294,6 +335,40 @@ fun ChatComposer(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AttachmentButton(
|
||||
icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||||
label: String,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Surface(
|
||||
onClick = onClick,
|
||||
modifier = modifier.height(80.dp),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = Color(0xFF2A2A3E),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(
|
||||
icon,
|
||||
contentDescription = label,
|
||||
tint = Color.White.copy(alpha = 0.8f),
|
||||
modifier = Modifier.size(24.dp),
|
||||
)
|
||||
Spacer(Modifier.height(6.dp))
|
||||
Text(
|
||||
label,
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = Color.White.copy(alpha = 0.8f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MiniOrb(
|
||||
seamColor: Color,
|
||||
|
||||
@ -97,7 +97,9 @@ fun ChatSheetContent(viewModel: MainViewModel) {
|
||||
attachments = attachments,
|
||||
seamColor = seamColor,
|
||||
talkEnabled = talkEnabled,
|
||||
onOpenCamera = { /* TODO: Implement camera capture */ },
|
||||
onPickImages = { pickImages.launch("image/*") },
|
||||
onPickFiles = { /* TODO: Implement file picker */ },
|
||||
onRemoveAttachment = { id -> attachments.removeAll { it.id == id } },
|
||||
onSetThinkingLevel = { level -> viewModel.setChatThinkingLevel(level) },
|
||||
onSelectSession = { key -> viewModel.switchChatSession(key) },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user