Skip to content

Commit 8917ec1

Browse files
authored
[Setting/#7] design system (#8)
* [Chore#7] `:core:coroutine` 모듈 추가 - `settings.gradle.kts`에 신규 모듈인 `:core:coroutine`을 추가하였습니다. * [Feat#7] `core:coroutine` 모듈 추가 및 Hilt 디스패처 설정 - `core:coroutine` 모듈을 신규 생성하고 기본 빌드 설정(`build.gradle.kts`) 및 `.gitignore`를 추가하였습니다. - `kindl.android.library` 및 `kindl.hilt` 컨벤션 플러그인을 적용하고 네임스페이스를 `core.coroutine`으로 설정하였습니다. - 코루틴 디스패처 의존성 주입을 위한 `@IoDispatcher` 한정자(Qualifier)를 정의하였습니다. - `DispatcherModule`을 추가하여 `Dispatchers.IO`를 `SingletonComponent` 내에서 제공하도록 구현하였습니다. * [Refactor#7] `ForbiddenAppRepository` 내 비동기 처리 적용 및 `IoDispatcher` 주입 - `ForbiddenAppRepository` 인터페이스와 `GetInstalledAppsUseCase`의 호출 방식을 `suspend` 함수로 변경하였습니다. - `ForbiddenAppRepositoryImpl`에서 `PackageManager`를 통한 앱 목록 조회 시 `IoDispatcher`를 사용하여 I/O 스레드에서 동작하도록 개선하였습니다. - `data:forbidden` 모듈의 의존성에 `core:coroutine` 프로젝트를 추가하였습니다. - `ForbiddenAppRepositoryImpl` 생성자에 Hilt의 `@IoDispatcher`를 통한 `CoroutineDispatcher` 주입 로직을 추가하였습니다. * [Feat#7] core:designsystem 테마 고도화 및 커스텀 디자인 시스템 구축 - `core:designsystem` 모듈의 컬러 시스템을 대폭 확장하였습니다. - Slate(기본), Coral(포인트), Blue/Teal/Amber(보조) 등 상세 팔레트를 정의하였습니다. - `KindlColors` 데이터 클래스를 통해 Surface, Interactive, State, Form, Chart 등 역할 기반 컬러 시스템을 구축하였습니다. - 라이트 및 다크 테마별 색상 값을 구체적으로 설정하고 `staticCompositionLocalOf`를 통해 접근 가능하도록 구현하였습니다. - 커스텀 타이포그래피 시스템을 구축하였습니다. - `Pretendard` 폰트 패밀리를 적용하고 Regular, SemiBold, Bold 등 웨이트별 토큰(Body, Title, Headline)을 정의하였습니다. - `PlatformTextStyle(includeFontPadding = false)`를 적용하여 폰트 상하단 패딩 문제를 해결하였습니다. - `KindlTheme` 설정을 업데이트하였습니다. - `MaterialTheme`와 연동되는 `KindlDarkColorScheme` 및 `KindlLightColorScheme`을 정의하였습니다. - `ProvideKindlColorsAndTypography`를 통해 커스텀 컬러 및 타이포그래피를 `CompositionLocal`로 제공하도록 개선하였습니다. - `KindlTheme` 싱글톤 객체를 추가하여 컴포저블 내에서 `KindlTheme.colors`와 같이 스타일 참조가 용이하도록 변경하였습니다. - `UrlImage` 컴포넌트의 `url` 매개변수 타입을 `Any?`에서 `String?`으로 타입을 구체화하였습니다. * [Refactor#7] 접근성 권한 설정 수정 및 ForbiddenAppItem UI 컴포넌트 개선 - `PermissionType`에서 `ACCESSIBILITY` 권한의 필수 여부(`isFocusRequired`)를 `true`에서 `false`로 변경하였습니다. - `ForbiddenAppItem` 컴포넌트의 이미지 로딩 방식을 `UrlImage`에서 `Image` 및 `Bitmap` 변환 방식으로 변경하고 `ContentScale.Crop`을 적용하였습니다. - `ForbiddenAppItem` 내 앱 명칭(`appName`)의 텍스트 스타일과 색상을 `KindlTheme` 가이드라인에 맞춰 업데이트하였습니다. - `HomeViewModel`에 `Timber` 로그 라이브러리 import를 추가하였습니다. * [Chore#7] CodeRabbit 설정 파일 추가 - CodeRabbit 자동 리뷰 설정을 위한 `.coderabbit.yaml` 파일을 신규 생성하였습니다. - 리뷰 언어를 한국어(`ko-KR`)로 설정하고, `develop` 및 `main` 브랜치에 대해 자동 리뷰가 동작하도록 구성하였습니다. - 빌드 산출물, `.gradle`, 생성된 코드 및 이미지 파일 등을 리뷰 대상에서 제외하도록 경로 필터(`path_filters`)를 설정하였습니다. - Kotlin 소스 코드(`.kt`)에 대해 Compose 모범 사례, Hilt 의존성 주입, 코루틴 사용 및 네이밍 컨벤션 등의 구체적인 리뷰 지침을 정의하였습니다. - Gradle 설정 파일(`build.gradle.kts`)에 대해 `libs.versions.toml` 활용 및 의존성 적절성 확인 지침을 추가하였습니다. * [Refactor#7] 홈 화면 앱 리스트 아이콘 렌더링 최적화 및 코드 정리 - `ForbiddenAppItem` 컴포넌트에서 `Drawable`을 `ImageBitmap`으로 변환하는 로직에 `remember`를 적용하여 리컴포지션 시 불필요한 연산을 방지하도록 최적화하였습니다. - `ForbiddenAppItem.kt` 내 사용하지 않는 `UrlImage` 임포트 구문을 제거하였습니다. - `KindlFont` 설정 파일에서 폰트 리소스 관련 `TODO` 주석을 삭제하였습니다.
1 parent 3572e9b commit 8917ec1

20 files changed

Lines changed: 584 additions & 88 deletions

File tree

.coderabbit.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
language: ko-KR
2+
3+
reviews:
4+
profile: chill
5+
request_changes_workflow: false
6+
high_level_summary: true
7+
poem: false
8+
review_status: true
9+
auto_review:
10+
enabled: true
11+
drafts: false
12+
base_branches:
13+
- develop
14+
- main
15+
16+
path_filters:
17+
- "!**/*.lock"
18+
- "!**/build/**"
19+
- "!**/.gradle/**"
20+
- "!**/generated/**"
21+
- "!**/*.png"
22+
- "!**/*.jpg"
23+
- "!**/*.webp"
24+
25+
path_instructions:
26+
- path: "**/*.kt"
27+
instructions: |
28+
Kotlin 코드는 다음 기준으로 리뷰해줘:
29+
- Compose 모범 사례 (remember, derivedStateOf, Stable/Immutable)
30+
- Hilt 의존성 주입 패턴
31+
- 코루틴 사용 (Dispatcher, scope, exception handling)
32+
- 네이밍 컨벤션 (PascalCase 클래스, camelCase 함수)
33+
- 매직 넘버나 하드코딩된 문자열 지적
34+
35+
- path: "**/build.gradle.kts"
36+
instructions: |
37+
Gradle 설정은 다음을 확인해줘:
38+
- 의존성 버전이 libs.versions.toml에서 관리되는지
39+
- 불필요한 의존성이 없는지
40+
41+
chat:
42+
auto_reply: true

.idea/deploymentTargetSelector.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/coroutine/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

core/coroutine/build.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import com.kindl.buildlogic.setNamespace
2+
3+
plugins {
4+
alias(libs.plugins.kindl.android.library)
5+
alias(libs.plugins.kindl.hilt)
6+
}
7+
8+
android {
9+
setNamespace("core.coroutine")
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.kindl.coroutine.di
2+
3+
import com.kindl.coroutine.qualifier.IoDispatcher
4+
import dagger.Module
5+
import dagger.Provides
6+
import dagger.hilt.InstallIn
7+
import dagger.hilt.components.SingletonComponent
8+
import kotlinx.coroutines.CoroutineDispatcher
9+
import kotlinx.coroutines.Dispatchers
10+
11+
@Module
12+
@InstallIn(SingletonComponent::class)
13+
object DispatcherModule {
14+
15+
@IoDispatcher
16+
@Provides
17+
fun providesIoDispatcher(): CoroutineDispatcher = Dispatchers.IO
18+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.kindl.coroutine.qualifier
2+
3+
import javax.inject.Qualifier
4+
5+
@Retention(AnnotationRetention.BINARY)
6+
@Qualifier
7+
annotation class IoDispatcher

core/designsystem/src/main/java/com/kindl/core/designsystem/component/UrlImage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import com.kindl.core.designsystem.R
1515

1616
@Composable
1717
fun UrlImage(
18-
url: Any?,
18+
url: String?,
1919
modifier: Modifier = Modifier,
2020
contentScale: ContentScale = ContentScale.Fit,
2121
contentDescription: String? = null,
Lines changed: 205 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,210 @@
11
package com.kindl.core.designsystem.theme
22

3+
import androidx.compose.runtime.Immutable
4+
import androidx.compose.runtime.staticCompositionLocalOf
35
import androidx.compose.ui.graphics.Color
46

5-
val Purple80 = Color(0xFFD0BCFF)
6-
val PurpleGrey80 = Color(0xFFCCC2DC)
7-
val Pink80 = Color(0xFFEFB8C8)
7+
// Main Color - Slate
8+
val KindlSlate50 = Color(0xFFF8F9FA)
9+
val KindlSlate100 = Color(0xFFE9ECEF)
10+
val KindlSlate200 = Color(0xFFD3D7DC)
11+
val KindlSlate300 = Color(0xFFB0B7C0)
12+
val KindlSlate400 = Color(0xFF7D8794)
13+
val KindlSlate500 = Color(0xFF4A5568)
14+
val KindlSlate600 = Color(0xFF2D3748)
15+
val KindlSlate700 = Color(0xFF1E2530)
16+
val KindlSlate800 = Color(0xFF151A23)
17+
val KindlSlate900 = Color(0xFF0D1117)
818

9-
val Purple40 = Color(0xFF6650a4)
10-
val PurpleGrey40 = Color(0xFF625b71)
11-
val Pink40 = Color(0xFF7D5260)
19+
// Point Color - Coral
20+
val KindlCoral50 = Color(0xFFFFF5F5)
21+
val KindlCoral100 = Color(0xFFFFE3E3)
22+
val KindlCoral200 = Color(0xFFFFC9C9)
23+
val KindlCoral300 = Color(0xFFFFA8A8)
24+
val KindlCoral400 = Color(0xFFFF8787)
25+
val KindlCoral500 = Color(0xFFFF6B6B)
26+
val KindlCoral600 = Color(0xFFFA5252)
27+
val KindlCoral700 = Color(0xFFF03E3E)
28+
val KindlCoral800 = Color(0xFFE03131)
29+
val KindlCoral900 = Color(0xFFC92A2A)
30+
31+
// Supporting Colors
32+
val KindlBlue500 = Color(0xFF339AF0)
33+
val KindlTeal500 = Color(0xFF20C997)
34+
val KindlAmber500 = Color(0xFFFCC419)
35+
36+
val White = Color(0xFFFFFFFF)
37+
38+
@Immutable
39+
data class KindlColors(
40+
// Surface
41+
val background: Color,
42+
val foreground: Color,
43+
val card: Color,
44+
val cardForeground: Color,
45+
val popover: Color,
46+
val popoverForeground: Color,
47+
48+
// Interactive
49+
val primary: Color,
50+
val primaryForeground: Color,
51+
val secondary: Color,
52+
val secondaryForeground: Color,
53+
54+
// State
55+
val muted: Color,
56+
val mutedForeground: Color,
57+
val accent: Color,
58+
val accentForeground: Color,
59+
val destructive: Color,
60+
val destructiveForeground: Color,
61+
val success: Color,
62+
val successForeground: Color,
63+
64+
// Form
65+
val border: Color,
66+
val input: Color,
67+
val inputBackground: Color,
68+
val switchBackground: Color,
69+
val ring: Color,
70+
71+
// Chart
72+
val chart1: Color,
73+
val chart2: Color,
74+
val chart3: Color,
75+
val chart4: Color,
76+
val chart5: Color,
77+
78+
// Sidebar
79+
val sidebar: Color,
80+
val sidebarForeground: Color,
81+
val sidebarPrimary: Color,
82+
val sidebarPrimaryForeground: Color,
83+
val sidebarAccent: Color,
84+
val sidebarAccentForeground: Color,
85+
val sidebarBorder: Color,
86+
val sidebarRing: Color,
87+
88+
// Raw palette (필요 시 직접 참조)
89+
val slate50: Color = KindlSlate50,
90+
val slate100: Color = KindlSlate100,
91+
val slate200: Color = KindlSlate200,
92+
val slate300: Color = KindlSlate300,
93+
val slate400: Color = KindlSlate400,
94+
val slate500: Color = KindlSlate500,
95+
val slate600: Color = KindlSlate600,
96+
val slate700: Color = KindlSlate700,
97+
val slate800: Color = KindlSlate800,
98+
val slate900: Color = KindlSlate900,
99+
100+
val coral50: Color = KindlCoral50,
101+
val coral100: Color = KindlCoral100,
102+
val coral200: Color = KindlCoral200,
103+
val coral300: Color = KindlCoral300,
104+
val coral400: Color = KindlCoral400,
105+
val coral500: Color = KindlCoral500,
106+
val coral600: Color = KindlCoral600,
107+
val coral700: Color = KindlCoral700,
108+
val coral800: Color = KindlCoral800,
109+
val coral900: Color = KindlCoral900,
110+
111+
val blue500: Color = KindlBlue500,
112+
val teal500: Color = KindlTeal500,
113+
val amber500: Color = KindlAmber500,
114+
115+
val isDark: Boolean,
116+
)
117+
118+
val lightKindlColors = KindlColors(
119+
background = White,
120+
foreground = KindlSlate700,
121+
card = White,
122+
cardForeground = KindlSlate700,
123+
popover = White,
124+
popoverForeground = KindlSlate700,
125+
126+
primary = KindlSlate700,
127+
primaryForeground = White,
128+
secondary = KindlCoral500,
129+
secondaryForeground = White,
130+
131+
muted = KindlSlate50,
132+
mutedForeground = KindlSlate400,
133+
accent = KindlCoral500,
134+
accentForeground = White,
135+
destructive = KindlCoral700,
136+
destructiveForeground= White,
137+
success = KindlTeal500,
138+
successForeground = White,
139+
140+
border = KindlSlate700.copy(alpha = 0.10f),
141+
input = Color.Transparent,
142+
inputBackground = KindlSlate50,
143+
switchBackground = KindlSlate200,
144+
ring = KindlCoral500,
145+
146+
chart1 = KindlCoral500,
147+
chart2 = KindlSlate700,
148+
chart3 = KindlBlue500,
149+
chart4 = KindlTeal500,
150+
chart5 = KindlAmber500,
151+
152+
sidebar = KindlSlate50,
153+
sidebarForeground = KindlSlate700,
154+
sidebarPrimary = KindlSlate700,
155+
sidebarPrimaryForeground = White,
156+
sidebarAccent = KindlSlate100,
157+
sidebarAccentForeground = KindlSlate700,
158+
sidebarBorder = KindlSlate700.copy(alpha = 0.10f),
159+
sidebarRing = KindlCoral500,
160+
161+
isDark = false,
162+
)
163+
164+
val darkKindlColors = KindlColors(
165+
background = KindlSlate900,
166+
foreground = KindlSlate50,
167+
card = KindlSlate800,
168+
cardForeground = KindlSlate50,
169+
popover = KindlSlate800,
170+
popoverForeground = KindlSlate50,
171+
172+
primary = KindlCoral500,
173+
primaryForeground = White,
174+
secondary = KindlSlate700,
175+
secondaryForeground = White,
176+
177+
muted = KindlSlate600,
178+
mutedForeground = KindlSlate300,
179+
accent = KindlCoral500,
180+
accentForeground = White,
181+
destructive = KindlCoral700,
182+
destructiveForeground= White,
183+
success = KindlTeal500,
184+
successForeground = KindlSlate900,
185+
186+
border = KindlCoral500.copy(alpha = 0.20f),
187+
input = KindlCoral500.copy(alpha = 0.10f),
188+
inputBackground = KindlSlate800,
189+
switchBackground = KindlSlate600,
190+
ring = KindlCoral500,
191+
192+
chart1 = KindlCoral500,
193+
chart2 = KindlBlue500,
194+
chart3 = KindlTeal500,
195+
chart4 = KindlAmber500,
196+
chart5 = KindlCoral400,
197+
198+
sidebar = KindlSlate800,
199+
sidebarForeground = KindlSlate50,
200+
sidebarPrimary = KindlCoral500,
201+
sidebarPrimaryForeground = White,
202+
sidebarAccent = KindlSlate600,
203+
sidebarAccentForeground = KindlSlate50,
204+
sidebarBorder = KindlCoral500.copy(alpha = 0.20f),
205+
sidebarRing = KindlCoral500,
206+
207+
isDark = true,
208+
)
209+
210+
val localKindlColors = staticCompositionLocalOf { darkKindlColors }

0 commit comments

Comments
 (0)