Skip to content

Commit

Permalink
Merge branch 'release/3.0.0' into ar/bump-210
Browse files Browse the repository at this point in the history
  • Loading branch information
alexrisch authored Dec 6, 2024
2 parents 38b69dd + ac1eeaa commit c038d60
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 64 deletions.
87 changes: 87 additions & 0 deletions components/ContextMenuItems.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { VStack } from "@/design-system/VStack";
import { memo, ReactElement } from "react";
import { TextStyle, ViewStyle } from "react-native";
import { ThemedStyle, useAppTheme } from "@/theme/useAppTheme";
import { HStack } from "@/design-system/HStack";
import { Text } from "@/design-system/Text";
import { Pressable } from "@/design-system/Pressable";
import { Icon } from "@/design-system/Icon/Icon";
import { IIconName } from "@/design-system/Icon/Icon.types";
import { iconSize } from "@/theme/icon";

export type ContextMenuItem = {
id: string;
title: string;
action?: () => void;
leftView?: ReactElement;
rightView?: ReactElement;
style?: ViewStyle;
titleStyle?: TextStyle;
};

export type ContextMenuItemsProps = {
items: ContextMenuItem[];
containerStyle?: ViewStyle;
};

export const ContextMenuIcon = ({
icon,
color,
}: {
icon: IIconName;
color?: string;
}) => {
return <Icon icon={icon} size={iconSize.sm} color={color} />;
};

export const ContextMenuItems = memo(
({ items, containerStyle }: ContextMenuItemsProps) => {
const { themed } = useAppTheme();

const sectionContent = items.map((i, index) => (
<Pressable key={i.id} onPress={i.action}>
<HStack
style={[
themed($defaultRowStyle),
index === items.length - 1 ? undefined : themed($borderStyle),
i.style,
]}
>
{i.leftView}
<Text
preset="body"
style={[themed($defaultTitleStyle), i.titleStyle]}
>
{i.title}
</Text>
{i.rightView}
</HStack>
</Pressable>
));
return (
<VStack style={themed($defaultContainerStyle)}>{sectionContent}</VStack>
);
}
);

const $borderStyle: ThemedStyle<ViewStyle> = (theme) => ({
borderBottomWidth: theme.borderWidth.sm,
borderBottomColor: theme.colors.border.subtle,
});

const $defaultRowStyle: ThemedStyle<ViewStyle> = (theme) => ({
paddingHorizontal: theme.spacing.sm,
paddingVertical: theme.spacing.xxs,
alignItems: "center",
});

const $defaultContainerStyle: ThemedStyle<ViewStyle> = (theme) => ({
marginVertical: theme.spacing.xxs,
backgroundColor: theme.colors.background.raised,
borderRadius: theme.borderRadius.sm,
width: 180,
});

const $defaultTitleStyle: ThemedStyle<TextStyle> = (theme) => ({
flex: 1,
});
45 changes: 12 additions & 33 deletions components/ConversationContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import {
} from "@/features/conversation-list/ConversationListContextMenu.store";
import { ConversationReadOnly } from "@/screens/ConversationReadOnly";
import { AnimatedBlurView } from "@components/AnimatedBlurView";
import TableView from "@components/TableView/TableView";
import {
BACKDROP_DARK_BACKGROUND_COLOR,
BACKDROP_LIGHT_BACKGROUND_COLOR,
contextMenuStyleGuide,
} from "@design-system/ContextMenu/ContextMenu.constants";
import { backgroundColor } from "@styles/colors";
import { animation } from "@theme/animations";
import { useAppTheme } from "@theme/useAppTheme";
import { ConversationTopic } from "@xmtp/react-native-sdk";
Expand All @@ -37,6 +34,7 @@ import Animated, {
useSharedValue,
withTiming,
} from "react-native-reanimated";
import { ContextMenuItems } from "./ContextMenuItems";

