Skip to content

Commit

Permalink
Various sets of fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
lourou committed Jan 16, 2025
1 parent 3706a85 commit 80e4f12
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 219 deletions.
16 changes: 9 additions & 7 deletions design-system/Table/TableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ export const TableRow = memo(function TableRow({
</HStack>
);

return row.onPress ? (
<TouchableOpacity style={themed($rowContainer)} onPress={row.onPress}>
{content}
</TouchableOpacity>
) : (
<HStack style={themed($rowContainer)}>{content}</HStack>
);
if (row.onPress) {
return (
<TouchableOpacity style={themed($rowContainer)} onPress={row.onPress}>
{content}
</TouchableOpacity>
);
}

return <HStack style={themed($rowContainer)}>{content}</HStack>;
});

const $rowContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
Expand Down
3 changes: 2 additions & 1 deletion design-system/chip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ const $chip: ThemedStyle<ViewStyle> = ({
borderColor: colors.border.subtle,
paddingVertical: spacing.xxs,
paddingHorizontal: spacing.sm,
minHeight: 32,
minHeight: 36, // from Figma
justifyContent: "center",
backgroundColor: colors.background.surface,
});

Expand Down
51 changes: 51 additions & 0 deletions features/notifications/hooks/use-notifications-permission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Platform, Linking } from "react-native";
import { useAppStore } from "@/data/store/appStore";
import { requestPushNotificationsPermissions } from "../utils/requestPushNotificationsPermissions";
import { useSettingsStore } from "@/data/store/accountsStore";

type UseNotificationsPermissionReturn = {
notificationsPermissionStatus: "granted" | "undetermined" | "denied";
requestPermission: () => Promise<void>;
setNotificationsSettings: (settings: {
showNotificationScreen: boolean;
}) => void;
};

