feat(mobile): MessageActionsSheet bottom modal — react/reply/delete
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import { Modal, Pressable, StyleSheet, Text } from 'react-native';
|
||||
|
||||
import { ReactionStrip } from './ReactionStrip';
|
||||
import { colors } from '../theme/colors';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
mine: boolean;
|
||||
onClose: () => void;
|
||||
onReact: (emoji: string) => void;
|
||||
onReply: () => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
// Bottom-sheet-style modal opened on long-press of a message bubble.
|
||||
// Contains the reaction quick-strip plus the action rows. The "Löschen"
|
||||
// row is hidden for messages not authored by the current user — the
|
||||
// server-side trigger would refuse anyway, but trimming UI keeps the
|
||||
// surface honest.
|
||||
export function MessageActionsSheet({
|
||||
visible,
|
||||
mine,
|
||||
onClose,
|
||||
onReact,
|
||||
onReply,
|
||||
onDelete,
|
||||
}: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
transparent
|
||||
animationType="fade"
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<Pressable style={styles.backdrop} onPress={onClose}>
|
||||
<Pressable style={styles.sheet} onPress={() => undefined}>
|
||||
<ReactionStrip
|
||||
onReact={(e) => {
|
||||
onReact(e);
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
<Action label="Antworten" onPress={() => { onReply(); onClose(); }} />
|
||||
{mine && (
|
||||
<Action
|
||||
label="Löschen"
|
||||
danger
|
||||
onPress={() => { onDelete(); onClose(); }}
|
||||
/>
|
||||
)}
|
||||
<Action label="Abbrechen" muted onPress={onClose} />
|
||||
</Pressable>
|
||||
</Pressable>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
function Action({
|
||||
label,
|
||||
danger,
|
||||
muted,
|
||||
onPress,
|
||||
}: {
|
||||
label: string;
|
||||
danger?: boolean;
|
||||
muted?: boolean;
|
||||
onPress: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
style={({ pressed }) => [styles.action, pressed && styles.actionPressed]}
|
||||
>
|
||||
<Text style={[styles.actionText, danger && styles.actionDanger, muted && styles.actionMuted]}>
|
||||
{label}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
backdrop: {
|
||||
flex: 1,
|
||||
justifyContent: 'flex-end',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
},
|
||||
sheet: {
|
||||
backgroundColor: colors.surface,
|
||||
borderTopLeftRadius: 16,
|
||||
borderTopRightRadius: 16,
|
||||
paddingBottom: 24,
|
||||
},
|
||||
action: {
|
||||
paddingVertical: 14,
|
||||
paddingHorizontal: 20,
|
||||
borderBottomColor: colors.border,
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
actionPressed: { backgroundColor: colors.bg },
|
||||
actionText: { color: colors.text, fontSize: 15, fontWeight: '500' },
|
||||
actionDanger: { color: colors.danger },
|
||||
actionMuted: { color: colors.textMuted },
|
||||
});
|
||||
Reference in New Issue
Block a user