diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts
index 1dc2dfa7..650997c9 100644
--- a/src/alf/atoms.ts
+++ b/src/alf/atoms.ts
@@ -145,6 +145,9 @@ export const atoms = {
flex_shrink: {
flexShrink: 1,
},
+ flex_shrink_0: {
+ flexShrink: 0,
+ },
justify_start: {
justifyContent: 'flex-start',
},
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 5462505e..d510eed8 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -1,87 +1,93 @@
+import React, {useEffect, useState} from 'react'
+import {View} from 'react-native'
+import Animated, {FadeInUp, FadeOutUp} from 'react-native-reanimated'
import RootSiblings from 'react-native-root-siblings'
-import React from 'react'
-import {Animated, StyleSheet, View} from 'react-native'
-import {Props as FontAwesomeProps} from '@fortawesome/react-native-fontawesome'
-import {Text} from './text/Text'
-import {colors} from 'lib/styles'
-import {useTheme} from 'lib/ThemeContext'
-import {usePalette} from 'lib/hooks/usePalette'
-import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
+import {useSafeAreaInsets} from 'react-native-safe-area-context'
+import {
+ FontAwesomeIcon,
+ Props as FontAwesomeProps,
+} from '@fortawesome/react-native-fontawesome'
+
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
import {IS_TEST} from '#/env'
-const TIMEOUT = 4e3
+const TIMEOUT = 3.7e3
export function show(
message: string,
- _icon: FontAwesomeProps['icon'] = 'check',
+ icon: FontAwesomeProps['icon'] = 'check',
) {
if (IS_TEST) return
- const item = new RootSiblings()
+ const item = new RootSiblings()
+ // timeout has some leeway to account for the animation
setTimeout(() => {
item.destroy()
- }, TIMEOUT)
+ }, TIMEOUT + 1e3)
}
-function Toast({message}: {message: string}) {
- const theme = useTheme()
- const pal = usePalette('default')
- const interp = useAnimatedValue(0)
+function Toast({
+ message,
+ icon,
+}: {
+ message: string
+ icon: FontAwesomeProps['icon']
+}) {
+ const t = useTheme()
+ const {top} = useSafeAreaInsets()
- React.useEffect(() => {
- Animated.sequence([
- Animated.timing(interp, {
- toValue: 1,
- duration: 150,
- useNativeDriver: true,
- }),
- Animated.delay(3700),
- Animated.timing(interp, {
- toValue: 0,
- duration: 150,
- useNativeDriver: true,
- }),
- ]).start()
- })
+ // for the exit animation to work on iOS the animated component
+ // must not be the root component
+ // so we need to wrap it in a view and unmount the toast ahead of time
+ const [alive, setAlive] = useState(true)
+
+ useEffect(() => {
+ setTimeout(() => {
+ setAlive(false)
+ }, TIMEOUT)
+ }, [])
- const opacityStyle = {opacity: interp}
return (
-
-
-
- {message}
-
-
+
+ {alive && (
+
+
+
+
+
+ {message}
+
+
+ )}
)
}
-
-const styles = StyleSheet.create({
- container: {
- position: 'absolute',
- top: 60,
- left: 0,
- right: 0,
- alignItems: 'center',
- },
- toast: {
- paddingHorizontal: 18,
- paddingVertical: 10,
- borderRadius: 24,
- borderWidth: 1,
- shadowColor: '#000',
- shadowOpacity: 0.1,
- shadowOffset: {width: 0, height: 4},
- marginHorizontal: 6,
- },
- toastDark: {
- backgroundColor: colors.gray6,
- shadowOpacity: 0.5,
- },
-})