Skip to content

Commit

Permalink
feat: mini notification (#1093)
Browse files Browse the repository at this point in the history
* rebase: conflict with store and mini chat fixed

* rebase: minichat screen consolelog removed

* feat: notification store updated when new message arrive

* notification for accept group request

* added no notifications UI

* fix : unused exports

* fix: tsc error

---------

Co-authored-by: Sujal Lama <[email protected]>
  • Loading branch information
sachin-into and sujal-into authored Mar 26, 2024
1 parent 5ab14d7 commit 112c112
Show file tree
Hide file tree
Showing 10 changed files with 385 additions and 114 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ substreams-*/target
/weshd/ios/Frameworks/
/weshd/android/libs/
/weshd/temp/
temp/

# eslint
/.eslintcache
Expand Down
38 changes: 38 additions & 0 deletions assets/icons/no-notifications.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
167 changes: 167 additions & 0 deletions packages/screens/Mini/Notifications/MessengerNotificationCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import moment from "moment";
import React, { useMemo } from "react";
import { View } from "react-native";

import { randomGradients } from "./notificationData";
import GradientBox from "../components/GradientBox";

import DoubleCheckWhiteSVG from "@/assets/icons/double-check-white.svg";
import DoubleCheckSVG from "@/assets/icons/double-check.svg";
import messageSvg from "@/assets/icons/social-threads/chat.svg";
import { BrandText } from "@/components/BrandText";
import { SVG } from "@/components/SVG";
import { SVGorImageIcon } from "@/components/SVG/SVGorImageIcon";
import { CustomPressable } from "@/components/buttons/CustomPressable";
import { SpacerColumn, SpacerRow } from "@/components/spacer";
import {
TypeNotification,
readNotification,
} from "@/store/slices/notification";
import { store } from "@/store/store";
import { useAppNavigation } from "@/utils/navigation";
import { neutralA3 } from "@/utils/style/colors";
import { fontSemibold13, fontSemibold14 } from "@/utils/style/fonts";
import { layout } from "@/utils/style/layout";

export default function MessengerNotificationCard({
item,
}: {
item: TypeNotification;
}) {
const navigation = useAppNavigation();
const randomIndex = useMemo(() => Math.floor(Math.random() * 4), []);

return (
<CustomPressable
style={{
flexDirection: "row",
}}
onPress={() => {
store.dispatch(readNotification({ id: item.id }));

if (item.type === "contact-request") {
navigation.navigate("MiniFriend", { activeTab: "requests" });
}

if (item.type === "group-invite") {
navigation.navigate("Conversation", { conversationId: item?.id });
}

if (item.type === "group-join") {
navigation.navigate("Conversation", { conversationId: item?.id });
}
}}
>
<View style={{ position: "relative" }}>
{item.avatar ? (
<SVGorImageIcon
icon={item.avatar}
iconSize={48}
style={{
borderRadius: 6,
}}
/>
) : (
<GradientBox
colors={randomGradients[randomIndex].colors}
direction={randomGradients[randomIndex].direction ?? "topBottom"}
/>
)}

<View
style={{
position: "absolute",
width: 20,
height: 20,
borderRadius: 20,
backgroundColor: "#fff",
right: -5,
bottom: -5,
alignItems: "center",
justifyContent: "center",
}}
>
<SVG source={messageSvg} width={16} height={16} fill="#000000" />
</View>
</View>
<SpacerRow size={3} />

{item.type === "contact-request" && (
<NotificationCardInnerContent
id={item.id}
title="You have received a new contact request!"
date={item.timestamp}
isRead={item.isRead}
/>
)}

{item.type === "group-invite" && (
<NotificationCardInnerContent
id={item.id}
title="You have received a group join request!"
date={item.timestamp}
isRead={item.isRead}
/>
)}

{item.type === "group-join" && (
<NotificationCardInnerContent
id={item.id}
title="Group join request is accepted!"
date={item.timestamp}
isRead={item.isRead}
/>
)}
</CustomPressable>
);
}

interface NotiCardContentProps {
id: string;
isRead: boolean;
title: string;
date?: string;
}

function NotificationCardInnerContent({
title,
date,
isRead,
}: NotiCardContentProps) {
return (
<View
style={{
flex: 1,
flexDirection: "row",
justifyContent: "space-between",
gap: layout.spacing_x2,
}}
>
<View style={{ flex: 1 }}>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
flex: 1,
}}
>
<BrandText style={[fontSemibold14]} numberOfLines={2}>
{title}
</BrandText>
</View>
</View>

<View style={{ alignItems: "flex-end" }}>
<BrandText style={[fontSemibold13, { color: neutralA3 }]}>
{moment(date).fromNow()}
</BrandText>
<SpacerColumn size={0.4} />
{!isRead ? (
<SVG source={DoubleCheckSVG} height={16} width={16} />
) : (
<SVG source={DoubleCheckWhiteSVG} height={16} width={16} />
)}
</View>
</View>
);
}
41 changes: 35 additions & 6 deletions packages/screens/Mini/Notifications/NotificationList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React from "react";
import { FlatList, View } from "react-native";
import { FlatList, View, useWindowDimensions } from "react-native";

import NotificationCard from "./NotificationCard";
import { notifications } from "./notificationData";
import MessengerNotificationCard from "./MessengerNotificationCard";

import NoNotificaionsSVG from "@/assets/icons/no-notifications.svg";
import { BrandText } from "@/components/BrandText";
import { SVG } from "@/components/SVG";
import { Separator } from "@/components/separators/Separator";
import { TypeNotification } from "@/store/slices/notification";
import { neutral77 } from "@/utils/style/colors";
import { fontMedium16 } from "@/utils/style/fonts";
import { layout } from "@/utils/style/layout";

