git.iko.soy/opencode-android
on e9b2cc3 help sign in
90 lines 3.7 kB history raw
1package soy.iko.opencode.ui.chat
3import androidx.compose.foundation.layout.Arrangement
4import androidx.compose.foundation.layout.Column
5import androidx.compose.foundation.layout.Row
6import androidx.compose.foundation.layout.fillMaxWidth
7import androidx.compose.foundation.layout.padding
8import androidx.compose.material.icons.Icons
9import androidx.compose.material.icons.filled.Shield
10import androidx.compose.material3.AlertDialog
11import androidx.compose.material3.Button
12import androidx.compose.material3.Icon
13import androidx.compose.material3.MaterialTheme
14import androidx.compose.material3.OutlinedButton
15import androidx.compose.material3.Text
16import androidx.compose.material3.TextButton
17import androidx.compose.runtime.Composable
18import androidx.compose.ui.Modifier
19import androidx.compose.ui.platform.LocalHapticFeedback
20import androidx.compose.ui.text.font.FontFamily
21import androidx.compose.ui.unit.dp
22import soy.iko.opencode.data.model.Permission
23import soy.iko.opencode.data.model.PermissionResponse
25/**
26 * Modal asking the user to approve a tool the agent wants to run. The agent run is
27 * paused until one of these responses is sent. Non-dismissable by tap-outside so the
28 * decision is explicit.
29 */
30@Composable
31fun PermissionDialog(
32 permission: Permission,
33 onRespond: (PermissionResponse) -> Unit,
34) {
35 val haptics = LocalHapticFeedback.current
36 AlertDialog(
37 onDismissRequest = { /* require an explicit choice */ },
38 icon = { Icon(Icons.Filled.Shield, contentDescription = null) },
39 title = { Text(permission.title ?: "Permission requested") },
40 text = {
41 Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
42 permission.type?.let {
43 Text(it, style = MaterialTheme.typography.labelLarge, fontFamily = FontFamily.Monospace)
44 }
45 permission.patternText?.let {
46 Text(
47 it,
48 style = MaterialTheme.typography.bodyMedium,
49 fontFamily = FontFamily.Monospace,
50 color = MaterialTheme.colorScheme.onSurfaceVariant,
51 )
52 }
53 Text(
54 "Allow this tool to run?",
55 style = MaterialTheme.typography.bodySmall,
56 color = MaterialTheme.colorScheme.onSurfaceVariant,
57 )
58 }
59 },
60 confirmButton = {
61 Column(
62 modifier = Modifier.fillMaxWidth(),
63 verticalArrangement = Arrangement.spacedBy(4.dp),
64 ) {
65 Button(
66 onClick = {
67 haptics.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.LongPress)
68 onRespond(PermissionResponse.ONCE)
69 },
70 modifier = Modifier.fillMaxWidth(),
71 ) { Text("Allow once") }
72 OutlinedButton(
73 onClick = {
74 haptics.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.LongPress)
75 onRespond(PermissionResponse.ALWAYS)
76 },
77 modifier = Modifier.fillMaxWidth(),
78 ) { Text("Always allow") }
79 }
80 },
81 dismissButton = {
82 TextButton(onClick = {
83 haptics.performHapticFeedback(androidx.compose.ui.hapticfeedback.HapticFeedbackType.LongPress)
84 onRespond(PermissionResponse.REJECT)
85 }) {
86 Text("Reject", color = MaterialTheme.colorScheme.error)
87 }
88 },
89 )