export function useNotificationsPermission(): UseNotificationsPermissionReturn {
const notificationsPermissionStatus = useAppStore(
(s) => s.notificationsPermissionStatus
);
const setNotificationsPermissionStatus = useAppStore(
(s) => s.setNotificationsPermissionStatus
);
const setNotificationsSettings = useSettingsStore(
(s) => s.setNotificationsSettings
);

const requestPermission = async () => {
if (notificationsPermissionStatus === "denied") {
if (Platform.OS === "android") {
// Android 13 is always denied first so let's try to show
const newStatus = await requestPushNotificationsPermissions();
if (newStatus === "denied") {
Linking.openSettings();
} else if (newStatus) {
setNotificationsPermissionStatus(newStatus);
}
} else {
Linking.openSettings();
}
} else if (notificationsPermissionStatus === "undetermined") {
// Open popup
const newStatus = await requestPushNotificationsPermissions();
if (!newStatus) return;
setNotificationsPermissionStatus(newStatus);
}
};

return {
notificationsPermissionStatus,
requestPermission,
setNotificationsSettings,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,7 @@ export const ContactCard = memo(function ContactCard({
{displayName}
</Text>
{userName && (
<Text
preset="smaller"
style={{ color: theme.colors.text.inverted.secondary }}
>
<Text inverted color="secondary" preset="smaller">
{userName}
</Text>
)}
Expand Down
91 changes: 91 additions & 0 deletions features/profiles/components/social-names.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from "react";
import { Alert, ViewStyle } from "react-native";
import { VStack } from "@/design-system/VStack";
import { HStack } from "@/design-system/HStack";
import { Text } from "@/design-system/Text";
import { Chip } from "@/design-system/chip";
import { ThemedStyle, useAppTheme } from "@/theme/useAppTheme";
import { translate } from "@/i18n";
import Clipboard from "@react-native-clipboard/clipboard";

type ISocialName = {
name: string;
domain?: string;
};

type ISocialNamesProps = {
socials?: {
userNames?: ISocialName[];
ensNames?: ISocialName[];
unstoppableDomains?: ISocialName[];
};
};

export function SocialNames({ socials }: ISocialNamesProps) {
const { theme, themed } = useAppTheme();

if (
!socials ||
((socials.userNames?.length ?? 0) === 0 &&
(socials.ensNames?.length ?? 0) === 0 &&
(socials.unstoppableDomains?.length ?? 0) === 0)
) {
return null;
}

const handleNamePress = (name: string) => {
Clipboard.setString(name);
Alert.alert(translate("profile.copied"));
};

const renderSocialChips = (
items: ISocialName[],
getValue: (item: ISocialName) => string
) => {
return items?.map((item) => (
<Chip
isActive
key={getValue(item)}
text={getValue(item)}
style={themed($chip)}
onPress={() => handleNamePress(getValue(item))}
/>
));
};

return (
<VStack style={[themed($section), { paddingTop: theme.spacing.md }]}>
<Text>{translate("profile.names")}</Text>
<HStack style={themed($chipContainer)}>
{renderSocialChips(socials.userNames ?? [], (item) => item.name)}
{renderSocialChips(socials.ensNames ?? [], (item) => item.name)}
{renderSocialChips(
(socials.unstoppableDomains ?? []).filter(
(d) => d.domain && !d.domain.toLowerCase().endsWith(".eth")
),
(item) => item.domain!
)}
</HStack>
</VStack>
);
}

const $section: ThemedStyle<ViewStyle> = ({ spacing, colors }) => ({
backgroundColor: colors.background.surface,
borderBottomWidth: spacing.xxs,
borderBottomColor: colors.background.sunken,
paddingHorizontal: spacing.lg,
paddingVertical: spacing.xs,
});

const $chipContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
flexWrap: "wrap",
gap: spacing.xs,
paddingVertical: spacing.sm,
});

const $chip: ThemedStyle<ViewStyle> = ({ colors, borderRadius }) => ({
backgroundColor: colors.background.surface,
borderColor: colors.border.subtle,
borderRadius: borderRadius.xs,
});
39 changes: 39 additions & 0 deletions features/profiles/utils/__tests__/format-converse-username.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { getConfig } from "@/config";
import { formatConverseUsername } from "../format-converse-username";

describe("formatConverseUsername", () => {
it("should return undefined when no username provided", () => {
const result = formatConverseUsername(undefined);
expect(result).toBeUndefined();
});

it("should format .conversedev.eth/.converse.xyz username and mark as Converse username", () => {
const result = formatConverseUsername(
`louisdev${getConfig().usernameSuffix}`
);
expect(result).toEqual({
isConverseUsername: true,
username: "@louisdev",
});
});

it("should return non-Converse usernames as-is with appropriate flag", () => {
expect(formatConverseUsername("louisdev.eth")).toEqual({
isConverseUsername: false,
username: "louisdev.eth",
});
expect(formatConverseUsername("louisdev")).toEqual({
isConverseUsername: false,
username: "louisdev",
});
expect(formatConverseUsername("@louisdev")).toEqual({
isConverseUsername: false,
username: "@louisdev",
});
});

it("should return undefined for empty string", () => {
const result = formatConverseUsername("");
expect(result).toBeUndefined();
});
});
29 changes: 0 additions & 29 deletions features/profiles/utils/__tests__/formatUsername.test.ts

This file was deleted.

34 changes: 34 additions & 0 deletions features/profiles/utils/format-converse-username.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { getConfig } from "@/config";

type IUsernameResult = {
isConverseUsername: boolean;
username: string;
};

/**
* Formats usernames from Converse domains by extracting the username part and adding @ prefix
* Returns a result object containing whether it's a Converse username and the formatted/raw username
* @param username - The username to format
* @returns Object containing isConverseUsername flag and formatted/raw username
*/
export function formatConverseUsername(
username: string | undefined
): IUsernameResult | undefined {
if (!username) return undefined;

// Check if it's a Converse username (either domain)
if (username.endsWith(getConfig().usernameSuffix)) {
// Extract everything before the domain
const cleanUsername = username.replace(getConfig().usernameSuffix, "");
return {
isConverseUsername: true,
username: `@${cleanUsername}`,
};
}

// Return the raw username for non-Converse usernames
return {
isConverseUsername: false,
username: username,
};
}
23 changes: 0 additions & 23 deletions features/profiles/utils/formatUsername.ts

This file was deleted.

1 change: 0 additions & 1 deletion i18n/translations/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,6 @@ 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
10 changes: 1 addition & 9 deletions screens/Navigation/ProfileNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,5 @@ export const ProfileScreenConfig = {
};

export default function ProfileNav() {
return (
<NativeStack.Screen
name="Profile"
component={ProfileScreen}
options={{
title: "Profile",
}}
/>
);
return <NativeStack.Screen name="Profile" component={ProfileScreen} />;
}
26 changes: 5 additions & 21 deletions screens/NotificationsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import { textPrimaryColor } from "@styles/colors";
import { PictoSizes } from "@styles/sizes";
import * as Linking from "expo-linking";
import React from "react";
import { Platform, StyleSheet, Text, useColorScheme, View } from "react-native";

import Button from "../components/Button/Button";
import Picto from "../components/Picto/Picto";
import { useSettingsStore } from "../data/store/accountsStore";
import { useAppStore } from "../data/store/appStore";
import { requestPushNotificationsPermissions } from "../features/notifications/utils/requestPushNotificationsPermissions";
import { useNotificationsPermission } from "@/features/notifications/hooks/use-notifications-permission";

export default function NotificationsScreen() {
const setNotificationsSettings = useSettingsStore(
(s) => s.setNotificationsSettings
);
const setNotificationsPermissionStatus = useAppStore(
(s) => s.setNotificationsPermissionStatus
);
const { requestPermission, setNotificationsSettings } =
useNotificationsPermission();
const styles = useStyles();
return (
<View style={styles.notifications}>
Expand All @@ -33,17 +26,8 @@ export default function NotificationsScreen() {
title="Accept notifications"
action="primary"
onPress={async () => {
// Open popup
const newStatus = await requestPushNotificationsPermissions();
if (!newStatus) return;
if (newStatus === "denied" && Platform.OS === "android") {
// Android 13 always show denied first but sometimes
// it will still show the popup. If not, go to Settings!
Linking.openSettings();
} else {
setNotificationsSettings({ showNotificationScreen: false });
}
setNotificationsPermissionStatus(newStatus);
await requestPermission();
setNotificationsSettings({ showNotificationScreen: false });
}}
/>
<Button
Expand Down
Loading

0 comments on commit 80e4f12

Please sign in to comment.