-
Notifications
You must be signed in to change notification settings - Fork 0
feat(mobile): 다크/라이트 모드 전환 기능 구현 #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
24e2d4e
refactor(mobile): 커스텀 tv/cn 유틸리티로 twMerge 충돌 방지
hijjoy 8b54786
refactor(mobile): 회원가입 헤더를 네이티브 Stack 헤더로 전환
hijjoy ec8bac4
fix(mobile): 다크모드 하드코딩 색상을 테마 변수로 전환
hijjoy b76460b
feat(mobile): 테마 설정 화면 및 ThemeProvider 구현
hijjoy e93ca3d
docs(mobile): 애니메이션 상수 사용 가이드 추가
hijjoy 11c2041
refactor(mobile): THEME_COLORS 하드코딩을 useResolveClassNames로 전환
hijjoy 76757e5
fix(mobile): 시스템 테마 전환 시 이전 테마가 유지되는 버그 수정
hijjoy 5c02e42
refactor(mobile): ThemeProvider 스토리지를 SecureStore에서 MMKV로 전환
hijjoy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import { ANIMATION } from '@src/shared/constants/animation.constants'; | ||
| import { type ThemeMode, useTheme } from '@src/shared/providers/theme-provider'; | ||
| import { DeviceIcon, MoonIcon, type StyledIconType, SunIcon } from '@src/shared/ui/Icon'; | ||
| import { ListRow } from '@src/shared/ui/ListRow/ListRow'; | ||
| import { StyledSafeAreaView } from '@src/shared/ui/SafeAreaView/SafeAreaView'; | ||
| import { RadioGroup, Spinner } from 'heroui-native'; | ||
| import { ScrollView } from 'react-native'; | ||
| import Animated, { Easing, useAnimatedStyle, withTiming } from 'react-native-reanimated'; | ||
|
|
||
| const ThemeSettingsScreen = () => { | ||
| const { mode, setMode, isLoading } = useTheme(); | ||
|
|
||
| if (isLoading) { | ||
| return ( | ||
| <StyledSafeAreaView | ||
| className="flex-1 bg-gray-1 items-center justify-center" | ||
| edges={['bottom']} | ||
| > | ||
| <Spinner /> | ||
| </StyledSafeAreaView> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <StyledSafeAreaView className="flex-1 bg-gray-1" edges={['bottom']}> | ||
| <ScrollView className="px-4 flex-1"> | ||
| <RadioGroup | ||
| value={mode} | ||
| onValueChange={(value) => setMode(value as ThemeMode)} | ||
| className="bg-white rounded-2xl overflow-hidden gap-0" | ||
| > | ||
| <ThemeRadioItem value="light" label="라이트 모드" Icon={SunIcon} /> | ||
| <ThemeRadioItem value="dark" label="다크 모드" Icon={MoonIcon} /> | ||
| <ThemeRadioItem value="system" label="시스템 설정" Icon={DeviceIcon} /> | ||
| </RadioGroup> | ||
| </ScrollView> | ||
| </StyledSafeAreaView> | ||
| ); | ||
| }; | ||
|
|
||
| export default ThemeSettingsScreen; | ||
|
|
||
| interface ThemeRadioItemProps { | ||
| value: ThemeMode; | ||
| label: string; | ||
| Icon: StyledIconType; | ||
| } | ||
|
|
||
| function ThemeRadioItem({ value, label, Icon }: ThemeRadioItemProps) { | ||
| return ( | ||
| <RadioGroup.Item value={value}> | ||
| {({ isSelected }) => ( | ||
| <ListRow | ||
| contents={ | ||
| <ListRow.Texts | ||
| type="1RowTypeA" | ||
| top={label} | ||
| topProps={{ size: 'b3', weight: 'semibold' }} | ||
| /> | ||
| } | ||
| right={ | ||
| <RadioGroup.Indicator> | ||
| <AnimatedThumbIcon Icon={Icon} isSelected={isSelected} /> | ||
| </RadioGroup.Indicator> | ||
| } | ||
| horizontalPadding="medium" | ||
| verticalPadding="large" | ||
| /> | ||
| )} | ||
| </RadioGroup.Item> | ||
| ); | ||
| } | ||
|
|
||
| interface AnimatedThumbIconProps { | ||
| Icon: StyledIconType; | ||
| isSelected: boolean; | ||
| } | ||
|
|
||
| function AnimatedThumbIcon({ Icon, isSelected }: AnimatedThumbIconProps) { | ||
| const animatedStyle = useAnimatedStyle(() => ({ | ||
| transform: [ | ||
| { | ||
| scale: withTiming(isSelected ? 1 : 1.8, { | ||
| duration: ANIMATION.duration.slow, | ||
| easing: Easing.out(Easing.ease), | ||
| }), | ||
| }, | ||
| ], | ||
| opacity: withTiming(isSelected ? 1 : 0, { duration: ANIMATION.duration.normal }), | ||
| })); | ||
|
|
||
| return ( | ||
| <Animated.View style={animatedStyle}> | ||
| <Icon colorClassName="text-white" width={14} height={14} /> | ||
| </Animated.View> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.