IntroductionStreami18nReadme
Top Level Components
UI Components
Layout Components
Composition Components
NotificationFeed
This component should be a child of <StreamApp/>
component.
Properties
Group
string | number | boolean | ReactElement<PropsWithElementAttributes<{ activityGroup: NotificationActivityEnriched<UT, AT, CT, RT, CRT>; onClickNotification?: ((activityGroup: NotificationActivityEnriched<UT, AT, CT, RT, CRT>) => void) | undefined; onClickUser?: OnClickUserHandler<...> | undefined; onMarkAsRead?: ((g...
<
UT extends DefaultUT = DefaultUT,
AT extends DefaultAT = DefaultAT,
CT extends UR = UR,
RT extends UR = UR,
CRT extends UR = UR
>({
activityGroup,
onMarkAsRead,
onClickUser,
onClickNotification,
className,
style,
}: NotificationProps<UT, AT, CT, RT, CRT>) => {
const { t, tDateTimeParser } = useTranslationContext();
const { activities } = activityGroup;
const [latestActivity, ...restOfActivities] = activities;
if (typeof latestActivity.object === 'string') return null;
const lastObject = latestActivity.object as EnrichedActivity;
const lastActor = userOrDefault(latestActivity.actor);
const headerText = getHeaderText(t, activities.length, latestActivity.verb, lastActor.data.name, lastObject.verb);
const handleUserClick = useOnClickUser<UT>(onClickUser);
const handleNotificationClick = onClickNotification
? (e: SyntheticEvent) => {
e.stopPropagation();
onClickNotification(activityGroup);
}
: undefined;
return (
<div
onClick={handleNotificationClick}
className={className ?? `raf-notification ${activityGroup.is_read ? 'raf-notification--read' : ''}`}
style={style}
>
<Avatar
onClick={handleUserClick?.(lastActor as EnrichedUser<UT>)}
image={lastActor.data.profileImage}
circle
size={30}
/>
<div className="raf-notification__content">
<div className="raf-notification__header">
<strong>{headerText}</strong>
{!activityGroup.is_read && onMarkAsRead && (
<Dropdown>
<div>
<Link
onClick={(e) => {
e.stopPropagation();
onMarkAsRead(activityGroup);
}}
>
Mark as read
</Link>
</div>
</Dropdown>
)}
</div>
<div>
<small>{humanizeTimestamp(latestActivity.time, tDateTimeParser)}</small>
</div>
{latestActivity.verb !== 'follow' && (
<AttachedActivity activity={latestActivity.object as EnrichedActivity<UT, AT, CT, RT, CRT>} />
)}
</div>
<div className="raf-notification__extra">
{activities.length > 1 && latestActivity.verb === 'follow' && (
<AvatarGroup
onClickUser={onClickUser}
avatarSize={30}
users={getUsers<UT, AT, CT, RT, CRT>(restOfActivities) as Array<EnrichedUser<UT>>}
/>
)}
</div>
</div>
);
}
LoadingIndicator
string | number | boolean | ReactElement<LoadingIndicatorProps, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)> | ComponentClass<...> | FunctionComponent<...> | null | undefined
Notifier
string | number | boolean | ReactElement<PropsWithElementAttributes<{ adds?: any; deletes?: string[] | undefined; labelFunction?: LabelFunction | undefined; labelPlural?: string | undefined; labelSingle?: string | undefined; onClick?: ((event: MouseEvent<...>) => void) | undefined; }, HTMLButtonElement>, string | .....
({
adds = [],
deletes = [],
labelPlural,
labelSingle,
onClick,
labelFunction,
className,
style,
}: NewActivitiesNotificationProps) => {
const { t } = useTranslationContext();
const attributes: Attributes = {
addCount: adds.length,
deleteCount: deletes.length,
count: adds.length + deletes.length,
labelPlural,
labelSingle,
};
const defaultLabelFunction: LabelFunction =
labelFunction ??
(({ addCount, labelPlural, labelSingle }) => {
if (!addCount) return null;
if (addCount > 1)
return labelPlural
? generateText(addCount, labelPlural)
: t('You have {{ notificationCount }} new notifications', {
notificationCount: addCount,
});
return labelSingle ? generateText(1, labelSingle) : t('You have 1 new notification');
});
const label = defaultLabelFunction(attributes);
if (!label) return null;
return (
<button
className={classNames('raf-new-activities-notification', className)}
type="button"
onClick={onClick}
style={style}
>
<Link>{label}</Link>
</button>
);
}
Paginator
string | number | boolean | ReactElement<LoadMorePaginatorProps, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)> | ComponentClass<...> | FunctionComponent<...> | null | undefined
({
LoadMoreButton = DefaultLoadMoreButton,
children,
reverse,
hasNextPage,
refreshing,
loadNextPage,
}: LoadMorePaginatorProps) => (
<>
{!reverse && children}
{hasNextPage && smartRender<LoadMoreButtonProps>(LoadMoreButton, { refreshing, onClick: loadNextPage })}
{reverse && children}
</>
)
Placeholder
string | number | boolean | ReactElement<PropsWithElementAttributes<{ text?: string | undefined; }, HTMLDivElement>, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<...>)> | ComponentClass<...> | FunctionComponent<...> | null | undefined
({ text, className, style }: FeedPlaceholderProps) => {
const { t } = useTranslationContext();
return (
<div className={classNames('raf-feed-placeholder', className)} style={style}>
<p>{text || t('No data to display...')}</p>
</div>
);
}
options
GetFeedOptions | undefined
feedGroup
string | undefined
notification
userId
string | undefined
analyticsLocation
string | undefined
doActivityDeleteRequest
DeleteRequestFn | undefined
doChildReactionAddRequest
((kind: string, reaction: Reaction<RT>, data?: CRT | undefined, options?: ReactionAddChildOptions | undefined) => Promise<ReactionAPIResponse<CRT>>) | undefined
doChildReactionDeleteRequest
DeleteRequestFn | undefined
doFeedRequest
((client: StreamClient<UT, AT, CT, RT, CRT, PT>, feedGroup: string, userId?: string | undefined, options?: GetFeedOptions | undefined) => Promise<FeedAPIResponse<UT, AT, CT, RT, CRT>>) | undefined
doReactionAddRequest
((kind: string, activity: Activity<AT>, data?: RT | undefined, options?: ReactionAddOptions | undefined) => Promise<ReactionAPIResponse<RT>>) | undefined
doReactionDeleteRequest
DeleteRequestFn | undefined
doReactionsFilterRequest
((options: ReactionFilterConditions) => Promise<ReactionFilterAPIResponse<RT, CRT, AT, UT>>) | undefined
notify
boolean | undefined