Address starter pack opt-out review feedback
This commit is contained in:
@@ -703,6 +703,7 @@ export type Events = {
|
|||||||
}
|
}
|
||||||
'starterPack:removeUser': {
|
'starterPack:removeUser': {
|
||||||
starterPack?: string
|
starterPack?: string
|
||||||
|
context?: 'opt-out'
|
||||||
}
|
}
|
||||||
'starterPack:share': {
|
'starterPack:share': {
|
||||||
starterPack: string
|
starterPack: string
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Default as ProfileCard} from '#/components/ProfileCard'
|
import {Default as ProfileCard} from '#/components/ProfileCard'
|
||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_NATIVE, IS_WEB} from '#/env'
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
import {type app} from '#/lexicons'
|
import {type app} from '#/lexicons'
|
||||||
|
|
||||||
@@ -159,9 +160,14 @@ function OptedOutControls({
|
|||||||
canRemove: boolean
|
canRemove: boolean
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
|
const [isRemoved, setIsRemoved] = useState(false)
|
||||||
const {mutate: removeMembership, isPending} = useListMembershipRemoveMutation(
|
const {mutate: removeMembership, isPending} = useListMembershipRemoveMutation(
|
||||||
{
|
{
|
||||||
onSuccess: () => Toast.show(_(msg`Removed from starter pack`)),
|
onSuccess: () => {
|
||||||
|
setIsRemoved(true)
|
||||||
|
Toast.show(_(msg`Removed from starter pack`))
|
||||||
|
},
|
||||||
onError: error =>
|
onError: error =>
|
||||||
Toast.show(cleanError(error), {
|
Toast.show(cleanError(error), {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -169,6 +175,8 @@ function OptedOutControls({
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (isRemoved) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Admonition.Outer type="info" style={[a.mt_sm]}>
|
<Admonition.Outer type="info" style={[a.mt_sm]}>
|
||||||
<Admonition.Row style={[a.align_center]}>
|
<Admonition.Row style={[a.align_center]}>
|
||||||
@@ -183,13 +191,14 @@ function OptedOutControls({
|
|||||||
label={_(msg`Remove user from starter pack`)}
|
label={_(msg`Remove user from starter pack`)}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
disabled={isPending}
|
disabled={isPending}
|
||||||
onPress={() =>
|
onPress={() => {
|
||||||
|
ax.metric('starterPack:removeUser', {context: 'opt-out'})
|
||||||
removeMembership({
|
removeMembership({
|
||||||
listUri,
|
listUri,
|
||||||
actorDid: item.subject.did,
|
actorDid: item.subject.did,
|
||||||
membershipUri: item.uri,
|
membershipUri: item.uri,
|
||||||
})
|
})
|
||||||
}>
|
}}>
|
||||||
{isPending ? (
|
{isPending ? (
|
||||||
<ButtonIcon icon={Loader} />
|
<ButtonIcon icon={Loader} />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ function WizardListCard({
|
|||||||
avatar,
|
avatar,
|
||||||
included,
|
included,
|
||||||
disabled,
|
disabled,
|
||||||
|
subjectOptedOut,
|
||||||
moderationUi,
|
moderationUi,
|
||||||
}: {
|
}: {
|
||||||
type: 'user' | 'algo'
|
type: 'user' | 'algo'
|
||||||
@@ -48,6 +49,7 @@ function WizardListCard({
|
|||||||
avatar?: string
|
avatar?: string
|
||||||
included?: boolean
|
included?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
subjectOptedOut?: boolean
|
||||||
moderationUi: ModerationUI
|
moderationUi: ModerationUI
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -97,6 +99,11 @@ function WizardListCard({
|
|||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</Text>
|
</Text>
|
||||||
|
{subjectOptedOut ? (
|
||||||
|
<Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
|
||||||
|
<Trans>Opted out</Trans>
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
{btnType === 'checkbox' ? (
|
{btnType === 'checkbox' ? (
|
||||||
<Checkbox />
|
<Checkbox />
|
||||||
@@ -123,12 +130,14 @@ export function WizardProfileCard({
|
|||||||
dispatch,
|
dispatch,
|
||||||
profile,
|
profile,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
|
subjectOptedOut = false,
|
||||||
}: {
|
}: {
|
||||||
btnType: 'checkbox' | 'remove'
|
btnType: 'checkbox' | 'remove'
|
||||||
state: WizardState
|
state: WizardState
|
||||||
dispatch: (action: WizardAction) => void
|
dispatch: (action: WizardAction) => void
|
||||||
profile: bsky.profile.AnyProfileView
|
profile: bsky.profile.AnyProfileView
|
||||||
moderationOpts: ModerationOpts
|
moderationOpts: ModerationOpts
|
||||||
|
subjectOptedOut?: boolean
|
||||||
}) {
|
}) {
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
@@ -138,7 +147,9 @@ export function WizardProfileCard({
|
|||||||
const isTarget = profile.did === targetProfileDid
|
const isTarget = profile.did === targetProfileDid
|
||||||
const included = isTarget || state.profiles.some(p => p.did === profile.did)
|
const included = isTarget || state.profiles.some(p => p.did === profile.did)
|
||||||
const disabled =
|
const disabled =
|
||||||
isTarget || (!included && state.profiles.length >= STARTER_PACK_MAX_SIZE)
|
subjectOptedOut ||
|
||||||
|
isTarget ||
|
||||||
|
(!included && state.profiles.length >= STARTER_PACK_MAX_SIZE)
|
||||||
const moderationUi = moderateProfile(profile, moderationOpts).ui('avatar')
|
const moderationUi = moderateProfile(profile, moderationOpts).ui('avatar')
|
||||||
const displayName = profile.displayName
|
const displayName = profile.displayName
|
||||||
? sanitizeDisplayName(profile.displayName)
|
? sanitizeDisplayName(profile.displayName)
|
||||||
@@ -169,6 +180,7 @@ export function WizardProfileCard({
|
|||||||
avatar={profile.avatar}
|
avatar={profile.avatar}
|
||||||
included={included}
|
included={included}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
subjectOptedOut={subjectOptedOut}
|
||||||
moderationUi={moderationUi}
|
moderationUi={moderationUi}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -557,6 +557,11 @@ function OverflowMenu({
|
|||||||
starterPack: starterPack.uri,
|
starterPack: starterPack.uri,
|
||||||
action,
|
action,
|
||||||
})
|
})
|
||||||
|
Toast.show(
|
||||||
|
action === 'optOut'
|
||||||
|
? _(msg`Opted out of starter pack`)
|
||||||
|
: _(msg`Opt-out undone`),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
onError: error => {
|
onError: error => {
|
||||||
logger.error('Failed to update starter pack opt-out', {
|
logger.error('Failed to update starter pack opt-out', {
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ export function Provider({
|
|||||||
currentStep: 'Details',
|
currentStep: 'Details',
|
||||||
name: starterPack.record.name,
|
name: starterPack.record.name,
|
||||||
description: starterPack.record.description,
|
description: starterPack.record.description,
|
||||||
profiles: listItems?.map(i => i.subject) ?? [],
|
profiles:
|
||||||
|
listItems?.filter(i => !i.subjectOptedOut).map(i => i.subject) ?? [],
|
||||||
feeds: starterPack.feeds ?? [],
|
feeds: starterPack.feeds ?? [],
|
||||||
processing: false,
|
processing: false,
|
||||||
transitionDirection: 'Forward',
|
transitionDirection: 'Forward',
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ function keyExtractor(item: bsky.profile.AnyProfileView) {
|
|||||||
|
|
||||||
export function StepProfiles({
|
export function StepProfiles({
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
|
optedOutDids,
|
||||||
}: {
|
}: {
|
||||||
moderationOpts: ModerationOpts
|
moderationOpts: ModerationOpts
|
||||||
|
optedOutDids: Set<string>
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const [state, dispatch] = useWizardState()
|
const [state, dispatch] = useWizardState()
|
||||||
@@ -59,6 +61,7 @@ export function StepProfiles({
|
|||||||
state={state}
|
state={state}
|
||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
moderationOpts={moderationOpts}
|
moderationOpts={moderationOpts}
|
||||||
|
subjectOptedOut={optedOutDids.has(item.did)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -341,7 +341,16 @@ function WizardInner({
|
|||||||
{state.currentStep === 'Details' ? (
|
{state.currentStep === 'Details' ? (
|
||||||
<StepDetails />
|
<StepDetails />
|
||||||
) : state.currentStep === 'Profiles' ? (
|
) : state.currentStep === 'Profiles' ? (
|
||||||
<StepProfiles moderationOpts={moderationOpts} />
|
<StepProfiles
|
||||||
|
moderationOpts={moderationOpts}
|
||||||
|
optedOutDids={
|
||||||
|
new Set(
|
||||||
|
currentListItems
|
||||||
|
?.filter(item => item.subjectOptedOut)
|
||||||
|
.map(item => item.subject.did),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
) : state.currentStep === 'Feeds' ? (
|
) : state.currentStep === 'Feeds' ? (
|
||||||
<StepFeeds moderationOpts={moderationOpts} />
|
<StepFeeds moderationOpts={moderationOpts} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
Reference in New Issue
Block a user