Add modal state provider, replace usage except methods (#1833)
* Add modal state provider, replace usage except methods * Replace easy spots * Fix sticky spots * Replace final usages * Memorize context objects * Add more warnings
This commit is contained in:
parent
5eadadffbf
commit
f18b15241a
70 changed files with 634 additions and 498 deletions
|
@ -21,7 +21,6 @@ import {Text} from './text/Text'
|
|||
import {TypographyVariant} from 'lib/ThemeContext'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {router} from '../../../routes'
|
||||
import {useStores, RootStoreModel} from 'state/index'
|
||||
import {
|
||||
convertBskyAppUrlIfNeeded,
|
||||
isExternalUrl,
|
||||
|
@ -31,6 +30,7 @@ import {isAndroid, isWeb} from 'platform/detection'
|
|||
import {sanitizeUrl} from '@braintree/sanitize-url'
|
||||
import {PressableWithHover} from './PressableWithHover'
|
||||
import FixedTouchableHighlight from '../pager/FixedTouchableHighlight'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
type Event =
|
||||
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
||||
|
@ -60,17 +60,17 @@ export const Link = memo(function Link({
|
|||
anchorNoUnderline,
|
||||
...props
|
||||
}: Props) {
|
||||
const store = useStores()
|
||||
const {closeModal} = useModalControls()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const anchorHref = asAnchor ? sanitizeUrl(href) : undefined
|
||||
|
||||
const onPress = React.useCallback(
|
||||
(e?: Event) => {
|
||||
if (typeof href === 'string') {
|
||||
return onPressInner(store, navigation, sanitizeUrl(href), e)
|
||||
return onPressInner(closeModal, navigation, sanitizeUrl(href), e)
|
||||
}
|
||||
},
|
||||
[store, navigation, href],
|
||||
[closeModal, navigation, href],
|
||||
)
|
||||
|
||||
if (noFeedback) {
|
||||
|
@ -160,8 +160,8 @@ export const TextLink = memo(function TextLink({
|
|||
warnOnMismatchingLabel?: boolean
|
||||
} & TextProps) {
|
||||
const {...props} = useLinkProps({to: sanitizeUrl(href)})
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {openModal, closeModal} = useModalControls()
|
||||
|
||||
if (warnOnMismatchingLabel && typeof text !== 'string') {
|
||||
console.error('Unable to detect mismatching label')
|
||||
|
@ -174,7 +174,7 @@ export const TextLink = memo(function TextLink({
|
|||
linkRequiresWarning(href, typeof text === 'string' ? text : '')
|
||||
if (requiresWarning) {
|
||||
e?.preventDefault?.()
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'link-warning',
|
||||
text: typeof text === 'string' ? text : '',
|
||||
href,
|
||||
|
@ -185,9 +185,17 @@ export const TextLink = memo(function TextLink({
|
|||
// @ts-ignore function signature differs by platform -prf
|
||||
return onPress()
|
||||
}
|
||||
return onPressInner(store, navigation, sanitizeUrl(href), e)
|
||||
return onPressInner(closeModal, navigation, sanitizeUrl(href), e)
|
||||
},
|
||||
[onPress, store, navigation, href, text, warnOnMismatchingLabel],
|
||||
[
|
||||
onPress,
|
||||
closeModal,
|
||||
openModal,
|
||||
navigation,
|
||||
href,
|
||||
text,
|
||||
warnOnMismatchingLabel,
|
||||
],
|
||||
)
|
||||
const hrefAttrs = useMemo(() => {
|
||||
const isExternal = isExternalUrl(href)
|
||||
|
@ -285,7 +293,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
|
|||
// needed customizations
|
||||
// -prf
|
||||
function onPressInner(
|
||||
store: RootStoreModel,
|
||||
closeModal = () => {},
|
||||
navigation: NavigationProp,
|
||||
href: string,
|
||||
e?: Event,
|
||||
|
@ -318,7 +326,7 @@ function onPressInner(
|
|||
if (newTab || href.startsWith('http') || href.startsWith('mailto')) {
|
||||
Linking.openURL(href)
|
||||
} else {
|
||||
store.shell.closeModal() // close any active modals
|
||||
closeModal() // close any active modals
|
||||
|
||||
// @ts-ignore we're not able to type check on this one -prf
|
||||
navigation.dispatch(StackActions.push(...router.matchPath(href)))
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import {Pressable, StyleProp, ViewStyle} from 'react-native'
|
||||
import {useStores} from 'state/index'
|
||||
import {Link} from './Link'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {makeProfileLink} from 'lib/routes/links'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
interface UserPreviewLinkProps {
|
||||
did: string
|
||||
|
@ -13,7 +13,7 @@ interface UserPreviewLinkProps {
|
|||
export function UserPreviewLink(
|
||||
props: React.PropsWithChildren<UserPreviewLinkProps>,
|
||||
) {
|
||||
const store = useStores()
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
if (isWeb) {
|
||||
return (
|
||||
|
@ -29,7 +29,7 @@ export function UserPreviewLink(
|
|||
return (
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'profile-preview',
|
||||
did: props.did,
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react'
|
|||
import {StyleProp, View, ViewStyle} from 'react-native'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||
import {useStores} from 'state/index'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {shareUrl} from 'lib/sharing'
|
||||
import {
|
||||
|
@ -10,6 +9,7 @@ import {
|
|||
DropdownItem as NativeDropdownItem,
|
||||
} from './NativeDropdown'
|
||||
import {EventStopper} from '../EventStopper'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export function PostDropdownBtn({
|
||||
testID,
|
||||
|
@ -37,9 +37,9 @@ export function PostDropdownBtn({
|
|||
onDeletePost: () => void
|
||||
style?: StyleProp<ViewStyle>
|
||||
}) {
|
||||
const store = useStores()
|
||||
const theme = useTheme()
|
||||
const defaultCtrlColor = theme.palette.default.postCtrl
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
const dropdownItems: NativeDropdownItem[] = [
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ export function PostDropdownBtn({
|
|||
!isAuthor && {
|
||||
label: 'Report post',
|
||||
onPress() {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'report',
|
||||
uri: itemUri,
|
||||
cid: itemCid,
|
||||
|
@ -129,7 +129,7 @@ export function PostDropdownBtn({
|
|||
isAuthor && {
|
||||
label: 'Delete post',
|
||||
onPress() {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'confirm',
|
||||
title: 'Delete this post?',
|
||||
message: 'Are you sure? This can not be undone.',
|
||||
|
|
|
@ -6,7 +6,7 @@ import {ModerationUI} from '@atproto/api'
|
|||
import {Text} from '../text/Text'
|
||||
import {ShieldExclamation} from 'lib/icons'
|
||||
import {describeModerationCause} from 'lib/moderation'
|
||||
import {useStores} from 'state/index'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export function ContentHider({
|
||||
testID,
|
||||
|
@ -22,10 +22,10 @@ export function ContentHider({
|
|||
style?: StyleProp<ViewStyle>
|
||||
childContainerStyle?: StyleProp<ViewStyle>
|
||||
}>) {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const [override, setOverride] = React.useState(false)
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
if (!moderation.blur || (ignoreMute && moderation.cause?.type === 'muted')) {
|
||||
return (
|
||||
|
@ -43,7 +43,7 @@ export function ContentHider({
|
|||
if (!moderation.noOverride) {
|
||||
setOverride(v => !v)
|
||||
} else {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'content',
|
||||
moderation,
|
||||
|
@ -62,7 +62,7 @@ export function ContentHider({
|
|||
]}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'content',
|
||||
moderation,
|
||||
|
|
|
@ -5,7 +5,7 @@ import {Text} from '../text/Text'
|
|||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {ShieldExclamation} from 'lib/icons'
|
||||
import {describeModerationCause} from 'lib/moderation'
|
||||
import {useStores} from 'state/index'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export function PostAlerts({
|
||||
moderation,
|
||||
|
@ -15,8 +15,8 @@ export function PostAlerts({
|
|||
includeMute?: boolean
|
||||
style?: StyleProp<ViewStyle>
|
||||
}) {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
const shouldAlert = !!moderation.cause && moderation.alert
|
||||
if (!shouldAlert) {
|
||||
|
@ -27,7 +27,7 @@ export function PostAlerts({
|
|||
return (
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'content',
|
||||
moderation,
|
||||
|
|
|
@ -8,7 +8,7 @@ import {Text} from '../text/Text'
|
|||
import {addStyle} from 'lib/styles'
|
||||
import {describeModerationCause} from 'lib/moderation'
|
||||
import {ShieldExclamation} from 'lib/icons'
|
||||
import {useStores} from 'state/index'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
interface Props extends ComponentProps<typeof Link> {
|
||||
// testID?: string
|
||||
|
@ -25,10 +25,10 @@ export function PostHider({
|
|||
children,
|
||||
...props
|
||||
}: Props) {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const [override, setOverride] = React.useState(false)
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
if (!moderation.blur) {
|
||||
return (
|
||||
|
@ -63,7 +63,7 @@ export function PostHider({
|
|||
]}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'content',
|
||||
moderation,
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
describeModerationCause,
|
||||
getProfileModerationCauses,
|
||||
} from 'lib/moderation'
|
||||
import {useStores} from 'state/index'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export function ProfileHeaderAlerts({
|
||||
moderation,
|
||||
|
@ -17,8 +17,8 @@ export function ProfileHeaderAlerts({
|
|||
moderation: ProfileModeration
|
||||
style?: StyleProp<ViewStyle>
|
||||
}) {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
const causes = getProfileModerationCauses(moderation)
|
||||
if (!causes.length) {
|
||||
|
@ -34,7 +34,7 @@ export function ProfileHeaderAlerts({
|
|||
testID="profileHeaderAlert"
|
||||
key={desc.name}
|
||||
onPress={() => {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'content',
|
||||
moderation: {cause},
|
||||
|
|
|
@ -18,7 +18,7 @@ import {NavigationProp} from 'lib/routes/types'
|
|||
import {Text} from '../text/Text'
|
||||
import {Button} from '../forms/Button'
|
||||
import {describeModerationCause} from 'lib/moderation'
|
||||
import {useStores} from 'state/index'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export function ScreenHider({
|
||||
testID,
|
||||
|
@ -34,12 +34,12 @@ export function ScreenHider({
|
|||
style?: StyleProp<ViewStyle>
|
||||
containerStyle?: StyleProp<ViewStyle>
|
||||
}>) {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
const palInverted = usePalette('inverted')
|
||||
const [override, setOverride] = React.useState(false)
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
if (!moderation.blur || override) {
|
||||
return (
|
||||
|
@ -72,7 +72,7 @@ export function ScreenHider({
|
|||
.{' '}
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'account',
|
||||
moderation,
|
||||
|
|
|
@ -16,6 +16,7 @@ import {useStores} from 'state/index'
|
|||
import {RepostButton} from './RepostButton'
|
||||
import {Haptics} from 'lib/haptics'
|
||||
import {HITSLOP_10, HITSLOP_20} from 'lib/constants'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
interface PostCtrlsOpts {
|
||||
itemUri: string
|
||||
|
@ -51,6 +52,7 @@ interface PostCtrlsOpts {
|
|||
export function PostCtrls(opts: PostCtrlsOpts) {
|
||||
const store = useStores()
|
||||
const theme = useTheme()
|
||||
const {closeModal} = useModalControls()
|
||||
const defaultCtrlColor = React.useMemo(
|
||||
() => ({
|
||||
color: theme.palette.default.postCtrl,
|
||||
|
@ -58,17 +60,17 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
|||
[theme],
|
||||
) as StyleProp<ViewStyle>
|
||||
const onRepost = useCallback(() => {
|
||||
store.shell.closeModal()
|
||||
closeModal()
|
||||
if (!opts.isReposted) {
|
||||
Haptics.default()
|
||||
opts.onPressToggleRepost().catch(_e => undefined)
|
||||
} else {
|
||||
opts.onPressToggleRepost().catch(_e => undefined)
|
||||
}
|
||||
}, [opts, store.shell])
|
||||
}, [opts, closeModal])
|
||||
|
||||
const onQuote = useCallback(() => {
|
||||
store.shell.closeModal()
|
||||
closeModal()
|
||||
store.shell.openComposer({
|
||||
quote: {
|
||||
uri: opts.itemUri,
|
||||
|
@ -86,6 +88,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
|||
opts.itemUri,
|
||||
opts.text,
|
||||
store.shell,
|
||||
closeModal,
|
||||
])
|
||||
|
||||
const onPressToggleLikeWrapper = async () => {
|
||||
|
|
|
@ -5,8 +5,8 @@ import {s, colors} from 'lib/styles'
|
|||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {Text} from '../text/Text'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
import {useStores} from 'state/index'
|
||||
import {HITSLOP_10, HITSLOP_20} from 'lib/constants'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
interface Props {
|
||||
isReposted: boolean
|
||||
|
@ -23,8 +23,8 @@ export const RepostButton = ({
|
|||
onRepost,
|
||||
onQuote,
|
||||
}: Props) => {
|
||||
const store = useStores()
|
||||
const theme = useTheme()
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
const defaultControlColor = React.useMemo(
|
||||
() => ({
|
||||
|
@ -34,13 +34,13 @@ export const RepostButton = ({
|
|||
)
|
||||
|
||||
const onPressToggleRepostWrapper = useCallback(() => {
|
||||
store.shell.openModal({
|
||||
openModal({
|
||||
name: 'repost',
|
||||
onRepost: onRepost,
|
||||
onQuote: onQuote,
|
||||
isReposted,
|
||||
})
|
||||
}, [onRepost, onQuote, isReposted, store.shell])
|
||||
}, [onRepost, onQuote, isReposted, openModal])
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue