Skip to content

Commit

Permalink
feat(rn-settings): Improve UI settings, modify the style of the setti…
Browse files Browse the repository at this point in the history
…ng lists

- Added `shiki` dependency to `package.json` and `pnpm-lock.yaml`.
- Updated `DropdownMenu` to disable selected options.
- Enhanced `GroupedList` to support a disabled state for navigation links.
- Refactored `SettingsList` to use a new `NavigationLinkGroup` component for better organization.
- Improved `About` screen layout with links for GitHub and icon library.
- Introduced new settings in `Appearance` for code highlight themes and inline style rendering.

Signed-off-by: Innei <tukon479@gmail.com>
  • Loading branch information
Innei committed Jan 21, 2025
1 parent 3475b74 commit eddc7cd
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 87 deletions.
1 change: 1 addition & 0 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"react-native-uikit-colors": "0.1.1",
"react-native-web": "~0.19.13",
"react-native-webview": "13.12.5",
"shiki": "1.24.1",
"swiftui-react-native": "6.3.3",
"tailwindcss": "3.4.16",
"usehooks-ts": "3.1.0",
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/src/components/ui/dropdown/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function DropdownMenu<T>({
: options.map((option) => ({
title: option.label,
selected: option.value === currentValue,
disabled: option.value === currentValue,
}))
}
onPress={(e) => {
Expand Down
15 changes: 9 additions & 6 deletions apps/mobile/src/components/ui/grouped/GroupedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,23 @@ export const GroupedInsetListNavigationLink: FC<{
label: string
icon?: React.ReactNode
onPress: () => void
}> = ({ label, icon, onPress }) => {
const tertiaryLabelColor = useColor("tertiaryLabel")
disabled?: boolean
}> = ({ label, icon, onPress, disabled }) => {
const rightIconColor = useColor("tertiaryLabel")

return (
<Pressable onPress={onPress}>
<Pressable onPress={onPress} disabled={disabled}>
{({ pressed }) => (
<GroupedInsetListBaseCell className={pressed ? "bg-system-fill" : undefined}>
<GroupedInsetListBaseCell
className={cn(pressed ? "bg-system-fill" : undefined, disabled && "opacity-40")}
>
<View className={"flex-1 flex-row items-center"}>
<View className="flex-row items-center">
{icon}
<Text className="text-[16px]">{label}</Text>
<Text className={"text-label text-[16px]"}>{label}</Text>
</View>
<View className="-mr-2 ml-auto">
<RightCuteReIcon height={18} width={18} color={tertiaryLabelColor} />
<RightCuteReIcon height={18} width={18} color={rightIconColor} />
</View>
</View>
</GroupedInsetListBaseCell>
Expand Down
110 changes: 48 additions & 62 deletions apps/mobile/src/modules/settings/SettingsList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"
import { useIsFocused } from "@react-navigation/native"
import type { FC, RefObject } from "react"
import { useContext, useEffect } from "react"
import { Fragment, useContext, useEffect } from "react"
import type { ScrollView } from "react-native"
import { View } from "react-native"
import { useSafeAreaInsets } from "react-native-safe-area-context"
Expand Down Expand Up @@ -34,6 +34,8 @@ interface GroupNavigationLink {
scrollRef: RefObject<ScrollView>,
) => void
iconBackgroundColor: string

todo?: boolean
}
const UserGroupNavigationLinks: GroupNavigationLink[] = [
{
Expand Down Expand Up @@ -73,6 +75,7 @@ const SettingGroupNavigationLinks: GroupNavigationLink[] = [
navigation.navigate("Notifications")
},
iconBackgroundColor: "#FBBF24",
todo: true,
},
{
label: "Appearance",
Expand Down Expand Up @@ -139,6 +142,40 @@ const PrivacyGroupNavigationLinks: GroupNavigationLink[] = [
},
]

const NavigationLinkGroup: FC<{
links: GroupNavigationLink[]
navigation: ReturnType<typeof useSettingsNavigation>
scrollRef: RefObject<ScrollView>
}> = ({ links, navigation, scrollRef }) => (
<GroupedInsetListCard>
{links.map((link) => (
<GroupedInsetListNavigationLink
key={link.label}
label={link.label + (link.todo ? " (Coming Soon)" : "")}
disabled={link.todo}
icon={
<GroupedInsetListNavigationLinkIcon backgroundColor={link.iconBackgroundColor}>
<link.icon height={18} width={18} color="#fff" />
</GroupedInsetListNavigationLinkIcon>
}
onPress={() => {
if (link.todo) {
return
}
link.onPress(navigation, scrollRef)
}}
/>
))}
</GroupedInsetListCard>
)

const navigationGroups = [
UserGroupNavigationLinks,
DataGroupNavigationLinks,
SettingGroupNavigationLinks,
PrivacyGroupNavigationLinks,
] as const

export const SettingsList: FC<{ scrollRef: RefObject<ScrollView> }> = ({ scrollRef }) => {
const navigation = useSettingsNavigation()

Expand All @@ -157,68 +194,17 @@ export const SettingsList: FC<{ scrollRef: RefObject<ScrollView> }> = ({ scrollR
className="bg-system-grouped-background flex-1 py-4"
style={{ paddingBottom: insets.bottom + tabBarHeight }}
>
<GroupedInsetListCard>
{UserGroupNavigationLinks.map((link) => (
<GroupedInsetListNavigationLink
key={link.label}
label={link.label}
icon={
<GroupedInsetListNavigationLinkIcon backgroundColor={link.iconBackgroundColor}>
<link.icon height={18} width={18} color="#fff" />
</GroupedInsetListNavigationLinkIcon>
}
onPress={() => link.onPress(navigation, scrollRef)}
/>
))}
</GroupedInsetListCard>

<View className="h-8" />
<GroupedInsetListCard>
{DataGroupNavigationLinks.map((link) => (
<GroupedInsetListNavigationLink
key={link.label}
label={link.label}
icon={
<GroupedInsetListNavigationLinkIcon backgroundColor={link.iconBackgroundColor}>
<link.icon height={18} width={18} color="#fff" />
</GroupedInsetListNavigationLinkIcon>
}
onPress={() => link.onPress(navigation, scrollRef)}
/>
))}
</GroupedInsetListCard>
<View className="h-8" />

<GroupedInsetListCard>
{SettingGroupNavigationLinks.map((link) => (
<GroupedInsetListNavigationLink
key={link.label}
label={link.label}
icon={
<GroupedInsetListNavigationLinkIcon backgroundColor={link.iconBackgroundColor}>
<link.icon height={18} width={18} color="#fff" />
</GroupedInsetListNavigationLinkIcon>
}
onPress={() => link.onPress(navigation, scrollRef)}
/>
))}
</GroupedInsetListCard>

<View className="h-8" />
<GroupedInsetListCard>
{PrivacyGroupNavigationLinks.map((link) => (
<GroupedInsetListNavigationLink
key={link.label}
label={link.label}
icon={
<GroupedInsetListNavigationLinkIcon backgroundColor={link.iconBackgroundColor}>
<link.icon height={18} width={18} color="#fff" />
</GroupedInsetListNavigationLinkIcon>
}
onPress={() => link.onPress(navigation, scrollRef)}
{navigationGroups.map((group, index) => (
<Fragment key={`nav-group-${index}`}>
<NavigationLinkGroup
key={`nav-group-${index}`}
links={group}
navigation={navigation}
scrollRef={scrollRef}
/>
))}
</GroupedInsetListCard>
{index < navigationGroups.length - 1 && <View className="h-8" />}
</Fragment>
))}
</View>
)
}
40 changes: 22 additions & 18 deletions apps/mobile/src/modules/settings/routes/About.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Constants from "expo-constants"
import { Link } from "expo-router"
import { Linking, Text, View } from "react-native"

import {
Expand All @@ -12,19 +13,10 @@ import {
GroupedInsetListSectionHeader,
} from "@/src/components/ui/grouped/GroupedList"
import { Logo } from "@/src/components/ui/logo"
import { Markdown } from "@/src/components/ui/typography/Markdown"
import { DiscordCuteFiIcon } from "@/src/icons/discord_cute_fi"
import { Github2CuteFiIcon } from "@/src/icons/github_2_cute_fi"
import { SocialXCuteReIcon } from "@/src/icons/social_x_cute_re"

const about = `
Follow is in the early stages of development. If you have any feedback or suggestions, please feel free to open an issue on the [GitHub repository](https://github.com/RSSNext/follow).
The icon library used is copyrighted by <a class="inline-flex items-center" href="https://mgc.mingcute.com/" target="_blank" rel="noreferrer">https://mgc.mingcute.com/</a> and cannot be redistributed.
Copyright © 2025 Follow. All rights reserved.
`

const links = [
{
title: "Github",
Expand Down Expand Up @@ -63,16 +55,28 @@ export const AboutScreen = () => {
{appVersion} ({buildId})
</Text>
</View>
<View className="flex-1 px-6">
<Markdown
value={about}
webViewProps={{
matchContents: true,
}}
className="text-[15px] leading-snug"
/>
<View className="mt-6 flex-1 px-9">
<Text className="text-label text-[15px]">
Follow is in the early stages of development. If you have any feedback or suggestions,
please feel free to open an issue on the{" "}
<Link className="text-accent" href="https://github.com/RSSNext/follow">
GitHub repository
</Link>
</Text>

<Text className="text-label mt-4 text-[15px]">
The icon library used is copyrighted by{" "}
<Link className="text-accent" href="https://mgc.mingcute.com/">
https://mgc.mingcute.com/
</Link>{" "}
and cannot be redistributed.
</Text>

<Text className="text-label mt-4 text-[15px]">
Copyright © 2025 Follow. All rights reserved.
</Text>
</View>
<View className="mt-6">
<View className="mt-10">
<GroupedInsetListSectionHeader label="Social Links" />
<GroupedInsetListCard>
{links.map((link) => (
Expand Down
58 changes: 57 additions & 1 deletion apps/mobile/src/modules/settings/routes/Appearance.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { View } from "react-native"
import { useColorScheme, View } from "react-native"
import { bundledThemesInfo } from "shiki/dist/themes.mjs"

import { setUISetting, useUISettingKey } from "@/src/atoms/settings/ui"
import {
Expand All @@ -18,6 +19,13 @@ export const AppearanceScreen = () => {
const hideExtraBadge = useUISettingKey("hideExtraBadge")
const thumbnailRatio = useUISettingKey("thumbnailRatio")

const codeThemeLight = useUISettingKey("codeHighlightThemeLight")
const codeThemeDark = useUISettingKey("codeHighlightThemeDark")

const colorScheme = useColorScheme()
const readerRenderInlineStyle = useUISettingKey("readerRenderInlineStyle")
const hideRecentReader = useUISettingKey("hideRecentReader")

return (
<SafeNavigationScrollView className="bg-system-grouped-background">
<NavigationBlurEffectHeader title="Appearance" />
Expand Down Expand Up @@ -67,6 +75,54 @@ export const AppearanceScreen = () => {
</View>
</GroupedInsetListCell>
</GroupedInsetListCard>

<View className="mt-6">
<GroupedInsetListSectionHeader label="Content" />
<GroupedInsetListCard>
<GroupedInsetListCell label="Code highlight theme">
<Select
wrapperClassName="w-[120px]"
options={bundledThemesInfo.map((theme) => ({
label: theme.displayName,
value: theme.id,
}))}
value={colorScheme === "dark" ? codeThemeDark : codeThemeLight}
onValueChange={(val) => {
setUISetting(
`codeHighlightTheme${colorScheme === "dark" ? "Dark" : "Light"}`,
val,
)
}}
/>
</GroupedInsetListCell>

<GroupedInsetListCell
label="Render inline style"
description="Allows rendering of the inline style of the original HTML."
>
<Switch
size="sm"
value={readerRenderInlineStyle}
onValueChange={(val) => {
setUISetting("readerRenderInlineStyle", val)
}}
/>
</GroupedInsetListCell>

<GroupedInsetListCell
label="Hide recent reader"
description="Hide the recent reader in the entry header."
>
<Switch
size="sm"
value={hideRecentReader}
onValueChange={(val) => {
setUISetting("hideRecentReader", val)
}}
/>
</GroupedInsetListCell>
</GroupedInsetListCard>
</View>
</View>
</SafeNavigationScrollView>
)
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit eddc7cd

Please sign in to comment.