diff --git a/src/components/ListCard.tsx b/src/components/ListCard.tsx index 0ed27cf50f..fd43636b0f 100644 --- a/src/components/ListCard.tsx +++ b/src/components/ListCard.tsx @@ -1,11 +1,18 @@ import React from 'react' import {View} from 'react-native' -import {AppBskyActorDefs, AppBskyGraphDefs, AtUri} from '@atproto/api' +import { + AppBskyActorDefs, + AppBskyGraphDefs, + AtUri, + moderateUserList, +} from '@atproto/api' import {Trans} from '@lingui/macro' import {useQueryClient} from '@tanstack/react-query' import {sanitizeHandle} from 'lib/strings/handles' +import {useModerationOpts} from 'state/preferences/moderation-opts' import {precacheList} from 'state/queries/feed' +import {useSession} from 'state/session' import {useTheme} from '#/alf' import {atoms as a} from '#/alf' import { @@ -43,6 +50,18 @@ type Props = { export function Default(props: Props) { const {view, showPinButton} = props + const {currentAccount} = useSession() + const moderationOpts = useModerationOpts() + + const moderation = moderationOpts + ? moderateUserList(view, moderationOpts) + : undefined + const modUi = moderation?.ui('contentView') + const isBlurred = Boolean(modUi?.blurs[0]) + + const isOwner = currentAccount?.did === view.creator.did + const isTitleHidden = !isOwner && isBlurred + return ( @@ -52,6 +71,7 @@ export function Default(props: Props) { title={view.name} creator={view.creator} purpose={view.purpose} + isHidden={isTitleHidden} /> {showPinButton && view.purpose === CURATELIST && ( @@ -89,18 +109,31 @@ export function TitleAndByline({ title, creator, purpose = CURATELIST, + isHidden, }: { title: string creator?: AppBskyActorDefs.ProfileViewBasic purpose?: AppBskyGraphDefs.ListView['purpose'] + isHidden?: boolean }) { const t = useTheme() return ( - - {title} - + {isHidden ? ( + + Hidden list + + ) : ( + + {title} + + )} + {creator && ( JSX.Element - style?: StyleProp - moderationOpts: ModerationOpts -}) => { - const {_} = useLingui() - const pal = usePalette('default') - const {currentAccount} = useSession() - - const isOwner = currentAccount?.did === list.creator.did - const isListHidden = list.labels?.findIndex(l => l.val === '!hide') !== -1 - const hideTitle = !isOwner && isListHidden - - const isModList = list.purpose === 'app.bsky.graph.defs#modlist' - const creatorHandle = sanitizeHandle(list.creator.handle, '@') - - const moderation = moderationOpts. - - const rkey = React.useMemo(() => { - try { - const urip = new AtUri(list.uri) - return urip.rkey - } catch { - return '' - } - }, [list]) - - const descriptionRichText = React.useMemo(() => { - if (list.description) { - return new RichText({ - text: list.description, - facets: list.descriptionFacets, - }) - } - return undefined - }, [list]) - - return ( - - - - - - - - - - - {hideTitle ? _(msg`Hidden list`) : sanitizeDisplayName(list.name)} - - - {isOwner ? ( - isModList ? ( - Moderation list by you - ) : ( - User list by you - ) - ) : isModList ? ( - Moderation list by {creatorHandle} - ) : ( - User list by {creatorHandle} - )} - - - {list.viewer?.muted ? ( - - Muted - - ) : null} - {list.viewer?.blocked ? ( - - Blocked - - ) : null} - - - {renderButton ? ( - {renderButton()} - ) : undefined} - - {descriptionRichText ? ( - - - - ) : undefined} - - ) -} - -function PillText({children}: {children: React.ReactNode}) { - const pal = usePalette('default') - return ( - - {children} - - ) -} - -const styles = StyleSheet.create({ - outer: { - borderTopWidth: StyleSheet.hairlineWidth, - paddingHorizontal: 6, - }, - outerNoBorder: { - borderTopWidth: 0, - }, - layout: { - flexDirection: 'row', - alignItems: 'center', - }, - layoutAvi: { - width: 54, - paddingLeft: 4, - paddingTop: 8, - paddingBottom: 10, - }, - avi: { - width: 40, - height: 40, - borderRadius: 20, - resizeMode: 'cover', - }, - layoutContent: { - flex: 1, - paddingRight: 10, - paddingTop: 10, - paddingBottom: 10, - }, - layoutButton: { - paddingRight: 10, - }, - details: { - paddingLeft: 54, - paddingRight: 10, - paddingBottom: 10, - }, - pill: { - borderRadius: 4, - paddingHorizontal: 6, - paddingVertical: 2, - }, - btn: { - paddingVertical: 7, - borderRadius: 50, - marginLeft: 6, - paddingHorizontal: 14, - }, -}) diff --git a/src/view/com/lists/MyLists.tsx b/src/view/com/lists/MyLists.tsx index 8059201ed4..b56fa6c75f 100644 --- a/src/view/com/lists/MyLists.tsx +++ b/src/view/com/lists/MyLists.tsx @@ -4,7 +4,6 @@ import { FlatList as RNFlatList, RefreshControl, StyleProp, - StyleSheet, View, ViewStyle, } from 'react-native' @@ -18,11 +17,13 @@ import {MyListsFilter, useMyListsQuery} from '#/state/queries/my-lists' import {useAnalytics} from 'lib/analytics/analytics' import {usePalette} from 'lib/hooks/usePalette' import {s} from 'lib/styles' +import {isWeb} from 'platform/detection' import {useModerationOpts} from 'state/preferences/moderation-opts' import {EmptyState} from 'view/com/util/EmptyState' +import {atoms as a, useTheme} from '#/alf' +import * as ListCard from '#/components/ListCard' import {ErrorMessage} from '../util/error/ErrorMessage' import {List} from '../util/List' -import {ListCard} from './ListCard' const LOADING = {_reactKey: '__loading__'} const EMPTY = {_reactKey: '__empty__'} @@ -42,6 +43,7 @@ export function MyLists({ testID?: string }) { const pal = usePalette('default') + const t = useTheme() const {track} = useAnalytics() const {_} = useLingui() const moderationOpts = useModerationOpts() @@ -87,7 +89,6 @@ export function MyLists({ if (item === EMPTY) { return ( ) } else if (item === LOADING) { return ( - + ) @@ -111,18 +111,18 @@ export function MyLists({ return renderItem ? ( renderItem(item, index) ) : ( - + + + ) }, - [error, onRefresh, renderItem, moderationOpts, _], + [renderItem, t.atoms.border_contrast_low, _, error, onRefresh], ) if (inline) { @@ -171,10 +171,3 @@ export function MyLists({ ) } } - -const styles = StyleSheet.create({ - item: { - paddingHorizontal: 18, - paddingVertical: 4, - }, -}) diff --git a/src/view/com/util/post-embeds/ListEmbed.tsx b/src/view/com/util/post-embeds/ListEmbed.tsx deleted file mode 100644 index fc5ad270fc..0000000000 --- a/src/view/com/util/post-embeds/ListEmbed.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' -import {usePalette} from 'lib/hooks/usePalette' -import {ListCard} from 'view/com/lists/ListCard' -import {AppBskyGraphDefs} from '@atproto/api' -import {s} from 'lib/styles' - -export function ListEmbed({ - item, - style, -}: { - item: AppBskyGraphDefs.ListView - style?: StyleProp -}) { - const pal = usePalette('default') - - return ( - - - - ) -} - -const styles = StyleSheet.create({ - container: { - borderRadius: 8, - }, - card: { - borderTopWidth: 0, - borderRadius: 8, - }, -}) diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx index 0462212fbd..a6e71bc56d 100644 --- a/src/view/com/util/post-embeds/index.tsx +++ b/src/view/com/util/post-embeds/index.tsx @@ -25,13 +25,13 @@ import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {usePalette} from 'lib/hooks/usePalette' import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' -import {atoms as a} from '#/alf' +import {atoms as a, useTheme} from '#/alf' +import * as ListCard from '#/components/ListCard' import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard' import {ContentHider} from '../../../../components/moderation/ContentHider' import {AutoSizedImage} from '../images/AutoSizedImage' import {ImageLayoutGrid} from '../images/ImageLayoutGrid' import {ExternalLinkEmbed} from './ExternalLinkEmbed' -import {ListEmbed} from './ListEmbed' import {MaybeQuoteEmbed} from './QuoteEmbed' type Embed = @@ -203,10 +203,19 @@ function MaybeListCard({view}: {view: AppBskyGraphDefs.ListView}) { const moderation = React.useMemo(() => { return moderationOpts ? moderateUserList(view, moderationOpts) : undefined }, [view, moderationOpts]) + const t = useTheme() return ( - + + + ) }