Fix toast positioning (close #9)

This commit is contained in:
Paul Frazee 2022-11-28 10:38:16 -06:00
parent c86ff23757
commit 0e6237e58c
15 changed files with 37 additions and 137 deletions

View file

@ -2,7 +2,7 @@ import React, {useState, useEffect} from 'react'
import * as view from './view/index' import * as view from './view/index'
import {RootStoreModel, setupState, RootStoreProvider} from './state' import {RootStoreModel, setupState, RootStoreProvider} from './state'
import {DesktopWebShell} from './view/shell/desktop-web' import {DesktopWebShell} from './view/shell/desktop-web'
import Toast from './view/com/util/Toast' import Toast from 'react-native-root-toast'
function App() { function App() {
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>( const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(

View file

@ -14,7 +14,7 @@ import LinearGradient from 'react-native-linear-gradient'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {UserAutocompleteViewModel} from '../../../state/models/user-autocomplete-view' import {UserAutocompleteViewModel} from '../../../state/models/user-autocomplete-view'
import {Autocomplete} from './Autocomplete' import {Autocomplete} from './Autocomplete'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import ProgressCircle from '../util/ProgressCircle' import ProgressCircle from '../util/ProgressCircle'
import {TextLink} from '../util/Link' import {TextLink} from '../util/Link'
import {UserAvatar} from '../util/UserAvatar' import {UserAvatar} from '../util/UserAvatar'
@ -106,13 +106,7 @@ export const ComposePost = observer(function ComposePost({
} }
onPost?.() onPost?.()
onClose() onClose()
Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`, { Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`)
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
shadow: true,
animation: true,
hideOnPress: true,
})
} }
const onSelectAutocompleteItem = (item: string) => { const onSelectAutocompleteItem = (item: string) => {
setText(replaceTextAutocompletePrefix(text, item)) setText(replaceTextAutocompletePrefix(text, item))

View file

@ -14,7 +14,7 @@ import _omit from 'lodash.omit'
import {ErrorScreen} from '../util/ErrorScreen' import {ErrorScreen} from '../util/ErrorScreen'
import {Link} from '../util/Link' import {Link} from '../util/Link'
import {UserAvatar} from '../util/UserAvatar' import {UserAvatar} from '../util/UserAvatar'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {useStores} from '../../../state' import {useStores} from '../../../state'
import * as apilib from '../../../state/lib/api' import * as apilib from '../../../state/lib/api'
import { import {
@ -63,10 +63,7 @@ export const SuggestedFollows = observer(
setFollows({[item.did]: res.uri, ...follows}) setFollows({[item.did]: res.uri, ...follows})
} catch (e) { } catch (e) {
console.log(e) console.log(e)
Toast.show('An issue occurred, please try again.', { Toast.show('An issue occurred, please try again.')
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
} }
} }
const onPressUnfollow = async (item: SuggestedActor) => { const onPressUnfollow = async (item: SuggestedActor) => {
@ -75,10 +72,7 @@ export const SuggestedFollows = observer(
setFollows(_omit(follows, [item.did])) setFollows(_omit(follows, [item.did]))
} catch (e) { } catch (e) {
console.log(e) console.log(e)
Toast.show('An issue occurred, please try again.', { Toast.show('An issue occurred, please try again.')
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
} }
} }

View file

@ -1,5 +1,5 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import { import {
ActivityIndicator, ActivityIndicator,
StyleSheet, StyleSheet,
@ -71,9 +71,7 @@ export function Component({}: {}) {
}, },
) )
.catch(e => console.error(e)) // an error here is not critical .catch(e => console.error(e)) // an error here is not critical
Toast.show('Scene created', { Toast.show('Scene created')
position: Toast.positions.TOP,
})
store.shell.closeModal() store.shell.closeModal()
store.nav.navigate(`/profile/${fullHandle}`) store.nav.navigate(`/profile/${fullHandle}`)
} catch (e: any) { } catch (e: any) {

View file

@ -1,5 +1,5 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import LinearGradient from 'react-native-linear-gradient' import LinearGradient from 'react-native-linear-gradient'
import {BottomSheetScrollView, BottomSheetTextInput} from '@gorhom/bottom-sheet' import {BottomSheetScrollView, BottomSheetTextInput} from '@gorhom/bottom-sheet'
@ -52,9 +52,7 @@ export function Component({
} }
}, },
) )
Toast.show('Profile updated', { Toast.show('Profile updated')
position: Toast.positions.TOP,
})
onUpdate?.() onUpdate?.()
store.shell.closeModal() store.shell.closeModal()
} catch (e: any) { } catch (e: any) {

View file

@ -1,6 +1,6 @@
import React, {useState, useEffect, useMemo} from 'react' import React, {useState, useEffect, useMemo} from 'react'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import { import {
ActivityIndicator, ActivityIndicator,
FlatList, FlatList,
@ -83,10 +83,7 @@ export const Component = observer(function Component({
follow.declaration.cid, follow.declaration.cid,
) )
setCreatedInvites({[follow.did]: assertionUri, ...createdInvites}) setCreatedInvites({[follow.did]: assertionUri, ...createdInvites})
Toast.show('Invite sent', { Toast.show('Invite sent')
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
} catch (e) { } catch (e) {
setError('There was an issue with the invite. Please try again.') setError('There was an issue with the invite. Please try again.')
console.error(e) console.error(e)
@ -119,10 +116,7 @@ export const Component = observer(function Component({
[assertion.uri]: true, [assertion.uri]: true,
...deletedPendingInvites, ...deletedPendingInvites,
}) })
Toast.show('Invite removed', { Toast.show('Invite removed')
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
} catch (e) { } catch (e) {
setError('There was an issue with the invite. Please try again.') setError('There was an issue with the invite. Please try again.')
console.error(e) console.error(e)

View file

@ -7,7 +7,7 @@ import {NotificationsViewItemModel} from '../../../state/models/notifications-vi
import {ConfirmModel} from '../../../state/models/shell-ui' import {ConfirmModel} from '../../../state/models/shell-ui'
import {useStores} from '../../../state' import {useStores} from '../../../state'
import {ProfileCard} from '../profile/ProfileCard' import {ProfileCard} from '../profile/ProfileCard'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {s, colors, gradients} from '../../lib/styles' import {s, colors, gradients} from '../../lib/styles'
export function InviteAccepter({item}: {item: NotificationsViewItemModel}) { export function InviteAccepter({item}: {item: NotificationsViewItemModel}) {
@ -46,10 +46,7 @@ export function InviteAccepter({item}: {item: NotificationsViewItemModel}) {
}, },
}) })
store.me.refreshMemberships() store.me.refreshMemberships()
Toast.show('Invite accepted', { Toast.show('Invite accepted')
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
setConfirmationUri(uri) setConfirmationUri(uri)
} }
return ( return (

View file

@ -8,7 +8,7 @@ import {PostThreadViewPostModel} from '../../../state/models/post-thread-view'
import {Link} from '../util/Link' import {Link} from '../util/Link'
import {RichText} from '../util/RichText' import {RichText} from '../util/RichText'
import {PostDropdownBtn} from '../util/DropdownBtn' import {PostDropdownBtn} from '../util/DropdownBtn'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {UserAvatar} from '../util/UserAvatar' import {UserAvatar} from '../util/UserAvatar'
import {s, colors} from '../../lib/styles' import {s, colors} from '../../lib/styles'
import {ago, pluralize} from '../../../lib/strings' import {ago, pluralize} from '../../../lib/strings'
@ -79,15 +79,11 @@ export const PostThreadItem = observer(function PostThreadItem({
item.delete().then( item.delete().then(
() => { () => {
setDeleted(true) setDeleted(true)
Toast.show('Post deleted', { Toast.show('Post deleted')
position: Toast.positions.TOP,
})
}, },
e => { e => {
console.error(e) console.error(e)
Toast.show('Failed to delete post, please try again', { Toast.show('Failed to delete post, please try again')
position: Toast.positions.TOP,
})
}, },
) )
} }

View file

@ -10,7 +10,7 @@ import {UserInfoText} from '../util/UserInfoText'
import {PostMeta} from '../util/PostMeta' import {PostMeta} from '../util/PostMeta'
import {PostCtrls} from '../util/PostCtrls' import {PostCtrls} from '../util/PostCtrls'
import {RichText} from '../util/RichText' import {RichText} from '../util/RichText'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {UserAvatar} from '../util/UserAvatar' import {UserAvatar} from '../util/UserAvatar'
import {useStores} from '../../../state' import {useStores} from '../../../state'
import {s, colors} from '../../lib/styles' import {s, colors} from '../../lib/styles'
@ -99,15 +99,11 @@ export const Post = observer(function Post({uri}: {uri: string}) {
item.delete().then( item.delete().then(
() => { () => {
setDeleted(true) setDeleted(true)
Toast.show('Post deleted', { Toast.show('Post deleted')
position: Toast.positions.TOP,
})
}, },
e => { e => {
console.error(e) console.error(e)
Toast.show('Failed to delete post, please try again', { Toast.show('Failed to delete post, please try again')
position: Toast.positions.TOP,
})
}, },
) )
} }

View file

@ -11,7 +11,7 @@ import {PostMeta} from '../util/PostMeta'
import {PostCtrls} from '../util/PostCtrls' import {PostCtrls} from '../util/PostCtrls'
import {PostEmbeds} from '../util/PostEmbeds' import {PostEmbeds} from '../util/PostEmbeds'
import {RichText} from '../util/RichText' import {RichText} from '../util/RichText'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {UserAvatar} from '../util/UserAvatar' import {UserAvatar} from '../util/UserAvatar'
import {s, colors} from '../../lib/styles' import {s, colors} from '../../lib/styles'
import {useStores} from '../../../state' import {useStores} from '../../../state'
@ -70,15 +70,11 @@ export const FeedItem = observer(function FeedItem({
item.delete().then( item.delete().then(
() => { () => {
setDeleted(true) setDeleted(true)
Toast.show('Post deleted', { Toast.show('Post deleted')
position: Toast.positions.TOP,
})
}, },
e => { e => {
console.error(e) console.error(e)
Toast.show('Failed to delete post, please try again', { Toast.show('Failed to delete post, please try again')
position: Toast.positions.TOP,
})
}, },
) )
} }

View file

@ -14,9 +14,8 @@ import {
import {pluralize} from '../../../lib/strings' import {pluralize} from '../../../lib/strings'
import {s, colors} from '../../lib/styles' import {s, colors} from '../../lib/styles'
import {getGradient} from '../../lib/asset-gen' import {getGradient} from '../../lib/asset-gen'
import {MagnifyingGlassIcon} from '../../lib/icons'
import {DropdownBtn, DropdownItem} from '../util/DropdownBtn' import {DropdownBtn, DropdownItem} from '../util/DropdownBtn'
import Toast from '../util/Toast' import * as Toast from '../util/Toast'
import {LoadingPlaceholder} from '../util/LoadingPlaceholder' import {LoadingPlaceholder} from '../util/LoadingPlaceholder'
import {RichText} from '../util/RichText' import {RichText} from '../util/RichText'
import {UserAvatar} from '../util/UserAvatar' import {UserAvatar} from '../util/UserAvatar'
@ -49,10 +48,6 @@ export const ProfileHeader = observer(function ProfileHeader({
`${view.myState.follow ? 'Following' : 'No longer following'} ${ `${view.myState.follow ? 'Following' : 'No longer following'} ${
view.displayName || view.handle view.displayName || view.handle
}`, }`,
{
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
},
) )
}, },
err => console.error('Failed to toggle follow', err), err => console.error('Failed to toggle follow', err),
@ -88,10 +83,7 @@ export const ProfileHeader = observer(function ProfileHeader({
did: store.me.did || '', did: store.me.did || '',
rkey: new AtUri(view.myState.member).rkey, rkey: new AtUri(view.myState.member).rkey,
}) })
Toast.show(`Scene left`, { Toast.show(`Scene left`)
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
} }
onRefreshAll() onRefreshAll()
} }

View file

@ -1,2 +0,0 @@
import Toast from 'react-native-root-toast'
export default Toast

View file

@ -1,62 +1,11 @@
/* import Toast from 'react-native-root-toast'
* Note: the dataSet properties are used to leverage custom CSS in public/index.html
*/
import React, {useState, useEffect} from 'react' export function show(message: string) {
// @ts-ignore no declarations available -prf Toast.show(message, {
import {Text, View} from 'react-native-web' duration: Toast.durations.LONG,
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' position: 50,
shadow: true,
interface ActiveToast { animation: true,
text: string hideOnPress: true,
}
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
// globals
// =
let globalSetActiveToast: GlobalSetActiveToast | undefined
let toastTimeout: NodeJS.Timeout | undefined
// components
// =
type ToastContainerProps = {}
const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
const [activeToast, setActiveToast] = useState<ActiveToast | undefined>()
useEffect(() => {
globalSetActiveToast = (t: ActiveToast | undefined) => {
setActiveToast(t)
}
}) })
return (
<>
{activeToast && (
<View dataSet={{'toast-container': 1}}>
<FontAwesomeIcon icon="check" size={24} />
<Text>{activeToast.text}</Text>
</View>
)}
</>
)
}
// exports
// =
export default {
show(text: string, _opts: any) {
console.log('TODO: toast', text)
if (toastTimeout) {
clearTimeout(toastTimeout)
}
globalSetActiveToast?.({text})
toastTimeout = setTimeout(() => {
globalSetActiveToast?.(undefined)
}, 2e3)
},
positions: {
TOP: 0,
},
durations: {
LONG: 0,
},
ToastContainer,
} }

View file

@ -47,6 +47,7 @@ export const Home = observer(function Home({
if (!visible) { if (!visible) {
return return
} }
if (hasSetup) { if (hasSetup) {
console.log('Updating home feed') console.log('Updating home feed')
defaultFeedView.update() defaultFeedView.update()

View file

@ -16,7 +16,7 @@ import {ErrorScreen} from '../com/util/ErrorScreen'
import {ErrorMessage} from '../com/util/ErrorMessage' import {ErrorMessage} from '../com/util/ErrorMessage'
import {EmptyState} from '../com/util/EmptyState' import {EmptyState} from '../com/util/EmptyState'
import {ViewHeader} from '../com/util/ViewHeader' import {ViewHeader} from '../com/util/ViewHeader'
import Toast from '../com/util/Toast' import * as Toast from '../com/util/Toast'
import {s, colors} from '../lib/styles' import {s, colors} from '../lib/styles'
const LOADING_ITEM = {_reactKey: '__loading__'} const LOADING_ITEM = {_reactKey: '__loading__'}
@ -78,10 +78,7 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
`You'll be able to invite them again if you change your mind.`, `You'll be able to invite them again if you change your mind.`,
async () => { async () => {
await uiState.members.removeMember(membership.did) await uiState.members.removeMember(membership.did)
Toast.show(`User removed`, { Toast.show(`User removed`)
duration: Toast.durations.LONG,
position: Toast.positions.TOP,
})
}, },
), ),
) )