Skip to content

Commit

Permalink
feat(Profile): update context menu styling and fix edit mode
Browse files Browse the repository at this point in the history
- Add Done button in header when in edit mode
- Fix edit mode toggle functionality
- Update context menu items with proper type safety
- Remove copy address option from other users' profiles
- Remove 0x wallet address from share own profile view
  • Loading branch information
lourou committed Jan 16, 2025
1 parent 7f68882 commit 64ca06b
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export function useHeaderWrapper() {
menuItems: [
{
actionKey: "app-settings",
actionTitle: translate("App settings"),
actionTitle: translate("app_settings"),
icon: {
iconType: "SYSTEM",
iconValue: iconRegistry["settings"],
Expand Down
5 changes: 3 additions & 2 deletions features/profiles/components/ContactCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ export const ContactCard = memo(function ContactCard({
name={displayName}
size={theme.avatarSize.lg}
/>
{isMyProfile && (
{/* TODO: "Names" menu to pick from when SCW will be done */}
{/* {isMyProfile && (
<Button
variant="link.bare"
size="sm"
Expand All @@ -118,7 +119,7 @@ export const ContactCard = memo(function ContactCard({
}}
onPress={onToggleEdit}
/>
)}
)} */}
</VStack>

{/* Name and Username - now positioned at bottom */}
Expand Down
4 changes: 3 additions & 1 deletion i18n/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export const en = {
"We could not find any result in your existing conversations. You might want to",
no_results_start_convo: "start a new conversation",
new_account: "New account",
"App settings": "App settings",
app_settings: "App settings",
add_an_account: "Add an account",
group_info: "Group info",
converse_match_maker: "Converse Match Maker",
Expand Down Expand Up @@ -353,11 +353,13 @@ export const en = {
change_or_add_account: "Change or add account",
profile: {
modify_profile: "Modify profile",
edit: "Edit",
block: {
title: "Block user",
message: "Are you sure you want to block {{name}}?",
},
save: "Save",
done: "Done",
settings: {
notifications: "Notifications",
archive: "Archive",
Expand Down
3 changes: 3 additions & 0 deletions i18n/translations/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,9 @@ export const fr = {
message: "Êtes-vous sûr de vouloir bloquer {{name}} ?",
},
modify_profile: "Modifier le profil",
edit: "Modifier",
save: "Enregistrer",
done: "Valider",
settings: {
notifications: "Notifications",
archive: "Archive",
Expand All @@ -371,6 +373,7 @@ export const fr = {
turn_on_notifications: "Activer les notifications",
attachment_message_error_download:
"Impossible de télécharger la pièce jointe",
done: "Valider",

// Revocation
current_installation_revoked: "Déconnecté",
Expand Down
219 changes: 129 additions & 90 deletions screens/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import React, { memo, useCallback, useState } from "react";
import { View, ViewStyle, Alert } from "react-native";
import React, { useCallback, useState } from "react";
import { View, ViewStyle, Alert, Share } from "react-native";
import { Screen } from "@/components/Screen/ScreenComp/Screen";
import { ContactCard } from "@/features/profiles/components/ContactCard";
import { FullWidthTable } from "@/design-system/table/FullWidthTable";
import { VStack } from "@/design-system/VStack";
import { Text } from "@/design-system/Text";
import { useRoute, useRouter } from "@navigation/useNavigation";
import { usePreferredName } from "@/hooks/usePreferredName";
import { usePreferredUsername } from "@/hooks/usePreferredUsername";
import { usePreferredAvatarUri } from "@/hooks/usePreferredAvatarUri";
import { useProfileSocials } from "@/hooks/useProfileSocials";
import {
useCurrentAccount,
useSettingsStore,
currentAccount,
} from "@/data/store/accountsStore";
import { useAppTheme, ThemedStyle } from "@/theme/useAppTheme";
import { translate } from "@/i18n";
Expand All @@ -25,9 +24,9 @@ import { navigate } from "@/utils/navigation";
import { ContextMenuButton } from "react-native-ios-context-menu";
import { Haptics } from "@/utils/haptics";
import Clipboard from "@react-native-clipboard/clipboard";
import { consentToAddressesOnProtocolByAccount } from "@utils/xmtpRN/contacts";
import { StackActions } from "@react-navigation/native";
import { useDisconnectActionSheet } from "@/hooks/useDisconnectActionSheet";
import { getConfig } from "@/config";

export default function ProfileScreen() {
const [editMode, setEditMode] = useState(false);
Expand All @@ -39,10 +38,9 @@ export default function ProfileScreen() {
const isMyProfile = peerAddress.toLowerCase() === userAddress?.toLowerCase();
const setPeersStatus = useSettingsStore((s) => s.setPeersStatus);

const { data: socials } = useProfileSocials(peerAddress);
const preferredName = usePreferredName(peerAddress);
const userName = usePreferredUsername(userAddress);
const displayName = usePreferredName(userAddress);
const preferredAvatarUri = usePreferredAvatarUri(peerAddress);
const userName = socials?.userNames?.find((e) => e.isPrimary)?.name;

const handleChatPress = useCallback(() => {
router.dispatch(StackActions.popToTop());
Expand All @@ -65,7 +63,7 @@ export default function ProfileScreen() {
safeAreaEdges: ["top"],
titleComponent: (
<Text preset="body">
{router.canGoBack()
{router.canGoBack() && router.getState().routes.length >= 2
? router.getState().routes[router.getState().routes.length - 2].name
: ""}
</Text>
Expand All @@ -80,97 +78,143 @@ export default function ProfileScreen() {
),
RightActionComponent: (
<HStack style={themed($headerRight)}>
{isMyProfile ? (
<HeaderAction
icon="qrcode"
{editMode ? (
<Button
text={translate("profile.done")}
variant="text"
onPress={() => {
navigate("ShareProfile");
handleEditProfile();
setEditMode(false);
}}
/>
) : (
<HeaderAction
style={themed($editIcon)}
icon="square.and.pencil"
onPress={handleChatPress}
/>
<>
{isMyProfile ? (
<HeaderAction
icon="qrcode"
onPress={() => {
navigate("ShareProfile");
}}
/>
) : (
<HeaderAction
style={themed($editIcon)}
icon="square.and.pencil"
onPress={handleChatPress}
/>
)}
<ContextMenuButton
style={themed($contextMenu)}
isMenuPrimaryAction
menuConfig={{
menuTitle: "",
menuItems: [
...(isMyProfile
? [
{
actionKey: "edit",
actionTitle: translate("profile.edit"),
icon: {
iconType: "SYSTEM" as const,
iconValue: "pencil",
},
},
{
actionKey: "share",
actionTitle: translate("share"),
icon: {
iconType: "SYSTEM" as const,
iconValue: "square.and.arrow.up",
},
},
]
: [
{
actionKey: "share",
actionTitle: translate("share"),
icon: {
iconType: "SYSTEM" as const,
iconValue: "square.and.arrow.up",
},
},
{
actionKey: "block",
actionTitle: translate("block"),
icon: {
iconType: "SYSTEM" as const,
iconValue: "person.crop.circle.badge.xmark",
},
menuAttributes: ["destructive" as const],
},
]),
],
}}
onPressMenuItem={({ nativeEvent }) => {
Haptics.selectionAsync();
if (nativeEvent.actionKey === "share") {
if (isMyProfile) {
navigate("ShareProfile");
} else {
const profileUrl = `https://${
getConfig().websiteDomain
}/dm/${userName}`;
Clipboard.setString(profileUrl);
Share.share({
message: profileUrl,
});
}
} else if (nativeEvent.actionKey === "edit") {
Alert.alert("Available soon");
// TODO - Profile Edit
// handleEditProfile();
} else if (nativeEvent.actionKey === "block") {
Alert.alert(
translate("profile.block.title"),
translate("profile.block.message", {
name: displayName,
}),
[
{
text: translate("cancel"),
style: "cancel",
},
{
text: translate("block"),
style: "destructive",
onPress: () => {
setPeersStatus({ [peerAddress]: "blocked" });
router.goBack();
},
},
]
);
}
}}
>
<HeaderAction icon="more_vert" />
</ContextMenuButton>
</>
)}
<ContextMenuButton
style={themed($contextMenu)}
isMenuPrimaryAction
onPressMenuItem={({ nativeEvent }) => {
Haptics.selectionAsync();
if (nativeEvent.actionKey === "share") {
navigate("ShareProfile");
} else if (nativeEvent.actionKey === "copy") {
Clipboard.setString(peerAddress);
} else if (nativeEvent.actionKey === "block") {
Alert.alert(
translate("profile.block.title"),
translate("profile.block.message", {
name: preferredName,
}),
[
{
text: translate("cancel"),
style: "cancel",
},
{
text: translate("block"),
style: "destructive",
onPress: () => {
setPeersStatus({ [peerAddress]: "blocked" });
router.goBack();
},
},
]
);
}
}}
menuConfig={{
menuTitle: "",
menuItems: [
{
actionKey: "share",
actionTitle: translate("share"),
icon: {
iconType: "SYSTEM",
iconValue: "square.and.arrow.up",
},
},
{
actionKey: "copy",
actionTitle: translate("copy"),
icon: {
iconType: "SYSTEM",
iconValue: "doc.on.doc",
},
},
{
actionKey: "block",
actionTitle: translate("block"),
icon: {
iconType: "SYSTEM",
iconValue: "person.crop.circle.badge.xmark",
},
menuAttributes: ["destructive"],
},
],
}}
>
<HeaderAction icon="more_vert" />
</ContextMenuButton>
</HStack>
),
},
[router, theme, peerAddress, preferredName, setPeersStatus, handleChatPress]
[
router,
theme,
peerAddress,
displayName,
setPeersStatus,
handleChatPress,
editMode,
]
);

return (
<Screen preset="fixed" style={themed($container)}>
<VStack>
<VStack style={themed($section)}>
<ContactCard
displayName={preferredName}
displayName={displayName}
userName={formatUsername(userName)}
avatarUri={preferredAvatarUri}
isMyProfile={isMyProfile}
Expand Down Expand Up @@ -273,8 +317,3 @@ const $contextMenu: ThemedStyle<ViewStyle> = ({ spacing }) => ({
paddingVertical: spacing.sm,
paddingRight: spacing.xxxs,
});

const $settingsSection: ThemedStyle<ViewStyle> = ({ spacing }) => ({
marginTop: spacing.xl,
borderTopWidth: spacing.xxs, // Add top border to create separation
});
5 changes: 0 additions & 5 deletions screens/ShareProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ const ShareProfileContent = ({
{username || shortAddress(userAddress || "")}
</Text>
)}
{username && (
<Text style={styles.address}>
{shortAddress(userAddress || "")}
</Text>
)}
</View>
<View style={[styles.qrCode, compact && styles.qrCodeCompact]}>
<QRCode
Expand Down

0 comments on commit 64ca06b

Please sign in to comment.