From 1b7fc496559244b3c6be3b147c5b1cd8b5ff66d0 Mon Sep 17 00:00:00 2001 From: "Hyunmin Woo (Hanul)" Date: Tue, 12 Dec 2023 10:32:48 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=EB=A7=88=EC=A7=80=EB=A7=89?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=B8=20=EC=B9=9C=EA=B5=AC=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20(#94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/friends-react-native/package.json | 1 + .../src/app/components/Timetable.tsx | 2 +- .../src/app/contexts/FeatureContext.ts | 15 ++++++++++ .../src/app/screens/MainScreen/index.tsx | 28 +++++++++++++++++-- .../src/entities/feature.ts | 3 ++ apps/friends-react-native/src/main.tsx | 8 +++++- yarn.lock | 19 +++++++++++++ 7 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 apps/friends-react-native/src/app/contexts/FeatureContext.ts create mode 100644 apps/friends-react-native/src/entities/feature.ts diff --git a/apps/friends-react-native/package.json b/apps/friends-react-native/package.json index c11311b..386b12c 100644 --- a/apps/friends-react-native/package.json +++ b/apps/friends-react-native/package.json @@ -19,6 +19,7 @@ "@tanstack/react-query": "^5.8.7", "react": "18.2.0", "react-native": "0.72.3", + "@react-native-async-storage/async-storage": "1.19.8", "react-native-gesture-handler": "2.12.0", "react-native-modal": "13.0.1", "react-native-reanimated": "3.4.2", diff --git a/apps/friends-react-native/src/app/components/Timetable.tsx b/apps/friends-react-native/src/app/components/Timetable.tsx index 8dc73f1..7cc5c4c 100644 --- a/apps/friends-react-native/src/app/components/Timetable.tsx +++ b/apps/friends-react-native/src/app/components/Timetable.tsx @@ -40,7 +40,7 @@ export const Timetable = memo(({ timetable, style, palette }: Props) => { const top = DAY_LABEL_HEIGHT + ((c.startMinute - startHour * 60) / 60) * hourHeight - 1; const cellHeight = ((c.endMinute - c.startMinute) / 60) * hourHeight; - const classLines = (cellHeight - (place ? 16 : 0)) / 12; + const classLines = Math.max(Math.ceil((cellHeight - (place ? 16 : 0)) / 12), 0); return ( (null); + +export const useFeatureContext = () => { + const context = useContext(featureContext); + if (!context) throw new Error('context not provided'); + return context; +}; diff --git a/apps/friends-react-native/src/app/screens/MainScreen/index.tsx b/apps/friends-react-native/src/app/screens/MainScreen/index.tsx index dfc9600..28f0672 100644 --- a/apps/friends-react-native/src/app/screens/MainScreen/index.tsx +++ b/apps/friends-react-native/src/app/screens/MainScreen/index.tsx @@ -1,10 +1,11 @@ import { createDrawerNavigator, DrawerContentComponentProps, DrawerHeaderProps } from '@react-navigation/drawer'; import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { createContext, Dispatch, useContext, useMemo, useReducer } from 'react'; +import { createContext, Dispatch, useContext, useEffect, useMemo, useReducer } from 'react'; import { Alert, TouchableOpacity } from 'react-native'; import { StyleSheet, View } from 'react-native'; import { CourseBook } from '../../../entities/courseBook'; +import { ClientFeature } from '../../../entities/feature'; import { FriendId } from '../../../entities/friend'; import { Nickname } from '../../../entities/user'; import { get } from '../../../utils/get'; @@ -17,6 +18,7 @@ import { WarningIcon } from '../../components/Icons/WarningIcon'; import { Input } from '../../components/Input'; import { NotificationDot } from '../../components/NotificationDot'; import { Typography } from '../../components/Typography'; +import { useFeatureContext } from '../../contexts/FeatureContext'; import { useServiceContext } from '../../contexts/ServiceContext'; import { useThemeContext } from '../../contexts/ThemeContext'; import { useFriendCourseBooks } from '../../queries/useFriendCourseBooks'; @@ -73,9 +75,29 @@ export const MainScreen = () => { isGuideModalOpen: false, }); - const backgroundColor = useThemeContext((data) => data.color.bg.default); + const { clientFeatures } = useFeatureContext(); + const { data: friends } = useFriends({ state: 'ACTIVE' }); - const selectedFriendIdWithDefault = state.selectedFriendId ?? friends?.[0]?.friendId; + + useEffect(() => { + if (!clientFeatures.includes(ClientFeature.ASYNC_STORAGE)) return; + + import('@react-native-async-storage/async-storage') + .then((storage) => { + if (state.selectedFriendId) storage.default.setItem('selectedFriendId', state.selectedFriendId); + else { + storage.default.getItem('selectedFriendId').then((item) => { + if (!friends) return; + const selectedFriend = friends.find((f) => f.friendId === item); + if (selectedFriend) dispatch({ type: 'setFriend', friendId: selectedFriend.friendId }); + }); + } + }) + .catch(() => null); + }, [state.selectedFriendId, clientFeatures, friends]); + + const backgroundColor = useThemeContext((data) => data.color.bg.default); + const selectedFriendIdWithDefault = state.selectedFriendId ?? friends?.at(0)?.friendId; const { data: courseBooks } = useFriendCourseBooks(selectedFriendIdWithDefault); const selectedCourseBookWithDefault = state.selectedCourseBook ?? courseBooks?.at(0); diff --git a/apps/friends-react-native/src/entities/feature.ts b/apps/friends-react-native/src/entities/feature.ts new file mode 100644 index 0000000..d22bd42 --- /dev/null +++ b/apps/friends-react-native/src/entities/feature.ts @@ -0,0 +1,3 @@ +export enum ClientFeature { + ASYNC_STORAGE = 'ASYNC_STORAGE', +} diff --git a/apps/friends-react-native/src/main.tsx b/apps/friends-react-native/src/main.tsx index 53bdc75..fe4d550 100644 --- a/apps/friends-react-native/src/main.tsx +++ b/apps/friends-react-native/src/main.tsx @@ -4,10 +4,12 @@ import { Text, View } from 'react-native'; import { App } from './app/App'; import { ErrorBoundary } from './app/components/ErrorBoundary'; +import { featureContext } from './app/contexts/FeatureContext'; import { serviceContext } from './app/contexts/ServiceContext'; import { textContext } from './app/contexts/TextContext'; import { themeContext } from './app/contexts/ThemeContext'; import { getThemeValues } from './app/styles/theme'; +import { ClientFeature } from './entities/feature'; import { createAssetService } from './infrastructures/createAssetService'; import { createColorRepository } from './infrastructures/createColorRepository'; import { createColorService } from './infrastructures/createColorService'; @@ -29,6 +31,7 @@ type ExternalProps = { 'x-app-version': string; theme: 'light' | 'dark'; allowFontScaling: boolean; + feature?: ClientFeature[]; }; export const Main = ({ @@ -36,6 +39,7 @@ export const Main = ({ 'x-access-apikey': xAccessApikey, theme, allowFontScaling = false, + feature = [], }: ExternalProps) => { const fetchClient = createFetchClient(API_URL, xAccessToken, xAccessApikey); const friendRepository = createFriendRepository(fetchClient); @@ -65,7 +69,9 @@ export const Main = ({ - + + + diff --git a/yarn.lock b/yarn.lock index 0ebc80e..abdef25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1560,6 +1560,13 @@ picocolors "^1.0.0" tslib "^2.6.0" +"@react-native-async-storage/async-storage@1.19.8": + version "1.19.8" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.19.8.tgz#a29fc4f4aa5c85805f8b3edea84e19f797c59fdd" + integrity sha512-O25eaSbmH+LEmOobkpwf43bAGIkqE9YGzfWcirTszI90xk4ItaDWpgJsQx9LeAbeAKzVkn1h+Nq5Bo6I6q2oFA== + dependencies: + merge-options "^3.0.4" + "@react-native-community/cli-clean@11.3.5": version "11.3.5" resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-11.3.5.tgz#07c8a01e433ea6c6e32eb647908be48952888cdd" @@ -4460,6 +4467,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -5330,6 +5342,13 @@ memoize-one@^5.0.0: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"