From f52338ce331293411038fb4660f7bb0d635c8401 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:30:23 +0800 Subject: [PATCH 01/13] fix: check view --- apps/mobile/src/store/entry/store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mobile/src/store/entry/store.ts b/apps/mobile/src/store/entry/store.ts index 41a8d01b78..571df4f77a 100644 --- a/apps/mobile/src/store/entry/store.ts +++ b/apps/mobile/src/store/entry/store.ts @@ -63,7 +63,7 @@ class EntryActions { } const subscription = getSubscription(feedId) - if (subscription?.view) { + if (typeof subscription?.view === "number") { draft.entryIdByView[subscription.view].add(entryId) } if (subscription?.category) { From 0014aebd4e84b9ae440f8b9b2af838ccf7ad951d Mon Sep 17 00:00:00 2001 From: Innei Date: Mon, 20 Jan 2025 16:33:04 +0800 Subject: [PATCH 02/13] feat(settings): enhance settings screen with animated header and blur effect - Introduced a new `SettingHeader` component that animates based on scroll position. - Added a `BlurEffect` to the header for improved visual aesthetics. - Refactored the `Settings` component to include the new header and maintain scroll functionality. - Updated imports to include necessary components for animation and styling. This update improves the user experience by providing a dynamic header that responds to scrolling. Signed-off-by: Innei --- .../src/modules/settings/routes/Privacy.tsx | 12 +++-- .../src/screens/(stack)/(tabs)/settings.tsx | 54 +++++++++++++------ 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/apps/mobile/src/modules/settings/routes/Privacy.tsx b/apps/mobile/src/modules/settings/routes/Privacy.tsx index 047e8b2b0d..52c8cdad7e 100644 --- a/apps/mobile/src/modules/settings/routes/Privacy.tsx +++ b/apps/mobile/src/modules/settings/routes/Privacy.tsx @@ -1,9 +1,13 @@ -import { Text, View } from "react-native" +import { ScrollView } from "react-native" + +import { GroupedInsetListCard, GroupedInsetListItem } from "@/src/components/ui/grouped/GroupedList" export const PrivacyScreen = () => { return ( - - Privacy Settings - + + + + + ) } diff --git a/apps/mobile/src/screens/(stack)/(tabs)/settings.tsx b/apps/mobile/src/screens/(stack)/(tabs)/settings.tsx index d4554f3308..736279b1fd 100644 --- a/apps/mobile/src/screens/(stack)/(tabs)/settings.tsx +++ b/apps/mobile/src/screens/(stack)/(tabs)/settings.tsx @@ -3,12 +3,14 @@ import { useIsFocused } from "@react-navigation/native" import { createNativeStackNavigator } from "@react-navigation/native-stack" import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react" import type { NativeScrollEvent, NativeSyntheticEvent, ScrollView } from "react-native" -import { findNodeHandle, UIManager } from "react-native" -import { useSharedValue, withTiming } from "react-native-reanimated" +import { findNodeHandle, Text, UIManager } from "react-native" +import type { SharedValue } from "react-native-reanimated" +import Animated, { useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated" import { useSafeAreaInsets } from "react-native-safe-area-context" import { useEventCallback } from "usehooks-ts" import { ReAnimatedScrollView } from "@/src/components/common/AnimatedComponents" +import { BlurEffect } from "@/src/components/common/HeaderBlur" import { BottomTabBarBackgroundContext } from "@/src/contexts/BottomTabBarBackgroundContext" import { SetBottomTabBarVisibleContext } from "@/src/contexts/BottomTabBarVisibleContext" import { SettingRoutes } from "@/src/modules/settings/routes" @@ -92,20 +94,42 @@ function Settings() { const scrollRef = useRef(null) return ( - { - setContentSize({ height: h, width: w }) - }} - style={{ paddingTop: insets.top }} - className="bg-system-grouped-background flex-1" - scrollIndicatorInsets={{ bottom: tabBarHeight - insets.bottom }} + <> + { + setContentSize({ height: h, width: w }) + }} + style={{ paddingTop: insets.top }} + className="bg-system-grouped-background flex-1" + scrollIndicatorInsets={{ bottom: tabBarHeight - insets.bottom }} + > + + + + + + + ) +} + +const SettingHeader = ({ scrollY }: { scrollY: SharedValue }) => { + const styles = useAnimatedStyle(() => { + return { + opacity: scrollY.value / 100, + } + }) + return ( + - + - - + Settings + ) } From 69d4c863b1d0af21361bda0ee1cf8b54a2d79b61 Mon Sep 17 00:00:00 2001 From: Innei Date: Mon, 20 Jan 2025 17:19:32 +0800 Subject: [PATCH 03/13] refactor(rn-base): split some ui components Signed-off-by: Innei --- .../src/components/common/BlurEffect.tsx | 34 ++++++++++ .../src/components/common/HeaderBlur.tsx | 16 ----- .../common/SafeNavigationScrollView.tsx | 63 ++++++++++++++++--- .../components/ui/dropdown/DropdownMenu.tsx | 52 +++++++++++++++ .../src/components/ui/form/PickerIos.tsx | 2 +- apps/mobile/src/components/ui/form/Select.tsx | 22 +++---- .../components/ui/typography/MarkdownWeb.tsx | 1 - apps/mobile/src/modules/discover/search.tsx | 2 +- .../mobile/src/modules/feed-drawer/header.tsx | 2 +- .../src/modules/settings/routes/Privacy.tsx | 23 +++++-- .../src/modules/settings/routes/Profile.tsx | 2 +- .../modules/subscription/header-actions.tsx | 12 ++-- apps/mobile/src/screens/(headless)/teams.tsx | 21 ++++++- .../src/screens/(modal)/rsshub-form.tsx | 5 +- .../src/screens/(stack)/(tabs)/index.tsx | 2 +- .../src/screens/(stack)/(tabs)/settings.tsx | 2 +- .../screens/(stack)/feeds/[feedId]/index.tsx | 2 +- 17 files changed, 203 insertions(+), 60 deletions(-) create mode 100644 apps/mobile/src/components/common/BlurEffect.tsx delete mode 100644 apps/mobile/src/components/common/HeaderBlur.tsx create mode 100644 apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx diff --git a/apps/mobile/src/components/common/BlurEffect.tsx b/apps/mobile/src/components/common/BlurEffect.tsx new file mode 100644 index 0000000000..aff6b96efe --- /dev/null +++ b/apps/mobile/src/components/common/BlurEffect.tsx @@ -0,0 +1,34 @@ +import { StyleSheet } from "react-native" +import { useColor } from "react-native-uikit-colors" + +import { ThemedBlurView } from "@/src/components/common/ThemedBlurView" + +const node = ( + +) +export const BlurEffect = () => { + return node +} + +const InternalBlurEffectWithBottomBorder = () => { + const border = useColor("opaqueSeparator") + return ( + + ) +} + +export const BlurEffectWithBottomBorder = () => diff --git a/apps/mobile/src/components/common/HeaderBlur.tsx b/apps/mobile/src/components/common/HeaderBlur.tsx deleted file mode 100644 index 06f8f01592..0000000000 --- a/apps/mobile/src/components/common/HeaderBlur.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { StyleSheet } from "react-native" - -import { ThemedBlurView } from "@/src/components/common/ThemedBlurView" - -const node = ( - -) -export const BlurEffect = () => { - return node -} diff --git a/apps/mobile/src/components/common/SafeNavigationScrollView.tsx b/apps/mobile/src/components/common/SafeNavigationScrollView.tsx index 089e8f3d86..54783fbebf 100644 --- a/apps/mobile/src/components/common/SafeNavigationScrollView.tsx +++ b/apps/mobile/src/components/common/SafeNavigationScrollView.tsx @@ -1,20 +1,65 @@ import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs" import { useHeaderHeight } from "@react-navigation/elements" +import { router, Stack, useNavigation } from "expo-router" import type { FC } from "react" import type { ScrollViewProps } from "react-native" -import { ScrollView, View } from "react-native" +import { ScrollView, TouchableOpacity, View } from "react-native" import { useSafeAreaInsets } from "react-native-safe-area-context" +import { useColor } from "react-native-uikit-colors" -export const SafeNavigationScrollView: FC = ({ children, ...props }) => { - const headerHeight = useHeaderHeight() - const tabBarHeight = useBottomTabBarHeight() +import { MingcuteLeftLineIcon } from "@/src/icons/mingcute_left_line" + +import { BlurEffectWithBottomBorder } from "./BlurEffect" + +type SafeNavigationScrollViewProps = ScrollViewProps & { + withHeaderBlur?: boolean +} + +export const SafeNavigationScrollView: FC = ({ + children, + + withHeaderBlur = true, + ...props +}) => { const insets = useSafeAreaInsets() + const tabBarHeight = useBottomTabBarHeight() + const headerHeight = useHeaderHeight() return ( - - - {children} - - + <> + {withHeaderBlur && } + + + {children} + + + + ) +} + +export interface NavigationBlurEffectHeaderProps { + title?: string +} +export const NavigationBlurEffectHeader = (props: NavigationBlurEffectHeaderProps) => { + const label = useColor("label") + + const canBack = useNavigation().canGoBack() + + return ( + ( + router.back()}> + + + ) + : undefined, + title: props.title, + }} + /> ) } diff --git a/apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx b/apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx new file mode 100644 index 0000000000..1e5379066c --- /dev/null +++ b/apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx @@ -0,0 +1,52 @@ +import type { NativeSyntheticEvent } from "react-native" +import type { ContextMenuOnPressNativeEvent } from "react-native-context-menu-view" +import ContextMenu from "react-native-context-menu-view" + +interface DropdownMenuAction { + title: string + actions?: DropdownMenuAction[] + selected?: boolean +} + +interface DropdownMenuSelector { + label: string + value: T +} + +export function DropdownMenu({ + options, + currentValue, + handleChangeValue, + handlePress, + children, +}: { + options: DropdownMenuSelector[] | DropdownMenuAction[] + currentValue?: T + handleChangeValue?: (value: T) => void + handlePress?: (e: NativeSyntheticEvent) => void + children: React.ReactNode +}) { + const isActionMenu = options.every((option) => "title" in option) + return ( + ({ + title: option.label, + selected: option.value === currentValue, + })) + } + onPress={(e) => { + if (!isActionMenu) { + const { index } = e.nativeEvent + handleChangeValue?.(options[index]!.value) + } + handlePress?.(e) + }} + > + {children} + + ) +} diff --git a/apps/mobile/src/components/ui/form/PickerIos.tsx b/apps/mobile/src/components/ui/form/PickerIos.tsx index 9456ce60f4..bf8cbe5eab 100644 --- a/apps/mobile/src/components/ui/form/PickerIos.tsx +++ b/apps/mobile/src/components/ui/form/PickerIos.tsx @@ -11,7 +11,7 @@ import { useEventCallback } from "usehooks-ts" import { MingcuteDownLineIcon } from "@/src/icons/mingcute_down_line" import { useColor } from "@/src/theme/colors" -import { BlurEffect } from "../../common/HeaderBlur" +import { BlurEffect } from "../../common/BlurEffect" interface PickerIosProps { options: { label: string; value: T }[] diff --git a/apps/mobile/src/components/ui/form/Select.tsx b/apps/mobile/src/components/ui/form/Select.tsx index ccd1d8fa4b..5e5309ac5b 100644 --- a/apps/mobile/src/components/ui/form/Select.tsx +++ b/apps/mobile/src/components/ui/form/Select.tsx @@ -2,12 +2,12 @@ import { cn } from "@follow/utils" import { useEffect, useMemo, useState } from "react" import type { StyleProp, ViewStyle } from "react-native" import { Text, View } from "react-native" -import ContextMenu from "react-native-context-menu-view" import { useEventCallback } from "usehooks-ts" import { MingcuteDownLineIcon } from "@/src/icons/mingcute_down_line" import { accentColor } from "@/src/theme/colors" +import { DropdownMenu } from "../dropdown/DropdownMenu" import { FormLabel } from "./Label" interface SelectProps { @@ -53,20 +53,18 @@ export function Select({ }, []) return ( - + {!!label && } + {/* Trigger */} - ({ - title: option.label, - selected: option.value === currentValue, + + options={options.map((option) => ({ + label: option.label, + value: option.value, }))} - onPress={(e) => { - const { index } = e.nativeEvent - handleChangeValue(options[index]!.value) - }} + currentValue={currentValue} + handleChangeValue={handleChangeValue} > ({ - + ) } diff --git a/apps/mobile/src/components/ui/typography/MarkdownWeb.tsx b/apps/mobile/src/components/ui/typography/MarkdownWeb.tsx index 37158ce36a..e09a17e639 100644 --- a/apps/mobile/src/components/ui/typography/MarkdownWeb.tsx +++ b/apps/mobile/src/components/ui/typography/MarkdownWeb.tsx @@ -24,7 +24,6 @@ const MarkdownWeb: WebComponent<{ value: string; style?: React.CSSProperties }> dangerouslySetInnerHTML={{ __html: ` body, html { - height: 100%; overflow: hidden; } `, diff --git a/apps/mobile/src/modules/discover/search.tsx b/apps/mobile/src/modules/discover/search.tsx index 6b1347489b..9d82df9187 100644 --- a/apps/mobile/src/modules/discover/search.tsx +++ b/apps/mobile/src/modules/discover/search.tsx @@ -17,7 +17,7 @@ import { } from "react-native" import { useSafeAreaFrame, useSafeAreaInsets } from "react-native-safe-area-context" -import { BlurEffect } from "@/src/components/common/HeaderBlur" +import { BlurEffect } from "@/src/components/common/BlurEffect" import { Search2CuteReIcon } from "@/src/icons/search_2_cute_re" import { accentColor, useColor } from "@/src/theme/colors" diff --git a/apps/mobile/src/modules/feed-drawer/header.tsx b/apps/mobile/src/modules/feed-drawer/header.tsx index 67471adc9e..57d5676637 100644 --- a/apps/mobile/src/modules/feed-drawer/header.tsx +++ b/apps/mobile/src/modules/feed-drawer/header.tsx @@ -3,7 +3,7 @@ import type { LayoutChangeEvent } from "react-native" import { Text, View } from "react-native" import { useSafeAreaInsets } from "react-native-safe-area-context" -import { BlurEffect } from "@/src/components/common/HeaderBlur" +import { BlurEffect } from "@/src/components/common/BlurEffect" import { useList } from "@/src/store/list/hooks" import { SortActionButton } from "../subscription/header-actions" diff --git a/apps/mobile/src/modules/settings/routes/Privacy.tsx b/apps/mobile/src/modules/settings/routes/Privacy.tsx index 52c8cdad7e..00739ae0b6 100644 --- a/apps/mobile/src/modules/settings/routes/Privacy.tsx +++ b/apps/mobile/src/modules/settings/routes/Privacy.tsx @@ -1,13 +1,26 @@ -import { ScrollView } from "react-native" +import { router } from "expo-router" -import { GroupedInsetListCard, GroupedInsetListItem } from "@/src/components/ui/grouped/GroupedList" +import { + NavigationBlurEffectHeader, + SafeNavigationScrollView, +} from "@/src/components/common/SafeNavigationScrollView" +import { + GroupedInsetListCard, + GroupedInsetListNavigationLink, +} from "@/src/components/ui/grouped/GroupedList" export const PrivacyScreen = () => { return ( - + + - + { + router.push("/teams") + }} + /> - + ) } diff --git a/apps/mobile/src/modules/settings/routes/Profile.tsx b/apps/mobile/src/modules/settings/routes/Profile.tsx index e7c3b1f2d6..a446277e69 100644 --- a/apps/mobile/src/modules/settings/routes/Profile.tsx +++ b/apps/mobile/src/modules/settings/routes/Profile.tsx @@ -7,7 +7,7 @@ import Animated, { useAnimatedScrollHandler, useSharedValue } from "react-native import { useSafeAreaInsets } from "react-native-safe-area-context" import { ReAnimatedScrollView } from "@/src/components/common/AnimatedComponents" -import { BlurEffect } from "@/src/components/common/HeaderBlur" +import { BlurEffect } from "@/src/components/common/BlurEffect" import { FallbackIcon } from "@/src/components/ui/icon/fallback-icon" import type { FeedIconRequiredFeed } from "@/src/components/ui/icon/feed-icon" import { FeedIcon } from "@/src/components/ui/icon/feed-icon" diff --git a/apps/mobile/src/modules/subscription/header-actions.tsx b/apps/mobile/src/modules/subscription/header-actions.tsx index ff8c091f35..ad2cff7a74 100644 --- a/apps/mobile/src/modules/subscription/header-actions.tsx +++ b/apps/mobile/src/modules/subscription/header-actions.tsx @@ -1,7 +1,7 @@ import { TouchableOpacity } from "react-native" import type { ContextMenuAction } from "react-native-context-menu-view" -import ContextMenu from "react-native-context-menu-view" +import { DropdownMenu } from "@/src/components/ui/dropdown/DropdownMenu" import { AZSortAscendingLettersCuteReIcon } from "@/src/icons/AZ_sort_ascending_letters_cute_re" import { AZSortDescendingLettersCuteReIcon } from "@/src/icons/AZ_sort_descending_letters_cute_re" import { Numbers90SortAscendingCuteReIcon } from "@/src/icons/numbers_90_sort_ascending_cute_re" @@ -42,10 +42,10 @@ export const SortActionButton = () => { const Icon = map[sortMethod][sortOrder] return ( - { + { const [firstArgs, secondary] = e.nativeEvent.indexPath switch (firstArgs) { @@ -74,6 +74,6 @@ export const SortActionButton = () => { - + ) } diff --git a/apps/mobile/src/screens/(headless)/teams.tsx b/apps/mobile/src/screens/(headless)/teams.tsx index 03a76ffaa9..395b4a252a 100644 --- a/apps/mobile/src/screens/(headless)/teams.tsx +++ b/apps/mobile/src/screens/(headless)/teams.tsx @@ -1,7 +1,9 @@ -import { Stack } from "expo-router" -import { View } from "react-native" +import { router, Stack, useNavigation } from "expo-router" +import { TouchableOpacity, View } from "react-native" +import { useColor } from "react-native-uikit-colors" import MarkdownWeb from "@/src/components/ui/typography/MarkdownWeb" +import { MingcuteLeftLineIcon } from "@/src/icons/mingcute_left_line" const txt = `# Terms of Service @@ -91,10 +93,23 @@ export const TeamsMarkdown = () => { } export default function Teams() { + const canGoBack = useNavigation().canGoBack() + const label = useColor("label") return ( ( + router.back()}> + + + ) + : undefined, + }} /> diff --git a/apps/mobile/src/screens/(modal)/rsshub-form.tsx b/apps/mobile/src/screens/(modal)/rsshub-form.tsx index 8b054f0987..8cdc53783d 100644 --- a/apps/mobile/src/screens/(modal)/rsshub-form.tsx +++ b/apps/mobile/src/screens/(modal)/rsshub-form.tsx @@ -167,7 +167,6 @@ function FormImpl({ route, routePrefix, name }: RsshubFormParams) { render={({ field: { onChange, value } }) => ( { + setGeneralSetting("translationLanguage", value) + }} + options={Object.values(LanguageMap)} + /> + + + + + {/* Subscriptions */} + + + + + { + setGeneralSetting("autoGroup", value) + }} + /> + + + + { + setGeneralSetting("unreadOnly", value) + }} + /> + + + + { + setGeneralSetting("groupByDate", value) + }} + /> + + + + { + setGeneralSetting("autoExpandLongSocialMedia", value) + }} + /> + + + + {/* Unread */} + + + + + { + setGeneralSetting("scrollMarkUnread", value) + }} + /> + + + + { + setGeneralSetting("renderMarkUnread", value) + }} + /> + + + + + ) } diff --git a/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx b/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx index 7580b1f23c..34ddf9c3ab 100644 --- a/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx +++ b/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx @@ -1,4 +1,5 @@ import { FeedViewType } from "@follow/constants" +import { transformUriPath } from "@follow/utils" import { PlatformPressable } from "@react-navigation/elements/src/PlatformPressable" import { router, Tabs } from "expo-router" import { useContext, useEffect, useMemo, useState } from "react" @@ -36,9 +37,11 @@ export default function TabLayout() { const [tabBarVisible, setTabBarVisible] = useState(true) useEffect(() => { - RNAnimated.spring(animatedTransformY, { + RNAnimated.timing(animatedTransformY, { toValue: tabBarVisible ? 1 : 0, useNativeDriver: true, + duration: 250, + easing: Easing.inOut(Easing.ease), }).start() }, [animatedTransformY, tabBarVisible]) diff --git a/apps/mobile/src/theme/navigation.ts b/apps/mobile/src/theme/navigation.ts index 80c9157905..bf8c512dd2 100644 --- a/apps/mobile/src/theme/navigation.ts +++ b/apps/mobile/src/theme/navigation.ts @@ -11,6 +11,7 @@ export const DefaultTheme: Theme = { colors: { ...NativeDefaultTheme.colors, primary: accentColor, + background: "white", }, } @@ -19,5 +20,6 @@ export const DarkTheme: Theme = { colors: { ...NativeDarkTheme.colors, primary: accentColor, + background: "black", }, } diff --git a/packages/hooks/exports.ts b/packages/hooks/exports.ts index 40f0b93bfb..0e0519b002 100644 --- a/packages/hooks/exports.ts +++ b/packages/hooks/exports.ts @@ -1 +1,2 @@ +export { useRefValue } from "./src/useRefValue" export { useTypeScriptHappyCallback } from "./src/useTypescriptHappyCallback" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a00d127396..813c16da7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -514,6 +514,9 @@ importers: expo-linking: specifier: ~7.0.3 version: 7.0.3(vc5zx7mqwgzirpvpjamp5nboge) + expo-localization: + specifier: ~16.0.1 + version: 16.0.1(expo@52.0.18(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react@18.3.1) expo-router: specifier: 4.0.11 version: 4.0.11(osuwzlrjsxkcgr2xnkwgib4g5q) @@ -8745,12 +8748,6 @@ packages: react: '*' react-native: '*' - expo-constants@17.0.3: - resolution: {integrity: sha512-lnbcX2sAu8SucHXEXxSkhiEpqH+jGrf+TF+MO6sHWIESjwOUVVYlT8qYdjR9xbxWmqFtrI4KV44FkeJf2DaFjQ==} - peerDependencies: - expo: '*' - react-native: '*' - expo-constants@17.0.4: resolution: {integrity: sha512-5c0VlZycmDyQUCMCr3Na3cpHAsVJJ+5o6KkkD4rmATQZ0++Xp/S2gpnjWyEo2riRmO91vxoyHwmAySXuktJddQ==} peerDependencies: @@ -8835,6 +8832,12 @@ packages: react: '*' react-native: '*' + expo-localization@16.0.1: + resolution: {integrity: sha512-kUrXiV/Pq9r7cG+TMt+Qa49IUQ9Y/czVwen4hmiboTclTopcWdIeCzYZv6JGtufoPpjEO9vVx1QJrXYl9V2u0Q==} + peerDependencies: + expo: '*' + react: '*' + expo-manifests@0.15.5: resolution: {integrity: sha512-3X3eQomnTa4G0Y9GoJeyewHPTscuzWMrTB3x4CknqOyXpGOJjOuCKjhzvccHxXZAt0XswqBI94iTbqIofo9Uqw==} peerDependencies: @@ -13298,6 +13301,9 @@ packages: rou3@0.5.1: resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==} + rtl-detect@1.1.2: + resolution: {integrity: sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -17367,7 +17373,7 @@ snapshots: '@expo/config': 10.0.8 '@expo/config-plugins': 9.0.14 '@expo/devcert': 1.1.4 - '@expo/env': 0.4.0 + '@expo/env': 0.4.1 '@expo/image-utils': 0.6.3 '@expo/json-file': 9.0.1 '@expo/metro-config': 0.19.8 @@ -24653,16 +24659,6 @@ snapshots: react: 18.3.1 react-native: 0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1) - expo-constants@17.0.3(4zmahxl5ymv4iqnmz7u7srsqim): - dependencies: - '@expo/config': 10.0.8 - '@expo/env': 0.4.0 - expo: 52.0.23(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1) - react-native: 0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1) - transitivePeerDependencies: - - supports-color - optional: true - expo-constants@17.0.4(4zmahxl5ymv4iqnmz7u7srsqim): dependencies: '@expo/config': 10.0.8 @@ -24789,6 +24785,12 @@ snapshots: - expo - supports-color + expo-localization@16.0.1(expo@52.0.18(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react@18.3.1): + dependencies: + expo: 52.0.18(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1) + react: 18.3.1 + rtl-detect: 1.1.2 + expo-manifests@0.15.5(expo@52.0.18(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1)): dependencies: '@expo/config': 10.0.8 @@ -24977,7 +24979,7 @@ snapshots: '@expo/vector-icons': 14.0.4 babel-preset-expo: 12.0.4(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0)) expo-asset: 11.0.1(q65rno7mdzia6zdespm3xhq57e) - expo-constants: 17.0.3(4zmahxl5ymv4iqnmz7u7srsqim) + expo-constants: 17.0.4(4zmahxl5ymv4iqnmz7u7srsqim) expo-file-system: 18.0.6(4zmahxl5ymv4iqnmz7u7srsqim) expo-font: 13.0.2(expo@52.0.23(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react@18.3.1) expo-keep-awake: 14.0.1(expo@52.0.23(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@expo/metro-runtime@4.0.0(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)))(bufferutil@4.0.8)(encoding@0.1.13)(graphql@16.8.1)(react-native-webview@13.12.5(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react-native@0.76.5(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@react-native-community/cli-server-api@14.1.0(bufferutil@4.0.8))(@types/react@18.3.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1))(react@18.3.1))(react@18.3.1) @@ -30060,6 +30062,8 @@ snapshots: rou3@0.5.1: {} + rtl-detect@1.1.2: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 From aa5d5f56791dce9dae425dc2f4c4db735ce8ab85 Mon Sep 17 00:00:00 2001 From: Innei Date: Tue, 21 Jan 2025 00:12:22 +0800 Subject: [PATCH 10/13] refactor(rn-com): refactor rn switch component Signed-off-by: Innei --- .../src/components/common/ThemedBlurView.tsx | 2 + apps/mobile/src/components/ui/form/Switch.tsx | 2 +- .../src/components/ui/grouped/GroupedList.tsx | 3 +- .../src/components/ui/switch/Switch.tsx | 129 +++++++----------- .../src/screens/(stack)/(tabs)/_layout.tsx | 1 - 5 files changed, 57 insertions(+), 80 deletions(-) diff --git a/apps/mobile/src/components/common/ThemedBlurView.tsx b/apps/mobile/src/components/common/ThemedBlurView.tsx index 7da5c91b0b..f917ab97bb 100644 --- a/apps/mobile/src/components/common/ThemedBlurView.tsx +++ b/apps/mobile/src/components/common/ThemedBlurView.tsx @@ -5,9 +5,11 @@ import { forwardRef } from "react" export const ThemedBlurView = forwardRef(({ tint, ...rest }, ref) => { const { colorScheme } = useColorScheme() + return ( diff --git a/apps/mobile/src/components/ui/form/Switch.tsx b/apps/mobile/src/components/ui/form/Switch.tsx index b724ed52c1..20fa0a280b 100644 --- a/apps/mobile/src/components/ui/form/Switch.tsx +++ b/apps/mobile/src/components/ui/form/Switch.tsx @@ -1,5 +1,5 @@ import { forwardRef } from "react" -import type { StyleProp, Switch as NativeSwitch, ViewStyle } from "react-native" +import type { StyleProp, ViewStyle } from "react-native" import { Text, View } from "react-native" import type { SwitchProps, SwitchRef } from "../switch/Switch" diff --git a/apps/mobile/src/components/ui/grouped/GroupedList.tsx b/apps/mobile/src/components/ui/grouped/GroupedList.tsx index 631417b10f..69c8a4bad1 100644 --- a/apps/mobile/src/components/ui/grouped/GroupedList.tsx +++ b/apps/mobile/src/components/ui/grouped/GroupedList.tsx @@ -3,9 +3,8 @@ import type { FC, PropsWithChildren } from "react" import * as React from "react" import { Fragment } from "react" import type { ViewProps } from "react-native" -import { Pressable, StyleSheet, Switch, Text, View } from "react-native" +import { Pressable, StyleSheet, Text, View } from "react-native" -import { setGeneralSetting } from "@/src/atoms/settings/general" import { RightCuteReIcon } from "@/src/icons/right_cute_re" import { useColor } from "@/src/theme/colors" diff --git a/apps/mobile/src/components/ui/switch/Switch.tsx b/apps/mobile/src/components/ui/switch/Switch.tsx index 0348dc0d2d..fe22f83732 100644 --- a/apps/mobile/src/components/ui/switch/Switch.tsx +++ b/apps/mobile/src/components/ui/switch/Switch.tsx @@ -1,7 +1,14 @@ -import type { useState } from "react" -import { forwardRef, useEffect, useImperativeHandle, useMemo } from "react" +import { forwardRef, useEffect, useImperativeHandle } from "react" import type { SwitchChangeEvent } from "react-native" -import { Animated, Easing, Pressable, StyleSheet, useAnimatedValue, View } from "react-native" +import { Pressable, StyleSheet, View } from "react-native" +import Animated, { + interpolate, + interpolateColor, + useAnimatedStyle, + useSharedValue, + withSpring, + withTiming, +} from "react-native-reanimated" import { accentColor, useColor } from "@/src/theme/colors" @@ -27,83 +34,62 @@ export type SwitchRef = { } export const Switch = forwardRef( ({ value, onValueChange, onChange, size = "default" }, ref) => { - const animatedValue = useAnimatedValue(0) - const circleWidthAnimatedValue = useAnimatedValue(0) - const translateX = useAnimatedValue(0) - const colorAnimatedValue = useAnimatedValue(0) - - useEffect(() => { - Animated.timing(animatedValue, { - toValue: value ? 1 : 0, - duration: 110, - easing: Easing.linear, - useNativeDriver: false, - }).start() - - Animated.timing(colorAnimatedValue, { - toValue: value ? 1 : 0, - duration: 300, - easing: Easing.linear, - useNativeDriver: false, - }).start() - }, [value]) + const progress = useSharedValue(value ? 1 : 0) + const scale = useSharedValue(1) + const translateX = useSharedValue(0) const onTouchStart = () => { - Animated.timing(circleWidthAnimatedValue, { - toValue: 1, - duration: 200, - useNativeDriver: false, - }).start() - if (value) - Animated.timing(translateX, { - toValue: size === "sm" ? -4 : -7, - duration: 200, - useNativeDriver: false, - }).start() + scale.value = withSpring(1.1) + if (value) { + translateX.value = withSpring(size === "sm" ? -4 : -7) + } } const onTouchEnd = () => { - Animated.timing(circleWidthAnimatedValue, { - toValue: 0, - duration: 100, - useNativeDriver: false, - }).start() - Animated.timing(translateX, { - toValue: 0, - duration: 100, - useNativeDriver: false, - }).start() + scale.value = withSpring(1) + translateX.value = withSpring(0) } - const moveToggle = useMemo( - () => - animatedValue.interpolate({ - inputRange: [0, 1], - outputRange: size === "sm" ? [2, 20] : [2.3, 22], - }), - [animatedValue, size], - ) - - const circleWidth = useMemo( - () => - circleWidthAnimatedValue.interpolate({ - inputRange: [0, 1], - outputRange: size === "sm" ? [18, 21] : [27.8, 35], - }), - [circleWidthAnimatedValue, size], - ) - useImperativeHandle(ref, () => ({ value: !!value, })) const activeBgColor = accentColor const inactiveBgColor = useColor("secondarySystemFill") - const bgColor = colorAnimatedValue.interpolate({ - inputRange: [0, 1], - outputRange: [inactiveBgColor, activeBgColor], + + const toggleStyle = useAnimatedStyle(() => { + const backgroundColor = interpolateColor( + progress.value, + [0, 1], + [inactiveBgColor, activeBgColor], + ) + + return { + backgroundColor, + } }) + const circleStyle = useAnimatedStyle(() => { + const marginLeft = interpolate(progress.value, [0, 1], size === "sm" ? [2, 20] : [2.3, 22]) + + const width = interpolate(scale.value, [1, 1.1], size === "sm" ? [18, 21] : [27.8, 35]) + + return { + marginLeft, + width, + transform: [{ translateX: translateX.value }, { translateY: -0.4 }, { scale: scale.value }], + } + }) + + useEffect(() => { + // Update progress when value changes + if (value && progress.value === 0) { + progress.value = withTiming(1) + } else if (!value && progress.value === 1) { + progress.value = withTiming(0) + } + }, [progress, value]) + return ( ( }} > diff --git a/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx b/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx index 34ddf9c3ab..c1eb696810 100644 --- a/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx +++ b/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx @@ -1,5 +1,4 @@ import { FeedViewType } from "@follow/constants" -import { transformUriPath } from "@follow/utils" import { PlatformPressable } from "@react-navigation/elements/src/PlatformPressable" import { router, Tabs } from "expo-router" import { useContext, useEffect, useMemo, useState } from "react" From 11828ea9276e5cbbf77f4a4c5538fc865abb2872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E7=A9=BA=E7=9A=84=E7=9B=A1=E9=A0=AD?= <9551552+ghostendsky@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:03:37 +0800 Subject: [PATCH 11/13] feat(locales): update zh-TW translations (#2621) --- locales/app/zh-TW.json | 4 ++-- locales/errors/zh-TW.json | 2 ++ locales/external/zh-TW.json | 1 + locales/settings/zh-TW.json | 18 ++++++++++++++++++ locales/shortcuts/zh-TW.json | 2 +- 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/locales/app/zh-TW.json b/locales/app/zh-TW.json index b9df31ea17..2fa987cc80 100644 --- a/locales/app/zh-TW.json +++ b/locales/app/zh-TW.json @@ -67,7 +67,7 @@ "discover.feed_maintainers": "由 RSSHub 提供,感謝 的支持", "discover.import.click_to_upload": "點擊上傳 OPML 文件", "discover.import.conflictItems": "衝突項目", - "discover.import.new_import_opml": "如果您以前使用過 RSS,您可以將資料配置匯出到 OPML 文件,並在此處匯入", + "discover.import.new_import_opml": "如果您以前使用過 RSS,您可以將資料配置匯出到 OPML 文件,並在此處匯入", "discover.import.noItems": "沒有項目", "discover.import.opml": "OPML 檔案", "discover.import.parsedErrorItems": "解析錯誤項目", @@ -379,7 +379,7 @@ "tip_modal.no_wallet": "您尚未擁有錢包。請創建錢包以進行贊助。", "tip_modal.tip_amount_sent": "已經發送給作者。", "tip_modal.tip_now": "立刻贊助", - "tip_modal.tip_sent": "贊助成功!謝謝您的支持", + "tip_modal.tip_sent": "贊助成功!謝謝您的支持。", "tip_modal.tip_support": "⭐ 贊助以表示你的支持!", "tip_modal.tip_title": "贊助 Power", "tip_modal.unclaimed_feed": "目前尚無人認領此 RSS 摘要。收到的 Power 將安全的存放在區塊鏈合約中,直到被認領為止。", diff --git a/locales/errors/zh-TW.json b/locales/errors/zh-TW.json index d834c91ab9..c704c2a131 100644 --- a/locales/errors/zh-TW.json +++ b/locales/errors/zh-TW.json @@ -26,6 +26,8 @@ "4004": "目標使用者錢包錯誤", "4005": "每日 power 計算中", "4006": "無效加成數量", + "4007": "無效的雙因素驗證碼", + "4008": "需要雙因素驗證碼", "4010": "空投不符合資格", "4011": "空投正在發送", "4012": "空投已發送", diff --git a/locales/external/zh-TW.json b/locales/external/zh-TW.json index bd7ebe7e67..28ce81c4d5 100644 --- a/locales/external/zh-TW.json +++ b/locales/external/zh-TW.json @@ -55,6 +55,7 @@ "login.signOut": "登出", "login.signUp": "使用電子信箱註冊", "login.submit": "送出", + "login.two_factor.code": "雙因素驗證碼", "login.welcomeTo": "歡迎來到 ", "redirect.continueInBrowser": "在瀏覽器中繼續", "redirect.instruction": "現在是時候打開 {{app_name}} 並安全地關閉此頁面。", diff --git a/locales/settings/zh-TW.json b/locales/settings/zh-TW.json index da9bc90382..8e76c952cd 100644 --- a/locales/settings/zh-TW.json +++ b/locales/settings/zh-TW.json @@ -97,6 +97,11 @@ "appearance.zen_mode.description": "禪定模式是一種防干擾的閱讀模式,你可以專注於內容而不受其他干擾。啟用禪定模式將會隱藏側邊欄。", "appearance.zen_mode.label": "禪定模式", "common.give_star": "喜歡我們的產品嗎? 在 GitHub 上給我們 star 吧!", + "customizeToolbar.more_actions.description": "將顯示在下拉選單中", + "customizeToolbar.more_actions.title": "更多操作", + "customizeToolbar.quick_actions.description": "自訂並重新排列您常用的操作", + "customizeToolbar.quick_actions.title": "快速操作", + "customizeToolbar.reset_layout": "重置為預設版面", "customizeToolbar.title": "自訂工具欄", "data_control.app_cache_limit.description": "程式快取大小的上限。一旦快取達到此上限,最早的項目將被刪除以釋放空間。", "data_control.app_cache_limit.label": "程式快取限制", @@ -284,11 +289,23 @@ "profile.name.description": "你的公開顯示名稱。", "profile.name.label": "顯示名稱", "profile.new_password.label": "新密碼", + "profile.no_password": "重設密碼以設定新密碼。", "profile.password.label": "密碼", "profile.reset_password_mail_sent": "重設密碼信件已發送。", "profile.sidebar_title": "個人資料", "profile.submit": "送出", "profile.title": "個人資料設定", + "profile.totp_code.init": "使用 Authenticator 掃描 QR Code", + "profile.totp_code.invalid": "無效的雙因素驗證碼。", + "profile.totp_code.label": "雙因素驗證碼", + "profile.totp_code.title": "輸入雙因素驗證碼", + "profile.two_factor.disable": "停用雙因素驗證", + "profile.two_factor.disabled": "雙因素驗證已停用。", + "profile.two_factor.enable": "啟用雙因素驗證", + "profile.two_factor.enable_notice": "需要啟用雙因素驗證才能執行此操作。", + "profile.two_factor.enabled": "雙因素驗證已啟用。", + "profile.two_factor.label": "雙因素驗證", + "profile.two_factor.no_password": "啟用雙因素驗證之前需要設定密碼。", "profile.updateSuccess": "個人資料已更新。", "profile.update_password_success": "密碼已更新。", "rsshub.addModal.access_key_label": "存取金鑰(選填)", @@ -304,6 +321,7 @@ "rsshub.table.official": "官方", "rsshub.table.owner": "建立者", "rsshub.table.price": "每月價格", + "rsshub.table.private": "私人", "rsshub.table.unlimited": "無限制", "rsshub.table.use": "使用", "rsshub.table.userCount": "使用者數量", diff --git a/locales/shortcuts/zh-TW.json b/locales/shortcuts/zh-TW.json index 04c1b17943..a88b0dd67a 100644 --- a/locales/shortcuts/zh-TW.json +++ b/locales/shortcuts/zh-TW.json @@ -21,7 +21,7 @@ "keys.feeds.switchToView": "切換到指定類別", "keys.layout.showShortcuts": "顯示/隱藏快捷鍵", "keys.layout.toggleSidebar": "顯示/隱藏摘要側邊欄", - "keys.layout.toggleWideMode": "切換寬屏模式", + "keys.layout.toggleWideMode": "切換寬螢幕模式", "keys.layout.zenMode": "禪定模式", "keys.misc.quickSearch": "快速搜尋", "keys.type.audio": "音訊", From 4d6a5a2acac43f5dee31623e76c78bc5c8e40043 Mon Sep 17 00:00:00 2001 From: Konv Suu <2583695112@qq.com> Date: Tue, 21 Jan 2025 11:03:53 +0800 Subject: [PATCH 12/13] feat(rsshub): add minimum value to input field (#2572) --- apps/renderer/src/modules/rsshub/set-modal-content.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/renderer/src/modules/rsshub/set-modal-content.tsx b/apps/renderer/src/modules/rsshub/set-modal-content.tsx index 5a0fa58813..3f6a0751a4 100644 --- a/apps/renderer/src/modules/rsshub/set-modal-content.tsx +++ b/apps/renderer/src/modules/rsshub/set-modal-content.tsx @@ -131,6 +131,7 @@ export function SetModalContent({ inputMode="numeric" pattern="[0-9]*" max={12} + min={hasPurchase ? 0 : 1} {...field} /> From 166e09563df97b0d23b495dbec38162f37e63083 Mon Sep 17 00:00:00 2001 From: Konv Suu <2583695112@qq.com> Date: Tue, 21 Jan 2025 11:04:18 +0800 Subject: [PATCH 13/13] feat(discover): implement localized search results (#2623) --- apps/renderer/src/modules/discover/form.tsx | 3 +-- locales/app/en.json | 3 +++ locales/app/zh-CN.json | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/renderer/src/modules/discover/form.tsx b/apps/renderer/src/modules/discover/form.tsx index b77a670fde..fb9ae3434f 100644 --- a/apps/renderer/src/modules/discover/form.tsx +++ b/apps/renderer/src/modules/discover/form.tsx @@ -262,8 +262,7 @@ export function DiscoverForm({ type = "search" }: { type?: string }) { {mutation.isSuccess && (
- Found {mutation.data?.length || 0} feed - {mutation.data?.length > 1 && "s"} + {t("discover.search.results", { count: mutation.data?.length || 0 })}
{discoverSearchData?.map((item) => ( diff --git a/locales/app/en.json b/locales/app/en.json index 7fe258c712..2400cdbe2b 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -98,6 +98,9 @@ "discover.preview": "Preview", "discover.rss_hub_route": "RSSHub Route", "discover.rss_url": "RSS URL", + "discover.search.results_one": "Found {{count}} feed", + "discover.search.results_other": "Found {{count}} feeds", + "discover.search.results_zero": "No feeds found", "discover.select_placeholder": "Select", "discover.target.feeds": "Feeds", "discover.target.label": "Search for", diff --git a/locales/app/zh-CN.json b/locales/app/zh-CN.json index 4a50d0c46b..c4a46b4fcc 100644 --- a/locales/app/zh-CN.json +++ b/locales/app/zh-CN.json @@ -98,6 +98,9 @@ "discover.preview": "预览", "discover.rss_hub_route": "RSSHub 路由", "discover.rss_url": "RSS URL", + "discover.search.results_one": "找到 {{count}} 个订阅源", + "discover.search.results_other": "找到 {{count}} 个订阅源", + "discover.search.results_zero": "搜索结果为空", "discover.select_placeholder": "选择", "discover.target.feeds": "订阅源", "discover.target.label": "搜索",