Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a61dbf7707 | |||
| ef72710399 | |||
| dbe1925a96 | |||
| 8b27043051 | |||
| 5166f670e7 | |||
| 7a6a30277d | |||
| 2671f1d85e | |||
| 6b91559a79 | |||
| b9503b7df3 | |||
| c535ca82a8 | |||
| a0c43b0dcf | |||
| 19f903b143 | |||
| c8008da312 | |||
| 0d066eb1a1 | |||
| 507b6f307f | |||
| b9b89a8147 | |||
| 57646523fb |
+1
-1
@@ -73,7 +73,7 @@
|
||||
"icons:optimize": "svgo -f ./assets/icons"
|
||||
},
|
||||
"dependencies": {
|
||||
"@atproto/api": "^0.18.11",
|
||||
"@atproto/api": "^0.18.13",
|
||||
"@bitdrift/react-native": "^0.6.8",
|
||||
"@braintree/sanitize-url": "^6.0.2",
|
||||
"@bsky.app/alf": "^0.1.6",
|
||||
|
||||
@@ -389,6 +389,7 @@ let Card = ({
|
||||
{data && moderationOpts ? (
|
||||
status.isActive ? (
|
||||
<LiveStatus
|
||||
status={status}
|
||||
profile={data}
|
||||
embed={status.embed}
|
||||
padding="lg"
|
||||
|
||||
@@ -3,6 +3,7 @@ import {createContext, useContext, useMemo, useState} from 'react'
|
||||
import {type AgeAssuranceRedirectDialogState} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {type Screen} from '#/components/dialogs/EmailDialog/types'
|
||||
import {type ReportSubject} from '#/components/moderation/ReportDialog'
|
||||
|
||||
type Control = Dialog.DialogControlProps
|
||||
|
||||
@@ -24,6 +25,7 @@ type ControlsContext = {
|
||||
share?: boolean
|
||||
}>
|
||||
ageAssuranceRedirectDialogControl: StatefulControl<AgeAssuranceRedirectDialogState>
|
||||
reportDialogControl: StatefulControl<{subject: ReportSubject}>
|
||||
}
|
||||
|
||||
const ControlsContext = createContext<ControlsContext | null>(null)
|
||||
@@ -51,6 +53,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
}>()
|
||||
const ageAssuranceRedirectDialogControl =
|
||||
useStatefulDialogControl<AgeAssuranceRedirectDialogState>()
|
||||
const reportDialogControl = useStatefulDialogControl<{
|
||||
subject: ReportSubject
|
||||
}>()
|
||||
|
||||
const ctx = useMemo<ControlsContext>(
|
||||
() => ({
|
||||
@@ -60,6 +65,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
emailDialogControl,
|
||||
linkWarningDialogControl,
|
||||
ageAssuranceRedirectDialogControl,
|
||||
reportDialogControl,
|
||||
}),
|
||||
[
|
||||
mutedWordsDialogControl,
|
||||
@@ -68,6 +74,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
emailDialogControl,
|
||||
linkWarningDialogControl,
|
||||
ageAssuranceRedirectDialogControl,
|
||||
reportDialogControl,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
import {useCallback, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type AppBskyActorDefs, ToolsOzoneReportDefs} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useMutation} from '@tanstack/react-query'
|
||||
|
||||
import {BLUESKY_MOD_SERVICE_HEADERS} from '#/lib/constants'
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {atoms as a, web} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function GoLiveDisabledDialog({
|
||||
control,
|
||||
status,
|
||||
}: {
|
||||
control: Dialog.DialogControlProps
|
||||
status: AppBskyActorDefs.StatusView
|
||||
}) {
|
||||
return (
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle />
|
||||
<DialogInner control={control} status={status} />
|
||||
</Dialog.Outer>
|
||||
)
|
||||
}
|
||||
|
||||
export function DialogInner({
|
||||
control,
|
||||
status,
|
||||
}: {
|
||||
control: Dialog.DialogControlProps
|
||||
status: AppBskyActorDefs.StatusView
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const agent = useAgent()
|
||||
const [details, setDetails] = useState('')
|
||||
|
||||
const {mutate, isPending} = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!agent.session?.did) {
|
||||
throw new Error('Not logged in')
|
||||
}
|
||||
if (!status.uri || !status.cid) {
|
||||
throw new Error('Status is missing uri or cid')
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
logger.info('Submitting go live appeal', {
|
||||
details,
|
||||
})
|
||||
} else {
|
||||
await agent.createModerationReport(
|
||||
{
|
||||
reasonType: ToolsOzoneReportDefs.REASONAPPEAL,
|
||||
subject: {
|
||||
$type: 'com.atproto.repo.strongRef',
|
||||
uri: status.uri,
|
||||
cid: status.cid,
|
||||
},
|
||||
reason: details,
|
||||
},
|
||||
{
|
||||
encoding: 'application/json',
|
||||
headers: BLUESKY_MOD_SERVICE_HEADERS,
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
Toast.show(_(msg`Failed to submit appeal, please try again.`), {
|
||||
type: 'error',
|
||||
})
|
||||
},
|
||||
onSuccess: () => {
|
||||
control.close()
|
||||
Toast.show(_(msg({message: 'Appeal submitted', context: 'toast'})), {
|
||||
type: 'success',
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = useCallback(() => mutate(), [mutate])
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Appeal livestream suspension`)}
|
||||
style={[web({maxWidth: 400})]}>
|
||||
<View style={[a.gap_lg]}>
|
||||
<View style={[a.gap_md]}>
|
||||
<Text
|
||||
style={[
|
||||
a.flex_1,
|
||||
a.text_2xl,
|
||||
a.font_semi_bold,
|
||||
a.leading_snug,
|
||||
a.pr_4xl,
|
||||
]}>
|
||||
<Trans>Going live is currently disabled for your account</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_md, a.leading_snug]}>
|
||||
<Trans>
|
||||
You are currently blocked from using the Go Live feature. To
|
||||
appeal this moderation decision, please submit the form below.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_md, a.leading_snug]}>
|
||||
<Trans>
|
||||
This appeal will be sent to Bluesky's moderation service.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_md]}>
|
||||
<Dialog.Input
|
||||
label={_(msg`Text input field`)}
|
||||
placeholder={_(
|
||||
msg`Please explain why you think your Go Live access was incorrectly disabled.`,
|
||||
)}
|
||||
value={details}
|
||||
onChangeText={setDetails}
|
||||
autoFocus={true}
|
||||
numberOfLines={3}
|
||||
multiline
|
||||
maxLength={300}
|
||||
/>
|
||||
<Button
|
||||
testID="submitBtn"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={onSubmit}
|
||||
label={_(msg`Submit`)}>
|
||||
<ButtonText>{_(msg`Submit`)}</ButtonText>
|
||||
{isPending && <ButtonIcon icon={Loader} />}
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
}
|
||||
@@ -17,6 +17,9 @@ import {unstableCacheProfileView} from '#/state/queries/profile'
|
||||
import {android, atoms as a, platform, tokens, useTheme, web} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo'
|
||||
import {createStaticClick, SimpleInlineLinkText} from '#/components/Link'
|
||||
import {useGlobalReportDialogControl} from '#/components/moderation/ReportDialog'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
@@ -28,6 +31,7 @@ export function LiveStatusDialog({
|
||||
control,
|
||||
profile,
|
||||
embed,
|
||||
status,
|
||||
}: {
|
||||
control: Dialog.DialogControlProps
|
||||
profile: bsky.profile.AnyProfileView
|
||||
@@ -38,7 +42,12 @@ export function LiveStatusDialog({
|
||||
return (
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
<Dialog.Handle difference={!!embed.external.thumb} />
|
||||
<DialogInner profile={profile} embed={embed} navigation={navigation} />
|
||||
<DialogInner
|
||||
status={status}
|
||||
profile={profile}
|
||||
embed={embed}
|
||||
navigation={navigation}
|
||||
/>
|
||||
</Dialog.Outer>
|
||||
)
|
||||
}
|
||||
@@ -47,10 +56,12 @@ function DialogInner({
|
||||
profile,
|
||||
embed,
|
||||
navigation,
|
||||
status,
|
||||
}: {
|
||||
profile: bsky.profile.AnyProfileView
|
||||
embed: AppBskyEmbedExternal.View
|
||||
navigation: NavigationProp
|
||||
status: AppBskyActorDefs.StatusView
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const control = Dialog.useDialogContext()
|
||||
@@ -69,6 +80,7 @@ function DialogInner({
|
||||
contentContainerStyle={[a.pt_0, a.px_0]}
|
||||
style={[web({maxWidth: 420}), a.overflow_hidden]}>
|
||||
<LiveStatus
|
||||
status={status}
|
||||
profile={profile}
|
||||
embed={embed}
|
||||
onPressOpenProfile={onPressOpenProfile}
|
||||
@@ -79,11 +91,13 @@ function DialogInner({
|
||||
}
|
||||
|
||||
export function LiveStatus({
|
||||
status,
|
||||
profile,
|
||||
embed,
|
||||
padding = 'xl',
|
||||
onPressOpenProfile,
|
||||
}: {
|
||||
status: AppBskyActorDefs.StatusView
|
||||
profile: bsky.profile.AnyProfileView
|
||||
embed: AppBskyEmbedExternal.View
|
||||
padding?: 'lg' | 'xl'
|
||||
@@ -94,6 +108,8 @@ export function LiveStatus({
|
||||
const queryClient = useQueryClient()
|
||||
const openLink = useOpenLink()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const reportDialogControl = useGlobalReportDialogControl()
|
||||
const dialogContext = Dialog.useDialogContext()
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -205,15 +221,43 @@ export function LiveStatus({
|
||||
</Button>
|
||||
</ProfileCard.Header>
|
||||
)}
|
||||
<Text
|
||||
<View
|
||||
style={[
|
||||
a.w_full,
|
||||
a.text_center,
|
||||
t.atoms.text_contrast_low,
|
||||
a.text_sm,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.justify_between,
|
||||
a.flex_1,
|
||||
a.pt_sm,
|
||||
]}>
|
||||
<Trans>Live feature is in beta testing</Trans>
|
||||
</Text>
|
||||
<View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
|
||||
<CircleInfoIcon size="sm" fill={t.atoms.text_contrast_low.color} />
|
||||
<Text style={[t.atoms.text_contrast_low, a.text_sm]}>
|
||||
<Trans>Live feature is in beta</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
{status && (
|
||||
<SimpleInlineLinkText
|
||||
label={_(msg`Report this livestream`)}
|
||||
{...createStaticClick(() => {
|
||||
function open() {
|
||||
reportDialogControl.open({
|
||||
subject: {
|
||||
...status,
|
||||
$type: 'app.bsky.actor.defs#statusView',
|
||||
},
|
||||
})
|
||||
}
|
||||
if (dialogContext.isWithinDialog) {
|
||||
dialogContext.close(open)
|
||||
} else {
|
||||
open()
|
||||
}
|
||||
})}
|
||||
style={[a.text_sm, a.underline, t.atoms.text_contrast_medium]}>
|
||||
<Trans>Report</Trans>
|
||||
</SimpleInlineLinkText>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -70,6 +70,7 @@ export function useSubmitReportMutation() {
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'status':
|
||||
case 'post':
|
||||
case 'list':
|
||||
case 'feed':
|
||||
|
||||
@@ -3,6 +3,8 @@ import {
|
||||
ToolsOzoneReportDefs as OzoneReportDefs,
|
||||
} from '@atproto/api'
|
||||
|
||||
import {type ParsedReportSubject} from '#/components/moderation/ReportDialog/types'
|
||||
|
||||
export const DMCA_LINK = 'https://bsky.social/about/support/copyright'
|
||||
export const SUPPORT_PAGE = 'https://bsky.social/about/support'
|
||||
|
||||
@@ -112,3 +114,10 @@ export const BSKY_LABELER_ONLY_REPORT_REASONS: Set<OzoneReportDefs.ReasonType> =
|
||||
OzoneReportDefs.REASONCHILDSAFETYOTHER,
|
||||
OzoneReportDefs.REASONVIOLENCEEXTREMISTCONTENT,
|
||||
])
|
||||
|
||||
/**
|
||||
* Set of _parsed_ subject types that should only be sent to Bluesky's
|
||||
* moderation service.
|
||||
*/
|
||||
export const BSKY_LABELER_ONLY_SUBJECT_TYPES: Set<ParsedReportSubject['type']> =
|
||||
new Set(['convoMessage', 'status'])
|
||||
|
||||
@@ -14,6 +14,12 @@ export function useCopyForSubject(subject: ParsedReportSubject) {
|
||||
subtitle: _(msg`Why should this user be reviewed?`),
|
||||
}
|
||||
}
|
||||
case 'status': {
|
||||
return {
|
||||
title: _(msg`Report this livestream`),
|
||||
subtitle: _(msg`Why should this livestream be reviewed?`),
|
||||
}
|
||||
}
|
||||
case 'post': {
|
||||
return {
|
||||
title: _(msg`Report this post`),
|
||||
|
||||
@@ -16,6 +16,7 @@ import {atoms as a, useGutters, useTheme} from '#/alf'
|
||||
import * as Admonition from '#/components/Admonition'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
||||
import {useDelayedLoading} from '#/components/hooks/useDelayedLoading'
|
||||
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Retry} from '#/components/icons/ArrowRotate'
|
||||
import {
|
||||
@@ -31,6 +32,7 @@ import {Text} from '#/components/Typography'
|
||||
import {useSubmitReportMutation} from './action'
|
||||
import {
|
||||
BSKY_LABELER_ONLY_REPORT_REASONS,
|
||||
BSKY_LABELER_ONLY_SUBJECT_TYPES,
|
||||
NEW_TO_OLD_REASONS_MAP,
|
||||
SUPPORT_PAGE,
|
||||
} from './const'
|
||||
@@ -44,17 +46,27 @@ import {
|
||||
useReportOptions,
|
||||
} from './utils/useReportOptions'
|
||||
|
||||
export {type ReportSubject} from './types'
|
||||
export {useDialogControl as useReportDialogControl} from '#/components/Dialog'
|
||||
|
||||
export function useGlobalReportDialogControl() {
|
||||
return useGlobalDialogsControlContext().reportDialogControl
|
||||
}
|
||||
|
||||
const logger = Logger.create(Logger.Context.ReportDialog)
|
||||
|
||||
export function GlobalReportDialog() {
|
||||
const {value, control} = useGlobalReportDialogControl()
|
||||
return <ReportDialog control={control} subject={value?.subject} />
|
||||
}
|
||||
|
||||
export function ReportDialog(
|
||||
props: Omit<ReportDialogProps, 'subject'> & {
|
||||
subject: ReportSubject
|
||||
subject?: ReportSubject
|
||||
},
|
||||
) {
|
||||
const subject = React.useMemo(
|
||||
() => parseReportSubject(props.subject),
|
||||
() => (props.subject ? parseReportSubject(props.subject) : undefined),
|
||||
[props.subject],
|
||||
)
|
||||
const onClose = React.useCallback(() => {
|
||||
@@ -116,8 +128,10 @@ function Inner(props: ReportDialogProps) {
|
||||
const isBskyOnlyReason = state?.selectedOption?.reason
|
||||
? BSKY_LABELER_ONLY_REPORT_REASONS.has(state.selectedOption.reason)
|
||||
: false
|
||||
// some subjects (chats) only go to Bluesky
|
||||
const isBskyOnlySubject = props.subject.type === 'convoMessage'
|
||||
// some subjects ONLY go to Bluesky
|
||||
const isBskyOnlySubject = BSKY_LABELER_ONLY_SUBJECT_TYPES.has(
|
||||
props.subject.type,
|
||||
)
|
||||
|
||||
/**
|
||||
* Labelers that support this `subject` and its NSID collection
|
||||
@@ -824,12 +838,7 @@ function LabelerCard({
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
style={[
|
||||
a.text_sm,
|
||||
,
|
||||
a.leading_snug,
|
||||
t.atoms.text_contrast_medium,
|
||||
]}>
|
||||
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||
<Trans>By {sanitizeHandle(labeler.creator.handle, '@')}</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -18,6 +18,7 @@ export type ReportSubject =
|
||||
| $Typed<AppBskyActorDefs.ProfileViewBasic>
|
||||
| $Typed<AppBskyActorDefs.ProfileView>
|
||||
| $Typed<AppBskyActorDefs.ProfileViewDetailed>
|
||||
| $Typed<AppBskyActorDefs.StatusView>
|
||||
| $Typed<AppBskyGraphDefs.ListView>
|
||||
| $Typed<AppBskyFeedDefs.GeneratorView>
|
||||
| $Typed<AppBskyGraphDefs.StarterPackView>
|
||||
@@ -38,6 +39,12 @@ export type ParsedReportSubject =
|
||||
quote: boolean
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: 'status'
|
||||
uri: string
|
||||
cid: string
|
||||
nsid: string
|
||||
}
|
||||
| {
|
||||
type: 'list'
|
||||
uri: string
|
||||
|
||||
@@ -33,6 +33,14 @@ export function parseReportSubject(
|
||||
did: subject.did,
|
||||
nsid: 'app.bsky.actor.profile',
|
||||
}
|
||||
} else if (AppBskyActorDefs.isStatusView(subject)) {
|
||||
if (!subject.uri || !subject.cid) return
|
||||
return {
|
||||
type: 'status',
|
||||
uri: subject.uri,
|
||||
cid: subject.cid,
|
||||
nsid: 'app.bsky.actor.status',
|
||||
}
|
||||
} else if (AppBskyGraphDefs.isListView(subject)) {
|
||||
return {
|
||||
type: 'list',
|
||||
|
||||
+21
-8
@@ -19,15 +19,27 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
|
||||
return useMemo(() => {
|
||||
tick! // revalidate every minute
|
||||
|
||||
if (
|
||||
shadowed &&
|
||||
'status' in shadowed &&
|
||||
shadowed.status &&
|
||||
validateStatus(shadowed.did, shadowed.status, config) &&
|
||||
isStatusStillActive(shadowed.status.expiresAt)
|
||||
) {
|
||||
if (shadowed && 'status' in shadowed && shadowed.status) {
|
||||
const isValid = validateStatus(shadowed.did, shadowed.status, config)
|
||||
const isDisabled = shadowed.status.isDisabled || false
|
||||
const isActive = isStatusStillActive(shadowed.status.expiresAt)
|
||||
if (isValid && !isDisabled && isActive) {
|
||||
return {
|
||||
uri: shadowed.status.uri,
|
||||
cid: shadowed.status.cid,
|
||||
isDisabled: false,
|
||||
isActive: true,
|
||||
status: 'app.bsky.actor.status#live',
|
||||
embed: shadowed.status.embed as $Typed<AppBskyEmbedExternal.View>, // temp_isStatusValid asserts this
|
||||
expiresAt: shadowed.status.expiresAt!, // isStatusStillActive asserts this
|
||||
record: shadowed.status.record,
|
||||
} satisfies AppBskyActorDefs.StatusView
|
||||
}
|
||||
return {
|
||||
isActive: true,
|
||||
uri: shadowed.status.uri,
|
||||
cid: shadowed.status.cid,
|
||||
isDisabled,
|
||||
isActive: false,
|
||||
status: 'app.bsky.actor.status#live',
|
||||
embed: shadowed.status.embed as $Typed<AppBskyEmbedExternal.View>, // temp_isStatusValid asserts this
|
||||
expiresAt: shadowed.status.expiresAt!, // isStatusStillActive asserts this
|
||||
@@ -36,6 +48,7 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
|
||||
} else {
|
||||
return {
|
||||
status: '',
|
||||
isDisabled: false,
|
||||
isActive: false,
|
||||
record: {},
|
||||
} satisfies AppBskyActorDefs.StatusView
|
||||
|
||||
@@ -49,6 +49,7 @@ import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/
|
||||
import {StarterPack} from '#/components/icons/StarterPack'
|
||||
import {EditLiveDialog} from '#/components/live/EditLiveDialog'
|
||||
import {GoLiveDialog} from '#/components/live/GoLiveDialog'
|
||||
import {GoLiveDisabledDialog} from '#/components/live/GoLiveDisabledDialog'
|
||||
import * as Menu from '#/components/Menu'
|
||||
import {
|
||||
ReportDialog,
|
||||
@@ -79,6 +80,7 @@ let ProfileMenu = ({
|
||||
const [devModeEnabled] = useDevMode()
|
||||
const verification = useFullVerificationState({profile})
|
||||
const canGoLive = useCanGoLive(currentAccount?.did)
|
||||
const status = useActorStatus(profile)
|
||||
|
||||
const [queueMute, queueUnmute] = useProfileMuteMutationQueue(profile)
|
||||
const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
|
||||
@@ -90,6 +92,7 @@ let ProfileMenu = ({
|
||||
const blockPromptControl = Prompt.usePromptControl()
|
||||
const loggedOutWarningPromptControl = Prompt.usePromptControl()
|
||||
const goLiveDialogControl = useDialogControl()
|
||||
const goLiveDisabledDialogControl = useDialogControl()
|
||||
const addToStarterPacksDialogControl = useDialogControl()
|
||||
|
||||
const showLoggedOutWarning = React.useMemo(() => {
|
||||
@@ -220,8 +223,6 @@ let ProfileMenu = ({
|
||||
return v.issuer === currentAccount?.did
|
||||
}) ?? []
|
||||
|
||||
const status = useActorStatus(profile)
|
||||
|
||||
return (
|
||||
<EventStopper onKeyDown={false}>
|
||||
<Menu.Root>
|
||||
@@ -330,13 +331,21 @@ let ProfileMenu = ({
|
||||
<Menu.Item
|
||||
testID="profileHeaderDropdownListAddRemoveBtn"
|
||||
label={
|
||||
status.isActive
|
||||
? _(msg`Edit live status`)
|
||||
: _(msg`Go live`)
|
||||
status.isDisabled
|
||||
? _(msg`Go live (disabled)`)
|
||||
: status.isActive
|
||||
? _(msg`Edit live status`)
|
||||
: _(msg`Go live`)
|
||||
}
|
||||
onPress={goLiveDialogControl.open}>
|
||||
onPress={
|
||||
status.isDisabled
|
||||
? goLiveDisabledDialogControl.open
|
||||
: goLiveDialogControl.open
|
||||
}>
|
||||
<Menu.ItemText>
|
||||
{status.isActive ? (
|
||||
{status.isDisabled ? (
|
||||
<Trans>Go live (disabled)</Trans>
|
||||
) : status.isActive ? (
|
||||
<Trans>Edit live status</Trans>
|
||||
) : (
|
||||
<Trans>Go live</Trans>
|
||||
@@ -517,7 +526,12 @@ let ProfileMenu = ({
|
||||
verifications={currentAccountVerifications}
|
||||
/>
|
||||
|
||||
{status.isActive ? (
|
||||
{status.isDisabled ? (
|
||||
<GoLiveDisabledDialog
|
||||
control={goLiveDisabledDialogControl}
|
||||
status={status}
|
||||
/>
|
||||
) : status.isActive ? (
|
||||
<EditLiveDialog
|
||||
control={goLiveDialogControl}
|
||||
status={status}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
|
||||
import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
|
||||
import {NuxDialogs} from '#/components/dialogs/nuxs'
|
||||
import {SigninDialog} from '#/components/dialogs/Signin'
|
||||
import {GlobalReportDialog} from '#/components/moderation/ReportDialog'
|
||||
import {
|
||||
Outlet as PolicyUpdateOverlayPortalOutlet,
|
||||
usePolicyUpdateContext,
|
||||
@@ -117,6 +118,7 @@ function ShellInner() {
|
||||
<LinkWarningDialog />
|
||||
<Lightbox />
|
||||
<NuxDialogs />
|
||||
<GlobalReportDialog />
|
||||
|
||||
{/* Until policy update has been completed by the user, don't render anything that is portaled */}
|
||||
{policyUpdateState.completed && (
|
||||
|
||||
@@ -24,6 +24,7 @@ import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
|
||||
import {NuxDialogs} from '#/components/dialogs/nuxs'
|
||||
import {SigninDialog} from '#/components/dialogs/Signin'
|
||||
import {useWelcomeModal} from '#/components/hooks/useWelcomeModal'
|
||||
import {GlobalReportDialog} from '#/components/moderation/ReportDialog'
|
||||
import {
|
||||
Outlet as PolicyUpdateOverlayPortalOutlet,
|
||||
usePolicyUpdateContext,
|
||||
@@ -73,6 +74,7 @@ function ShellInner() {
|
||||
<LinkWarningDialog />
|
||||
<Lightbox />
|
||||
<NuxDialogs />
|
||||
<GlobalReportDialog />
|
||||
|
||||
{welcomeModalControl.isOpen && (
|
||||
<WelcomeModal control={welcomeModalControl} />
|
||||
|
||||
@@ -82,12 +82,12 @@
|
||||
"@atproto/xrpc" "^0.7.6"
|
||||
"@atproto/xrpc-server" "^0.10.0"
|
||||
|
||||
"@atproto/api@^0.18.11":
|
||||
version "0.18.11"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.11.tgz#38b8bacecaae4c24bc29bd98b34f270d8be675b3"
|
||||
integrity sha512-YhgyL4rOBFOIs+e/8s5S+EjwM3T5q65IKh30ZoIrWcQS/2uteiIzg1xB+iXmexZq4Cwug0NLfRUJDViDK/ut0w==
|
||||
"@atproto/api@^0.18.13":
|
||||
version "0.18.13"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.13.tgz#63eee310e6715752eb87748323cf9ab57dd91e4b"
|
||||
integrity sha512-CULZ01pSJDltLS/Gc9MMrhFzB6OM3ezyZw7KoeLT/sBfwgA1ddA4mWdTh7DIRosPRigXtA05bnoiCutZbQDo+Q==
|
||||
dependencies:
|
||||
"@atproto/common-web" "^0.4.10"
|
||||
"@atproto/common-web" "^0.4.11"
|
||||
"@atproto/lexicon" "^0.6.0"
|
||||
"@atproto/syntax" "^0.4.2"
|
||||
"@atproto/xrpc" "^0.7.7"
|
||||
@@ -208,13 +208,13 @@
|
||||
pino-http "^8.2.1"
|
||||
typed-emitter "^2.1.0"
|
||||
|
||||
"@atproto/common-web@^0.4.10":
|
||||
version "0.4.10"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.10.tgz#3d29df4dc3ea8f5c149161209f55e146f27867c1"
|
||||
integrity sha512-TLDZSgSKzT8ZgOrBrTGK87J1CXve9TEuY6NVVUBRkOMzRRtQzpFb9/ih5WVS/hnaWVvE30CfuyaetRoma+WKNw==
|
||||
"@atproto/common-web@^0.4.11":
|
||||
version "0.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.11.tgz#eb41dc02c1ea4221388630e193d181fb098186e0"
|
||||
integrity sha512-VHejNmSABU8/03VrQ3e36AmT5U3UIeio+qSUqCrO1oNgrJcWfGy1rpj0FVtUugWF8Un29+yzkukzWGZfXL70rQ==
|
||||
dependencies:
|
||||
"@atproto/lex-data" "0.0.6"
|
||||
"@atproto/lex-json" "0.0.6"
|
||||
"@atproto/lex-data" "0.0.7"
|
||||
"@atproto/lex-json" "0.0.7"
|
||||
zod "^3.23.8"
|
||||
|
||||
"@atproto/common-web@^0.4.4", "@atproto/common-web@^0.4.6":
|
||||
@@ -415,10 +415,10 @@
|
||||
uint8arrays "3.0.0"
|
||||
unicode-segmenter "^0.14.0"
|
||||
|
||||
"@atproto/lex-data@0.0.6":
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lex-data/-/lex-data-0.0.6.tgz#280d05ec9579ab091dc4a8b696ebbeddcb8ee37d"
|
||||
integrity sha512-MBNB4ghRJQzuXK1zlUPljpPbQcF1LZ5dzxy274KqPt4p3uPuRw0mHjgcCoWzRUNBQC685WMQR4IN9DHtsnG57A==
|
||||
"@atproto/lex-data@0.0.7":
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lex-data/-/lex-data-0.0.7.tgz#6aa87423f6d47849bec8ff3ca0b00ce93964adc8"
|
||||
integrity sha512-W/Q5o9o7n2Sv3UywckChu01X5lwQUtaiiOkGJLnRsdkQTyC6813nPgY+p2sG7NwwM+82lu+FUV9fE/Ul3VqaJw==
|
||||
dependencies:
|
||||
"@atproto/syntax" "0.4.2"
|
||||
multiformats "^9.9.0"
|
||||
@@ -451,12 +451,12 @@
|
||||
"@atproto/lex-data" "0.0.3"
|
||||
tslib "^2.8.1"
|
||||
|
||||
"@atproto/lex-json@0.0.6":
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lex-json/-/lex-json-0.0.6.tgz#50618efb1cc11708b3897de14dcd3bd9c06e064d"
|
||||
integrity sha512-EILnN5cditPvf+PCNjXt7reMuzjugxAL1fpSzmzJbEMGMUwxOf5pPWxRsaA/M3Boip4NQZ+6DVrPOGUMlnqceg==
|
||||
"@atproto/lex-json@0.0.7":
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lex-json/-/lex-json-0.0.7.tgz#c06e1fc3e06d739bbb74694f5d846055bed37866"
|
||||
integrity sha512-bjNPD5M/MhLfjNM7tcxuls80UgXpHqxdOxDXEUouAtZQV/nIDhGjmNUvKxOmOgnDsiZRnT2g5y3onrnjH3a44g==
|
||||
dependencies:
|
||||
"@atproto/lex-data" "0.0.6"
|
||||
"@atproto/lex-data" "0.0.7"
|
||||
tslib "^2.8.1"
|
||||
|
||||
"@atproto/lex-resolver@0.0.5":
|
||||
|
||||
Reference in New Issue
Block a user