| 1 | import { |
| 2 | AlertDialog, |
| 3 | Host, |
| 4 | OutlinedTextField, |
| 5 | Text, |
| 6 | TextButton, |
| 7 | useNativeState, |
| 8 | } from "@expo/ui/jetpack-compose"; |
| 9 | |
| 10 | import { useAppearancePreferences } from "../features/settings/appearance/AppearancePreferencesProvider"; |
| 11 | import { useScaledTextRole } from "../features/settings/appearance/useScaledTextRole"; |
| 12 | import type { MaterialConfirmDialogProps } from "./MaterialConfirmDialog"; |
| 13 | |
| 14 | export function MaterialConfirmDialog(props: MaterialConfirmDialogProps) { |
| 15 | const { themeAppearance, themeVariables: colors } = useAppearancePreferences(); |
| 16 | const titleTypography = useScaledTextRole("title"); |
| 17 | const bodyTypography = useScaledTextRole("footnote"); |
| 18 | const inputTypography = useScaledTextRole("body"); |
| 19 | const inputState = useNativeState(props.inputInitialValue ?? ""); |
| 20 | const inputSelection = useNativeState({ start: 0, end: props.inputInitialValue?.length ?? 0 }); |
| 21 | const confirm = () => { |
| 22 | if (props.confirmDisabled) return; |
| 23 | const value = props.inputInitialValue === undefined ? undefined : inputState.get(); |
| 24 | if (value !== undefined && !value.trim()) return; |
| 25 | props.onConfirm(value); |
| 26 | }; |
| 27 | return ( |
| 28 | <Host |
| 29 | colorScheme={themeAppearance} |
| 30 | ignoreSafeAreaKeyboardInsets |
| 31 | style={{ height: 0, width: 0 }} |
| 32 | > |
| 33 | <AlertDialog |
| 34 | onDismissRequest={props.onCancel} |
| 35 | tonalElevation={0} |
| 36 | colors={{ |
| 37 | containerColor: colors["--color-card-alt"], |
| 38 | titleContentColor: colors["--color-foreground"], |
| 39 | textContentColor: colors["--color-foreground-secondary"], |
| 40 | }} |
| 41 | > |
| 42 | <AlertDialog.Title> |
| 43 | <Text style={titleTypography}>{props.request.title}</Text> |
| 44 | </AlertDialog.Title> |
| 45 | {props.inputInitialValue !== undefined ? ( |
| 46 | <AlertDialog.Text> |
| 47 | <OutlinedTextField |
| 48 | autoFocus |
| 49 | singleLine |
| 50 | value={inputState} |
| 51 | selection={inputSelection} |
| 52 | onValueChange={props.onInputChange} |
| 53 | textStyle={inputTypography} |
| 54 | keyboardOptions={{ imeAction: "done" }} |
| 55 | keyboardActions={{ |
| 56 | onDone: confirm, |
| 57 | }} |
| 58 | colors={{ |
| 59 | focusedTextColor: colors["--color-foreground"], |
| 60 | unfocusedTextColor: colors["--color-foreground"], |
| 61 | focusedIndicatorColor: colors["--color-focus"], |
| 62 | unfocusedIndicatorColor: colors["--color-border"], |
| 63 | cursorColor: colors["--color-focus"], |
| 64 | }} |
| 65 | > |
| 66 | <OutlinedTextField.Label> |
| 67 | <Text style={bodyTypography}>{props.request.title}</Text> |
| 68 | </OutlinedTextField.Label> |
| 69 | </OutlinedTextField> |
| 70 | </AlertDialog.Text> |
| 71 | ) : props.request.message ? ( |
| 72 | <AlertDialog.Text> |
| 73 | <Text style={bodyTypography}>{props.request.message}</Text> |
| 74 | </AlertDialog.Text> |
| 75 | ) : null} |
| 76 | <AlertDialog.DismissButton> |
| 77 | <TextButton |
| 78 | onClick={props.onCancel} |
| 79 | colors={{ contentColor: colors["--color-primary-text"] }} |
| 80 | > |
| 81 | <Text style={bodyTypography}>{props.request.cancelText ?? "Cancel"}</Text> |
| 82 | </TextButton> |
| 83 | </AlertDialog.DismissButton> |
| 84 | <AlertDialog.ConfirmButton> |
| 85 | <TextButton |
| 86 | onClick={confirm} |
| 87 | enabled={!props.confirmDisabled} |
| 88 | colors={{ |
| 89 | contentColor: |
| 90 | colors[ |
| 91 | props.request.destructive ? "--color-danger-foreground" : "--color-primary-text" |
| 92 | ], |
| 93 | }} |
| 94 | > |
| 95 | <Text style={bodyTypography}>{props.request.confirmText}</Text> |
| 96 | </TextButton> |
| 97 | </AlertDialog.ConfirmButton> |
| 98 | </AlertDialog> |
| 99 | </Host> |
| 100 | ); |
| 101 | } |