From 4e620f8987ca63384ccbbaab4671a72bdf8b03d2 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Tue, 14 Mar 2023 00:40:28 +0100 Subject: [PATCH] Test #722 --- src/components/Timeline/Shared/Card/Neodb.tsx | 125 ++++++++++++++++++ .../Shared/{Card.tsx => Card/index.tsx} | 11 +- src/utils/queryHooks/neodb.ts | 40 ++++++ 3 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 src/components/Timeline/Shared/Card/Neodb.tsx rename src/components/Timeline/Shared/{Card.tsx => Card/index.tsx} (93%) create mode 100644 src/utils/queryHooks/neodb.ts diff --git a/src/components/Timeline/Shared/Card/Neodb.tsx b/src/components/Timeline/Shared/Card/Neodb.tsx new file mode 100644 index 00000000..98bffedd --- /dev/null +++ b/src/components/Timeline/Shared/Card/Neodb.tsx @@ -0,0 +1,125 @@ +import GracefullyImage from '@components/GracefullyImage' +import openLink from '@components/openLink' +import CustomText from '@components/Text' +import { useNeodbQuery } from '@utils/queryHooks/neodb' +import { StyleConstants } from '@utils/styles/constants' +import { useTheme } from '@utils/styles/ThemeManager' +import * as Linking from 'expo-linking' +import { Pressable, View } from 'react-native' + +export const CardNeodb = ({ card }: { card: Mastodon.Card }) => { + const { colors } = useTheme() + + const segments = Linking.parse(card.url).path?.split('/') + if (!segments || !(segments[0] === 'movie' || segments[0] === 'book')) return null + + const { data } = useNeodbQuery({ path: `${segments[0]}/${segments[1]}` }) + + if (!data) return null + + switch (segments[0]) { + case 'movie': + return ( + openLink(card.url)} + > + + + + {[ + data.data.title, + data.data.orig_title, + data.data.year ? `(${data.data.year})` : null + ] + .filter(d => d) + .join(' ')} + + + {[ + data.data.duration ? `${data.data.duration}分钟` : null, + data.data.area?.join(' '), + data.data.genre?.join(' '), + data.data.director?.join(' ') + ] + .filter(d => d) + .join(' / ')} + + + + ) + case 'book': + return ( + openLink(card.url)} + > + + + + {[ + data.data.title, + data.data.pub_year && data.data.pub_month + ? `(${data.data.pub_year}年${data.data.pub_month}月)` + : null + ] + .filter(d => d) + .join(' ')} + + + {[ + data.data.author?.join(' '), + data.data.language, + data.data.pages ? `${data.data.pages}页` : null, + data.data.pub_house + ] + .filter(d => d) + .join(' / ')} + + + + ) + default: + return null + } +} diff --git a/src/components/Timeline/Shared/Card.tsx b/src/components/Timeline/Shared/Card/index.tsx similarity index 93% rename from src/components/Timeline/Shared/Card.tsx rename to src/components/Timeline/Shared/Card/index.tsx index d77ae525..254787f3 100644 --- a/src/components/Timeline/Shared/Card.tsx +++ b/src/components/Timeline/Shared/Card/index.tsx @@ -11,14 +11,21 @@ import { useStatusQuery } from '@utils/queryHooks/status' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useContext, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' import { Pressable, View } from 'react-native' -import TimelineDefault from '../Default' -import StatusContext from './Context' +import TimelineDefault from '../../Default' +import StatusContext from '../Context' +import { CardNeodb } from './Neodb' const TimelineCard: React.FC = () => { const { status, spoilerHidden, disableDetails, inThread } = useContext(StatusContext) if (!status || !status.card) return null + const { i18n } = useTranslation() + if (status.card.url.includes('://neodb.social/') && i18n.language === 'zh-hans') { + return + } + const { colors } = useTheme() const navigation = useNavigation>() diff --git a/src/utils/queryHooks/neodb.ts b/src/utils/queryHooks/neodb.ts new file mode 100644 index 00000000..fce9cfdf --- /dev/null +++ b/src/utils/queryHooks/neodb.ts @@ -0,0 +1,40 @@ +import { QueryFunctionContext, useQuery, UseQueryOptions } from '@tanstack/react-query' +import apiGeneral from '@utils/api/general' +import { AxiosError } from 'axios' + +export type QueryKeyNeodb = ['Neodb', { path: string }] + +const queryFunction = async ({ queryKey }: QueryFunctionContext) => { + const data: any = {} + + await Promise.all([ + apiGeneral({ + method: 'get', + domain: 'neodb.social', + url: `/${queryKey[1].path}` + }).then(res => { + const matches = (res.body as string).match(/"(\/media\/.+autocrop.+?)"/) + data.image = matches?.[1] + }), + apiGeneral({ + method: 'get', + domain: 'neodb.social', + url: `/api/${queryKey[1].path}` + }).then(res => (data.data = res.body)) + ]) + + return data +} + +export const useNeodbQuery = ( + params: QueryKeyNeodb[1] & { + options?: UseQueryOptions + } +) => { + const queryKey: QueryKeyNeodb = ['Neodb', { path: params.path }] + return useQuery(queryKey, queryFunction, { + ...params?.options, + staleTime: Infinity, + cacheTime: Infinity + }) +}