feat(mobile): discoverLanguage ui setting
This commit is contained in:
parent
ebfdda7c2e
commit
7702d8a459
|
|
@ -1,9 +1,14 @@
|
|||
import { defaultUISettings } from "@follow/shared/src/settings/defaults"
|
||||
import type { UISettings } from "@follow/shared/src/settings/interface"
|
||||
|
||||
import { getDeviceLanguage } from "@/src/lib/i18n"
|
||||
|
||||
import { createSettingAtom } from "./internal/helper"
|
||||
|
||||
export const createDefaultSettings = (): UISettings => defaultUISettings
|
||||
export const createDefaultSettings = (): UISettings => ({
|
||||
...defaultUISettings,
|
||||
discoverLanguage: getDeviceLanguage().startsWith("zh") ? "all" : "eng",
|
||||
})
|
||||
|
||||
export const {
|
||||
useSettingKey: useUISettingKey,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import type { RSSHubCategory } from "@follow/constants"
|
||||
import { CategoryMap, RSSHubCategories } from "@follow/constants"
|
||||
import { LinearGradient } from "expo-linear-gradient"
|
||||
import { memo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Pressable, StyleSheet, Text, View } from "react-native"
|
||||
|
||||
import { Grid } from "@/src/components/ui/grid"
|
||||
import { ItemPressable } from "@/src/components/ui/pressable/ItemPressable"
|
||||
import { FilterCuteReIcon } from "@/src/icons/filter_cute_re"
|
||||
import { Grid2CuteReIcon } from "@/src/icons/grid_2_cute_re"
|
||||
import { useNavigation } from "@/src/lib/navigation/hooks"
|
||||
import { Recommendations } from "@/src/modules/discover/Recommendations"
|
||||
import { RecommendationCategoryScreen } from "@/src/screens/(stack)/recommendation/RecommendationCategoryScreen"
|
||||
|
||||
export const Category = () => {
|
||||
return (
|
||||
<>
|
||||
<View className="mt-4 flex-row items-center justify-between pb-1 pl-6 pr-5 pt-4">
|
||||
<View className="flex-row items-center gap-2">
|
||||
<Grid2CuteReIcon width={24} height={24} />
|
||||
<Text className="text-label text-2xl font-bold leading-[1.1]">Categories</Text>
|
||||
</View>
|
||||
<ItemPressable className="rounded-lg p-1">
|
||||
<FilterCuteReIcon width={20} height={20} />
|
||||
</ItemPressable>
|
||||
</View>
|
||||
|
||||
<Grid columns={2} gap={12} className="p-4">
|
||||
{RSSHubCategories.map((category) => (
|
||||
<CategoryItem key={category} category={category} />
|
||||
))}
|
||||
</Grid>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const CategoryItem = memo(({ category }: { category: RSSHubCategory }) => {
|
||||
const { t } = useTranslation("common")
|
||||
const name = t(`discover.category.${category}`)
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
className="overflow-hidden rounded-2xl"
|
||||
key={category}
|
||||
onPress={() => {
|
||||
if (category === "all") {
|
||||
navigation.pushControllerView(Recommendations)
|
||||
} else {
|
||||
navigation.pushControllerView(RecommendationCategoryScreen, {
|
||||
category,
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[`${CategoryMap[category].color}80`, CategoryMap[category].color]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 0, y: 1 }}
|
||||
className="rounded-2xl p-4"
|
||||
style={styles.cardItem}
|
||||
>
|
||||
<View className="flex-1">
|
||||
<Text className="absolute right-2 top-2 text-4xl">{CategoryMap[category].emoji}</Text>
|
||||
<Text className="absolute bottom-0 left-2 text-xl font-bold text-white">{name}</Text>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
cardItem: {
|
||||
aspectRatio: 16 / 9,
|
||||
},
|
||||
})
|
||||
|
|
@ -1,97 +1,13 @@
|
|||
import type { RSSHubCategory } from "@follow/constants"
|
||||
import { CategoryMap, RSSHubCategories } from "@follow/constants"
|
||||
import { LinearGradient } from "expo-linear-gradient"
|
||||
import { memo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Pressable, StyleSheet, Text, View } from "react-native"
|
||||
import { View } from "react-native"
|
||||
|
||||
import { Grid } from "@/src/components/ui/grid"
|
||||
// import { ItemPressable } from "@/src/components/ui/pressable/ItemPressable"
|
||||
// import { FilterCuteReIcon } from "@/src/icons/filter_cute_re"
|
||||
import { Grid2CuteReIcon } from "@/src/icons/grid_2_cute_re"
|
||||
import { TrendingUpCuteReIcon } from "@/src/icons/trending_up_cute_re"
|
||||
import { useNavigation } from "@/src/lib/navigation/hooks"
|
||||
import { Recommendations } from "@/src/modules/discover/Recommendations"
|
||||
import { Category } from "@/src/modules/discover/Category"
|
||||
import { Trending } from "@/src/modules/discover/Trending"
|
||||
import { RecommendationCategoryScreen } from "@/src/screens/(stack)/recommendation/RecommendationCategoryScreen"
|
||||
|
||||
export function DiscoverContent() {
|
||||
return (
|
||||
<View>
|
||||
<View className="flex-row items-center justify-between pb-1 pl-6 pr-5 pt-4">
|
||||
<View className="flex-row items-center gap-2">
|
||||
<TrendingUpCuteReIcon width={24} height={24} />
|
||||
<Text className="text-label text-2xl font-bold leading-[1.1]">Trending</Text>
|
||||
</View>
|
||||
{/* <ItemPressable className="rounded-lg p-1">
|
||||
<FilterCuteReIcon width={20} height={20} />
|
||||
</ItemPressable> */}
|
||||
</View>
|
||||
|
||||
<Trending className="mt-4" itemClassName="px-6" />
|
||||
|
||||
<View className="mt-4 flex-row items-center justify-between pb-1 pl-6 pr-5 pt-4">
|
||||
<View className="flex-row items-center gap-2">
|
||||
<Grid2CuteReIcon width={24} height={24} />
|
||||
<Text className="text-label text-2xl font-bold leading-[1.1]">Categories</Text>
|
||||
</View>
|
||||
{/* <ItemPressable className="rounded-lg p-1">
|
||||
<FilterCuteReIcon width={20} height={20} />
|
||||
</ItemPressable> */}
|
||||
</View>
|
||||
|
||||
<DiscoverGrid />
|
||||
<Trending itemClassName="px-6" />
|
||||
<Category />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const DiscoverGrid = () => {
|
||||
return (
|
||||
<Grid columns={2} gap={12} className="p-4">
|
||||
{RSSHubCategories.map((category) => (
|
||||
<CategoryItem key={category} category={category} />
|
||||
))}
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
const CategoryItem = memo(({ category }: { category: RSSHubCategory }) => {
|
||||
const { t } = useTranslation("common")
|
||||
const name = t(`discover.category.${category}`)
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
className="overflow-hidden rounded-2xl"
|
||||
key={category}
|
||||
onPress={() => {
|
||||
if (category === "all") {
|
||||
navigation.pushControllerView(Recommendations)
|
||||
} else {
|
||||
navigation.pushControllerView(RecommendationCategoryScreen, {
|
||||
category,
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[`${CategoryMap[category].color}80`, CategoryMap[category].color]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 0, y: 1 }}
|
||||
className="rounded-2xl p-4"
|
||||
style={styles.cardItem}
|
||||
>
|
||||
<View className="flex-1">
|
||||
<Text className="absolute right-2 top-2 text-4xl">{CategoryMap[category].emoji}</Text>
|
||||
<Text className="absolute bottom-0 left-2 text-xl font-bold text-white">{name}</Text>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
cardItem: {
|
||||
aspectRatio: 16 / 9,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import type { SharedValue } from "react-native-reanimated"
|
|||
import { useSharedValue } from "react-native-reanimated"
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context"
|
||||
|
||||
import { useUISettingKey } from "@/src/atoms/settings/ui"
|
||||
import { AnimatedScrollView } from "@/src/components/common/AnimatedComponents"
|
||||
import { BlurEffect } from "@/src/components/common/BlurEffect"
|
||||
import { UINavigationHeaderActionButton } from "@/src/components/layouts/header/NavigationHeader"
|
||||
|
|
@ -117,6 +118,12 @@ export const Recommendations = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const LanguageMap = {
|
||||
all: "all",
|
||||
eng: "en",
|
||||
cmn: "zh-CN",
|
||||
} as const
|
||||
|
||||
export const RecommendationTab: TabComponent<{
|
||||
contentContainerStyle?: ContentStyle
|
||||
insets?: { top?: number; bottom?: number }
|
||||
|
|
@ -129,9 +136,12 @@ export const RecommendationTab: TabComponent<{
|
|||
insets: customInsets,
|
||||
...rest
|
||||
}) => {
|
||||
const discoverLanguage = useUISettingKey("discoverLanguage")
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ["rsshub-popular", "cache", tab.value],
|
||||
queryFn: () => fetchRsshubPopular(tab.value, "all").then((res) => res.data),
|
||||
queryFn: () =>
|
||||
fetchRsshubPopular(tab.value, LanguageMap[discoverLanguage]).then((res) => res.data),
|
||||
})
|
||||
const keys = useMemo(() => {
|
||||
if (!data) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
import { cn } from "@follow/utils"
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Text, View } from "react-native"
|
||||
|
||||
import { useUISettingKey } from "@/src/atoms/settings/ui"
|
||||
import { PlatformActivityIndicator } from "@/src/components/ui/loading/PlatformActivityIndicator"
|
||||
import { ItemPressableStyle } from "@/src/components/ui/pressable/enum"
|
||||
import { ItemPressable } from "@/src/components/ui/pressable/ItemPressable"
|
||||
import { FilterCuteReIcon } from "@/src/icons/filter_cute_re"
|
||||
import { TrendingUpCuteReIcon } from "@/src/icons/trending_up_cute_re"
|
||||
|
||||
import { fetchFeedTrending } from "./api"
|
||||
import { FeedSummary } from "./FeedSummary"
|
||||
|
|
@ -15,51 +19,63 @@ export const Trending = ({
|
|||
className?: string
|
||||
itemClassName?: string
|
||||
}) => {
|
||||
const { i18n } = useTranslation()
|
||||
const discoverLanguage = useUISettingKey("discoverLanguage")
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ["trending", "feeds"],
|
||||
queryFn: () =>
|
||||
fetchFeedTrending({
|
||||
lang: i18n.language.startsWith("zh") ? undefined : "eng",
|
||||
lang: discoverLanguage === "all" ? undefined : discoverLanguage,
|
||||
limit: 20,
|
||||
}).then((res) => res.data),
|
||||
})
|
||||
|
||||
return (
|
||||
<View className={className}>
|
||||
{isLoading ? (
|
||||
<View className="mt-5 flex h-12 items-center justify-center">
|
||||
<PlatformActivityIndicator />
|
||||
<View className={cn("flex-row items-center justify-between pb-1 pt-4", itemClassName)}>
|
||||
<View className="flex-row items-center gap-2">
|
||||
<TrendingUpCuteReIcon width={24} height={24} />
|
||||
<Text className="text-label text-2xl font-bold leading-[1.1]">Trending</Text>
|
||||
</View>
|
||||
) : (
|
||||
data?.map((item, index) => (
|
||||
<FeedSummary
|
||||
key={item.feed?.id}
|
||||
item={item}
|
||||
className={cn("flex flex-1 flex-row items-center bg-none py-3", itemClassName)}
|
||||
simple
|
||||
preChildren={
|
||||
<View
|
||||
className={cn(
|
||||
"mr-4 flex size-6 items-center justify-center rounded-full",
|
||||
index < 3
|
||||
? cn(
|
||||
"bg-accent text-white",
|
||||
index === 0 && "bg-accent",
|
||||
index === 1 && "bg-accent/90",
|
||||
index === 2 && "bg-accent/80",
|
||||
)
|
||||
: "bg-gray-5/60",
|
||||
)}
|
||||
>
|
||||
<Text className={cn("text-xs font-medium", index < 3 && "text-white")}>
|
||||
{index + 1}
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
<ItemPressable className="rounded-lg p-1" itemStyle={ItemPressableStyle.UnStyled}>
|
||||
<FilterCuteReIcon width={20} height={20} />
|
||||
</ItemPressable>
|
||||
</View>
|
||||
|
||||
<View className="mt-4">
|
||||
{isLoading ? (
|
||||
<View className="mt-5 flex h-12 items-center justify-center">
|
||||
<PlatformActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
data?.map((item, index) => (
|
||||
<FeedSummary
|
||||
key={item.feed?.id}
|
||||
item={item}
|
||||
className={cn("flex flex-1 flex-row items-center bg-none py-3", itemClassName)}
|
||||
simple
|
||||
preChildren={
|
||||
<View
|
||||
className={cn(
|
||||
"mr-4 flex size-6 items-center justify-center rounded-full",
|
||||
index < 3
|
||||
? cn(
|
||||
"bg-accent text-white",
|
||||
index === 0 && "bg-accent",
|
||||
index === 1 && "bg-accent/90",
|
||||
index === 2 && "bg-accent/80",
|
||||
)
|
||||
: "bg-gray-5/60",
|
||||
)}
|
||||
>
|
||||
<Text className={cn("text-xs font-medium", index < 3 && "text-white")}>
|
||||
{index + 1}
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue