[APP-635] Mutelists (#601)
* Add lists and profilelist screens * Implement lists screen and lists-list in profiles * Add empty states to the lists screen * Switch (mostly) from blocklists to mutelists * Rework: create a new moderation screen and move everything related under it * Fix moderation screen on desktop web * Tune the empty state code * Change content moderation modal to content filtering * Add CreateMuteList modal * Implement mutelist creation * Add lists listings * Add the ability to create new mutelists * Add 'add to list' tool * Satisfy the hashtag hyphen haters * Add update/delete/subscribe/unsubscribe to lists * Show which list caused a mute * Add list un/subscribe * Add the mute override when viewing a profile's posts * Update to latest backend * Add simulation tests and tune some behaviors * Fix lint * Bump deps * Fix list refresh after creation * Mute list subscriptions -> Mute lists
This commit is contained in:
parent
34d8fa5991
commit
ebcd633386
48 changed files with 2984 additions and 151 deletions
|
@ -32,7 +32,7 @@ export const ProfileCard = observer(
|
|||
noBorder?: boolean
|
||||
followers?: AppBskyActorDefs.ProfileView[] | undefined
|
||||
overrideModeration?: boolean
|
||||
renderButton?: () => JSX.Element
|
||||
renderButton?: (profile: AppBskyActorDefs.ProfileViewBasic) => JSX.Element
|
||||
}) => {
|
||||
const store = useStores()
|
||||
const pal = usePalette('default')
|
||||
|
@ -92,7 +92,7 @@ export const ProfileCard = observer(
|
|||
)}
|
||||
</View>
|
||||
{renderButton ? (
|
||||
<View style={styles.layoutButton}>{renderButton()}</View>
|
||||
<View style={styles.layoutButton}>{renderButton(profile)}</View>
|
||||
) : undefined}
|
||||
</View>
|
||||
{profile.description ? (
|
||||
|
|
|
@ -23,6 +23,7 @@ import {DropdownButton, DropdownItem} from '../util/forms/DropdownButton'
|
|||
import * as Toast from '../util/Toast'
|
||||
import {LoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {TextLink} from '../util/Link'
|
||||
import {RichText} from '../util/text/RichText'
|
||||
import {UserAvatar} from '../util/UserAvatar'
|
||||
import {UserBanner} from '../util/UserBanner'
|
||||
|
@ -30,6 +31,7 @@ import {ProfileHeaderWarnings} from '../util/moderation/ProfileHeaderWarnings'
|
|||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useAnalytics} from 'lib/analytics'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {listUriToHref} from 'lib/strings/url-helpers'
|
||||
import {isDesktopWeb, isNative} from 'platform/detection'
|
||||
import {FollowState} from 'state/models/cache/my-follows'
|
||||
import {shareUrl} from 'lib/sharing'
|
||||
|
@ -146,12 +148,21 @@ const ProfileHeaderLoaded = observer(
|
|||
navigation.push('ProfileFollows', {name: view.handle})
|
||||
}, [track, navigation, view])
|
||||
|
||||
const onPressShare = React.useCallback(async () => {
|
||||
const onPressShare = React.useCallback(() => {
|
||||
track('ProfileHeader:ShareButtonClicked')
|
||||
const url = toShareUrl(`/profile/${view.handle}`)
|
||||
shareUrl(url)
|
||||
}, [track, view])
|
||||
|
||||
const onPressAddRemoveLists = React.useCallback(() => {
|
||||
track('ProfileHeader:AddToListsButtonClicked')
|
||||
store.shell.openModal({
|
||||
name: 'list-add-remove-user',
|
||||
subject: view.did,
|
||||
displayName: view.displayName || view.handle,
|
||||
})
|
||||
}, [track, view, store])
|
||||
|
||||
const onPressMuteAccount = React.useCallback(async () => {
|
||||
track('ProfileHeader:MuteAccountButtonClicked')
|
||||
try {
|
||||
|
@ -233,6 +244,11 @@ const ProfileHeaderLoaded = observer(
|
|||
label: 'Share',
|
||||
onPress: onPressShare,
|
||||
},
|
||||
{
|
||||
testID: 'profileHeaderDropdownListAddRemoveBtn',
|
||||
label: 'Add to Lists',
|
||||
onPress: onPressAddRemoveLists,
|
||||
},
|
||||
]
|
||||
if (!isMe) {
|
||||
items.push({sep: true})
|
||||
|
@ -269,6 +285,7 @@ const ProfileHeaderLoaded = observer(
|
|||
onPressUnblockAccount,
|
||||
onPressBlockAccount,
|
||||
onPressReportAccount,
|
||||
onPressAddRemoveLists,
|
||||
])
|
||||
|
||||
const blockHide = !isMe && (view.viewer.blocking || view.viewer.blockedBy)
|
||||
|
@ -422,31 +439,42 @@ const ProfileHeaderLoaded = observer(
|
|||
{view.viewer.blocking ? (
|
||||
<View
|
||||
testID="profileHeaderBlockedNotice"
|
||||
style={[styles.moderationNotice, pal.view, pal.border]}>
|
||||
<FontAwesomeIcon icon="ban" style={[pal.text, s.mr5]} />
|
||||
<Text type="md" style={[s.mr2, pal.text]}>
|
||||
style={[styles.moderationNotice, pal.viewLight]}>
|
||||
<FontAwesomeIcon icon="ban" style={[pal.text]} />
|
||||
<Text type="lg-medium" style={pal.text}>
|
||||
Account blocked
|
||||
</Text>
|
||||
</View>
|
||||
) : view.viewer.muted ? (
|
||||
<View
|
||||
testID="profileHeaderMutedNotice"
|
||||
style={[styles.moderationNotice, pal.view, pal.border]}>
|
||||
style={[styles.moderationNotice, pal.viewLight]}>
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'eye-slash']}
|
||||
style={[pal.text, s.mr5]}
|
||||
style={[pal.text]}
|
||||
/>
|
||||
<Text type="md" style={[s.mr2, pal.text]}>
|
||||
Account muted
|
||||
<Text type="lg-medium" style={pal.text}>
|
||||
Account muted{' '}
|
||||
{view.viewer.mutedByList && (
|
||||
<Text type="lg-medium" style={pal.text}>
|
||||
by{' '}
|
||||
<TextLink
|
||||
type="lg-medium"
|
||||
style={pal.link}
|
||||
href={listUriToHref(view.viewer.mutedByList.uri)}
|
||||
text={view.viewer.mutedByList.name}
|
||||
/>
|
||||
</Text>
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
) : undefined}
|
||||
{view.viewer.blockedBy && (
|
||||
<View
|
||||
testID="profileHeaderBlockedNotice"
|
||||
style={[styles.moderationNotice, pal.view, pal.border]}>
|
||||
<FontAwesomeIcon icon="ban" style={[pal.text, s.mr5]} />
|
||||
<Text type="md" style={[s.mr2, pal.text]}>
|
||||
style={[styles.moderationNotice, pal.viewLight]}>
|
||||
<FontAwesomeIcon icon="ban" style={[pal.text]} />
|
||||
<Text type="lg-medium" style={pal.text}>
|
||||
This account has blocked you
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -595,10 +623,10 @@ const styles = StyleSheet.create({
|
|||
moderationNotice: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 14,
|
||||
gap: 8,
|
||||
},
|
||||
|
||||
br40: {borderRadius: 40},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue