Skip to content

Commit 487022b

Browse files
committed
feat: Display the translation information in the details page.
1 parent 1a5e341 commit 487022b

File tree

8 files changed

+115
-37
lines changed

8 files changed

+115
-37
lines changed

.changeset/large-cats-call.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"xlog": patch
3+
---
4+
5+
Display the translation information in the details page.

src/components/AlertDialog.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,16 @@ export const AlertDialog: FC<Props> = ({
112112
<XStack space="$3" justifyContent="flex-end">
113113
<TAlertDialog.Cancel asChild>
114114
{
115-
renderCancel ? renderCancel(params) : <Button onPress={onCancel}>{cancelText}</Button>
115+
typeof renderCancel === "undefined"
116+
? <Button size={"$3"} onPress={onCancel}>{cancelText}</Button>
117+
: !renderCancel ? null : renderCancel(params)
116118
}
117119
</TAlertDialog.Cancel>
118120
<TAlertDialog.Action asChild>
119121
{
120-
renderConfirm ? renderConfirm(params) : <Button onPress={onConfirm}>{confirmText}</Button>
122+
typeof renderConfirm === "undefined"
123+
? <Button size={"$3"} onPress={onConfirm}>{confirmText}</Button>
124+
: !renderConfirm ? null : renderConfirm(params)
121125
}
122126
</TAlertDialog.Action>
123127
</XStack>

src/i18n/en/index.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,10 @@
3434
"Cancel Download": "Cancel",
3535
"link post-vs-page" : "https://wordpress.com/zh-cn/support/post-vs-page/",
3636
"delete_confirmation_post": "Are you sure you want to DELETE this post?",
37-
"delete_confirmation_page": "Are you sure you want to DELETE this page?"
37+
"delete_confirmation_page": "Are you sure you want to DELETE this page?",
38+
"Translated by": "This article has been translated from {{from}} into {{to}} through AI. You can go to the settings to change the language to view the original article.",
39+
"en": "English",
40+
"ja": "Japanese",
41+
"zh": "Chinese",
42+
"zh-TW": "Traditional Chinese"
3843
}

src/i18n/zh/index.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,5 +299,10 @@
299299
"Comments": "评论",
300300
"You can subscribe to comments through an RSS reader to receive timely reminders.": "你可以通过 RSS 阅读器订阅评论,以便及时收到提醒。",
301301
"Subscription address:": "订阅地址:",
302-
"Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.": "该帖子数据的所有权\n由区块链和智能合约保证仅属于创建者。"
302+
"Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.": "该帖子数据的所有权\n由区块链和智能合约保证仅属于创建者。",
303+
"Translated by": "这篇文章通过AI由 {{from}} 翻译成 {{to}}, 可以通过在设置中更换语言来查看原文。",
304+
"en": "英语",
305+
"ja": "日语",
306+
"zh": "中文",
307+
"zh-TW": "繁体中文"
303308
}

src/pages/PostDetails/Header.tsx

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,31 @@
1-
import { Fragment, type FC } from "react";
2-
import { Dimensions, StyleSheet } from "react-native";
3-
import QRCode from "react-native-qrcode-svg";
4-
import { useSharedValue } from "react-native-reanimated";
1+
import { type FC } from "react";
2+
import { Dimensions } from "react-native";
3+
import Animated, { useSharedValue } from "react-native-reanimated";
54
import Carousel from "react-native-reanimated-carousel";
65
import { useSafeAreaInsets } from "react-native-safe-area-context";
76

8-
import { useCharacter, useNote } from "@crossbell/indexer";
9-
import { HeaderHeightContext } from "@react-navigation/elements";
7+
import { useCharacter } from "@crossbell/indexer";
108
import { Canvas, LinearGradient, Rect, vec } from "@shopify/react-native-skia";
11-
import type { NoteEntity } from "crossbell";
129
import { Image } from "expo-image";
1310
import moment from "moment";
14-
import { SizableText, Spacer, Stack, Text, Theme, View, XStack, YStack } from "tamagui";
11+
import { SizableText, Spacer, Stack, Text, XStack, YStack } from "tamagui";
1512

1613
import { Avatar } from "@/components/Avatar";
1714
import { CarouselPagination } from "@/components/CarouselPagination";
1815
import { bgs } from "@/constants/bgs";
19-
import { useCoverImage } from "@/hooks/use-cover-image";
2016
import { useThemeStore } from "@/hooks/use-theme-store";
21-
import { useGetPage } from "@/queries/page";
2217
import type { ExpandedNote } from "@/types/crossbell";
2318
import { withCompressedImage } from "@/utils/get-compressed-image-url";
24-
import { getNoteSlug } from "@/utils/get-slug";
2519
import { toGateway } from "@/utils/ipfs-parser";
2620
import { isShortNotes } from "@/utils/is-short-notes";
2721

