Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(native-app): Notifications final improvements #15240

Merged
merged 5 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/native/app/src/messages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ export const en: TranslatedMessages = {
'notifications.markAllAsRead': 'Mark all as read',
'notifications.settings': 'My settings',
'notifications.errorUnknown': 'Error occurred while loading notifications',
'notifications.emptyListTitle': 'No notifications',
'notifications.emptyListDescription':
'When you receive notifications, they will appear here.',

// profile
'profile.screenTitle': 'More',
Expand Down
3 changes: 3 additions & 0 deletions apps/native/app/src/messages/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@ export const is = {
'notifications.markAllAsRead': 'Merkja allt lesið',
'notifications.settings': 'Mínar stillingar',
'notifications.errorUnknown': 'Villa kom upp við að sækja tilkynningar',
'notifications.emptyListTitle': 'Engar tilkynningar',
'notifications.emptyListDescription':
'Þegar þú færð sendar tilkynningar þá birtast þær hér.',

// applications screen
'applications.title': 'Umsóknir',
Expand Down
1 change: 1 addition & 0 deletions apps/native/app/src/screens/inbox/inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ function useInboxQuery(incomingFilters?: Filters) {
...(data.documentsV2?.data ?? []),
],
totalCount: data.documentsV2?.totalCount ?? 0,
unreadCount: data.documentsV2?.unreadCount ?? 0,
}))
} else {
setData(data.documentsV2)
Expand Down
125 changes: 84 additions & 41 deletions apps/native/app/src/screens/notifications/notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import {
NotificationCard,
Problem,
ListItemSkeleton,
EmptyList,
} from '@ui'
import { useApolloClient } from '@apollo/client'

import { dismissAllNotificationsAsync } from 'expo-notifications'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useIntl } from 'react-intl'
import { ActivityIndicator, FlatList, SafeAreaView } from 'react-native'
import {
ActivityIndicator,
FlatList,
SafeAreaView,
View,
Image,
} from 'react-native'
import {
Navigation,
NavigationFunctionComponent,
Expand All @@ -37,6 +44,7 @@ import { isAndroid } from '../../utils/devices'
import { testIDs } from '../../utils/test-ids'
import settings from '../../assets/icons/settings.png'
import inboxRead from '../../assets/icons/inbox-read.png'
import emptyIllustrationSrc from '../../assets/illustrations/le-company-s3.png'

const LoadingWrapper = styled.View`
padding-vertical: ${({ theme }) => theme.spacing[3]}px;
Expand All @@ -47,10 +55,14 @@ const ButtonWrapper = styled.View`
flex-direction: row;
margin-horizontal: ${({ theme }) => theme.spacing[2]}px;
margin-top: ${({ theme }) => theme.spacing[2]}px;
margin-bottom: ${({ theme }) => theme.spacing[2]}px;
`

const DEFAULT_PAGE_SIZE = 50

const FALLBACK_ICON_URL =
'https://images.ctfassets.net/8k0h54kbe6bj/6XhCz5Ss17OVLxpXNVDxAO/d3d6716bdb9ecdc5041e6baf68b92ba6/coat_of_arms.svg'

const { getNavigationOptions, useNavigationOptions } =
createNavigationOptionHooks(() => ({
topBar: {
Expand All @@ -62,7 +74,12 @@ type NotificationItem = NonNullable<
NonNullable<GetUserNotificationsQuery['userNotifications']>['data']
>[0]

type ListItem = SkeletonItem | NotificationItem
export type EmptyItem = {
id: string
__typename: 'Empty'
}

type ListItem = SkeletonItem | NotificationItem | EmptyItem

export const NotificationsScreen: NavigationFunctionComponent = ({
componentId,
Expand Down Expand Up @@ -123,6 +140,10 @@ export const NotificationsScreen: NavigationFunctionComponent = ({
return createSkeletonArr(9)
}

if (data?.userNotifications?.data?.length === 0) {
return [{ id: '0', __typename: 'Empty' }]
}

return data?.userNotifications?.data || []
}, [data, loading])

Expand Down Expand Up @@ -185,18 +206,38 @@ export const NotificationsScreen: NavigationFunctionComponent = ({
return <ListItemSkeleton multilineMessage />
}

if (item.__typename === 'Empty') {
return (
<View style={{ marginTop: 80 }}>
<EmptyList
title={intl.formatMessage({ id: 'notifications.emptyListTitle' })}
description={intl.formatMessage({
id: 'notifications.emptyListDescription',
})}
image={
<Image
source={emptyIllustrationSrc}
style={{ width: 134, height: 176 }}
resizeMode="contain"
/>
}
/>
</View>
)
}

return (
<NotificationCard
key={item.id}
id={item.id}
title={item.message.title}
message={item.message.displayBody}
date={new Date(item.metadata.sent)}
icon={
item.sender?.logoUrl && {
uri: `${item.sender.logoUrl}?w=64&h=64&fit=pad&fm=png`,
}
}
icon={{
uri: `${
item.sender.logoUrl ?? FALLBACK_ICON_URL
}?w=64&h=64&fit=pad&fm=png`,
}}
unread={!item.metadata.read}
onPress={() => onNotificationPress(item)}
testID={testIDs.NOTIFICATION_CARD_BUTTON}
Expand All @@ -219,40 +260,6 @@ export const NotificationsScreen: NavigationFunctionComponent = ({
showLoading={loading && !!data}
/>
<SafeAreaView style={{ flex: 1 }} testID={testIDs.SCREEN_NOTIFICATIONS}>
<ButtonWrapper>
<Button
isOutlined
isUtilityButton
title={intl.formatMessage({
id: 'notifications.markAllAsRead',
defaultMessage: 'Merkja allt lesið',
})}
style={{
marginRight: theme.spacing[2],
maxWidth: 145,
}}
icon={inboxRead}
iconStyle={{ tintColor: theme.color.blue400 }}
onPress={() => markAllUserNotificationsAsRead()}
/>
<Button
isOutlined
isUtilityButton
title={intl.formatMessage({
id: 'notifications.settings',
defaultMessage: 'Mínar stillingar',
})}
onPress={() => navigateTo('/settings', componentId)}
icon={settings}
style={{
maxWidth: 145,
}}
iconStyle={{
tintColor: theme.color.blue400,
resizeMode: 'contain',
}}
/>
</ButtonWrapper>
{showError ? (
<Problem type="error" withContainer />
) : (
Expand All @@ -265,6 +272,42 @@ export const NotificationsScreen: NavigationFunctionComponent = ({
onEndReached={handleEndReached}
scrollEventThrottle={16}
scrollToOverflowEnabled
ListHeaderComponent={
<ButtonWrapper>
<Button
isOutlined
isUtilityButton
title={intl.formatMessage({
id: 'notifications.markAllAsRead',
defaultMessage: 'Merkja allt lesið',
})}
style={{
marginRight: theme.spacing[2],
maxWidth: 145,
}}
icon={inboxRead}
iconStyle={{ tintColor: theme.color.blue400 }}
onPress={() => markAllUserNotificationsAsRead()}
/>
<Button
isOutlined
isUtilityButton
title={intl.formatMessage({
id: 'notifications.settings',
defaultMessage: 'Mínar stillingar',
})}
onPress={() => navigateTo('/settings', componentId)}
icon={settings}
style={{
maxWidth: 145,
}}
iconStyle={{
tintColor: theme.color.blue400,
resizeMode: 'contain',
}}
/>
</ButtonWrapper>
}
ListFooterComponent={
loadingMore && !error ? (
<LoadingWrapper>
Expand Down
20 changes: 6 additions & 14 deletions apps/native/app/src/ui/lib/empty-state/empty-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react'
import { View } from 'react-native'
import styled from 'styled-components/native'

import { font } from '../../utils/font'
import { dynamicColor } from '@ui/utils'
import { Typography } from '../typography/typography'

const Host = styled.View`
display: flex;
Expand All @@ -12,6 +12,7 @@ const Host = styled.View`
justify-content: center;
align-items: center;
padding: 0 53px;
margin-top: ${({ theme }) => theme.spacing[3]}px;
`

const HostWithBorder = styled.View`
Expand All @@ -36,21 +37,12 @@ const ImageWrap = styled.View`
margin-bottom: 50px;
`

const Title = styled.Text`
margin-bottom: ${({ theme }) => theme.spacing[2]}px;

${font({
fontWeight: '600',
})}

const Title = styled(Typography)`
margin-bottom: ${({ theme }) => theme.spacing[1]}px;
text-align: center;
`

const Description = styled.Text`
${font({
fontWeight: '300',
lineHeight: 24,
})}
const Description = styled(Typography)`
text-align: center;
`

Expand All @@ -74,7 +66,7 @@ export function EmptyList({ title, description, image, small }: HeadingProps) {
return (
<Host>
<ImageWrap>{image}</ImageWrap>
<Title>{title}</Title>
<Title variant={'heading3'}>{title}</Title>
<Description>{description}</Description>
</Host>
)
Expand Down
Loading