Skip to content

Commit 95a7ca0

Browse files
authored
feat: Add media support in notification card
1 parent 75650ce commit 95a7ca0

File tree

14 files changed

+97
-30
lines changed

14 files changed

+97
-30
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ itemsPerFetch | Number of notifications fetch per api request (have a max cap of
6666
windowViewOnly | Toggle to enable fit-to-screen window or modal view | boolean | false |
6767
notificationIcon | Option to use custom notification Icon | JSX Element | null |
6868
headerProps | Props for customizing the header.<br> title - Title of the notification inbox<br> hideHeader - Toggle to hide or show the header section.<br> hideClearAll - Toggle to hide or show the clear all button.<br> customHeader - Custom header component. | HeaderProps| { title: 'Notifications', <br>hideHeader: false,<br> hideClearAll: false, <br>customHeader: null } |
69-
cardProps | Props for customizing the notification cards. <br>hideDelete - Toggle to hide or show delete icon<br> hideAvatar - Toggle to hide or show the avatar.<br> disableAutoMarkAsRead - Toggle to disable or enable the markAsReadById functionality on card click.<br> deleteIcon - Custom delete icon <br> onAvatarClick - Custom click handler for avatar | CardProps | { hideDelete: false,<br> hideAvatar: false,<br> disableAutoMarkAsRead: false, <br> deleteIcon: null, <br> onAvatarClick: ()=>null } |
69+
cardProps | Props for customizing the notification cards. <br>hideDelete - Toggle to hide or show delete icon<br> hideAvatar - Toggle to hide or show the avatar.<br> hideMediaThumbnail - Toggle to hide or show thumbnail image<br> disableAutoMarkAsRead - Toggle to disable or enable the markAsReadById functionality on card click.<br> deleteIcon - Custom delete icon <br> onAvatarClick - Custom click handler for avatar <br> onMediaThumbnailClick - Custom click handler for media thumbnail | CardProps | { hideDelete: false,<br> hideAvatar: false,<br> disableAutoMarkAsRead: false, <br> hideMediaThumbnail: false, <br>deleteIcon: null, <br> onAvatarClick: ()=>null,<br> onMediaThumbnailClick: () => null } |
7070
customCard | Function for rendering custom notification cards | (notification)=> JSX Element | null |
7171
onCardClick | Custom click handler for notification cards | (notification)=> void | ()=>null |
7272
listEmptyComponent | Custom component for empty notification list | JSX Element | null |
@@ -194,9 +194,11 @@ Please note that the badgeStyle, window shadow and border props are only applica
194194
type CardProps = {
195195
hideDelete?: boolean,
196196
hideAvatar?: boolean,
197+
hideMediaThumbnail?: boolean,
197198
disableAutoMarkAsRead?: boolean,
198199
deleteIcon?: JSX.Element,
199200
onAvatarClick?: () => void,
201+
onMediaThumbnailClick?: () => void,
200202
};
201203
```
202204

example/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ const App: React.FC = () => {
255255
customHeader: showCustomHeader ? renderCustomHeader() : undefined
256256
}}
257257
darkMode={sdkDarkModeEnabled}
258-
cardProps={{ hideAvatar: hideAvatar, showMedia: true, onAvatarClick: () => console.log('avatar click') }}
258+
cardProps={{ hideAvatar: hideAvatar, onAvatarClick: () => console.log('avatar click') }}
259259
theme={windowThemes[windowThemeIndex]}
260260
customFooter={showCustomFooter ? renderCustomFooter() : undefined}
261261
listEmptyComponent={

package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"typescript": "^5.3.3"
8585
},
8686
"dependencies": {
87-
"test_notification": "^1.1.1",
87+
"@sirenapp/js-sdk": "^1.1.0",
8888
"pubsub-js": "^1.9.4"
8989
}
9090
}
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading

src/components/Card.tsx

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import React, { type FC, useState } from "react";
44
import CloseIcon from "./CloseIcon";
55
import TimerIcon from "./TimerIcon";
66
import defaultAvatarDark from "../assets/dark/defaultAvatarDark.png";
7+
import failedImageDark from "../assets/dark/failedImageDark.svg";
78
import defaultAvatarLight from "../assets/light/defaultAvatarLight.png";
9+
import failedImageLight from "../assets/light/failedImageLight.svg";
810
import type { NotificationCardProps } from "../types";
911
import { generateElapsedTimeText } from "../utils/commonUtils";
1012
import "../styles/card.css";
@@ -52,13 +54,17 @@ const Card: FC<NotificationCardProps> = ({
5254
deleteNotificationById,
5355
}) => {
5456
const { createdAt, message, isRead } = notification;
55-
const { avatar, header, subHeader, body } = message;
56-
const { hideAvatar, hideDelete, disableAutoMarkAsRead, deleteIcon = null, onAvatarClick } = cardProps ?? {};
57+
const { avatar, header, subHeader, body, thumbnailUrl } = message;
58+
const { hideAvatar, hideDelete, hideMediaThumbnail, disableAutoMarkAsRead, deleteIcon = null, onAvatarClick, onMediaThumbnailClick } = cardProps ?? {};
5759
const {
5860
markAsReadById
5961
} = useSiren();
6062

6163
const [deleteAnimationStyle, setDeleteAnimationStyle] = useState('');
64+
65+
const defaultAvatar = darkMode ? defaultAvatarDark : defaultAvatarLight;
66+
const failedImage = darkMode ? failedImageDark: failedImageLight;
67+
6268

6369
const onDelete = async (event: React.MouseEvent): Promise<void> => {
6470

@@ -79,8 +85,6 @@ const Card: FC<NotificationCardProps> = ({
7985
}
8086
};
8187

82-
83-
const defaultAvatar = darkMode ? defaultAvatarDark : defaultAvatarLight;
8488
const cardContainerStyle: CSSProperties = isRead
8589
? {
8690
...styles.defaultCardContainer,
@@ -102,6 +106,20 @@ const Card: FC<NotificationCardProps> = ({
102106
event.stopPropagation();
103107
};
104108

109+
const handleMediaClick = (event: React.MouseEvent) => {
110+
onMediaThumbnailClick && onMediaThumbnailClick(notification);
111+
event.stopPropagation();
112+
};
113+
114+
const [imageLoaded, setImageLoaded] = useState(true); // Initially assume image is loaded
115+
116+
const [imageSource, setImageSource] = useState(thumbnailUrl ? thumbnailUrl : '');
117+
118+
const onErrorMedia = (): void => {
119+
setImageLoaded(false);
120+
setImageSource(failedImage);
121+
};
122+
105123
return (
106124
<div
107125
style={cardContainerStyle}
@@ -143,6 +161,19 @@ const Card: FC<NotificationCardProps> = ({
143161
>
144162
{body}
145163
</div>
164+
{!hideMediaThumbnail && thumbnailUrl &&(
165+
<div
166+
className="siren-sdk-card-thumbnail-container"
167+
style={{...(onAvatarClick && { cursor: "pointer" }),
168+
backgroundColor: darkMode ? '#4C4C4C' : '#F0F2F5'}}
169+
onClick={handleMediaClick}>
170+
<img
171+
className={`siren-sdk-card-thumbnail-image ${thumbnailUrl && imageLoaded ? 'siren-sdk-card-thumbnail-with-image' : ''}`}
172+
src={imageSource}
173+
onError={onErrorMedia}
174+
/>
175+
</div>
176+
)}
146177
<div className="siren-sdk-card-date-container">
147178
<TimerIcon
148179
color={styles.timerIcon.color}
@@ -170,4 +201,4 @@ const Card: FC<NotificationCardProps> = ({
170201
);
171202
};
172203

173-
export default Card;
204+
export default Card;

src/components/SirenPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
NotificationDataType,
77
NotificationsApiResponse,
88
SirenErrorType,
9-
} from "test_notification/dist/esm/types";
9+
} from "@sirenapp/js-sdk/dist/esm/types";
1010

1111
import "../styles/sirenPanel.css";
1212
import NotificationCard from "./Card";

src/components/SirenProvider.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React, { createContext, useContext, useEffect, useState } from "react";
22

3-
import PubSub from "pubsub-js";
4-
import { Siren } from "test_notification";
3+
import { Siren } from "@sirenapp/js-sdk";
54
import type {
65
InitConfigType,
76
NotificationsApiResponse,
87
SirenErrorType,
98
UnviewedCountApiResponse,
10-
} from "test_notification/dist/esm/types";
9+
} from "@sirenapp/js-sdk/dist/esm/types";
10+
import PubSub from "pubsub-js";
1111

1212
import type { SirenProviderConfigProps } from "../types";
1313
import { logger } from "../utils/commonUtils";

src/styles/card.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
.siren-sdk-delete-button {
2727
cursor: pointer;
28+
overflow: hidden;
2829
}
2930

3031
.siren-sdk-card-text-break {
@@ -35,6 +36,30 @@
3536
overflow: hidden;
3637
}
3738

39+
.siren-sdk-card-thumbnail-container{
40+
height: 130px;
41+
display: flex;
42+
justify-content: center;
43+
align-items: center;
44+
border-radius: 6px;
45+
margin-bottom: 10px;
46+
overflow: hidden;
47+
}
48+
49+
.siren-sdk-card-thumbnail-error{
50+
height: 26px;
51+
}
52+
53+
.siren-sdk-card-thumbnail-image {
54+
border-radius: 6px;
55+
}
56+
57+
.siren-sdk-card-thumbnail-with-image {
58+
height: 100%;
59+
object-fit: cover;
60+
width: 100%;
61+
}
62+
3863
.siren-sdk-card-date-container {
3964
display: grid;
4065
grid-template-columns: max-content max-content;

0 commit comments

Comments
 (0)