diff --git a/apps/rebreak-native/components/chat/ChatBubble.tsx b/apps/rebreak-native/components/chat/ChatBubble.tsx
index 8534574..a083d3d 100644
--- a/apps/rebreak-native/components/chat/ChatBubble.tsx
+++ b/apps/rebreak-native/components/chat/ChatBubble.tsx
@@ -131,6 +131,26 @@ export function ChatBubble({
function copyContent() {
if (msg.content) Clipboard.setStringAsync(msg.content);
}
+
+ // Scharfe Kopie der Bubble fürs Kontextmenü (bleibt über dem Blur sichtbar).
+ const previewNode = (
+
+ {msg.attachmentUrl && msg.attachmentType === 'image' ? (
+
+ ) : msg.content !== '' ? (
+ {msg.content}
+ ) : null}
+
+ );
+
return (
<>
onReact?.(msg, r.emoji)}
- activeOpacity={0.7}
- style={[
- styles.reactionPill,
- {
- backgroundColor: colors.surfaceElevated,
- borderColor: r.mine ? colors.brandOrange : colors.border,
- },
- ]}
+ activeOpacity={0.6}
+ style={styles.reactionPill}
>
- {r.emoji}
+ {r.emoji}
{r.count > 1 && {r.count}}
))}
@@ -374,6 +388,7 @@ export function ChatBubble({
isOwn={msg.isOwn}
hasContent={hasContent}
myReaction={myReaction}
+ preview={previewNode}
onClose={() => setMenuVisible(false)}
onReact={(emoji) => onReact?.(msg, emoji)}
onReply={() => onReply(msg)}
@@ -405,10 +420,7 @@ function makeStyles(colors: ReturnType) {
reactionPill: {
flexDirection: 'row',
alignItems: 'center',
- borderRadius: 12,
- borderWidth: StyleSheet.hairlineWidth,
- paddingHorizontal: 7,
- paddingVertical: 2,
+ paddingHorizontal: 2,
},
reactionPillCount: {
fontSize: 11,
diff --git a/apps/rebreak-native/components/chat/MessageActionMenu.tsx b/apps/rebreak-native/components/chat/MessageActionMenu.tsx
index 03f9f44..0c09ee7 100644
--- a/apps/rebreak-native/components/chat/MessageActionMenu.tsx
+++ b/apps/rebreak-native/components/chat/MessageActionMenu.tsx
@@ -8,7 +8,7 @@
* Blur-Backdrop (iOS) / semi-transparent (Android). Smart-Position: Menü unter
* der Bubble, oder darüber wenn unten kein Platz ist.
*/
-import { useMemo } from 'react';
+import { useMemo, type ReactNode } from 'react';
import {
Dimensions,
Modal,
@@ -37,6 +37,8 @@ type Props = {
hasContent: boolean;
/** Aktuelles eigenes Reaktions-Emoji auf dieser Message (für Highlight). */
myReaction?: string | null;
+ /** Scharfe Kopie der gedrückten Bubble — bleibt über dem Blur sichtbar (WA-Stil). */
+ preview?: ReactNode;
onClose: () => void;
onReact: (emoji: string) => void;
onReply: () => void;
@@ -50,6 +52,7 @@ export function MessageActionMenu({
isOwn,
hasContent,
myReaction,
+ preview,
onClose,
onReact,
onReply,
@@ -117,25 +120,39 @@ export function MessageActionMenu({
)}
+ {/* Scharfe Kopie der gedrückten Bubble — bleibt über dem Blur sichtbar (WA-Stil) */}
+ {preview && (
+
+ {preview}
+
+ )}
+
{/* Emoji-Reaktions-Leiste (nur fremde Nachrichten) */}
{showReactions && (
- {REACTION_EMOJIS.map((emoji) => {
- const active = myReaction === emoji;
- return (
- {
- onReact(emoji);
- onClose();
- }}
- style={[styles.reactionBtn, active && { backgroundColor: colors.surfaceElevated }]}
- >
- {emoji}
-
- );
- })}
+ {REACTION_EMOJIS.map((emoji) => (
+ {
+ onReact(emoji);
+ onClose();
+ }}
+ style={styles.reactionBtn}
+ >
+
+ {emoji}
+
+
+ ))}
)}
@@ -194,6 +211,7 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
reactionEmoji: { fontSize: 26 },
+ reactionEmojiActive: { fontSize: 30 },
menu: {
position: 'absolute',
minWidth: 200,