1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Use flash message instead of toast

This commit is contained in:
Zhiyuan Zheng
2021-02-28 22:49:55 +01:00
parent 78898059cb
commit b20b75f22e
13 changed files with 154 additions and 199 deletions

View File

@ -1,4 +1,4 @@
import { toast, toastConfig } from '@components/toast'
import { displayMessage, Message } from '@components/Message'
import {
NavigationContainer,
NavigationContainerRef
@ -20,7 +20,6 @@ import React, { createRef, useCallback, useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { Alert, Platform, StatusBar } from 'react-native'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import Toast from 'react-native-toast-message'
import { useDispatch, useSelector } from 'react-redux'
import * as Sentry from 'sentry-expo'
@ -77,11 +76,12 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
useEffect(() => {
const showLocalCorrect = () => {
if (localCorrupt) {
toast({
type: 'error',
displayMessage({
autoHide: false,
message: t('index.localCorrupt'),
description: localCorrupt.length ? localCorrupt : undefined,
autoHide: false
type: 'error',
mode
})
navigationRef.current?.navigate('Screen-Tabs', {
screen: 'Tab-Me'
@ -178,9 +178,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
/>
</Stack.Navigator>
{Platform.select({
ios: <Toast ref={Toast.setRef} config={toastConfig} />
})}
<Message />
</NavigationContainer>
</>
)

100
src/components/Message.tsx Normal file
View File

@ -0,0 +1,100 @@
import Icon from '@components/Icon'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { getTheme } from '@utils/styles/themes'
import React from 'react'
import FlashMessage, { showMessage } from 'react-native-flash-message'
import haptics from './haptics'
const displayMessage = ({
autoHide = true,
message,
description,
onPress,
mode,
type
}:
| {
autoHide?: boolean
message: string
description?: string
onPress?: () => void
mode?: undefined
type?: undefined
}
| {
autoHide?: boolean
message: string
description?: string
onPress?: () => void
mode: 'light' | 'dark'
type: 'success' | 'error' | 'warning'
}) => {
enum iconMapping {
success = 'CheckCircle',
error = 'XCircle',
warning = 'AlertCircle'
}
enum colorMapping {
success = 'blue',
error = 'red',
warning = 'secondary'
}
if (type && type === 'error') {
haptics('Error')
}
showMessage({
autoHide,
message,
description,
onPress,
...(mode &&
type && {
renderFlashMessageIcon: props => {
console.log(props)
return (
<Icon
name={iconMapping[type]}
size={StyleConstants.Font.LineHeight.M}
color={getTheme(mode)[colorMapping[type]]}
style={{ marginRight: StyleConstants.Spacing.S }}
/>
)
}
})
})
}
const Message = React.memo(
() => {
const { mode, theme } = useTheme()
return (
<FlashMessage
icon='auto'
position='top'
floating
style={{
backgroundColor: theme.background,
shadowColor: theme.primary,
shadowOffset: { width: 0, height: 0 },
shadowOpacity: mode === 'light' ? 0.16 : 0.32,
shadowRadius: 4
}}
titleStyle={{
color: theme.primary,
...StyleConstants.FontStyle.M,
fontWeight: StyleConstants.Font.Weight.Bold
}}
textStyle={{ color: theme.primary, ...StyleConstants.FontStyle.M }}
// @ts-ignore
textProps={{ numberOfLines: 2 }}
/>
)
},
() => true
)
export { Message, displayMessage }

View File

@ -1,13 +1,14 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import { toast } from '@components/toast'
import { displayMessage } from '@components/Message'
import {
QueryKeyRelationship,
useRelationshipMutation
} from '@utils/queryHooks/relationship'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, View } from 'react-native'
@ -18,6 +19,7 @@ export interface Props {
}
const RelationshipIncoming: React.FC<Props> = ({ id }) => {
const { mode } = useTheme()
const { t } = useTranslation()
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }]
@ -36,8 +38,9 @@ const RelationshipIncoming: React.FC<Props> = ({ id }) => {
},
onError: (err: any, { type }) => {
haptics('Error')
toast({
displayMessage({
type: 'error',
mode,
message: t('common:toastMessage.error.message', {
function: t(`relationship:${type}.function`)
}),

View File

@ -1,13 +1,14 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import { toast } from '@components/toast'
import { displayMessage } from '@components/Message'
import {
QueryKeyRelationship,
useRelationshipMutation,
useRelationshipQuery
} from '@utils/queryHooks/relationship'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useQueryClient } from 'react-query'
@ -18,6 +19,7 @@ export interface Props {
const RelationshipOutgoing = React.memo(
({ id }: Props) => {
const { mode } = useTheme()
const { t } = useTranslation('componentRelationship')
const query = useRelationshipQuery({ id })
@ -37,8 +39,8 @@ const RelationshipOutgoing = React.memo(
}
},
onError: (err: any, { payload: { action } }) => {
haptics('Error')
toast({
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(`${action}.function`)

View File

@ -1,7 +1,6 @@
import analytics from '@components/analytics'
import haptics from '@components/haptics'
import Icon from '@components/Icon'
import { toast } from '@components/toast'
import { displayMessage } from '@components/Message'
import { useNavigation } from '@react-navigation/native'
import {
MutationVarsTimelineUpdateStatusProperty,
@ -32,7 +31,7 @@ const TimelineActions: React.FC<Props> = ({
}) => {
const navigation = useNavigation()
const { t } = useTranslation('componentTimeline')
const { theme } = useTheme()
const { mode, theme } = useTheme()
const iconColor = theme.secondary
const iconColorAction = (state: boolean) =>
state ? theme.primary : theme.secondary
@ -84,8 +83,8 @@ const TimelineActions: React.FC<Props> = ({
},
onError: (err: any, params, oldData) => {
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
haptics('Error')
toast({
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(

View File

@ -1,8 +1,7 @@
import analytics from '@components/analytics'
import haptics from '@components/haptics'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import { ParseEmojis } from '@components/Parse'
import { toast } from '@components/toast'
import {
QueryKeyTimeline,
useTimelineMutation
@ -46,6 +45,7 @@ export interface Props {
const HeaderConversation = React.memo(
({ queryKey, conversation }: Props) => {
const { mode } = useTheme()
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
@ -53,8 +53,8 @@ const HeaderConversation = React.memo(
queryClient,
onMutate: true,
onError: (err: any, _, oldData) => {
haptics('Error')
toast({
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(`shared.header.conversation.delete.function`)
@ -65,8 +65,7 @@ const HeaderConversation = React.memo(
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
}),
autoHide: false
})
})
queryClient.setQueryData(queryKey, oldData)
}

View File

@ -2,9 +2,9 @@ import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import { ParseEmojis } from '@components/Parse'
import RelativeTime from '@components/RelativeTime'
import { toast } from '@components/toast'
import {
MutationVarsTimelineUpdateStatusProperty,
QueryKeyTimeline,
@ -61,8 +61,8 @@ const TimelinePoll: React.FC<Props> = ({
},
onError: (err: any, params) => {
const theParams = params as MutationVarsTimelineUpdateStatusProperty
haptics('Error')
toast({
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
// @ts-ignore

View File

@ -1,134 +0,0 @@
import Icon from '@components/Icon'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Platform, StyleSheet, Text, ToastAndroid, View } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import Toast from 'react-native-toast-message'
export interface Params {
type: 'success' | 'error' | 'warning'
position?: 'top' | 'bottom'
message: string
description?: string
autoHide?: boolean
onShow?: () => void
onHide?: () => void
}
type Config = {
type: Params['type']
position: Params['position']
text1: Params['message']
text2: Params['description']
}
const toast = ({
type,
position = 'top',
message,
description,
autoHide = true,
onShow,
onHide
}: Params) => {
switch (Platform.OS) {
case 'ios':
return Toast.show({
type,
position,
text1: message,
text2: description,
visibilityTime: 1500,
autoHide,
topOffset: 0,
bottomOffset: 0,
onShow: onShow,
onHide: onHide
})
case 'android':
return ToastAndroid.show(message, ToastAndroid.SHORT)
}
}
const ToastBase = ({ config }: { config: Config }) => {
const { theme } = useTheme()
const iconSet = {
success: 'CheckCircle',
error: 'XCircle',
warning: 'AlertCircle'
}
enum colorMapping {
success = 'blue',
error = 'red',
warning = 'secondary'
}
return (
<SafeAreaView
style={[
styles.base,
{ backgroundColor: theme.background, borderBottomColor: theme.primary }
]}
>
<View style={styles.container}>
<Icon
name={iconSet[config.type]}
size={StyleConstants.Font.Size.M}
color={theme[colorMapping[config.type]]}
/>
<View style={styles.texts}>
<Text
style={[styles.text1, { color: theme.primary }]}
numberOfLines={2}
>
{config.text1}
</Text>
{config.text2 && (
<Text
style={[styles.text2, { color: theme.secondary }]}
numberOfLines={2}
>
{config.text2}
</Text>
)}
</View>
</View>
</SafeAreaView>
)
}
const toastConfig = {
success: (config: Config) => <ToastBase config={config} />,
warning: (config: Config) => <ToastBase config={config} />,
error: (config: Config) => {
// Sentry.Native.captureException([config.text1, config.text2])
return <ToastBase config={config} />
}
}
const styles = StyleSheet.create({
base: {
width: '100%',
borderBottomWidth: 1
},
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: StyleConstants.Spacing.M
},
texts: {
marginLeft: StyleConstants.Spacing.S
},
text1: {
...StyleConstants.FontStyle.M
},
text2: {
...StyleConstants.FontStyle.S,
marginTop: StyleConstants.Spacing.XS
}
})
export { toast, toastConfig }

View File

@ -1,12 +1,12 @@
import analytics from '@components/analytics'
import haptics from '@components/haptics'
import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
import { toast } from '@components/toast'
import { displayMessage } from '@components/Message'
import {
MutationVarsTimelineUpdateAccountProperty,
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useQueryClient } from 'react-query'
@ -24,6 +24,7 @@ const ActionsAccount: React.FC<Props> = ({
account,
dismiss
}) => {
const { mode } = useTheme()
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
@ -31,8 +32,8 @@ const ActionsAccount: React.FC<Props> = ({
queryClient,
onSuccess: (_, params) => {
const theParams = params as MutationVarsTimelineUpdateAccountProperty
haptics('Success')
toast({
displayMessage({
mode,
type: 'success',
message: t('common:toastMessage.success.message', {
function: t(
@ -46,8 +47,8 @@ const ActionsAccount: React.FC<Props> = ({
},
onError: (err: any, params) => {
const theParams = params as MutationVarsTimelineUpdateAccountProperty
haptics('Error')
toast({
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(

View File

@ -2,11 +2,12 @@ import analytics from '@components/analytics'
import MenuContainer from '@components/Menu/Container'
import MenuHeader from '@components/Menu/Header'
import MenuRow from '@components/Menu/Row'
import { toast } from '@components/toast'
import { displayMessage } from '@components/Message'
import {
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
@ -25,12 +26,14 @@ const ActionsDomain: React.FC<Props> = ({
domain,
dismiss
}) => {
const { mode } = useTheme()
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
const mutation = useTimelineMutation({
queryClient,
onSettled: () => {
toast({
displayMessage({
mode,
type: 'success',
message: t('common:toastMessage.success.message', {
function: t(`shared.header.actions.domain.block.function`)

View File

@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
import { useQueryClient } from 'react-query'
import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
import { toast } from '@components/toast'
import {
MutationVarsTimelineUpdateStatusProperty,
QueryKeyTimeline,
@ -12,6 +11,8 @@ import {
import analytics from '@components/analytics'
import { StackNavigationProp } from '@react-navigation/stack'
import deleteItem from '@utils/queryHooks/timeline/deleteItem'
import { displayMessage } from '@components/Message'
import { useTheme } from '@utils/styles/ThemeManager'
export interface Props {
navigation: StackNavigationProp<Nav.RootStackParamList, 'Screen-Actions'>
@ -28,6 +29,7 @@ const ActionsStatus: React.FC<Props> = ({
status,
dismiss
}) => {
const { mode } = useTheme()
const { t } = useTranslation('componentTimeline')
const queryClient = useQueryClient()
@ -39,7 +41,8 @@ const ActionsStatus: React.FC<Props> = ({
.payload
? (params as MutationVarsTimelineUpdateStatusProperty).payload.property
: 'delete'
toast({
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(`shared.header.actions.status.${theFunction}.function`)