Skip to content

Commit

Permalink
feat(rn-settings): impl data settings
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <[email protected]>
  • Loading branch information
Innei committed Jan 21, 2025
1 parent 1ec6c87 commit a031ac3
Show file tree
Hide file tree
Showing 12 changed files with 348 additions and 11 deletions.
6 changes: 6 additions & 0 deletions apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
favicon: iconPath,
},
plugins: [
[
"expo-document-picker",
{
iCloudContainerEnvironment: "Production",
},
],
"expo-localization",
[
"expo-router",
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"expo-clipboard": "~7.0.0",
"expo-constants": "~17.0.4",
"expo-dev-client": "^5.0.9",
"expo-document-picker": "~13.0.2",
"expo-file-system": "~18.0.6",
"expo-font": "~13.0.1",
"expo-haptics": "~14.0.0",
Expand Down
18 changes: 18 additions & 0 deletions apps/mobile/src/atoms/settings/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { DataSettings } from "@/src/interfaces/settings/data"

import { createSettingAtom } from "./internal/helper"

export const createDefaultSettings = (): DataSettings => ({
sendAnonymousData: true,
})

export const {
useSettingKey: useDataSettingKey,
useSettingSelector: useDataSettingSelector,
useSettingKeys: useDataSettingKeys,
setSetting: setDataSetting,
clearSettings: clearDataSettings,
initializeDefaultSettings: initializeDefaultDataSettings,
getSettings: getDataSettings,
useSettingValue: useDataSettingValue,
} = createSettingAtom("data", createDefaultSettings)
33 changes: 30 additions & 3 deletions apps/mobile/src/components/ui/grouped/GroupedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ export const GroupedInsetListNavigationLink: FC<{
<GroupedInsetListBaseCell
className={cn(pressed ? "bg-system-fill" : undefined, disabled && "opacity-40")}
>
<View className={"flex-1 flex-row items-center"}>
<View className={"flex-1 flex-row items-center justify-between"}>
<View className="flex-row items-center">
{icon}
<Text className={"text-label text-[16px]"}>{label}</Text>
</View>
<View className="-mr-2 ml-auto">
<View className="-mr-2 ml-4">
<RightCuteReIcon height={18} width={18} color={rightIconColor} />
</View>
</View>
Expand Down Expand Up @@ -120,7 +120,7 @@ export const GroupedInsetListNavigationLinkIcon: FC<
export const GroupedInsetListCell: FC<{
label: string
description?: string
children: React.ReactNode
children?: React.ReactNode
}> = ({ label, description, children }) => {
return (
<GroupedInsetListBaseCell className="flex-1">
Expand All @@ -133,3 +133,30 @@ export const GroupedInsetListCell: FC<{
</GroupedInsetListBaseCell>
)
}

export const GroupedInsetListActionCell: FC<{
label: string
description?: string
onPress: () => void
disabled?: boolean
}> = ({ label, description, onPress, disabled }) => {
const rightIconColor = useColor("tertiaryLabel")
return (
<Pressable onPress={onPress} disabled={disabled}>
{({ pressed }) => (
<GroupedInsetListBaseCell
className={cn(pressed ? "bg-system-fill" : undefined, disabled && "opacity-40")}
>
<View className="flex-1">
<Text>{label}</Text>
{!!description && <Text className="text-secondary-label text-sm">{description}</Text>}
</View>

<View className="-mr-2 ml-4">
<RightCuteReIcon height={18} width={18} color={rightIconColor} />
</View>
</GroupedInsetListBaseCell>
)}
</Pressable>
)
}
26 changes: 26 additions & 0 deletions apps/mobile/src/icons/exit_cute_fi.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from "react"
import Svg, { Path } from "react-native-svg"

interface ExitCuteFiIconProps {
width?: number
height?: number
color?: string
}

export const ExitCuteFiIcon = ({
width = 24,
height = 24,
color = "#10161F",
}: ExitCuteFiIconProps) => {
return (
<Svg width={width} height={height} fill="none" viewBox="0 0 24 24">
<Path fill="#fff" fillOpacity={0.01} d="M24 0v24H0V0z" />
<Path
stroke={color}
strokeLinecap="round"
strokeWidth={3}
d="M12.5 12H20m-2.5-2.828a8.616 8.616 0 0 1 2.478 2.307.89.89 0 0 1 0 1.042A8.631 8.631 0 0 1 17.5 14.83M12.5 3.5c-3.44.002-5.21.053-6.328 1.171C5 5.843 5 7.73 5 11.5v1c0 3.771 0 5.657 1.172 6.828C7.29 20.447 9.06 20.498 12.5 20.5"
/>
</Svg>
)
}
3 changes: 3 additions & 0 deletions apps/mobile/src/interfaces/settings/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface DataSettings {
sendAnonymousData: boolean
}
25 changes: 23 additions & 2 deletions apps/mobile/src/lib/api-fetch.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
import type { AppType } from "@follow/shared"
import { router } from "expo-router"
import { ofetch } from "ofetch"
import { FetchError, ofetch } from "ofetch"

import { getCookie } from "./auth"
import { getApiUrl } from "./env"
Expand All @@ -12,11 +12,16 @@ export const apiFetch = ofetch.create({
retry: false,

baseURL: getApiUrl(),
onRequest: async ({ options, request }) => {
onRequest: async (ctx) => {
const { options, request } = ctx
if (__DEV__) {
// Logger
console.log(`---> ${options.method} ${request as string}`)
}

// add cookie
options.headers = options.headers || new Headers()
options.headers.set("cookie", getCookie())
},
onRequestError: ({ error, request, options }) => {
if (__DEV__) {
Expand Down Expand Up @@ -54,3 +59,19 @@ export const apiClient = hc<AppType>(getApiUrl(), {
}
},
})

export const getBizFetchErrorMessage = (error: unknown) => {
if (error instanceof FetchError && error.response) {
try {
const data = JSON.parse(error.response._data)

if (data.message && data.code) {
// TODO i18n handle by code
return data.message
}
} catch {
return ""
}
}
return ""
}
2 changes: 1 addition & 1 deletion apps/mobile/src/modules/login/email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export function EmailLogin() {
<ReAnimatedPressable
disabled={submitMutation.isPending || !formState.isValid}
onPress={login}
className="mt-8 h-10 flex-row items-center justify-center rounded-lg"
className="mt-8 h-10 flex-row items-center justify-center rounded-3xl"
style={buttonStyle}
>
{submitMutation.isPending ? (
Expand Down
34 changes: 33 additions & 1 deletion apps/mobile/src/modules/settings/SettingsList.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs"
import { useIsFocused } from "@react-navigation/native"
import * as FileSystem from "expo-file-system"
import type { FC, RefObject } from "react"
import { Fragment, useContext, useEffect } from "react"
import type { ScrollView } from "react-native"
import { View } from "react-native"
import { Alert, View } from "react-native"
import { useSafeAreaInsets } from "react-native-safe-area-context"

import {
Expand All @@ -12,9 +13,11 @@ import {
GroupedInsetListNavigationLinkIcon,
} from "@/src/components/ui/grouped/GroupedList"
import { SetBottomTabBarVisibleContext } from "@/src/contexts/BottomTabBarVisibleContext"
import { getDbPath } from "@/src/database"
import { BellRingingCuteFiIcon } from "@/src/icons/bell_ringing_cute_fi"
import { CertificateCuteFiIcon } from "@/src/icons/certificate_cute_fi"
import { DatabaseIcon } from "@/src/icons/database"
import { ExitCuteFiIcon } from "@/src/icons/exit_cute_fi"
import { Magic2CuteFiIcon } from "@/src/icons/magic_2_cute_fi"
import { PaletteCuteFiIcon } from "@/src/icons/palette_cute_fi"
import { RadaCuteFiIcon } from "@/src/icons/rada_cute_fi"
Expand All @@ -23,6 +26,7 @@ import { Settings7CuteFiIcon } from "@/src/icons/settings_7_cute_fi"
import { StarCuteFiIcon } from "@/src/icons/star_cute_fi"
import { TrophyCuteFiIcon } from "@/src/icons/trophy_cute_fi"
import { User3CuteFiIcon } from "@/src/icons/user_3_cute_fi"
import { signOut } from "@/src/lib/auth"

import { useSettingsNavigation } from "./hooks"

Expand Down Expand Up @@ -142,6 +146,33 @@ const PrivacyGroupNavigationLinks: GroupNavigationLink[] = [
},
]

const ActionGroupNavigationLinks: GroupNavigationLink[] = [
{
label: "Sign out",
icon: ExitCuteFiIcon,
onPress: () => {
Alert.alert("Sign out", "Are you sure you want to sign out?", [
{
text: "Cancel",
style: "cancel",
},
{
text: "Sign out",
style: "destructive",
onPress: async () => {
// sign out
await signOut()
const dbPath = getDbPath()
await FileSystem.deleteAsync(dbPath)
await expo.reloadAppAsync("User sign out")
},
},
])
},
iconBackgroundColor: "#F87181",
},
]

const NavigationLinkGroup: FC<{
links: GroupNavigationLink[]
navigation: ReturnType<typeof useSettingsNavigation>
Expand Down Expand Up @@ -174,6 +205,7 @@ const navigationGroups = [
DataGroupNavigationLinks,
SettingGroupNavigationLinks,
PrivacyGroupNavigationLinks,
ActionGroupNavigationLinks,
] as const

export const SettingsList: FC<{ scrollRef: RefObject<ScrollView> }> = ({ scrollRef }) => {
Expand Down
Loading

0 comments on commit a031ac3

Please sign in to comment.