22+
import { I18nSwitcher } from "./I18nSwitcher";
23+
2824
interface Props {
2925
isCapturing: boolean
3026
headerContainerHeight: number
3127
postUri?: string
32-
note: NoteEntity
28+
note: ExpandedNote
3329
characterId: number
3430
placeholderCoverImageIndex: number
3531
coverImage: string
@@ -67,25 +63,24 @@ export const Header: FC<Props> = (props) => {
6763
? attachments.map(attachment => withCompressedImage(toGateway(attachment.address), "high")).filter(Boolean)
6864
: [coverImage];
6965

70-
const userinfoEle = (
71-
<Stack minHeight={28}>
72-
{
73-
character?.data && (
74-
<XStack alignItems="center" gap={"$2"} marginBottom={"$1"}>
75-
<Avatar character={character.data} useDefault size={26}/>
76-
<XStack alignItems="center" gap="$4">
77-
<SizableText size="$3" color={"$color"}>
78-
{character.data?.metadata?.content?.name || character.data?.handle}
79-
</SizableText>
80-
<SizableText size="$3" color={"#929190"}>
81-
{moment(note?.createdAt).format("YYYY-MM-DD")}
82-
</SizableText>
83-
</XStack>
66+
const userinfoEle = (<XStack minHeight={28} justifyContent="space-between" alignItems="center" >
67+
{character?.data && (
68+
<XStack animation={"quick"} enterStyle={{ opacity: 0 }} opacity={1} justifyContent="space-between" alignItems="center" flex={1}>
69+
<XStack alignItems="center" gap={"$2"} marginBottom={"$1"}>
70+
<Avatar character={character.data} useDefault size={26}/>
71+
<XStack alignItems="center" gap="$4">
72+
<SizableText size="$3" color={"$color"}>
73+
{character.data?.metadata?.content?.name || character.data?.handle}
74+
</SizableText>
75+
<SizableText size="$3" color={"#929190"}>
76+
{moment(note?.createdAt).format("YYYY-MM-DD")}
77+
</SizableText>
8478
</XStack>
85-
)
86-
}
87-
</Stack>
88-
);
79+
</XStack>
80+
<I18nSwitcher note={note}/>
81+
</XStack>
82+
)}
83+
</XStack>);
8984

9085
return (
9186
<YStack backgroundColor={isDarkMode ? "black" : "white"} marginBottom={isShort ? 0 : 50} paddingTop={isShort ? top : 0}>
@@ -111,7 +106,7 @@ export const Header: FC<Props> = (props) => {
111106
{
112107
isShort
113108
? (
114-
<YStack paddingHorizontal="$2" paddingTop="$2">
109+
<YStack paddingHorizontal="$2" paddingTop="$2" flex={1}>
115110
{
116111
data.length > 1 && (
117112
<Stack alignItems="center" paddingVertical="$3">
@@ -136,7 +131,7 @@ export const Header: FC<Props> = (props) => {
136131
</YStack>
137132
)
138133
: (
139-
<YStack gap="$4" position="absolute" bottom={-40} paddingHorizontal="$2">
134+
<YStack gap="$4" position="absolute" bottom={-40} paddingHorizontal="$2" flex={1} width={"100%"} paddingRight="$3">
140135
<Text fontSize={24} fontWeight={"700"} numberOfLines={2} color="white">{noteTitle}</Text>
141136
{userinfoEle}
142137
</YStack>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { useState, type FC, useCallback } from "react";
2+
import { Trans, useTranslation } from "react-i18next";
3+
4+
import { Languages } from "@tamagui/lucide-icons";
5+
import { Text } from "tamagui";
6+
7+
import { AlertDialog } from "@/components/AlertDialog";
8+
import { Button } from "@/components/Base/Button";
9+
import { DelayedRender } from "@/components/DelayRender";
10+
import { XTouch } from "@/components/XTouch";
11+
import type { ExpandedNote } from "@/types/crossbell";
12+
13+
export const I18nSwitcher: FC<{
14+
note: ExpandedNote
15+
}> = ({ note }) => {
16+
const [modalVisible, setModalVisible] = useState(false);
17+
const i18n = useTranslation("translation");
18+
19+
const openModal = useCallback(() => {
20+
setModalVisible(true);
21+
}, []);
22+
23+
const closeModal = useCallback(() => {
24+
setModalVisible(false);
25+
}, []);
26+
27+
if (!note.metadata.content.translatedFrom || !note.metadata.content.translatedTo) return null;
28+
29+
return (
30+
<>
31+
<XTouch onPress={openModal}>
32+
<Languages size={16} color={"#929190"} />
33+
</XTouch>
34+
<DelayedRender when={modalVisible}>
35+
<AlertDialog
36+
visible={modalVisible}
37+
title={undefined}
38+
containerStyle={{
39+
paddingHorizontal: 4,
40+
}}
41+
description={(
42+
<Text lineHeight={"$2"}>
43+
<Trans
44+
i18nKey={"Translated by"}
45+
ns="translation"
46+
values={{
47+
from: i18n.t(note.metadata.content.translatedFrom),
48+
to: i18n.t(note.metadata.content.translatedTo),
49+
}}
50+
/>
51+
</Text>
52+
)}
53+
renderCancel={null}
54+
renderConfirm={() => (
55+
<Button size={"$3"} backgroundColor={"$primary"} onPress={closeModal}>{i18n.t("Cancel", { ns: "common" })}</Button>
56+
)}
57+
/>
58+
</DelayedRender>
59+
</>
60+
);
61+
};

src/pages/PostDetails/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { usePostWebViewLink } from "@/hooks/use-post-link";
1313
import { useScrollVisibilityHandler } from "@/hooks/use-scroll-visibility-handler";
1414
import { useThemeStore } from "@/hooks/use-theme-store";
1515
import type { RootStackParamList } from "@/navigation/types";
16+
import type { ExpandedNote } from "@/types/crossbell";
1617
import { GA } from "@/utils/GA";
1718

1819
import type { BottomSheetModalInstance } from "./BottomSheetModal";
@@ -24,7 +25,7 @@ import { Navigator } from "./Navigator";
2425

2526
export interface Props {
2627
characterId: number
27-
note: NoteEntity
28+
note: ExpandedNote
2829
coverImage?: string
2930
placeholderCoverImageIndex?: number
3031
}

src/types/crossbell.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ export type ExpandedNote = NoteEntity & {
109109
images?: string[]
110110
imageDimensions?: Record<string, { width: number; height: number }>
111111
frontMatter?: Record<string, any>
112+
translatedFrom?: string
113+
translatedTo?: string
112114
slug?: string
113115
audio?: string
114116
score?: {

0 commit comments

Comments
 (0)