diff --git a/App.tsx b/App.tsx
index 5ce588e97..03169612a 100644
--- a/App.tsx
+++ b/App.tsx
@@ -5,7 +5,6 @@ import { configure as configureCoinbase } from "@coinbase/wallet-mobile-sdk";
import DebugButton from "@components/DebugButton";
import { BottomSheetModalProvider } from "@design-system/BottomSheet/BottomSheetModalProvider";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
-import { PortalProvider } from "@gorhom/portal";
import { useAppStateHandlers } from "@hooks/useAppStateHandlers";
import { PrivyProvider } from "@privy-io/expo";
import { queryClient } from "@queries/queryClient";
@@ -144,10 +143,8 @@ export default function AppWithProviders() {
-
-
-
-
+
+
diff --git a/components/Drawer.tsx b/components/Drawer.tsx
index 925cba15d..30c22514d 100644
--- a/components/Drawer.tsx
+++ b/components/Drawer.tsx
@@ -16,21 +16,22 @@ import {
ViewStyle,
useColorScheme,
useWindowDimensions,
+ Modal,
} from "react-native";
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
} from "react-native-gesture-handler";
-import { Portal } from "react-native-paper";
-import {
- LinearTransition,
+import Animated, {
interpolateColor,
runOnJS,
useAnimatedKeyboard,
useAnimatedStyle,
useSharedValue,
withTiming,
+ FadeIn,
+ FadeOut,
} from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context";
@@ -166,26 +167,32 @@ export const Drawer = forwardRef(function Drawer(
}
return (
-
-
- {/* A bit of a pain but have to wrap this in a gesture handler */}
-
-
-
-
-
-
- {showHandle && }
- {children}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ {showHandle && }
+ {children}
+
+
+
+
+
+
);
});
diff --git a/design-system/BlurView.tsx b/design-system/BlurView.tsx
index d308e3475..b33fa26ac 100644
--- a/design-system/BlurView.tsx
+++ b/design-system/BlurView.tsx
@@ -1,6 +1,7 @@
import { BlurViewProps, BlurView as RNBlurView } from "expo-blur";
import { memo } from "react";
import Animated, { AnimatedProps, FadeIn } from "react-native-reanimated";
+import { useAppTheme } from "@theme/useAppTheme";
import { IVStackProps } from "./VStack";
@@ -13,12 +14,15 @@ export const BlurView = memo(function BlurView({
children,
isAbsolute,
style,
+ tint,
...rest
}: IBlurViewProps) {
+ const { theme } = useAppTheme();
+
return (
(
+ function BottomSheet(props, ref) {
+ const {
+ children,
+ backdropComponent = BottomSheetBackdropOpacity,
+ handleIndicatorStyle,
+ handleStyle,
+ backgroundStyle,
+ ...rest
+ } = props;
+
+ const { theme } = useAppTheme();
+
+ const combinedHandleIndicatorStyle = useMemo(
+ () => [
+ {
+ backgroundColor: theme.colors.background.raised,
+ },
+ handleIndicatorStyle,
+ ],
+ [theme.colors.background.raised, handleIndicatorStyle]
+ );
+
+ const combinedHandleStyle = useMemo(
+ () => [
+ {
+ backgroundColor: theme.colors.background.raised,
+ borderTopLeftRadius: theme.borderRadius.sm,
+ borderTopRightRadius: theme.borderRadius.sm,
+ },
+ handleStyle,
+ ],
+ [theme.colors.background.raised, theme.borderRadius.sm, handleStyle]
+ );
+
+ const combinedBackgroundStyle = useMemo(
+ () => [
+ {
+ backgroundColor: theme.colors.background.raised,
+ },
+ backgroundStyle,
+ ],
+ [theme.colors.background.raised, backgroundStyle]
+ );
+
+ return (
+
+ {children}
+
+ );
+ }
+ )
+);
diff --git a/features/conversation/conversation-message/conversation-message-context-menu/conversation-message-context-menu.tsx b/features/conversation/conversation-message/conversation-message-context-menu/conversation-message-context-menu.tsx
index e123e08f1..9a4d71222 100644
--- a/features/conversation/conversation-message/conversation-message-context-menu/conversation-message-context-menu.tsx
+++ b/features/conversation/conversation-message/conversation-message-context-menu/conversation-message-context-menu.tsx
@@ -17,21 +17,19 @@ import {
getMessageById,
useConversationMessageReactions,
} from "@/features/conversation/conversation-message/conversation-message.utils";
-import {
- ConversationStoreProvider,
- useCurrentConversationTopic,
-} from "@/features/conversation/conversation.store-context";
+import { useCurrentConversationTopic } from "@/features/conversation/conversation.store-context";
import { useReactOnMessage } from "@/features/conversation/hooks/use-react-on-message";
import { useRemoveReactionOnMessage } from "@/features/conversation/hooks/use-remove-reaction-on-message";
import { messageIsFromCurrentAccountInboxId } from "@/features/conversation/utils/message-is-from-current-user";
import { useConversationQuery } from "@/queries/useConversationQuery";
import { calculateMenuHeight } from "@design-system/ContextMenu/ContextMenu.utils";
-import { Portal } from "@gorhom/portal";
import { memo, useCallback } from "react";
-import { StyleSheet } from "react-native";
+import { StyleSheet, Modal, View, Platform } from "react-native";
import { MessageContextMenuAboveMessageReactions } from "./conversation-message-context-menu-above-message-reactions";
import { MessageContextMenuContainer } from "./conversation-message-context-menu-container";
import { useMessageContextMenuItems } from "./conversation-message-context-menu.utils";
+import { useAppTheme } from "@theme/useAppTheme";
+import Animated from "react-native-reanimated";
export const MESSAGE_CONTEXT_MENU_SPACE_BETWEEN_ABOVE_MESSAGE_REACTIONS_AND_MESSAGE = 16;
@@ -53,6 +51,7 @@ const Content = memo(function Content(props: {
>;
}) {
const { messageContextMenuData } = props;
+ const { theme } = useAppTheme();
const { messageId, itemRectX, itemRectY, itemRectHeight, itemRectWidth } =
messageContextMenuData;
@@ -124,11 +123,13 @@ const Content = memo(function Content(props: {
return (
<>
-
-
+
+
{!!bySender && }
@@ -179,110 +180,9 @@ const Content = memo(function Content(props: {
-
-
+
+
>
);
});
-
-/**
- * Tried different approaches to implement native context menu, but it's not
- * working as expected. Still missing some pieces from libraries to achieve what we want
- */
-
-// import { MessageContextMenu } from "@/components/Chat/Message/MessageContextMenu";
-// import ContextMenu from "react-native-context-menu-view";
-// import * as ContextMenu from "zeego/context-menu";
-
-{
- /* {
- console.log("onMenuWillShow");
- }}
- menuConfig={{
- menuTitle: "Message Options",
- menuItems: [
- {
- actionKey: "copy",
- actionTitle: "Copy",
- icon: {
- type: "IMAGE_SYSTEM",
- imageValue: {
- systemName: "doc.on.doc",
- },
- },
- },
- {
- actionKey: "delete",
- actionTitle: "Delete",
- menuAttributes: ["destructive"],
- icon: {
- type: "IMAGE_SYSTEM",
- imageValue: {
- systemName: "trash",
- },
- },
- },
- ],
- }}
- auxiliaryPreviewConfig={{
- transitionEntranceDelay: "RECOMMENDED",
- anchorPosition: "top",
- // alignmentHorizontal: "previewTrailing",
- verticalAnchorPosition: "top",
- // height: 600,
- // preferredHeight: {
- // mode: "percentRelativeToWindow",
- // percent: 50,
- // },
- }}
- previewConfig={{ previewType: "CUSTOM" }}
- // renderPreview={() => (
- //
- // {textContent}
- //
- // )}
- isAuxiliaryPreviewEnabled={true}
- renderPreview={() => (
- //
-
- {textContent}
-
- )}
- renderAuxiliaryPreview={() => (
-
- 😅
- 🤣
- 😂
- 🤩
- 🤗
- 🤔
-
- )}
- > */
-}
diff --git a/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.service.ts b/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.service.ts
index fe7221bd1..e07dc3cec 100644
--- a/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.service.ts
+++ b/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.service.ts
@@ -1,36 +1,21 @@
-import { createBottomSheetModalRef } from "@design-system/BottomSheet/BottomSheet.utils";
import { RolledUpReactions } from "../conversation-message-reactions.types";
import {
resetMessageReactionsStore,
useMessageReactionsStore,
+ IMessageReactionsStore,
} from "./conversation-message-reaction-drawer.store";
-export const bottomSheetModalRef = createBottomSheetModalRef();
-
export function openMessageReactionsDrawer(
rolledUpReactions: RolledUpReactions
) {
- try {
- if (!bottomSheetModalRef.current) {
- throw new Error(
- "Bottom sheet modal reference is not initialized. Ensure the component is mounted."
- );
- }
- const setReactions =
- useMessageReactionsStore.getState().setRolledUpReactions;
- setReactions(rolledUpReactions);
- bottomSheetModalRef.current.present();
- } catch (error) {
- console.error("Failed to open message reactions drawer:", error);
- resetMessageReactionsDrawer();
- }
+ const store = useMessageReactionsStore.getState();
+ store.setRolledUpReactions(rolledUpReactions);
}
export function closeMessageReactionsDrawer(arg?: { resetStore?: boolean }) {
const { resetStore = true } = arg ?? {};
- bottomSheetModalRef.current?.dismiss();
if (resetStore) {
- resetMessageReactionsDrawer();
+ resetMessageReactionsStore();
}
}
diff --git a/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.store.ts b/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.store.ts
new file mode 100644
index 000000000..b33e68139
--- /dev/null
+++ b/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.store.ts
@@ -0,0 +1,30 @@
+import { create } from "zustand";
+import { RolledUpReactions } from "../conversation-message-reactions.types";
+
+export type IMessageReactionsStore = {
+ rolledUpReactions: RolledUpReactions;
+ setRolledUpReactions: (reactions: RolledUpReactions) => void;
+};
+
+export const useMessageReactionsStore = create(
+ (set) => ({
+ rolledUpReactions: {
+ preview: [],
+ detailed: [],
+ totalCount: 0,
+ userReacted: false,
+ },
+ setRolledUpReactions: (reactions) => set({ rolledUpReactions: reactions }),
+ })
+);
+
+export function resetMessageReactionsStore() {
+ useMessageReactionsStore.setState({
+ rolledUpReactions: {
+ preview: [],
+ detailed: [],
+ totalCount: 0,
+ userReacted: false,
+ },
+ });
+}
diff --git a/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.tsx b/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.tsx
index 18c4a5e1c..6ad629836 100644
--- a/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.tsx
+++ b/features/conversation/conversation-message/conversation-message-reactions/conversation-message-reaction-drawer/conversation-message-reaction-drawer.tsx
@@ -1,20 +1,21 @@
import Avatar from "@components/Avatar";
import { BottomSheetContentContainer } from "@design-system/BottomSheet/BottomSheetContentContainer";
import { BottomSheetHeader } from "@design-system/BottomSheet/BottomSheetHeader";
-import { BottomSheetModal } from "@design-system/BottomSheet/BottomSheetModal";
+import { BottomSheet } from "@design-system/BottomSheet/BottomSheet";
import { HStack } from "@design-system/HStack";
import { Text } from "@design-system/Text";
import { BottomSheetScrollView } from "@gorhom/bottom-sheet";
import { FlashList } from "@shopify/flash-list";
import { ThemedStyle, useAppTheme } from "@theme/useAppTheme";
-import { memo, useCallback, useState } from "react";
-import { TextStyle, TouchableHighlight, ViewStyle } from "react-native";
+import { memo, useCallback, useState, useRef, useEffect } from "react";
+import { TextStyle, ViewStyle, Modal, Platform } from "react-native";
+import { TouchableHighlight } from "@design-system/touchable-highlight";
import { ScrollView } from "react-native-gesture-handler";
import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { BottomSheetMethods } from "@gorhom/bottom-sheet/lib/typescript/types";
import {
- bottomSheetModalRef,
- resetMessageReactionsDrawer,
+ closeMessageReactionsDrawer,
useMessageReactionsRolledUpReactions,
} from "./conversation-message-reaction-drawer.service";
@@ -22,121 +23,137 @@ export const MessageReactionsDrawer = memo(function MessageReactionsDrawer() {
const { theme, themed } = useAppTheme();
const insets = useSafeAreaInsets();
const rolledUpReactions = useMessageReactionsRolledUpReactions();
+ const bottomSheetRef = useRef(null);
+ const [filterReactions, setFilterReactions] = useState(null);
+ // Centralized dismiss handler that:
+ // 1. Closes the bottom sheet UI component
+ // 2. Resets the global drawer state
+ // 3. Clears any active reaction filters
+ // This ensures consistent cleanup and prevents UI state mismatches
const handleDismiss = useCallback(() => {
- resetMessageReactionsDrawer();
+ bottomSheetRef.current?.close();
+ closeMessageReactionsDrawer();
setFilterReactions(null);
}, []);
- // State for managing the active filter, e.g., ❤️, 👍, etc.
- const [filterReactions, setFilterReactions] = useState(null);
+ const isVisible = !!rolledUpReactions.totalCount;
return (
-
-
-
+ {
+ if (index === -1) {
+ handleDismiss();
+ }
+ }}
+ topInset={insets.top}
+ >
+
+
- {/* Preview of all reactions with counts and filter buttons */}
-
- {/* "All" button to clear the filter */}
- setFilterReactions(null)}
- style={[
- themed($chip),
- filterReactions === null && themed($chipActive),
- ]}
- underlayColor={theme.colors.border.subtle}
- accessible
- accessibilityRole="button"
- accessibilityLabel="Show all reactions"
+ {/* Preview of all reactions with counts and filter buttons */}
+
-
-
- All {rolledUpReactions.totalCount}
-
-
-
-
- {/* Buttons for each unique reaction type with counts */}
- {rolledUpReactions.preview.map((reaction, index) => (
+ {/* "All" button to clear the filter */}
- setFilterReactions(
- reaction.content === filterReactions ? null : reaction.content
- )
- }
+ onPress={() => setFilterReactions(null)}
style={[
themed($chip),
- filterReactions === reaction.content && themed($chipActive),
+ filterReactions === null && themed($chipActive),
]}
- underlayColor={theme.colors.border.subtle}
- accessible
- accessibilityRole="button"
- accessibilityLabel={`${reaction.count} ${reaction.content} reactions`}
>
-
- {reaction.content} {reaction.count}
-
+
+
+ All {rolledUpReactions.totalCount}
+
+
- ))}
-
-
-
- {/* Detailed list of each reaction, sorted and filtered with all own reactions on top */}
-
- !filterReactions || item.content === filterReactions
- )}
- renderItem={({ item, index }) => (
-
-
- {item.reactor.userName}
- {item.content}
-
- )}
- keyExtractor={(item, index) =>
- `${item.content}-${item.reactor.address}-${index}`
- }
- />
-
-
+ {/* Buttons for each unique reaction type with counts */}
+ {rolledUpReactions.preview.map((reaction, index) => (
+
+ setFilterReactions(
+ reaction.content === filterReactions
+ ? null
+ : reaction.content
+ )
+ }
+ style={[
+ themed($chip),
+ filterReactions === reaction.content && themed($chipActive),
+ ]}
+ >
+
+ {reaction.content} {reaction.count}
+
+
+ ))}
+
+
+
+
+ {/* Detailed list of each reaction, sorted and filtered with all own reactions on top */}
+
+ !filterReactions || item.content === filterReactions
+ )}
+ renderItem={({ item, index }) => (
+
+
+ {item.reactor.userName}
+ {item.content}
+
+ )}
+ keyExtractor={(item, index) =>
+ `${item.content}-${item.reactor.address}-${index}`
+ }
+ />
+
+
+
);
});
diff --git a/package.json b/package.json
index 5a6f414b5..812877bab 100644
--- a/package.json
+++ b/package.json
@@ -46,8 +46,7 @@
"@expo/metro-runtime": "~4.0.0",
"@expo/react-native-action-sheet": "^4.0.1",
"@expo/vector-icons": "^14.0.3",
- "@gorhom/bottom-sheet": "^5.0.2",
- "@gorhom/portal": "^1.0.14",
+ "@gorhom/bottom-sheet": "5.0.6",
"@material-symbols/svg-400": "^0.5.0",
"@mfellner/react-native-fast-create-hash": "^1.0.0-alpha.2",
"@noble/secp256k1": "^1.5.2",
diff --git a/yarn.lock b/yarn.lock
index 14b1d6172..d36cbe598 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2060,7 +2060,7 @@
"@babel/parser" "^7.25.9"
"@babel/types" "^7.25.9"
-"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3":
+"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9":
version "7.26.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.4.tgz#ac3a2a84b908dde6d463c3bfa2c5fdc1653574bd"
integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==
@@ -2102,19 +2102,6 @@
debug "^4.3.1"
globals "^11.1.0"
-"@babel/traverse@^7.25.9":
- version "7.26.4"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.4.tgz#ac3a2a84b908dde6d463c3bfa2c5fdc1653574bd"
- integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==
- dependencies:
- "@babel/code-frame" "^7.26.2"
- "@babel/generator" "^7.26.3"
- "@babel/parser" "^7.26.3"
- "@babel/template" "^7.25.9"
- "@babel/types" "^7.26.3"
- debug "^4.3.1"
- globals "^11.1.0"
-
"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.24.7", "@babel/types@^7.3.3":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2"
@@ -4079,15 +4066,15 @@
lit "^2.2.3"
three "^0.146.0"
-"@gorhom/bottom-sheet@^5.0.2":
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.0.2.tgz#28675943f24fa9787ba58bcf592028af171cdb41"
- integrity sha512-bctrT0PDeVUdUG4xm/d9A7ikHFgQ9wchhU0oIE1vIBncFri501GTs/8Bf16ryyKHo3Q0220Dnj5CKm3Ed6ejEg==
+"@gorhom/bottom-sheet@5.0.6":
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.0.6.tgz#f20736502399c7bcf8c73ea09e6b571dc07fe0eb"
+ integrity sha512-SI/AhPvgRfnCWN6/+wbE6TXwRE4X8F2fLyE4L/0bRwgE34Zenq585qLT139uEcfCIyovC2swC3ICqQpkmWEcFA==
dependencies:
"@gorhom/portal" "1.0.14"
invariant "^2.2.4"
-"@gorhom/portal@1.0.14", "@gorhom/portal@^1.0.14":
+"@gorhom/portal@1.0.14":
version "1.0.14"
resolved "https://registry.yarnpkg.com/@gorhom/portal/-/portal-1.0.14.tgz#1953edb76aaba80fb24021dc774550194a18e111"
integrity sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==