mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Refine neodb cards
Added card for games
This commit is contained in:
		| @@ -17,7 +17,15 @@ export const CardNeodb: React.FC<Props> = ({ card }) => { | |||||||
|   const { colors } = useTheme() |   const { colors } = useTheme() | ||||||
|  |  | ||||||
|   const segments = Linking.parse(card.url).path?.split('/') |   const segments = Linking.parse(card.url).path?.split('/') | ||||||
|   if (!segments || !(segments[0] === 'movie' || segments[0] === 'book' || segments[0] === 'tv')) |   if ( | ||||||
|  |     !segments || | ||||||
|  |     !( | ||||||
|  |       segments[0] === 'movie' || | ||||||
|  |       segments[0] === 'book' || | ||||||
|  |       (segments[0] === 'tv' && segments[1] !== 'season') || | ||||||
|  |       segments[0] === 'game' | ||||||
|  |     ) | ||||||
|  |   ) | ||||||
|     return null |     return null | ||||||
|  |  | ||||||
|   const [headingLines, setHeadingLines] = useState(3) |   const [headingLines, setHeadingLines] = useState(3) | ||||||
| @@ -26,121 +34,104 @@ export const CardNeodb: React.FC<Props> = ({ card }) => { | |||||||
|  |  | ||||||
|   if (!data) return null |   if (!data) return null | ||||||
|  |  | ||||||
|   const pressableProps = { |   const Content = ({ heading, details }: { heading: string[]; details: string[] }) => ( | ||||||
|     style: { |     <Pressable | ||||||
|       marginTop: StyleConstants.Spacing.M, |       style={{ | ||||||
|       backgroundColor: colors.shimmerDefault, |         marginTop: StyleConstants.Spacing.M, | ||||||
|       borderRadius: StyleConstants.BorderRadius, |         backgroundColor: colors.shimmerDefault, | ||||||
|       padding: StyleConstants.Spacing.S, |         borderRadius: StyleConstants.BorderRadius, | ||||||
|       flexDirection: 'row' as 'row' |         padding: StyleConstants.Spacing.S, | ||||||
|     }, |         flexDirection: 'row' | ||||||
|     onPress: () => openLink(card.url) |  | ||||||
|   } |  | ||||||
|   const contentProps = { style: { flex: 1, gap: StyleConstants.Spacing.S } } |  | ||||||
|  |  | ||||||
|   const itemImage = data.cover_image_url ? ( |  | ||||||
|     <GracefullyImage |  | ||||||
|       sources={{ default: { uri: data.cover_image_url } }} |  | ||||||
|       dimension={{ |  | ||||||
|         width: StyleConstants.Font.LineHeight.M * 4, |  | ||||||
|         height: StyleConstants.Font.LineHeight.M * 5 |  | ||||||
|       }} |       }} | ||||||
|       style={{ marginRight: StyleConstants.Spacing.S }} |       onPress={() => openLink(card.url)} | ||||||
|       imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }} |     > | ||||||
|       dim |       {data.cover_image_url ? ( | ||||||
|     /> |         <GracefullyImage | ||||||
|   ) : null |           sources={{ default: { uri: data.cover_image_url } }} | ||||||
|   const itemHeading = (value: string) => ( |           dimension={{ | ||||||
|     <CustomText |             width: StyleConstants.Font.LineHeight.M * 4, | ||||||
|       fontStyle='S' |             height: StyleConstants.Font.LineHeight.M * 5 | ||||||
|       fontWeight='Bold' |           }} | ||||||
|       style={{ color: colors.primaryDefault }} |           style={{ marginRight: StyleConstants.Spacing.S }} | ||||||
|       numberOfLines={3} |           imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }} | ||||||
|       children={value} |           dim | ||||||
|       onTextLayout={({ nativeEvent }) => setHeadingLines(nativeEvent.lines.length)} |         /> | ||||||
|     /> |       ) : null} | ||||||
|   ) |       <View style={{ flex: 1, gap: StyleConstants.Spacing.S, justifyContent: 'space-between' }}> | ||||||
|   const itemDetails = (value: string) => ( |         <View style={{ gap: StyleConstants.Spacing.S }}> | ||||||
|     <CustomText |           <CustomText | ||||||
|       fontStyle='S' |             fontStyle='S' | ||||||
|       style={{ color: colors.secondary }} |             fontWeight='Bold' | ||||||
|       numberOfLines={4 - headingLines} |             style={{ color: colors.primaryDefault }} | ||||||
|       children={value} |             numberOfLines={3} | ||||||
|     /> |             onTextLayout={({ nativeEvent }) => setHeadingLines(nativeEvent.lines.length)} | ||||||
|  |             children={heading.filter(d => d).join(' ')} | ||||||
|  |           /> | ||||||
|  |           <Rating rating={data.rating / 2} /> | ||||||
|  |         </View> | ||||||
|  |  | ||||||
|  |         <CustomText | ||||||
|  |           fontStyle='S' | ||||||
|  |           style={{ color: colors.secondary }} | ||||||
|  |           numberOfLines={4 - headingLines} | ||||||
|  |           children={details.filter(d => d).join(' / ')} | ||||||
|  |         /> | ||||||
|  |       </View> | ||||||
|  |     </Pressable> | ||||||
|   ) |   ) | ||||||
|  |  | ||||||
|   switch (segments[0]) { |   switch (segments[0]) { | ||||||
|     case 'movie': |     case 'movie': | ||||||
|       return ( |       return ( | ||||||
|         <Pressable {...pressableProps}> |         <Content | ||||||
|           {itemImage} |           heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]} | ||||||
|           <View {...contentProps}> |           details={[ | ||||||
|             {itemHeading( |             data.duration | ||||||
|               [data.title, data.orig_title, data.year ? `(${data.year})` : null] |               ? parseInt(data.duration).toString() === data.duration | ||||||
|                 .filter(d => d) |                 ? `${data.duration}分钟` | ||||||
|                 .join(' ') |                 : data.duration | ||||||
|             )} |               : null, | ||||||
|             <Rating rating={data.rating / 2} /> |             data.area?.join(' '), | ||||||
|             {itemDetails( |             data.genre?.join(' '), | ||||||
|               [ |             data.director?.join(' ') | ||||||
|                 data.duration |           ]} | ||||||
|                   ? parseInt(data.duration).toString() === data.duration |         /> | ||||||
|                     ? `${data.duration}分钟` |  | ||||||
|                     : data.duration |  | ||||||
|                   : null, |  | ||||||
|                 data.area?.join(' '), |  | ||||||
|                 data.genre?.join(' '), |  | ||||||
|                 data.director?.join(' ') |  | ||||||
|               ] |  | ||||||
|                 .filter(d => d) |  | ||||||
|                 .join(' / ') |  | ||||||
|             )} |  | ||||||
|           </View> |  | ||||||
|         </Pressable> |  | ||||||
|       ) |       ) | ||||||
|     case 'book': |     case 'book': | ||||||
|       return ( |       return ( | ||||||
|         <Pressable {...pressableProps}> |         <Content | ||||||
|           {itemImage} |           heading={[data.title]} | ||||||
|           <View {...contentProps}> |           details={[ | ||||||
|             {itemHeading(data.title)} |             data.author?.join(' '), | ||||||
|             <Rating rating={data.rating / 2} /> |             data.pages ? `${data.pages}页` : null, | ||||||
|             {itemDetails( |             data.language, | ||||||
|               [ |             data.pub_house | ||||||
|                 data.author?.join(' '), |           ]} | ||||||
|                 data.pages ? `${data.pages}页` : null, |         /> | ||||||
|                 data.language, |  | ||||||
|                 data.pub_house |  | ||||||
|               ] |  | ||||||
|                 .filter(d => d) |  | ||||||
|                 .join(' / ') |  | ||||||
|             )} |  | ||||||
|           </View> |  | ||||||
|         </Pressable> |  | ||||||
|       ) |       ) | ||||||
|     case 'tv': |     case 'tv': | ||||||
|       return ( |       return ( | ||||||
|         <Pressable {...pressableProps}> |         <Content | ||||||
|           {itemImage} |           heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]} | ||||||
|           <View {...contentProps}> |           details={[ | ||||||
|             {itemHeading( |             data.season_count ? `共${data.season_count}季` : null, | ||||||
|               [data.title, data.orig_title, data.year ? `(${data.year})` : null] |             data.area?.join(' '), | ||||||
|                 .filter(d => d) |             data.genre?.join(' '), | ||||||
|                 .join(' ') |             data.director?.join(' ') | ||||||
|             )} |           ]} | ||||||
|             <Rating rating={data.rating / 2} /> |         /> | ||||||
|             {itemDetails( |       ) | ||||||
|               [ |     case 'game': | ||||||
|                 data.season_count ? `共${data.season_count}季` : null, |       return ( | ||||||
|                 data.area?.join(' '), |         <Content | ||||||
|                 data.genre?.join(' '), |           heading={[data.title]} | ||||||
|                 data.director?.join(' ') |           details={[ | ||||||
|               ] |             data.genre?.join(' '), | ||||||
|                 .filter(d => d) |             data.developer?.join(' '), | ||||||
|                 .join(' / ') |             data.platform?.join(' '), | ||||||
|             )} |             data.release_date | ||||||
|           </View> |           ]} | ||||||
|         </Pressable> |         /> | ||||||
|       ) |       ) | ||||||
|     default: |     default: | ||||||
|       return null |       return null | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import openLink from '@components/openLink' | |||||||
| import CustomText from '@components/Text' | import CustomText from '@components/Text' | ||||||
| import { useNavigation } from '@react-navigation/native' | import { useNavigation } from '@react-navigation/native' | ||||||
| import { StackNavigationProp } from '@react-navigation/stack' | import { StackNavigationProp } from '@react-navigation/stack' | ||||||
|  | import { isDevelopment } from '@utils/helpers/checkEnvironment' | ||||||
| import { urlMatcher } from '@utils/helpers/urlMatcher' | import { urlMatcher } from '@utils/helpers/urlMatcher' | ||||||
| import { TabLocalStackParamList } from '@utils/navigation/navigators' | import { TabLocalStackParamList } from '@utils/navigation/navigators' | ||||||
| import { useAccountQuery } from '@utils/queryHooks/account' | import { useAccountQuery } from '@utils/queryHooks/account' | ||||||
| @@ -27,8 +28,9 @@ const TimelineCard: React.FC = () => { | |||||||
|  |  | ||||||
|   const { i18n } = useTranslation() |   const { i18n } = useTranslation() | ||||||
|   if ( |   if ( | ||||||
|     status.card.url.includes('://neodb.social/') && |     (status.card.url.includes('://neodb.social/') && | ||||||
|     i18n.language.toLowerCase().startsWith('zh-hans') |       i18n.language.toLowerCase().startsWith('zh-hans')) || | ||||||
|  |     isDevelopment | ||||||
|   ) { |   ) { | ||||||
|     return <CardNeodb card={status.card} /> |     return <CardNeodb card={status.card} /> | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user