const ConversationContextMenuComponent: FC = () => {
const isVisible = useConversationListContextMenuIsVisible();
Expand Down Expand Up @@ -133,7 +131,6 @@ const ConversationContextMenuComponent: FC = () => {
>
<View style={styles.overlay}>
<Animated.View style={[styles.container, animatedStyle]}>
<View style={styles.handle} />
<View style={styles.previewContainer}>
<GestureDetector
gesture={Gesture.Tap().onEnd(() => {
Expand All @@ -146,7 +143,10 @@ const ConversationContextMenuComponent: FC = () => {
</GestureDetector>
</View>
<View style={styles.menuContainer}>
<TableView style={styles.table} items={contextMenuItems} />
<ContextMenuItems
containerStyle={styles.table}
items={contextMenuItems}
/>
</View>
</Animated.View>
</View>
Expand All @@ -158,8 +158,6 @@ const ConversationContextMenuComponent: FC = () => {
};

const useStyles = () => {
const colorScheme = useColorScheme();

const { theme } = useAppTheme();

return StyleSheet.create({
Expand All @@ -171,36 +169,17 @@ const useStyles = () => {
flex: 1,
justifyContent: "flex-end",
},
handle: {
marginTop: 70,
marginBottom: 10,
width: 36,
height: 5,
backgroundColor: contextMenuStyleGuide.palette.secondary,
alignSelf: "center",
borderRadius: 2.5,
},
previewContainer: {
flex: 1,
margin: theme.spacing.md,
paddingBottom: contextMenuStyleGuide.spacing,
marginHorizontal: theme.spacing.md,
marginTop: theme.spacing["5xl"],
marginBottom: theme.spacing.zero,
paddingBottom: theme.spacing.xxs,
overflow: "hidden",
justifyContent: "flex-start",
minHeight: 210,
backgroundColor: backgroundColor(colorScheme),
borderRadius: 16,
},
conversationName: {
...contextMenuStyleGuide.typography.body,
fontWeight: "600",
marginBottom: contextMenuStyleGuide.spacing,
},
lastMessagePreview: {
...contextMenuStyleGuide.typography.callout,
color:
Platform.OS === "ios"
? contextMenuStyleGuide.palette.secondary
: contextMenuStyleGuide.palette.common.black,
backgroundColor: theme.colors.background.raised,
borderRadius: theme.borderRadius.sm,
},
menuContainer: {
marginHorizontal: theme.spacing.md,
Expand All @@ -214,7 +193,7 @@ const useStyles = () => {
table: {
width: 180,
backgroundColor:
Platform.OS === "android" ? backgroundColor(colorScheme) : undefined,
Platform.OS === "android" ? theme.colors.background.raised : undefined,
borderRadius: Platform.OS === "android" ? 10 : undefined,
},
});
Expand Down
54 changes: 54 additions & 0 deletions components/PinnedConversations/PinnedMessagePreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { HStack } from "@/design-system/HStack";
import { Text } from "@/design-system/Text";
import { ThemedStyle, useAppTheme } from "@/theme/useAppTheme";
import { DecodedMessageWithCodecsType } from "@/utils/xmtpRN/client";
import { useMemo } from "react";
import { ViewStyle } from "react-native";
import { isTextMessage } from "../Chat/Message/message-utils";

export type PinnedMessagePreviewProps = {
message: DecodedMessageWithCodecsType;
};

export const PinnedMessagePreview = (props: PinnedMessagePreviewProps) => {
const { message } = props;

if (!isTextMessage(message)) {
throw new Error(
"Pinned message preview can only be used for text messages"
);
}

const { themed } = useAppTheme();

const content = useMemo(() => {
return message.content() as string;
}, [message]);

return (
<HStack style={themed($containerStyle)}>
<Text numberOfLines={2} preset="smaller">
{content}
</Text>
</HStack>
);
};

const $containerStyle: ThemedStyle<ViewStyle> = ({
colors,
borderRadius,
borderWidth,
spacing,
}) => ({
backgroundColor: colors.background.raised,
position: "absolute",
top: 0,
paddingHorizontal: spacing.xs,
paddingVertical: spacing.xxs,
alignSelf: "center",
justifyContent: "center",
alignItems: "center",
borderRadius: borderRadius.sm,
borderWidth: borderWidth.sm,
borderColor: colors.border.subtle,
});
52 changes: 41 additions & 11 deletions components/PinnedConversations/PinnedV3DMConversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { PinnedConversation } from "./PinnedConversation";
import { useCallback, useMemo } from "react";
import { navigate } from "@utils/navigation";
import Avatar from "@components/Avatar";
import { AvatarSizes } from "@styles/sizes";
import { DmWithCodecsType } from "@utils/xmtpRN/client";
import { usePreferredInboxName } from "@hooks/usePreferredInboxName";
import { usePreferredInboxAvatar } from "@hooks/usePreferredInboxAvatar";
Expand All @@ -18,6 +17,10 @@ import { useToggleReadStatus } from "@/features/conversation-list/hooks/useToggl
import { useConversationIsUnread } from "@/features/conversation-list/hooks/useMessageIsUnread";
import { useHandleDeleteDm } from "@/features/conversation-list/hooks/useHandleDeleteDm";
import { useAppTheme } from "@/theme/useAppTheme";
import { ContextMenuIcon, ContextMenuItem } from "../ContextMenuItems";
import { isTextMessage } from "../Chat/Message/message-utils";
import { VStack } from "@/design-system/VStack";
import { PinnedMessagePreview } from "./PinnedMessagePreview";

type PinnedV3DMConversationProps = {
conversation: DmWithCodecsType;
Expand Down Expand Up @@ -68,7 +71,9 @@ export const PinnedV3DMConversation = ({
conversation,
});

const contextMenuItems = useMemo(
const { theme } = useAppTheme();

const contextMenuItems: ContextMenuItem[] = useMemo(
() => [
{
title: translate("unpin"),
Expand All @@ -77,6 +82,7 @@ export const PinnedV3DMConversation = ({
closeContextMenu();
},
id: "pin",
rightView: <ContextMenuIcon icon="pin.slash" />,
},
{
title: isUnread
Expand All @@ -87,6 +93,11 @@ export const PinnedV3DMConversation = ({
closeContextMenu();
},
id: "markAsUnread",
rightView: (
<ContextMenuIcon
icon={isUnread ? "checkmark.message" : "message.badge"}
/>
),
},
{
title: translate("delete"),
Expand All @@ -95,9 +106,22 @@ export const PinnedV3DMConversation = ({
closeContextMenu();
},
id: "delete",
titleStyle: {
color: theme.colors.global.caution,
},
rightView: (
<ContextMenuIcon icon="trash" color={theme.colors.global.caution} />
),
},
],
[isUnread, setPinnedConversations, topic, toggleReadStatus, handleDelete]
[
isUnread,
theme.colors.global.caution,
setPinnedConversations,
topic,
toggleReadStatus,
handleDelete,
]
);

const onLongPress = useCallback(() => {
Expand All @@ -110,7 +134,8 @@ export const PinnedV3DMConversation = ({

const title = preferredName;

const { theme } = useAppTheme();
const displayMessagePreview =
isTextMessage(conversation.lastMessage) && isUnread;

const avatarComponent = useMemo(() => {
return (
Expand All @@ -124,12 +149,17 @@ export const PinnedV3DMConversation = ({
}, [peerInboxId, preferredAvatar, preferredName, theme.avatarSize.xxl]);

return (
<PinnedConversation
avatarComponent={avatarComponent}
onLongPress={onLongPress}
onPress={onPress}
showUnread={isUnread}
title={title ?? ""}
/>
<VStack>
<PinnedConversation
avatarComponent={avatarComponent}
onLongPress={onLongPress}
onPress={onPress}
showUnread={isUnread}
title={title ?? ""}
/>
{displayMessagePreview && (
<PinnedMessagePreview message={conversation.lastMessage!} />
)}
</VStack>
);
};
Loading

0 comments on commit c038d60

Please sign in to comment.