diff --git a/.changeset/forty-needles-compare.md b/.changeset/forty-needles-compare.md new file mode 100644 index 00000000..5bb4fe99 --- /dev/null +++ b/.changeset/forty-needles-compare.md @@ -0,0 +1,5 @@ +--- +"xlog": patch +--- + +Login directly in the introduction page. diff --git a/.changeset/gold-yaks-confess.md b/.changeset/gold-yaks-confess.md new file mode 100644 index 00000000..20fa786b --- /dev/null +++ b/.changeset/gold-yaks-confess.md @@ -0,0 +1,5 @@ +--- +"xlog": patch +--- + +New profile page. diff --git a/.changeset/pretty-chicken-argue.md b/.changeset/pretty-chicken-argue.md new file mode 100644 index 00000000..1bfd3a18 --- /dev/null +++ b/.changeset/pretty-chicken-argue.md @@ -0,0 +1,5 @@ +--- +"xlog": patch +--- + +Some style changes. diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index a36c3773..c4a07b44 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -9,7 +9,7 @@ import { Circle, Text, Avatar as _Avatar } from "tamagui"; import { useNavigateToUserInfo } from "@/hooks/use-navigate-to-user-info"; import { toGateway } from "@/utils/ipfs-parser"; -import { LogoResource, LogoLightResource } from "./Logo"; +import { LogoBlueResource } from "./Logo"; import { XTouch } from "./XTouch"; interface Props { @@ -64,7 +64,7 @@ export const Avatar: FC = (props) => { alignItems="center" justifyContent="center" > - + ); } @@ -81,11 +81,11 @@ export const Avatar: FC = (props) => { <_Avatar size={size} circular - backgroundColor="white" + backgroundColor="black" > - <_Avatar.Image src={toGateway(uri)} /> + <_Avatar.Image src={toGateway(uri)}/> <_Avatar.Fallback> - + @@ -95,7 +95,7 @@ export const Avatar: FC = (props) => { const styles = StyleSheet.create({ container: { flex: 1, - backgroundColor: "#fff", + backgroundColor: "#000", alignItems: "center", justifyContent: "center", transform: [ diff --git a/src/components/ConnectEmailButton.tsx b/src/components/ConnectEmailButton.tsx index 08d46d71..17d6ccba 100644 --- a/src/components/ConnectEmailButton.tsx +++ b/src/components/ConnectEmailButton.tsx @@ -1,15 +1,18 @@ import React from "react"; import { useTranslation } from "react-i18next"; +import { TouchableOpacity } from "react-native-gesture-handler"; import { useConnectedAccount, useAccountState } from "@crossbell/react-account"; import { Mail } from "@tamagui/lucide-icons"; import { openAuthSessionAsync } from "expo-web-browser"; import type { ButtonProps } from "tamagui"; -import { Button } from "tamagui"; +import { Button, Stack, XStack, Text } from "tamagui"; import { APP_SCHEME } from "@/constants"; import { useGlobalLoading } from "@/hooks/use-global-loading"; +import { Center } from "./Base/Center"; + export const ConnectEmailButton = (props: ButtonProps) => { const i18n = useTranslation(); const account = useConnectedAccount(); @@ -34,18 +37,18 @@ export const ConnectEmailButton = (props: ButtonProps) => { if (account) return null; return ( - + +
+ + + {i18n.t("Connect with Email")} + +
+
+ ); }; diff --git a/src/components/ConnectionButton.tsx b/src/components/ConnectionButton.tsx index 9aabb8d8..a5c3b22d 100644 --- a/src/components/ConnectionButton.tsx +++ b/src/components/ConnectionButton.tsx @@ -2,6 +2,7 @@ import type { FC } from "react"; import { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import { Alert, Linking } from "react-native"; +import { TouchableOpacity } from "react-native-gesture-handler"; import Animated, { FadeIn, FadeOut, FlipInXDown } from "react-native-reanimated"; import { @@ -15,9 +16,10 @@ import { Plug, Wallet } from "@tamagui/lucide-icons"; import { useToastController } from "@tamagui/toast"; import { useWalletConnectModal } from "@walletconnect/modal-react-native"; import * as Haptics from "expo-haptics"; +import { LinearGradient } from "expo-linear-gradient"; import * as Sentry from "sentry-expo"; import type { StackProps } from "tamagui"; -import { Stack } from "tamagui"; +import { Stack, Text, XStack } from "tamagui"; import { IS_IOS } from "@/constants"; import { useAppIsActive } from "@/hooks/use-app-state"; @@ -29,6 +31,7 @@ import { GA } from "@/utils/GA"; import type { AlertDialogInstance } from "./AlertDialog"; import { AlertDialog } from "./AlertDialog"; import { Button } from "./Base/Button"; +import { Center } from "./Base/Center"; import { DelayedRender } from "./DelayRender"; interface Props extends StackProps { @@ -152,20 +155,22 @@ function ConnectBtn({ navigateToLogin }: { navigateToLogin: boolean }) { }; return ( - - - + + + +
+ + + {i18n.t("Connect with Wallet")} + +
+
+
); } diff --git a/src/components/FeedList/FeedListItem/index.tsx b/src/components/FeedList/FeedListItem/index.tsx index 727e4b82..32de984d 100644 --- a/src/components/FeedList/FeedListItem/index.tsx +++ b/src/components/FeedList/FeedListItem/index.tsx @@ -62,7 +62,8 @@ export const FeedListItem: FC = (props) => { { characterId: note.characterId, noteId: note.noteId, - coverImageIndex: placeholderBgIndex, + placeholderCoverImageIndex: placeholderBgIndex, + coverImage, }, ); }, [note]); diff --git a/src/components/FeedList/index.tsx b/src/components/FeedList/index.tsx index d60cebd1..2c439c6d 100644 --- a/src/components/FeedList/index.tsx +++ b/src/components/FeedList/index.tsx @@ -1,138 +1,28 @@ import type { FC } from "react"; -import { useEffect, useMemo, useRef } from "react"; -import type { useAnimatedScrollHandler } from "react-native-reanimated"; -import Animated from "react-native-reanimated"; -import type { ContentStyle, MasonryFlashListProps, MasonryFlashListRef } from "@shopify/flash-list"; -import { SizableText, Spinner, Stack, useWindowDimensions } from "tamagui"; - -import { useCharacterId } from "@/hooks/use-character-id"; -import type { FeedType, SearchType } from "@/models/home.model"; -import { useGetFeed } from "@/queries/home"; import type { ExpandedNote } from "@/types/crossbell"; -import { debounce } from "@/utils/debounce"; -import { GA } from "@/utils/GA"; -import { FeedListItem } from "./FeedListItem"; -import { Skeleton } from "./Skeleton"; +import type { Props as FeedListProps } from "./useFeedList"; +import { useFeedList } from "./useFeedList"; -import topics from "../../data/topics.json"; -import { Center } from "../Base/Center"; -import { FillSpinner } from "../FillSpinner"; import { MasonryFlashList } from "../MasonryFlashList"; -import { MeasureContainer } from "../utils/MeasureContainer"; - -export interface Props { - onScroll?: ReturnType - type?: FeedType - noteIds?: string[] - /** - * @default 7 - * */ - daysInterval?: number - searchKeyword?: string - tag?: string - topic?: string - searchType?: SearchType - contentContainerStyle?: ContentStyle -} - -export const FeedList: FC = (props) => { - const { type, searchType, searchKeyword, contentContainerStyle = {}, tag, topic, noteIds, daysInterval = 7, onScroll } = props; - const characterId = useCharacterId(); - const gaLog = debounce(() => GA.logSearch({ search_term: searchKeyword }), 2000); - const { width } = useWindowDimensions(); - const listRef = useRef>(null); +import { TabMasonryFlashList } from "../TabMasonryFlashList"; - useEffect(() => { - typeof searchKeyword === "string" && gaLog(); - }, [searchKeyword]); +interface MasonryProps extends FeedListProps {} - useEffect(() => { - listRef.current?.scrollToOffset({ offset: 0, animated: false }); - }, [type, daysInterval]); +export const MasonryFeedList: FC = (props) => { + const _props = useFeedList(props); - const queryParams = useMemo(() => ({ - type, - limit: 30, - characterId, - noteIds, - daysInterval, - searchKeyword, - searchType, - tag, - topicIncludeKeywords: topic - ? topics.find(t => t.name === topic)?.includeKeywords - : undefined, - }), [ - type, - characterId, - noteIds, - daysInterval, - searchKeyword, - searchType, - tag, - topic, - ]); - - // TODO - const feed = useGetFeed(queryParams); - const feedList = useMemo(() => (feed.data?.pages?.flatMap(page => page?.list) || []), [feed.data?.pages]); + return {..._props}/>; +}; - return ( - - data={feedList} - ref={listRef} - numColumns={2} - keyExtractor={post => `${post.characterId}-${post.noteId}`} - renderItem={({ item, index }) => ( - - )} - ListEmptyComponent={( - - { - feed.isFetching - ? - : ( -
- - There are no posts yet. - -
- ) - } -
- )} - bounces - estimatedItemSize={251} - ListFooterComponent={feed.isFetchingNextPage && } - contentContainerStyle={{ ...contentContainerStyle, paddingHorizontal: 4 }} - scrollEventThrottle={16} - onScroll={onScroll} - onEndReachedThreshold={2} - onEndReached={() => { - if ( - feedList.length === 0 - || feed.isFetchingNextPage - || feed.hasNextPage === false - ) - return; +interface TabMasonryProps extends FeedListProps { + index: number + characterId: number +} - GA.logEvent("feed_list_view", { - feed_length: feedList.length, - feed_type: queryParams.type, - query_limit: queryParams.limit, - character_id: queryParams.characterId, - note_ids: queryParams.noteIds, - days_interval: queryParams.daysInterval, - search_keyword: queryParams.searchKeyword, - search_type: queryParams.searchType, - tag: queryParams.tag, - topic_include_keywords: queryParams.topicIncludeKeywords, - }); +export const TabMasonryFeedList: FC = (props) => { + const _props = useFeedList(props); - feed?.fetchNextPage?.(); - }} - /> - ); + return {..._props}/>; }; diff --git a/src/components/FeedList/useFeedList.tsx b/src/components/FeedList/useFeedList.tsx new file mode 100644 index 00000000..cef46092 --- /dev/null +++ b/src/components/FeedList/useFeedList.tsx @@ -0,0 +1,141 @@ +import type { FC } from "react"; +import { useEffect, useMemo, useRef } from "react"; +import type { useAnimatedScrollHandler } from "react-native-reanimated"; + +import type { ContentStyle, MasonryFlashListRef } from "@shopify/flash-list"; +import { SizableText, Spinner, Stack, useWindowDimensions } from "tamagui"; + +import { useCharacterId } from "@/hooks/use-character-id"; +import type { FeedType, SearchType } from "@/models/home.model"; +import { useGetFeed } from "@/queries/home"; +import type { ExpandedNote } from "@/types/crossbell"; +import { debounce } from "@/utils/debounce"; +import { GA } from "@/utils/GA"; + +import { FeedListItem } from "./FeedListItem"; +import { Skeleton } from "./Skeleton"; + +import topics from "../../data/topics.json"; +import { Center } from "../Base/Center"; + +export interface Props { + onScroll?: ReturnType + type?: FeedType + noteIds?: string[] + /** + * @default 7 + * */ + daysInterval?: number + searchKeyword?: string + tag?: string + topic?: string + searchType?: SearchType + contentContainerStyle?: ContentStyle + characterId?: number +} + +export const useFeedList = (props: Props & T) => { + const { type, searchType, searchKeyword, contentContainerStyle = {}, tag, topic, noteIds, daysInterval = 7, onScroll, characterId, ...restProps } = props; + const _characterId = useCharacterId(); + const gaLog = debounce(() => GA.logSearch({ search_term: searchKeyword }), 2000); + const { width } = useWindowDimensions(); + const listRef = useRef>(null); + + useEffect(() => { + typeof searchKeyword === "string" && gaLog(); + }, [searchKeyword]); + + useEffect(() => { + listRef.current?.scrollToOffset({ offset: 0, animated: false }); + }, [type, daysInterval]); + + const queryParams = useMemo(() => ({ + type, + limit: 30, + characterId: characterId ?? _characterId, + noteIds, + daysInterval, + searchKeyword, + searchType, + tag, + topicIncludeKeywords: topic + ? topics.find(t => t.name === topic)?.includeKeywords + : undefined, + }), [ + type, + characterId, + _characterId, + noteIds, + daysInterval, + searchKeyword, + searchType, + tag, + topic, + ]); + + const feed = useGetFeed(queryParams); + const feedList = useMemo(() => (feed.data?.pages?.flatMap(page => page?.list) || []), [feed.data?.pages]); + + return useMemo(() => ({ + data: feedList, + ref: listRef, + numColumns: 2, + keyExtractor: post => `${post.characterId}-${post.noteId}`, + renderItem: ({ item, index }) => ( + + ), + ListEmptyComponent: + { + feed.isFetching + ? + : ( +
+ +There are no posts yet. + +
+ ) + } +
, + bounces: true, + estimatedItemSize: 251, + ListFooterComponent: feed.isFetchingNextPage && , + contentContainerStyle: { ...contentContainerStyle, paddingHorizontal: 4 }, + scrollEventThrottle: 16, + onScroll, + onEndReachedThreshold: 2, + onEndReached: () => { + if ( + feedList.length === 0 + || feed.isFetchingNextPage + || feed.hasNextPage === false + ) + return; + + GA.logEvent("feed_list_view", { + feed_length: feedList.length, + feed_type: queryParams.type, + query_limit: queryParams.limit, + character_id: queryParams.characterId, + note_ids: queryParams.noteIds, + days_interval: queryParams.daysInterval, + search_keyword: queryParams.searchKeyword, + search_type: queryParams.searchType, + tag: queryParams.tag, + topic_include_keywords: queryParams.topicIncludeKeywords, + }); + + feed?.fetchNextPage?.(); + }, + ...(restProps as T), + }), [ + feed, + width, + contentContainerStyle, + onScroll, + restProps, + queryParams, + searchKeyword, + feedList, + ]); +}; diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx index c4933f9f..1b5b645d 100644 --- a/src/components/Logo.tsx +++ b/src/components/Logo.tsx @@ -1,4 +1,4 @@ -export { default as LogoResource } from "../assets/logo.png"; +export { default as LogoDefaultResource } from "../assets/logo.png"; export { default as LogoLightResource } from "../assets/logo-light.png"; export { default as LogoDarkResource } from "../assets/logo-dark.png"; export { default as LogoBlueResource } from "../assets/logo-blue.png"; diff --git a/src/pages/Feed/Background.tsx b/src/components/PolarLightBackground.tsx similarity index 86% rename from src/pages/Feed/Background.tsx rename to src/components/PolarLightBackground.tsx index d65d7ed0..a762305d 100644 --- a/src/pages/Feed/Background.tsx +++ b/src/components/PolarLightBackground.tsx @@ -9,12 +9,12 @@ export const width = Dimensions.get("window").width; export const height = width / 1.58; const bgs = [ - require("../../assets/home-grid-bg/0.png"), - require("../../assets/home-grid-bg/1.png"), - require("../../assets/home-grid-bg/2.png"), + require("../assets/home-grid-bg/0.png"), + require("../assets/home-grid-bg/1.png"), + require("../assets/home-grid-bg/2.png"), ]; -export const Background: FC<{ +export const PolarLightBackground: FC<{ activeIndex: number }> = ({ activeIndex }) => { return ( diff --git a/src/components/TabFlashList.tsx b/src/components/TabFlashList.tsx new file mode 100644 index 00000000..1cb30ba2 --- /dev/null +++ b/src/components/TabFlashList.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +import type { FlashListProps } from "@shopify/flash-list"; +import { FlashList } from "@shopify/flash-list"; + +import { TabFlashListScrollView } from "./TabFlashListScrollView"; + +export type TabFlashListProps = Omit< +FlashListProps, +"renderScrollComponent" +> & { + index: number +}; + +function TabFlashListComponent( + props: TabFlashListProps, + ref: React.Ref>, +) { + return ( + + ); +} + +export const TabFlashList = React.forwardRef(TabFlashListComponent) as ( + props: TabFlashListProps & { + ref?: React.Ref> + } +) => React.ReactElement; diff --git a/src/components/TabFlashListScrollView.tsx b/src/components/TabFlashListScrollView.tsx new file mode 100644 index 00000000..d2b793d5 --- /dev/null +++ b/src/components/TabFlashListScrollView.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import type { ScrollViewProps } from "react-native"; +import Animated from "react-native-reanimated"; + +import { SceneComponent } from "@showtime-xyz/tab-view"; + +type TabScrollViewProps = ScrollViewProps & { + index: number +}; +function TabFlashListScrollViewComponent(props: TabScrollViewProps, ref: any) { + return ( + + ); +} + +export const TabFlashListScrollView = React.forwardRef( + TabFlashListScrollViewComponent, +); diff --git a/src/components/TabMasonryFlashList.tsx b/src/components/TabMasonryFlashList.tsx new file mode 100644 index 00000000..c76d8668 --- /dev/null +++ b/src/components/TabMasonryFlashList.tsx @@ -0,0 +1,37 @@ +import type { RefObject } from "react"; +import React from "react"; + +import type { MasonryFlashListProps, MasonryFlashListRef } from "@shopify/flash-list"; +import { MasonryFlashList } from "@shopify/flash-list"; +import { useHeaderTabContext } from "@showtime-xyz/tab-view"; + +import { TabFlashListScrollView } from "./TabFlashListScrollView"; + +export type TabMasonryFlashListProps = Omit< +MasonryFlashListProps, +"renderScrollComponent" +> & { + index: number +}; + +function TabMasonryFlashListComponent( + props: TabMasonryFlashListProps, + ref: RefObject>, +) { + const { scrollViewPaddingTop } = useHeaderTabContext(); + + return ( + + ); +} + +export const TabMasonryFlashList = React.forwardRef(TabMasonryFlashListComponent) as ( + props: TabMasonryFlashListProps & { + ref?: RefObject> + } +) => React.ReactElement; diff --git a/src/i18n/zh/common.json b/src/i18n/zh/common.json index 07343d0b..fc6baaa2 100644 --- a/src/i18n/zh/common.json +++ b/src/i18n/zh/common.json @@ -1,10 +1,9 @@ { "Connect": "连接", - "Connect Wallet": "连接钱包", - "Connect Email": "连接邮箱", - "Followers": "关注者", + "Connect with Wallet": "连接钱包", + "Connect with Email": "连接邮箱", + "Follower": "关注者", "Following": "正在关注", - "Followings": "正在关注", "Follow": "关注", "Unfollow": "取消关注", "intlDateTime": "{{val, datetime}}", diff --git a/src/i18n/zh/dashboard.json b/src/i18n/zh/dashboard.json index 234ac129..913bc75e 100644 --- a/src/i18n/zh/dashboard.json +++ b/src/i18n/zh/dashboard.json @@ -10,7 +10,7 @@ "Site Stats": "站点统计", "Published posts": "发布的文章", "Received comments": "收到的评论", - "Followers": "关注者", + "Follower": "关注者", "Viewed": "浏览量", "Received tips": "收到的打赏", "Site Duration": "站点运行时间", diff --git a/src/models/home.model.ts b/src/models/home.model.ts index a920736a..8dcafd5b 100644 --- a/src/models/home.model.ts +++ b/src/models/home.model.ts @@ -20,6 +20,7 @@ export type FeedType = | "search" | "tag" | "comments" + | "character" | "featured"; export type SearchType = "latest" | "hottest"; @@ -692,6 +693,34 @@ export async function getFeed({ }; break; } + case "character": { + const result = await indexer.note.getMany({ + sources: "xlog", + tags: ["post"], + limit, + cursor, + characterId, + includeCharacter: true, + }); + + const list = await Promise.all( + result.list.map((page: NoteEntity) => + expandCrossbellNote({ + note: page, + useStat: false, + useScore: true, + useHTML, + }), + ), + ); + + resultAll = { + list, + cursor: result.cursor, + count: result.count, + }; + break; + } case "search": { const result = await indexer.search.notes(searchKeyword!, { sources: ["xlog"], diff --git a/src/navigation/root.tsx b/src/navigation/root.tsx index fe303bbc..9377603d 100644 --- a/src/navigation/root.tsx +++ b/src/navigation/root.tsx @@ -68,6 +68,7 @@ export const RootNavigator = () => { > + { - diff --git a/src/pages/Feed/Header.tsx b/src/pages/Feed/Header.tsx index 7e276fd1..8089fbac 100644 --- a/src/pages/Feed/Header.tsx +++ b/src/pages/Feed/Header.tsx @@ -7,11 +7,11 @@ import type Animated from "react-native-reanimated"; import { useConnectedAccount } from "@crossbell/react-account"; import { Stack, Text, XStack } from "tamagui"; +import { PolarLightBackground } from "@/components/PolarLightBackground"; import { useHitSlopSize } from "@/hooks/use-hit-slop-size"; import { HeaderAnimatedLayout } from "@/pages/Feed/HeaderAnimatedLayout"; import { GA } from "@/utils/GA"; -import { Background } from "./Background"; import { feedTypes, type FeedType } from "./feedTypes"; import { HotInterval } from "./HotInterval"; @@ -41,7 +41,7 @@ export const Header: FC = (props) => { return ( - + { diff --git a/src/pages/Feed/index.tsx b/src/pages/Feed/index.tsx index 884503b6..eacb2cbe 100644 --- a/src/pages/Feed/index.tsx +++ b/src/pages/Feed/index.tsx @@ -3,16 +3,14 @@ import { useContext, useState } from "react"; import Animated from "react-native-reanimated"; import * as Haptics from "expo-haptics"; -import { ScrollView, Stack, YStack } from "tamagui"; +import { Stack } from "tamagui"; -import { FeedList } from "@/components/FeedList"; -import { PolarLight, PolarLightPalettes } from "@/components/PolarLight"; +import { MasonryFeedList } from "@/components/FeedList"; import { GlobalAnimationContext } from "@/context/global-animation-context"; -import { useScrollVisibilityHandler } from "@/hooks/use-scroll-visibility-handler"; import type { FeedType } from "./feedTypes"; import { feedTypes } from "./feedTypes"; -import { Header, HeaderTabHeight } from "./Header"; +import { Header } from "./Header"; export interface Props { feedType?: FeedType @@ -39,7 +37,7 @@ export const FeedPage: FC = (props) => { }} /> - = () => { - return ( - - - - - - - - - - - - ); -}; diff --git a/src/pages/Introduction/index.tsx b/src/pages/Introduction/index.tsx index 7e240dbe..736cf85b 100644 --- a/src/pages/Introduction/index.tsx +++ b/src/pages/Introduction/index.tsx @@ -3,26 +3,26 @@ import { TouchableOpacity } from "react-native-gesture-handler"; import { SafeAreaView } from "react-native-safe-area-context"; import { Settings } from "@tamagui/lucide-icons"; -import { LinearGradient } from "expo-linear-gradient"; -import { Image, ScrollView, Stack, Text, XStack, YStack } from "tamagui"; +import { Image, ScrollView, Spacer, Text, XStack, YStack } from "tamagui"; -import { Center } from "@/components/Base/Center"; +import { ConnectEmailButton } from "@/components/ConnectEmailButton"; +import { ConnectionButton } from "@/components/ConnectionButton"; import { LogoBlueResource } from "@/components/Logo"; +import { PolarLightBackground } from "@/components/PolarLightBackground"; import { useRootNavigation } from "@/hooks/use-navigation"; -import { Background } from "./Background"; - export interface Props { } export const IntroductionPage: FC = () => { const navigation = useRootNavigation(); + const navigateToTerms = () => navigation.navigate("Web", { url: "https://rss3.notion.site/Legal-Public-f30edd47c3be4dd7ae5ed4e39aefbbd9?pvs=4" }); return ( - + - + @@ -64,22 +64,13 @@ export const IntroductionPage: FC = () => { ); }) } - navigation.navigate("Login")} - > - - -
- Connect -
-
-
+ + + + + + By connecting you agree to our Terms & Conditions +
diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index 32a32882..fe1a8484 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -63,8 +63,8 @@ export const LoginPage: FC> Discovering amazing teams and creators on xLog! - - By connecting you agree to our Terms & Conditions + + By connecting you agree to our Terms & Conditions diff --git a/src/pages/PostDetails/BottomSheetLikeList.tsx b/src/pages/PostDetails/BottomSheetLikeList.tsx index 254e488d..2f81e27c 100644 --- a/src/pages/PostDetails/BottomSheetLikeList.tsx +++ b/src/pages/PostDetails/BottomSheetLikeList.tsx @@ -3,18 +3,13 @@ import { useTranslation } from "react-i18next"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { BottomSheetFlatList } from "@gorhom/bottom-sheet"; -import { FlashList } from "@shopify/flash-list"; -import { CharacterEntity } from "crossbell"; -import dayjs from "dayjs"; -import { Stack, Text, XStack, useWindowDimensions } from "tamagui"; +import { Stack, Text, XStack } from "tamagui"; import { Avatar } from "@/components/Avatar"; import { useDate } from "@/hooks/use-date"; import { useGetLikes } from "@/queries/page"; import type { ExpandedNote } from "@/types/crossbell"; -import CharacterListItem from "../CharacterList/CharacterListItem"; - export const BottomSheetLikeList: FC<{ note: ExpandedNote }> = ({ @@ -44,7 +39,7 @@ export const BottomSheetLikeList: FC<{ keyExtractor={item => item?.characterId?.toString()} renderItem={({ item }) => { return ( - + {item?.character?.handle} diff --git a/src/pages/PostDetails/Header.tsx b/src/pages/PostDetails/Header.tsx index 1a7f86fd..514bf0a1 100644 --- a/src/pages/PostDetails/Header.tsx +++ b/src/pages/PostDetails/Header.tsx @@ -23,13 +23,14 @@ interface Props { postUri?: string noteId: number characterId: number - coverImageIndex: number + placeholderCoverImageIndex: number + coverImage: string } const { width } = Dimensions.get("window"); export const Header: FC = (props) => { - const { noteId, characterId, coverImageIndex = 0, postUri, isCapturing, headerContainerHeight } = props; + const { noteId, characterId, coverImage, placeholderCoverImageIndex = 0, postUri, isCapturing, headerContainerHeight } = props; const note = useNote(characterId, noteId); const page = useGetPage( { @@ -39,8 +40,7 @@ export const Header: FC = (props) => { }, ); const character = useCharacter(characterId); - const defaultCoverImage = bgs[coverImageIndex]; - const coverImage = useCoverImage(page.data); + const defaultCoverImage = bgs[placeholderCoverImageIndex]; const { bottom, top } = useSafeAreaInsets(); const { isDarkMode } = useThemeStore(); diff --git a/src/pages/PostDetails/Navigator.tsx b/src/pages/PostDetails/Navigator.tsx index 7ae4d43b..26f63266 100644 --- a/src/pages/PostDetails/Navigator.tsx +++ b/src/pages/PostDetails/Navigator.tsx @@ -260,7 +260,7 @@ export const Navigator: FC = (props) => { snapPoints={snapPoints} enablePanDownToClose index={0} - backgroundStyle={{ backgroundColor: background }} + backgroundStyle={{ backgroundColor: "#1C1C1C" }} onPressBackdrop={closeBottomSheetModal} > diff --git a/src/pages/PostDetails/index.tsx b/src/pages/PostDetails/index.tsx index b4ac909f..8b80e0ca 100644 --- a/src/pages/PostDetails/index.tsx +++ b/src/pages/PostDetails/index.tsx @@ -24,7 +24,8 @@ import { Navigator } from "./Navigator"; export interface Props { noteId: number characterId: number - coverImageIndex?: number + coverImage?: string + placeholderCoverImageIndex?: number } const animationTimeout = 800; @@ -34,7 +35,7 @@ export const PostDetailsPage: FC([]); const { isDarkMode } = useThemeStore(); - const { bottom, top } = useSafeAreaInsets(); + const { bottom } = useSafeAreaInsets(); const bottomBarHeight = bottom + 45; const headerContainerHeight = 45; const contentRef = React.useRef(null); @@ -79,7 +80,8 @@ export const PostDetailsPage: FC ); }} diff --git a/src/pages/Profile/Dashboard/index.tsx b/src/pages/Profile/Dashboard/index.tsx index f642bafa..2f05256c 100644 --- a/src/pages/Profile/Dashboard/index.tsx +++ b/src/pages/Profile/Dashboard/index.tsx @@ -49,7 +49,7 @@ export const DashboardPage: FC - = (props) => { return isMe && isProfilePage; }, [myCharacterId, characterId, currentRouteName]); - const headerAnimatedStyles = useAnimatedStyle(() => { - if (!titleAnimatedValue) return {}; - return { - opacity: interpolate(titleAnimatedValue.value, [-80, -140], [0, 1]), - transform: [ - { - translateY: interpolate(titleAnimatedValue.value, [-80, -140], [40, 0], Extrapolate.CLAMP), - }, - ], - }; - }, [titleAnimatedValue]); - const navigateToSettingsPage = useCallback(() => { navigation.navigate("SettingsNavigator"); }, []); - useEffect(() => { - titleAnimatedValue && navigation.setOptions({ - headerShown: true, - headerTitleContainerStyle: { overflow: "hidden" }, - headerTitle(props) { - return ( - - {character.data?.metadata?.content?.name} - - ); - }, - }); - }, [titleAnimatedValue, headerAnimatedStyles]); - return ( @@ -90,25 +65,29 @@ export const Header: FC = (props) => { { [ - { label: i18n.t("Followers"), value: subscriptions.data?.pages?.[0]?.count ?? 0 }, - { label: i18n.t("Followings"), value: toSubscriptions.data?.pages?.[0]?.count ?? 0 }, - { label: i18n.t("Viewed"), value: stat.data?.viewsCount ?? 0 }, + { label: i18n.t("Follower"), value: subscriptions.data?.pages?.[0]?.count ?? 0 }, + { label: i18n.t("Following"), value: toSubscriptions.data?.pages?.[0]?.count ?? 0 }, ].map((item, index) => ( - - + + {item.value} {item.label} { - index < 2 && + index < 1 && } )) } - -

{character.data?.metadata?.content?.name}

+ + +

{character.data?.metadata?.content?.name}

+ + {character?.data?.metadata?.content?.bio} + +
{ replaceFollowButtonWithOtherComponent || ( @@ -125,6 +104,7 @@ export const Header: FC = (props) => {