Add blocking announcement dialog feature
This commit is contained in:
@@ -22,6 +22,7 @@ export const Context = createContext<DialogContextProps>({
|
||||
disableDrag: false,
|
||||
setDisableDrag: () => {},
|
||||
isWithinDialog: false,
|
||||
preventDismiss: false,
|
||||
})
|
||||
|
||||
export function useDialogContext() {
|
||||
|
||||
@@ -54,6 +54,7 @@ export function Outer({
|
||||
control,
|
||||
onClose,
|
||||
nativeOptions,
|
||||
preventDismiss,
|
||||
testID,
|
||||
}: React.PropsWithChildren<DialogOuterProps>) {
|
||||
const themeName = useThemeName()
|
||||
@@ -165,6 +166,7 @@ export function Outer({
|
||||
cornerRadius={20}
|
||||
backgroundColor={t.atoms.bg.backgroundColor}
|
||||
{...nativeOptions}
|
||||
preventDismiss={preventDismiss ?? nativeOptions?.preventDismiss}
|
||||
onSnapPointChange={onSnapPointChange}
|
||||
onStateChange={onStateChange}
|
||||
disableDrag={disableDrag}>
|
||||
|
||||
@@ -40,6 +40,7 @@ export function Outer({
|
||||
control,
|
||||
onClose,
|
||||
webOptions,
|
||||
preventDismiss,
|
||||
}: React.PropsWithChildren<DialogOuterProps>) {
|
||||
const {_} = useLingui()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -52,7 +53,9 @@ export function Outer({
|
||||
}, [setIsOpen, setDialogIsOpen, control.id])
|
||||
|
||||
const close = React.useCallback<DialogControlProps['close']>(
|
||||
cb => {
|
||||
(cb, force) => {
|
||||
if (preventDismiss && !force) return
|
||||
|
||||
setDialogIsOpen(control.id, false)
|
||||
setIsOpen(false)
|
||||
|
||||
@@ -72,7 +75,7 @@ export function Outer({
|
||||
|
||||
onClose?.()
|
||||
},
|
||||
[control.id, onClose, setDialogIsOpen],
|
||||
[control.id, onClose, setDialogIsOpen, preventDismiss],
|
||||
)
|
||||
|
||||
const handleBackgroundPress = React.useCallback(async () => {
|
||||
@@ -96,8 +99,9 @@ export function Outer({
|
||||
disableDrag: false,
|
||||
setDisableDrag: () => {},
|
||||
isWithinDialog: true,
|
||||
preventDismiss: preventDismiss ?? false,
|
||||
}),
|
||||
[close],
|
||||
[close, preventDismiss],
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -239,7 +243,10 @@ export const InnerFlatList = React.forwardRef<
|
||||
|
||||
export function Close() {
|
||||
const {_} = useLingui()
|
||||
const {close} = React.useContext(Context)
|
||||
const {close, preventDismiss} = React.useContext(Context)
|
||||
|
||||
if (preventDismiss) return null
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React from 'react'
|
||||
import type {
|
||||
AccessibilityProps,
|
||||
GestureResponderEvent,
|
||||
ScrollViewProps,
|
||||
import {
|
||||
type AccessibilityProps,
|
||||
type GestureResponderEvent,
|
||||
type ScrollViewProps,
|
||||
} from 'react-native'
|
||||
import {ViewStyle} from 'react-native'
|
||||
import {StyleProp} from 'react-native'
|
||||
import {type ViewStyle} from 'react-native'
|
||||
import {type StyleProp} from 'react-native'
|
||||
import type React from 'react'
|
||||
|
||||
import {ViewStyleProp} from '#/alf'
|
||||
import {BottomSheetViewProps} from '../../../modules/bottom-sheet'
|
||||
import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types'
|
||||
import {type ViewStyleProp} from '#/alf'
|
||||
import {type BottomSheetViewProps} from '../../../modules/bottom-sheet'
|
||||
import {type BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types'
|
||||
|
||||
type A11yProps = Required<AccessibilityProps>
|
||||
|
||||
@@ -26,7 +26,7 @@ export type DialogControlRefProps = {
|
||||
open: (
|
||||
options?: DialogControlOpenOptions & Partial<GestureResponderEvent>,
|
||||
) => void
|
||||
close: (callback?: () => void) => void
|
||||
close: (callback?: () => void, force?: boolean) => void
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,6 +46,7 @@ export type DialogContextProps = {
|
||||
setDisableDrag: React.Dispatch<React.SetStateAction<boolean>>
|
||||
// in the event that the hook is used outside of a dialog
|
||||
isWithinDialog: boolean
|
||||
preventDismiss: boolean
|
||||
}
|
||||
|
||||
export type DialogControlOpenOptions = {
|
||||
@@ -62,6 +63,7 @@ export type DialogOuterProps = {
|
||||
control: DialogControlProps
|
||||
onClose?: () => void
|
||||
nativeOptions?: Omit<BottomSheetViewProps, 'children'>
|
||||
preventDismiss?: boolean
|
||||
webOptions?: {
|
||||
alignCenter?: boolean
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
import {type ReactNode, useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import {Span, Text} from '#/components/Typography'
|
||||
|
||||
export function BlockingAlertDialog() {
|
||||
const {enabled} = usePolicyUpdate20250801()
|
||||
|
||||
return (
|
||||
<>
|
||||
{enabled && (
|
||||
<BlockingAnnouncementDialogOuter>
|
||||
<PolicyUpdate20250801 />
|
||||
</BlockingAnnouncementDialogOuter>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function useForceClose() {
|
||||
const {close} = Dialog.useDialogContext()
|
||||
return useCallback(
|
||||
(cb?: () => void) => {
|
||||
close(cb, true)
|
||||
},
|
||||
[close],
|
||||
)
|
||||
}
|
||||
|
||||
export function BlockingAnnouncementDialogOuter({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode
|
||||
}) {
|
||||
const {signinDialogControl: control} = useGlobalDialogsControlContext()
|
||||
|
||||
Dialog.useAutoOpen(control, 1e3)
|
||||
|
||||
return (
|
||||
<Dialog.Outer preventDismiss control={control}>
|
||||
<Dialog.Handle />
|
||||
{children}
|
||||
</Dialog.Outer>
|
||||
)
|
||||
}
|
||||
|
||||
export function AnnouncementBadge() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<View style={[a.align_start]}>
|
||||
<View
|
||||
style={[
|
||||
a.pl_md,
|
||||
a.pr_lg,
|
||||
a.py_sm,
|
||||
a.rounded_full,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.gap_xs,
|
||||
{
|
||||
backgroundColor: t.palette.primary_25,
|
||||
},
|
||||
]}>
|
||||
<Logo fill={t.palette.primary_600} width={14} />
|
||||
<Text
|
||||
style={[
|
||||
a.font_bold,
|
||||
{
|
||||
color: t.palette.primary_600,
|
||||
},
|
||||
]}>
|
||||
<Trans>Announcement</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function usePolicyUpdate20250801() {
|
||||
return {
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
function PolicyUpdate20250801() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const forceClose = useForceClose()
|
||||
|
||||
const linkStyle = [a.text_md]
|
||||
const links = {
|
||||
terms: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Terms of Service`),
|
||||
style: linkStyle,
|
||||
},
|
||||
privacy: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Privacy Policy`),
|
||||
style: linkStyle,
|
||||
},
|
||||
copyright: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Copyright Policy`),
|
||||
style: linkStyle,
|
||||
},
|
||||
guidelines: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Community Guidelines`),
|
||||
style: linkStyle,
|
||||
},
|
||||
blog: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Our blog post`),
|
||||
style: linkStyle,
|
||||
},
|
||||
}
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
forceClose(() => {
|
||||
console.log('closed')
|
||||
})
|
||||
}, [forceClose])
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Sign in to Bluesky or create a new account`)}
|
||||
style={[web({maxWidth: 420})]}>
|
||||
<View style={[a.align_start, a.gap_xl]}>
|
||||
<AnnouncementBadge />
|
||||
|
||||
<View style={[a.gap_sm]}>
|
||||
<Text style={[a.text_2xl, a.font_bold, a.leading_snug]}>
|
||||
<Trans>Hey there 👋</Trans>
|
||||
</Text>
|
||||
<Text emoji style={[a.leading_snug, a.text_md]}>
|
||||
<Trans>
|
||||
We’re updating our{' '}
|
||||
<InlineLinkText {...links.terms}>Terms of Service</InlineLinkText>
|
||||
,{' '}
|
||||
<InlineLinkText {...links.privacy}>Privacy Policy</InlineLinkText>
|
||||
, and{' '}
|
||||
<InlineLinkText {...links.copyright}>
|
||||
Copyright Policy
|
||||
</InlineLinkText>
|
||||
, <Span style={[]}>effective September 1st, 2025.</Span>
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text style={[a.leading_snug, a.text_md]}>
|
||||
<Trans>
|
||||
We're also updating our{' '}
|
||||
<InlineLinkText {...links.guidelines}>
|
||||
Community Guidelines
|
||||
</InlineLinkText>
|
||||
, <Span style={[]}>and we want your input!</Span> These new
|
||||
guidelines will take effect on{' '}
|
||||
<Span style={[]}>October 1st, 2025.</Span>
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text emoji style={[a.leading_snug, a.text_md]}>
|
||||
<Trans>
|
||||
Learn more about these changes and how to share your thoughts with
|
||||
us by{' '}
|
||||
<InlineLinkText {...links.blog}>
|
||||
reading our blog post.
|
||||
</InlineLinkText>
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={[a.w_full, a.gap_md]}>
|
||||
<Button
|
||||
label={_(msg`Continue`)}
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={handleClose}>
|
||||
<ButtonText>
|
||||
<Trans>Continue</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
|
||||
<Text
|
||||
style={[
|
||||
a.leading_snug,
|
||||
a.text_sm,
|
||||
a.italic,
|
||||
t.atoms.text_contrast_medium,
|
||||
]}>
|
||||
<Trans>
|
||||
By clicking "Continue" you acknowledge that you understand and
|
||||
agree to these updates.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {Nux} from '#/state/queries/nuxs'
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {
|
||||
AnnouncementBadge,
|
||||
useAnnouncementState,
|
||||
useForceClose,
|
||||
} from '#/components/dialogs/BlockingAnnouncements/common'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import {Span, Text} from '#/components/Typography'
|
||||
|
||||
export function useLocalState() {
|
||||
return useAnnouncementState({
|
||||
id: Nux.BlockingAnnouncementPolicyUpdate20250801,
|
||||
})
|
||||
}
|
||||
|
||||
export function Announcement() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const forceClose = useForceClose()
|
||||
const {complete} = useLocalState()
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
forceClose(() => complete())
|
||||
}, [forceClose, complete])
|
||||
|
||||
const linkStyle = [a.text_md]
|
||||
const links = {
|
||||
terms: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Terms of Service`),
|
||||
style: linkStyle,
|
||||
},
|
||||
privacy: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Privacy Policy`),
|
||||
style: linkStyle,
|
||||
},
|
||||
copyright: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Copyright Policy`),
|
||||
style: linkStyle,
|
||||
},
|
||||
guidelines: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Community Guidelines`),
|
||||
style: linkStyle,
|
||||
},
|
||||
blog: {
|
||||
overridePresentation: true,
|
||||
to: `https://bsky.social/about/support`,
|
||||
label: _(msg`Our blog post`),
|
||||
style: linkStyle,
|
||||
},
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`We’re updating our policies`)}
|
||||
style={[web({maxWidth: 420})]}>
|
||||
<View style={[a.align_start, a.gap_xl]}>
|
||||
<AnnouncementBadge />
|
||||
|
||||
<View style={[a.gap_sm]}>
|
||||
<Text style={[a.text_2xl, a.font_bold, a.leading_snug]}>
|
||||
<Trans>Hey there 👋</Trans>
|
||||
</Text>
|
||||
<Text emoji style={[a.leading_snug, a.text_md]}>
|
||||
<Trans>
|
||||
We’re updating our{' '}
|
||||
<InlineLinkText {...links.terms}>Terms of Service</InlineLinkText>
|
||||
,{' '}
|
||||
<InlineLinkText {...links.privacy}>Privacy Policy</InlineLinkText>
|
||||
, and{' '}
|
||||
<InlineLinkText {...links.copyright}>
|
||||
Copyright Policy
|
||||
</InlineLinkText>
|
||||
, <Span style={[]}>effective September 1st, 2025.</Span>
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text style={[a.leading_snug, a.text_md]}>
|
||||
<Trans>
|
||||
We're also updating our{' '}
|
||||
<InlineLinkText {...links.guidelines}>
|
||||
Community Guidelines
|
||||
</InlineLinkText>
|
||||
, <Span style={[]}>and we want your input!</Span> These new
|
||||
guidelines will take effect on{' '}
|
||||
<Span style={[]}>October 1st, 2025.</Span>
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text emoji style={[a.leading_snug, a.text_md]}>
|
||||
<Trans>
|
||||
Learn more about these changes and how to share your thoughts with
|
||||
us by{' '}
|
||||
<InlineLinkText {...links.blog}>
|
||||
reading our blog post.
|
||||
</InlineLinkText>
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={[a.w_full, a.gap_md]}>
|
||||
<Button
|
||||
label={_(msg`Continue`)}
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={handleClose}>
|
||||
<ButtonText>
|
||||
<Trans>Continue</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
|
||||
<Text
|
||||
style={[
|
||||
a.leading_snug,
|
||||
a.text_sm,
|
||||
a.italic,
|
||||
t.atoms.text_contrast_medium,
|
||||
]}>
|
||||
<Trans>
|
||||
By clicking "Continue" you acknowledge that you understand and
|
||||
agree to these updates.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import {type ReactNode, useCallback, useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {Trans} from '@lingui/macro'
|
||||
|
||||
import {type Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function useForceClose() {
|
||||
const {close} = Dialog.useDialogContext()
|
||||
return useCallback(
|
||||
(cb?: () => void) => {
|
||||
close(cb, true)
|
||||
},
|
||||
[close],
|
||||
)
|
||||
}
|
||||
|
||||
export function useAnnouncementState({id}: {id: Nux}) {
|
||||
const nux = useNux(id)
|
||||
const {mutate: save, variables} = useSaveNux()
|
||||
const optimisticallyCompleted = !!variables?.completed
|
||||
return useMemo(
|
||||
() => ({
|
||||
/**
|
||||
* Until data has loaded, assumed completed
|
||||
*/
|
||||
completed:
|
||||
optimisticallyCompleted || nux.status === 'ready'
|
||||
? nux.nux?.completed === true
|
||||
: true,
|
||||
complete() {
|
||||
save({
|
||||
id,
|
||||
completed: true,
|
||||
data: undefined,
|
||||
})
|
||||
},
|
||||
}),
|
||||
[id, nux, save, optimisticallyCompleted],
|
||||
)
|
||||
}
|
||||
|
||||
export function BlockingAnnouncementDialogOuter({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode
|
||||
}) {
|
||||
const {signinDialogControl: control} = useGlobalDialogsControlContext()
|
||||
|
||||
Dialog.useAutoOpen(control, 1e3)
|
||||
|
||||
return (
|
||||
<Dialog.Outer preventDismiss control={control}>
|
||||
<Dialog.Handle />
|
||||
{children}
|
||||
</Dialog.Outer>
|
||||
)
|
||||
}
|
||||
|
||||
export function AnnouncementBadge() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<View style={[a.align_start]}>
|
||||
<View
|
||||
style={[
|
||||
a.pl_md,
|
||||
a.pr_lg,
|
||||
a.py_sm,
|
||||
a.rounded_full,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.gap_xs,
|
||||
{
|
||||
backgroundColor: t.palette.primary_25,
|
||||
},
|
||||
]}>
|
||||
<Logo fill={t.palette.primary_600} width={14} />
|
||||
<Text
|
||||
style={[
|
||||
a.font_bold,
|
||||
{
|
||||
color: t.palette.primary_600,
|
||||
},
|
||||
]}>
|
||||
<Trans>Announcement</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import {BlockingAnnouncementDialogOuter} from '#/components/dialogs/BlockingAnnouncements/common'
|
||||
import * as PolicyUpdate20250801 from '#/components/dialogs/BlockingAnnouncements/PolicyUpdate20250801'
|
||||
|
||||
export function BlockingAnnouncements() {
|
||||
const policyUpdate20250801 = PolicyUpdate20250801.useLocalState()
|
||||
|
||||
/*
|
||||
* See `window.clearNux` example in `/state/queries/nuxs` for a way to clear
|
||||
* NUX state for local testing and debugging.
|
||||
*/
|
||||
|
||||
return (
|
||||
<>
|
||||
{!policyUpdate20250801.completed && (
|
||||
<BlockingAnnouncementDialogOuter>
|
||||
<PolicyUpdate20250801.Announcement />
|
||||
</BlockingAnnouncementDialogOuter>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,11 @@ export enum Nux {
|
||||
ActivitySubscriptions = 'ActivitySubscriptions',
|
||||
AgeAssuranceDismissibleNotice = 'AgeAssuranceDismissibleNotice',
|
||||
AgeAssuranceDismissibleFeedBanner = 'AgeAssuranceDismissibleFeedBanner',
|
||||
|
||||
/*
|
||||
* Blocking announcements. New IDs are required for each new announcement.
|
||||
*/
|
||||
BlockingAnnouncementPolicyUpdate20250801 = 'BlockingAnnouncementPolicyUpdate20250801',
|
||||
}
|
||||
|
||||
export const nuxNames = new Set(Object.values(Nux))
|
||||
@@ -38,6 +43,10 @@ export type AppNux = BaseNux<
|
||||
id: Nux.AgeAssuranceDismissibleFeedBanner
|
||||
data: undefined
|
||||
}
|
||||
| {
|
||||
id: Nux.BlockingAnnouncementPolicyUpdate20250801
|
||||
data: undefined
|
||||
}
|
||||
>
|
||||
|
||||
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||
@@ -47,4 +56,5 @@ export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||
[Nux.ActivitySubscriptions]: undefined,
|
||||
[Nux.AgeAssuranceDismissibleNotice]: undefined,
|
||||
[Nux.AgeAssuranceDismissibleFeedBanner]: undefined,
|
||||
[Nux.BlockingAnnouncementPolicyUpdate20250801]: undefined,
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
||||
import {atoms as a, select, useTheme} from '#/alf'
|
||||
import {setSystemUITheme} from '#/alf/util/systemUI'
|
||||
import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
|
||||
import {BlockingAnnouncements} from '#/components/dialogs/BlockingAnnouncements'
|
||||
import {EmailDialog} from '#/components/dialogs/EmailDialog'
|
||||
import {InAppBrowserConsentDialog} from '#/components/dialogs/InAppBrowserConsent'
|
||||
import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
|
||||
@@ -155,6 +156,7 @@ function ShellInner() {
|
||||
<ModalsContainer />
|
||||
<MutedWordsDialog />
|
||||
<SigninDialog />
|
||||
<BlockingAnnouncements />
|
||||
<EmailDialog />
|
||||
<AgeAssuranceRedirectDialog />
|
||||
<InAppBrowserConsentDialog />
|
||||
|
||||
@@ -18,6 +18,7 @@ import {ModalsContainer} from '#/view/com/modals/Modal'
|
||||
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
||||
import {atoms as a, select, useTheme} from '#/alf'
|
||||
import {AgeAssuranceRedirectDialog} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
|
||||
import {BlockingAnnouncements} from '#/components/dialogs/BlockingAnnouncements'
|
||||
import {EmailDialog} from '#/components/dialogs/EmailDialog'
|
||||
import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
|
||||
import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
|
||||
@@ -70,6 +71,7 @@ function ShellInner() {
|
||||
<ModalsContainer />
|
||||
<MutedWordsDialog />
|
||||
<SigninDialog />
|
||||
<BlockingAnnouncements />
|
||||
<EmailDialog />
|
||||
<AgeAssuranceRedirectDialog />
|
||||
<LinkWarningDialog />
|
||||
|
||||
Reference in New Issue
Block a user