Skip to content

Commit

Permalink
refactor(rn-base): split some ui components
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <tukon479@gmail.com>
  • Loading branch information
Innei committed Jan 20, 2025
1 parent 0014aeb commit 69d4c86
Show file tree
Hide file tree
Showing 17 changed files with 203 additions and 60 deletions.
34 changes: 34 additions & 0 deletions apps/mobile/src/components/common/BlurEffect.tsx
Original file line number Diff line number Diff line change
@@ -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 = (
<ThemedBlurView
style={{

Check warning on line 8 in apps/mobile/src/components/common/BlurEffect.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint and Typecheck (lts/*)

Inline style: { overflow: 'hidden', backgroundColor: 'transparent' }
...StyleSheet.absoluteFillObject,
overflow: "hidden",
backgroundColor: "transparent",
}}
/>
)
export const BlurEffect = () => {
return node
}

const InternalBlurEffectWithBottomBorder = () => {
const border = useColor("opaqueSeparator")
return (
<ThemedBlurView
style={{

Check warning on line 23 in apps/mobile/src/components/common/BlurEffect.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint and Typecheck (lts/*)

Inline style: { overflow: 'hidden', backgroundColor: 'transparent' }
...StyleSheet.absoluteFillObject,
overflow: "hidden",
backgroundColor: "transparent",
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: border,
}}
/>
)
}

export const BlurEffectWithBottomBorder = () => <InternalBlurEffectWithBottomBorder />
16 changes: 0 additions & 16 deletions apps/mobile/src/components/common/HeaderBlur.tsx

This file was deleted.

63 changes: 54 additions & 9 deletions apps/mobile/src/components/common/SafeNavigationScrollView.tsx
Original file line number Diff line number Diff line change
@@ -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<ScrollViewProps> = ({ 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<SafeNavigationScrollViewProps> = ({
children,

withHeaderBlur = true,
...props
}) => {
const insets = useSafeAreaInsets()
const tabBarHeight = useBottomTabBarHeight()
const headerHeight = useHeaderHeight()

return (
<ScrollView contentInsetAdjustmentBehavior="automatic" {...props}>
<View style={{ height: headerHeight - insets.top }} />
<View>{children}</View>
<View style={{ height: tabBarHeight - insets.bottom }} />
</ScrollView>
<>
{withHeaderBlur && <NavigationBlurEffectHeader />}
<ScrollView contentInsetAdjustmentBehavior="automatic" {...props}>
<View style={{ height: headerHeight - insets.top }} />
<View>{children}</View>
<View style={{ height: tabBarHeight - insets.bottom }} />
</ScrollView>
</>
)
}

export interface NavigationBlurEffectHeaderProps {
title?: string
}
export const NavigationBlurEffectHeader = (props: NavigationBlurEffectHeaderProps) => {
const label = useColor("label")

const canBack = useNavigation().canGoBack()

return (
<Stack.Screen
options={{
headerBackground: BlurEffectWithBottomBorder,
headerTransparent: true,

headerLeft: canBack
? () => (
<TouchableOpacity hitSlop={10} onPress={() => router.back()}>
<MingcuteLeftLineIcon height={20} width={20} color={label} />
</TouchableOpacity>
)
: undefined,
title: props.title,
}}
/>
)
}
52 changes: 52 additions & 0 deletions apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -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<T> {
title: string
actions?: DropdownMenuAction<T>[]
selected?: boolean
}

interface DropdownMenuSelector<T> {
label: string
value: T
}

export function DropdownMenu<T>({
options,
currentValue,
handleChangeValue,
handlePress,
children,
}: {
options: DropdownMenuSelector<T>[] | DropdownMenuAction<T>[]
currentValue?: T
handleChangeValue?: (value: T) => void
handlePress?: (e: NativeSyntheticEvent<ContextMenuOnPressNativeEvent>) => void
children: React.ReactNode
}) {
const isActionMenu = options.every((option) => "title" in option)
return (
<ContextMenu
dropdownMenuMode
actions={
isActionMenu
? options
: options.map((option) => ({
title: option.label,
selected: option.value === currentValue,
}))
}
onPress={(e) => {
if (!isActionMenu) {
const { index } = e.nativeEvent
handleChangeValue?.(options[index]!.value)
}
handlePress?.(e)
}}
>
{children}
</ContextMenu>
)
}
2 changes: 1 addition & 1 deletion apps/mobile/src/components/ui/form/PickerIos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
options: { label: string; value: T }[]
Expand Down
22 changes: 10 additions & 12 deletions apps/mobile/src/components/ui/form/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
Expand Down Expand Up @@ -53,20 +53,18 @@ export function Select<T>({
}, [])

return (
<View className="w-full flex-1 flex-row items-center">
<View className="flex-1 flex-row items-center">
{!!label && <FormLabel className="pl-2" label={label} />}

<View className="flex-1" />
{/* Trigger */}
<ContextMenu
dropdownMenuMode
actions={options.map((option) => ({
title: option.label,
selected: option.value === currentValue,
<DropdownMenu<T>
options={options.map((option) => ({
label: option.label,
value: option.value,
}))}
onPress={(e) => {
const { index } = e.nativeEvent
handleChangeValue(options[index]!.value)
}}
currentValue={currentValue}
handleChangeValue={handleChangeValue}
>
<View
className={cn(
Expand All @@ -81,7 +79,7 @@ export function Select<T>({
<MingcuteDownLineIcon color={accentColor} height={18} width={18} />
</View>
</View>
</ContextMenu>
</DropdownMenu>
</View>
)
}
1 change: 0 additions & 1 deletion apps/mobile/src/components/ui/typography/MarkdownWeb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const MarkdownWeb: WebComponent<{ value: string; style?: React.CSSProperties }>
dangerouslySetInnerHTML={{
__html: `
body, html {
height: 100%;
overflow: hidden;
}
`,
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/modules/discover/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/modules/feed-drawer/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
23 changes: 18 additions & 5 deletions apps/mobile/src/modules/settings/routes/Privacy.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<ScrollView>
<SafeNavigationScrollView className="bg-system-grouped-background">
<NavigationBlurEffectHeader title="Privacy" />
<GroupedInsetListCard>
<GroupedInsetListItem />
<GroupedInsetListNavigationLink
label="Teams"
onPress={() => {
router.push("/teams")
}}
/>
</GroupedInsetListCard>
</ScrollView>
</SafeNavigationScrollView>
)
}
2 changes: 1 addition & 1 deletion apps/mobile/src/modules/settings/routes/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 6 additions & 6 deletions apps/mobile/src/modules/subscription/header-actions.tsx
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -42,10 +42,10 @@ export const SortActionButton = () => {

const Icon = map[sortMethod][sortOrder]
return (
<ContextMenu
dropdownMenuMode
actions={actions}
onPress={(e) => {
<DropdownMenu
options={actions}
currentValue={sortMethod}
handlePress={(e) => {
const [firstArgs, secondary] = e.nativeEvent.indexPath

switch (firstArgs) {
Expand Down Expand Up @@ -74,6 +74,6 @@ export const SortActionButton = () => {
<TouchableOpacity className="size-6 rounded-full">
<Icon color={accentColor} />
</TouchableOpacity>
</ContextMenu>
</DropdownMenu>
)
}
21 changes: 18 additions & 3 deletions apps/mobile/src/screens/(headless)/teams.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -91,10 +93,23 @@ export const TeamsMarkdown = () => {
}

export default function Teams() {
const canGoBack = useNavigation().canGoBack()
const label = useColor("label")
return (
<View className="flex-1">
<Stack.Screen
options={{ headerBackTitle: "Login", headerTitle: "Terms of Service", headerShown: true }}
options={{
headerBackTitle: "Login",
headerTitle: "Terms of Service",
headerShown: true,
headerLeft: canGoBack
? () => (
<TouchableOpacity hitSlop={10} onPress={() => router.back()}>
<MingcuteLeftLineIcon height={20} width={20} color={label} />
</TouchableOpacity>
)
: undefined,
}}
/>

<TeamsMarkdown />
Expand Down
5 changes: 4 additions & 1 deletion apps/mobile/src/screens/(modal)/rsshub-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ function FormImpl({ route, routePrefix, name }: RsshubFormParams) {
render={({ field: { onChange, value } }) => (
<Select
label={keyItem.name}
wrapperClassName="mt-2"
options={parameters.options ?? []}
value={value}
onValueChange={onChange}
Expand All @@ -190,6 +189,10 @@ function FormImpl({ route, routePrefix, name }: RsshubFormParams) {
{!!route.description && (
<View className="bg-system-background mt-4 flex-1 px-4">
<MarkdownWeb
style={{
paddingTop: 16,
paddingBottom: 16,
}}
value={route.description.replaceAll("::: ", ":::")}
dom={{ matchContents: true, scrollEnabled: false }}
/>
Expand Down
Loading

0 comments on commit 69d4c86

Please sign in to comment.