Clean up state, remove Portal edits
This commit is contained in:
@@ -73,7 +73,7 @@ export function createPortalGroup() {
|
||||
return null
|
||||
}
|
||||
|
||||
return {Provider, Outlet, Portal, Context}
|
||||
return {Provider, Outlet, Portal}
|
||||
}
|
||||
|
||||
const DefaultPortal = createPortalGroup()
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import {View} from 'react-native'
|
||||
import {Trans} from '@lingui/macro'
|
||||
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
createContext,
|
||||
type ReactNode,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {type ReactNode} from 'react'
|
||||
import {ScrollView, View} from 'react-native'
|
||||
import {
|
||||
useSafeAreaFrame,
|
||||
@@ -21,29 +15,6 @@ import {LockScroll} from '#/components/LockScroll'
|
||||
|
||||
const GUTTER = 24
|
||||
|
||||
export const Context = createContext({
|
||||
close: () => {},
|
||||
})
|
||||
|
||||
export function useAnnouncementDialogContext() {
|
||||
return useContext(Context)
|
||||
}
|
||||
|
||||
export function AnnouncementDialogOuter({children}: {children: ReactNode}) {
|
||||
const [open, setOpen] = useState(true)
|
||||
|
||||
const ctx = useMemo(
|
||||
() => ({
|
||||
close() {
|
||||
setOpen(false)
|
||||
},
|
||||
}),
|
||||
[setOpen],
|
||||
)
|
||||
|
||||
return <Context.Provider value={ctx}>{open && children}</Context.Provider>
|
||||
}
|
||||
|
||||
export function AnnouncementDialog({
|
||||
children,
|
||||
label,
|
||||
|
||||
@@ -4,37 +4,23 @@ import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {isAndroid} from '#/platform/detection'
|
||||
import {Nux} from '#/state/queries/nuxs'
|
||||
import {useA11y} from '#/state/a11y'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import {
|
||||
AnnouncementBadge,
|
||||
useAnnouncementState,
|
||||
} from '#/components/dialogs/BlockingAnnouncements/common'
|
||||
import {AnnouncementBadge} from '#/components/dialogs/BlockingAnnouncements/AnnouncementBadge'
|
||||
import {AnnouncementDialog} from '#/components/dialogs/BlockingAnnouncements/AnnouncementDialog'
|
||||
import {type AnnouncementState} from '#/components/dialogs/BlockingAnnouncements/useAnnouncementState'
|
||||
import {InlineLinkText, Link} from '#/components/Link'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {
|
||||
AnnouncementDialog,
|
||||
useAnnouncementDialogContext,
|
||||
} from '#/components/dialogs/BlockingAnnouncements/AnnouncementDialog'
|
||||
import {useA11y} from '#/state/a11y'
|
||||
|
||||
export function useLocalState() {
|
||||
return useAnnouncementState({
|
||||
id: Nux.BlockingAnnouncementPolicyUpdate20250801,
|
||||
})
|
||||
}
|
||||
|
||||
export function Announcement() {
|
||||
export function Announcement({state}: {state: AnnouncementState}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {complete} = useLocalState()
|
||||
const {close} = useAnnouncementDialogContext()
|
||||
const {screenReaderEnabled} = useA11y()
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
close()
|
||||
}, [close, complete])
|
||||
state.complete()
|
||||
}, [state])
|
||||
|
||||
const linkStyle = [a.text_md]
|
||||
const links = {
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -1,38 +1,34 @@
|
||||
import {useContext} from 'react'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {Nux} from '#/state/queries/nuxs'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {AnnouncementDialogOuter} from '#/components/dialogs/BlockingAnnouncements/AnnouncementDialog'
|
||||
import * as PolicyUpdate20250801 from '#/components/dialogs/BlockingAnnouncements/PolicyUpdate20250801'
|
||||
import {useAnnouncementState} from '#/components/dialogs/BlockingAnnouncements/useAnnouncementState'
|
||||
import {createPortalGroup} from '#/components/Portal'
|
||||
|
||||
const portalGroup = createPortalGroup()
|
||||
|
||||
export const Provider = portalGroup.Provider
|
||||
export const Portal = portalGroup.Portal
|
||||
|
||||
export function Outlet() {
|
||||
const {outlet} = useContext(portalGroup.Context)
|
||||
return outlet ? (
|
||||
<View style={[a.fixed, a.inset_0, {zIndex: 9999}]}>{outlet}</View>
|
||||
) : null
|
||||
}
|
||||
export const Outlet = portalGroup.Outlet
|
||||
|
||||
export function BlockingAnnouncements() {
|
||||
const policyUpdate20250801 = PolicyUpdate20250801.useLocalState()
|
||||
const state = useAnnouncementState({
|
||||
id: Nux.BlockingAnnouncementPolicyUpdate20250801,
|
||||
})
|
||||
|
||||
/*
|
||||
* See `window.clearNux` example in `/state/queries/nuxs` for a way to clear
|
||||
* NUX state for local testing and debugging.
|
||||
*/
|
||||
|
||||
if (policyUpdate20250801.completed) return null
|
||||
if (state.completed) return null
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<AnnouncementDialogOuter>
|
||||
<PolicyUpdate20250801.Announcement />
|
||||
</AnnouncementDialogOuter>
|
||||
<View style={[a.fixed, a.inset_0, {zIndex: 9999}]}>
|
||||
<PolicyUpdate20250801.Announcement state={state} />
|
||||
</View>
|
||||
</Portal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import {useMemo} from 'react'
|
||||
|
||||
import {type Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
|
||||
export type AnnouncementState = {
|
||||
completed: boolean
|
||||
complete: () => void
|
||||
}
|
||||
|
||||
export function useAnnouncementState({id}: {id: Nux}) {
|
||||
const nux = useNux(id)
|
||||
const {mutate: save, variables} = useSaveNux()
|
||||
return useMemo(() => {
|
||||
/**
|
||||
* Until data has loaded, assumed completed
|
||||
*/
|
||||
let completed = nux.status === 'ready' ? nux.nux?.completed === true : true
|
||||
|
||||
if (variables?.completed) {
|
||||
completed = true
|
||||
}
|
||||
|
||||
return {
|
||||
completed,
|
||||
complete() {
|
||||
save({
|
||||
id,
|
||||
completed: true,
|
||||
data: undefined,
|
||||
})
|
||||
},
|
||||
}
|
||||
}, [id, nux, save, variables])
|
||||
}
|
||||
Reference in New Issue
Block a user