export type NotificationType = {
Expand All @@ -20,7 +25,12 @@ export type NotificationType = {
to?: string;
};

export default function NotificationList() {
export default function NotificationList({
notifications,
}: {
notifications: TypeNotification[];
}) {
const { height: windowHeight } = useWindowDimensions();
return (
<View
style={{
Expand All @@ -32,11 +42,30 @@ export default function NotificationList() {
<FlatList
data={notifications}
renderItem={({ item }) => (
<React.Fragment key={item.notificationId}>
<NotificationCard item={item} />
<React.Fragment key={item.id}>
<MessengerNotificationCard item={item} />
<Separator style={{ marginVertical: layout.spacing_x1_5 }} />
</React.Fragment>
)}
ListEmptyComponent={
<View
style={{
justifyContent: "center",
alignItems: "center",
height: windowHeight - 220,
}}
>
<SVG source={NoNotificaionsSVG} height={148} width={148} />
<BrandText
style={[
fontMedium16,
{ color: neutral77, marginTop: layout.spacing_x2_5 },
]}
>
No notifications yet
</BrandText>
</View>
}
/>
</View>
);
Expand Down
7 changes: 6 additions & 1 deletion packages/screens/Mini/Notifications/NotificationScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useState } from "react";
import { useWindowDimensions, View } from "react-native";
import { useSelector } from "react-redux";

import NotificationList from "./NotificationList";
import CustomAppBar from "../components/AppBar/CustomAppBar";
import DropdownWithCheck from "../components/Dropdown/DropdownWithCheck";

import { BrandText } from "@/components/BrandText";
import { ScreenContainer } from "@/components/ScreenContainer";
import { selectNotificationList } from "@/store/slices/notification";
import { ScreenFC } from "@/utils/navigation";
import { fontSemibold18 } from "@/utils/style/fonts";

Expand Down Expand Up @@ -45,6 +47,9 @@ const filterOptionsConst = [

const NotificationScreen: ScreenFC<"Notifications"> = ({ navigation }) => {
const [, setFilterOptions] = useState<any>([]);
const notifications = useSelector(selectNotificationList);

console.log("notifications:", notifications);

const { width: windowWidth } = useWindowDimensions();

Expand Down Expand Up @@ -75,7 +80,7 @@ const NotificationScreen: ScreenFC<"Notifications"> = ({ navigation }) => {
width: windowWidth,
}}
>
<NotificationList />
<NotificationList notifications={notifications} />
</View>
</ScreenContainer>
);
Expand Down
104 changes: 0 additions & 104 deletions packages/screens/Mini/Notifications/notificationData.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { NotificationType } from "./NotificationList";
import { GradientDirectionEnum } from "../components/GradientBox";

import {
Expand All @@ -9,109 +8,6 @@ import {
purpleDefault,
} from "@/utils/style/colors";

export const notifications: NotificationType[] = [
{
notificationId: "1",
img: {
url: "https://images.unsplash.com/photo-1591102972305-213abaa76d6f?q=80&w=2836&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
},
type: "purchase",
message: "Beyond",
user: { id: "23", username: "Norman", avatarUrl: "" },
price: 15000,
postedAt: "10 min ago",
},
{
notificationId: "2",
img: {
url: "https://images.unsplash.com/photo-1601887389937-0b02c26b602c?q=80&w=2523&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
},
type: "comment",
message: '"Happy to announce my new..."',
user: { id: "23", username: "Utopia96", avatarUrl: "" },
postedAt: "70 min ago",
},
{
notificationId: "3",
img: {
url: "https://images.unsplash.com/photo-1630313107085-987b5eb46062?q=80&w=3087&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
},
type: "collection",
message: "M E N T A L",
postedAt: "50 min ago",
},
{
notificationId: "4",
img: {
url: "https://images.unsplash.com/photo-1572379371012-9e11bfc61b35?q=80&w=3087&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
},
type: "tip",
price: 3000,
from: "Doubleface",
for: '"GM Teritori 🖐️"',
postedAt: "11 min ago",
},
{
notificationId: "5",
img: { url: "" },
type: "transfer",
price: 5000,
from: "Eagl3",
postedAt: "22 min ago",
},
{
notificationId: "6",
img: {
url: "https://www.haddonstone.com/en-us/wp-content/uploads/sites/14/2019/01/Winter_Statue-HE765-A_0.jpg",
},
type: "purchase",
message: "Beyond",
user: { id: "23", username: "Norman", avatarUrl: "" },
price: 15000,
postedAt: "30 min ago",
},
{
notificationId: "7",
img: { url: "" },
type: "comment",
message: '"Happy to announce my new..."',
user: { id: "23", username: "Utopia96", avatarUrl: "" },
postedAt: "10 min ago",
},
{
notificationId: "8",
img: { url: "" },
type: "collection",
message: "M E N T A L",
postedAt: "40 min ago",
},
{
notificationId: "9",
img: { url: "" },
type: "tip",
price: 3000,
from: "Doubleface",
for: '"GM Teritori 🖐️"',
postedAt: "80 min ago",
},
{
notificationId: "10",
img: { url: "" },
type: "transfer",
price: 5000,
from: "Eagl3",
postedAt: "20 min ago",
},
{
notificationId: "11",
img: { url: "" },
type: "transfer",
price: 5000,
from: "Eagl3",
postedAt: "4 min ago",
},
];

export const randomGradients = [
{
direction: GradientDirectionEnum.bottomTop,
Expand Down
Loading

0 comments on commit 112c112

Please sign in to comment.