diff --git a/src/components/ModerationServiceCard/Card.tsx b/src/components/ModerationServiceCard/Card.tsx index c86b4cdc7b..47f3b8708f 100644 --- a/src/components/ModerationServiceCard/Card.tsx +++ b/src/components/ModerationServiceCard/Card.tsx @@ -5,9 +5,10 @@ import {Trans} from '@lingui/macro' import {atoms as a, useTheme, ViewStyleProp, flatten} from '#/alf' import {Text} from '#/components/Typography' import {RichText} from '#/components/RichText' -import {RaisingHande4Finger_Stroke2_Corner0_Rounded as RaisingHand} from '#/components/icons/RaisingHand' +import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '../icons/Chevron' import {UserAvatar} from '#/view/com/util/UserAvatar' import {sanitizeHandle} from '#/lib/strings/handles' +import {pluralize} from '#/lib/strings/helpers' export function Outer({ children, @@ -64,10 +65,12 @@ export function Content({ title, description, handle, + likeCount, }: { title: string description?: string handle: string + likeCount?: number }) { const t = useTheme() @@ -85,9 +88,23 @@ export function Content({ )} + + {typeof likeCount === 'number' && ( + + + Liked by {likeCount || 0} {pluralize(likeCount || 0, 'user')} + + + )} - + ) } diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx index 1113dff282..3e604933ce 100644 --- a/src/view/com/profile/ProfileHeader.tsx +++ b/src/view/com/profile/ProfileHeader.tsx @@ -56,14 +56,10 @@ import {Shadow} from '#/state/cache/types' import {useRequireAuth} from '#/state/session' import {LabelsOnMe} from '../util/moderation/LabelsOnMe' import {useProfileShadow} from 'state/cache/profile-shadow' -import * as ModerationServiceCard from '#/components/ModerationServiceCard' -import {getModerationServiceTitle} from '#/lib/moderation' import {useOpenGlobalDialog} from '#/components/dialogs' import {ReportDialog} from '#/components/dialogs/ReportDialog' import {NEW_REPORT_DIALOG_ENABLED} from '#/lib/build-flags' -import {useTheme} from '#/alf' - let ProfileHeaderLoading = (_props: {}): React.ReactNode => { const pal = usePalette('default') return ( @@ -99,7 +95,6 @@ let ProfileHeader = ({ hideBackButton = false, isPlaceholderProfile, }: Props): React.ReactNode => { - const t = useTheme() const profile: Shadow = useProfileShadow(profileUnshadowed) const pal = usePalette('default') @@ -637,31 +632,6 @@ let ProfileHeader = ({ {isMe && ( )} - - ( - - {ctx => ( - - - - )} - - )} - /> {showSuggestedFollows && ( diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index abafff8148..4e3586a463 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -10,7 +10,7 @@ import { import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' -import {CenteredView} from '../com/util/Views' +import {CenteredView, ScrollView} from '../com/util/Views' import {ListRef} from '../com/util/List' import {ScreenHider} from 'view/com/util/moderation/ScreenHider' import {Feed} from 'view/com/posts/Feed' @@ -49,6 +49,10 @@ import {usePalette} from 'lib/hooks/usePalette' import {isNative} from '#/platform/detection' import {isInvalidHandle} from '#/lib/strings/handles' +import {useTheme, atoms as a} from '#/alf' +import * as ModerationServiceCard from '#/components/ModerationServiceCard' +import {RaisingHande4Finger_Stroke2_Corner0_Rounded as RaisingHand} from '#/components/icons/RaisingHand' + interface SectionRef { scrollToTop: () => void } @@ -158,6 +162,7 @@ function ProfileScreenLoaded({ const likesSectionRef = React.useRef(null) const feedsSectionRef = React.useRef(null) const listsSectionRef = React.useRef(null) + const moderationSectionRef = React.useRef(null) useSetTitle(combinedDisplayName(profile)) @@ -175,6 +180,9 @@ function ProfileScreenLoaded({ const showLikesTab = isMe const showFeedsTab = hasSession && (isMe || extraInfoQuery.data?.hasFeedgens) const showListsTab = hasSession && (isMe || extraInfoQuery.data?.hasLists) + const showModerationTab = + hasSession && (isMe || true) /* TODO true should be associated modservice */ + const sectionTitles = useMemo(() => { return [ _(msg`Posts`), @@ -183,8 +191,16 @@ function ProfileScreenLoaded({ showLikesTab ? _(msg`Likes`) : undefined, showFeedsTab ? _(msg`Feeds`) : undefined, showListsTab ? _(msg`Lists`) : undefined, + showModerationTab ? _(msg`Moderation`) : undefined, ].filter(Boolean) as string[] - }, [showRepliesTab, showLikesTab, showFeedsTab, showListsTab, _]) + }, [ + showRepliesTab, + showLikesTab, + showFeedsTab, + showListsTab, + showModerationTab, + _, + ]) let nextIndex = 0 const postsIndex = nextIndex++ @@ -205,6 +221,10 @@ function ProfileScreenLoaded({ if (showListsTab) { listsIndex = nextIndex++ } + let moderationIndex: number | null = null + if (showModerationTab) { + moderationIndex = nextIndex++ + } const scrollSectionToTop = React.useCallback( (index: number) => { @@ -220,9 +240,19 @@ function ProfileScreenLoaded({ feedsSectionRef.current?.scrollToTop() } else if (index === listsIndex) { listsSectionRef.current?.scrollToTop() + } else if (index === moderationIndex) { + moderationSectionRef.current?.scrollToTop() } }, - [postsIndex, repliesIndex, mediaIndex, likesIndex, feedsIndex, listsIndex], + [ + postsIndex, + repliesIndex, + mediaIndex, + likesIndex, + feedsIndex, + listsIndex, + moderationIndex, + ], ) useFocusEffect( @@ -372,6 +402,17 @@ function ProfileScreenLoaded({ /> ) : null} + {showModerationTab + ? ({headerHeight, isFocused, scrollElRef}) => ( + + ) + : null} {hasSession && ( + ( + + {ctx => ( + + + + + + + )} + + )} + /> + + ) +} + function useRichText(text: string): [RichTextAPI, boolean] { const [prevText, setPrevText] = React.useState(text) const [rawRT, setRawRT] = React.useState(() => new RichTextAPI({text}))