Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
75793c9
[FEAT/#76] ImePadding 이중 패딩 관련 modifier 확장함수 추가
sohee6989 Jan 18, 2026
dd39692
[FEAT/#76] ImePadding 패딩관련 Manifest에 adjustResize 추가
sohee6989 Jan 18, 2026
a765f39
[FEAT/#76] Dto 생성
sohee6989 Jan 18, 2026
fe0ce09
[FEAT/#76] Service 생성
sohee6989 Jan 18, 2026
34ff267
[FEAT/#76] DataSource 생성
sohee6989 Jan 18, 2026
fc7808c
[FEAT/#76] Model 생성
sohee6989 Jan 18, 2026
6112d22
[FEAT/#76] Repository 생성
sohee6989 Jan 18, 2026
73f6fe3
[FEAT/#76] 네비 관련 세팅
sohee6989 Jan 18, 2026
f18c53f
[FEAT/#76] 모듈 생성
sohee6989 Jan 18, 2026
37cec53
[FEAT/#76] 온보딩-정보입력 서버 연결
sohee6989 Jan 18, 2026
8686f6b
[FEAT/#76] 자동 회전 막기
sohee6989 Jan 18, 2026
17f15dc
[CHORE/#76] ktlint 체크
sohee6989 Jan 18, 2026
3fc46e7
[CHORE/#76] ktlint 체크
sohee6989 Jan 18, 2026
3d173a3
[CHORE/#76] 오타 수정
sohee6989 Jan 18, 2026
7761fb6
[FEAT/#76] 이름 & 나이 에러 처리 추가
sohee6989 Jan 18, 2026
2a72d45
[CHORE/#76] ktlint 체크
sohee6989 Jan 18, 2026
5c4e32d
[CHORE/#76] 버튼 enable 분기 추가
sohee6989 Jan 18, 2026
1eb0deb
[CHORE/#76] ktlint 체크
sohee6989 Jan 18, 2026
8469849
Merge from develop
sohee6989 Jan 18, 2026
86f78c8
[FEAT/76] 스플래시, 온보딩 화면 네비 연결
sohee6989 Jan 18, 2026
1904cea
[CHORE/#85] 코드리뷰 반영
sohee6989 Jan 19, 2026
c5e3f98
Merge from develop
sohee6989 Jan 19, 2026
5754243
[CHORE/#76] ktlint 체크
sohee6989 Jan 19, 2026
671d003
[CHORE/#76] 임포트 추가
sohee6989 Jan 19, 2026
bd235c7
[CHORE/#76] 래빗이 리뷰 반영
sohee6989 Jan 19, 2026
7d2fba7
[CHORE/#76] ktlint 체크
sohee6989 Jan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
android:theme="@style/Theme.Cherrish" >
<activity
android:name=".presentation.main.MainActivity"
android:windowSoftInputMode="adjustResize"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Cherrish" >
Expand All @@ -27,4 +28,4 @@
</activity>
</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import android.graphics.BlurMaskFilter
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.imePadding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawBehind
Expand All @@ -17,6 +23,9 @@ import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.findRootCoordinates
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
Expand Down Expand Up @@ -86,3 +95,19 @@ fun Modifier.dropShadow(
}
}
}

fun Modifier.advancedImePadding() = composed {
var consumePadding by remember { mutableStateOf(0) }
onGloballyPositioned { coordinates ->
consumePadding = (
coordinates.findRootCoordinates().size.height -
(coordinates.positionInWindow().y + coordinates.size.height).toInt()
).coerceAtLeast(
0
)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
.consumeWindowInsets(
PaddingValues(bottom = with(LocalDensity.current) { consumePadding.toDp() })
)
.imePadding()
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.cherrish.android.data.di

import com.cherrish.android.data.remote.datasource.CalendarDataSource
import com.cherrish.android.data.remote.datasource.OnboardingProfileDataSource
import com.cherrish.android.data.remote.datasourceimpl.CalendarDataSourceImpl
import com.cherrish.android.data.remote.datasourceimpl.OnboardingProfileDataSourceImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -16,4 +18,10 @@ abstract class DataSourceModule {
abstract fun bindCalendarDataSource(
calendarDataSourceImpl: CalendarDataSourceImpl
): CalendarDataSource

@Binds
@Singleton
abstract fun bindOnboardingProfileDataSource(
onboardingProfileDataSourceImpl: OnboardingProfileDataSourceImpl
): OnboardingProfileDataSource
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.cherrish.android.data.di

import com.cherrish.android.data.repository.CalendarRepository
import com.cherrish.android.data.repository.OnboardingProfileRepository
import com.cherrish.android.data.repositoryimpl.CalendarRepositoryImpl
import com.cherrish.android.data.repositoryimpl.OnboardingProfileRepositoryImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -16,4 +18,10 @@ abstract class RepositoryModule {
abstract fun bindCalendarRepository(
calendarRepositoryImpl: CalendarRepositoryImpl
): CalendarRepository

@Binds
@Singleton
abstract fun bindOnboardingProfileRepository(
onboardingProfileRepositoryImpl: OnboardingProfileRepositoryImpl
): OnboardingProfileRepository
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.cherrish.android.data.di

import com.cherrish.android.data.remote.service.CalendarService
import com.cherrish.android.data.remote.service.OnboardingProfileService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -16,4 +17,10 @@ object ServiceModule {
fun provideCalendarService(
retrofit: Retrofit
): CalendarService = retrofit.create(CalendarService::class.java)

@Provides
@Singleton
fun provideOnboardingProfileService(
retrofit: Retrofit
): OnboardingProfileService = retrofit.create(OnboardingProfileService::class.java)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.cherrish.android.data.model

import com.cherrish.android.data.remote.dto.request.OnboardingProfileRequestDto

data class OnboardingProfileRequestModel(
val name: String,
val age: Int
)

fun OnboardingProfileRequestModel.toDto() = OnboardingProfileRequestDto(
name = this.name,
age = this.age
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.cherrish.android.data.model

import com.cherrish.android.data.remote.dto.response.OnboardingProfileResponseDto

data class OnboardingProfileResponseModel(
val id: Long,
val name: String,
val date: String
)

fun OnboardingProfileResponseDto.toModel() = OnboardingProfileResponseModel(
id = this.id,
name = this.name,
date = this.date
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.cherrish.android.data.remote.datasource

import com.cherrish.android.core.network.BaseResponse
import com.cherrish.android.data.remote.dto.request.OnboardingProfileRequestDto
import com.cherrish.android.data.remote.dto.response.OnboardingProfileResponseDto

interface OnboardingProfileDataSource {
suspend fun postOnboardingProfile(
request: OnboardingProfileRequestDto
): BaseResponse<OnboardingProfileResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.cherrish.android.data.remote.datasourceimpl

import com.cherrish.android.core.network.BaseResponse
import com.cherrish.android.data.remote.datasource.OnboardingProfileDataSource
import com.cherrish.android.data.remote.dto.request.OnboardingProfileRequestDto
import com.cherrish.android.data.remote.dto.response.OnboardingProfileResponseDto
import com.cherrish.android.data.remote.service.OnboardingProfileService
import javax.inject.Inject

class OnboardingProfileDataSourceImpl @Inject constructor(
private val onboardingProfileService: OnboardingProfileService
) : OnboardingProfileDataSource {
override suspend fun postOnboardingProfile(
request: OnboardingProfileRequestDto
): BaseResponse<OnboardingProfileResponseDto> {
return onboardingProfileService.postOnboardingProfile(request)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.cherrish.android.data.remote.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class OnboardingProfileRequestDto(
@SerialName("name")
val name: String,
@SerialName("age")
val age: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cherrish.android.data.remote.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class OnboardingProfileResponseDto(
@SerialName("id")
val id: Long,
@SerialName("name")
val name: String,
@SerialName("date")
val date: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cherrish.android.data.remote.service

import com.cherrish.android.core.network.BaseResponse
import com.cherrish.android.data.remote.dto.request.OnboardingProfileRequestDto
import com.cherrish.android.data.remote.dto.response.OnboardingProfileResponseDto
import retrofit2.http.Body
import retrofit2.http.POST

interface OnboardingProfileService {
@POST("api/onboarding/profiles")
suspend fun postOnboardingProfile(
@Body request: OnboardingProfileRequestDto
): BaseResponse<OnboardingProfileResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.cherrish.android.data.repository

import com.cherrish.android.data.model.OnboardingProfileRequestModel
import com.cherrish.android.data.model.OnboardingProfileResponseModel

interface OnboardingProfileRepository {
suspend fun postOnboardingProfile(
request: OnboardingProfileRequestModel
): Result<OnboardingProfileResponseModel>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.cherrish.android.data.repositoryimpl

import com.cherrish.android.core.util.suspendRunCatching
import com.cherrish.android.data.model.OnboardingProfileRequestModel
import com.cherrish.android.data.model.OnboardingProfileResponseModel
import com.cherrish.android.data.model.toDto
import com.cherrish.android.data.model.toModel
import com.cherrish.android.data.remote.datasource.OnboardingProfileDataSource
import com.cherrish.android.data.repository.OnboardingProfileRepository
import javax.inject.Inject

class OnboardingProfileRepositoryImpl @Inject constructor(
private val onboardingProfileDataSource: OnboardingProfileDataSource
) : OnboardingProfileRepository {
override suspend fun postOnboardingProfile(
request: OnboardingProfileRequestModel
): Result<OnboardingProfileResponseModel> =
suspendRunCatching {
onboardingProfileDataSource.postOnboardingProfile(
request = request.toDto()
).data!!.toModel()
}
Comment on lines +18 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

data!! 강제 언래핑은 NPE 위험이 있습니다.

API 응답이 성공적으로 반환되더라도 datanull인 경우 NullPointerException이 발생합니다. suspendRunCatching이 예외를 Result.failure로 변환하긴 하지만, 명시적인 null 처리가 더 안전합니다.

🛠️ 제안하는 수정 방안
     override suspend fun postOnboardingProfile(
         request: OnboardingProfileRequestModel
     ): Result<OnboardingProfileResponseModel> =
         suspendRunCatching {
             onboardingProfileDataSource.postOnboardingProfile(
                 request = request.toDto()
-            ).data!!.toModel()
+            ).data?.toModel()
+                ?: throw IllegalStateException("Onboarding profile response data is null")
         }

또는 API 응답 구조에서 data가 항상 non-null임이 보장된다면, DTO의 data 필드를 non-nullable로 변경하는 것이 더 근본적인 해결책입니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
suspendRunCatching {
onboardingProfileDataSource.postOnboardingProfile(
request = request.toDto()
).data!!.toModel()
}
suspendRunCatching {
onboardingProfileDataSource.postOnboardingProfile(
request = request.toDto()
).data?.toModel()
?: throw IllegalStateException("Onboarding profile response data is null")
}
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/data/repositoryimpl/OnboardingProfileRepositoryImpl.kt`
around lines 18 - 22, Replace the forced unwrap of response.data in the
suspendRunCatching block: call
onboardingProfileDataSource.postOnboardingProfile(request = request.toDto()),
capture the response, and explicitly handle a null data (response.data) before
calling toModel(); e.g., if data is null return/emit a Result.failure or throw a
clear exception with context rather than using !!, or alternatively make the
DTO's data field non-nullable if it is guaranteed by the API; reference
onboardingProfileDataSource.postOnboardingProfile, suspendRunCatching,
response.data, toModel() and toDto() when applying the change.

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.cherrish.android.presentation.main

import android.content.pm.ActivityInfo
import android.graphics.Color
import android.os.Bundle
import androidx.activity.ComponentActivity
Expand All @@ -13,11 +14,11 @@ import dagger.hilt.android.AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

enableEdgeToEdge(
statusBarStyle = SystemBarStyle.dark(Color.TRANSPARENT),
navigationBarStyle = SystemBarStyle.dark(Color.TRANSPARENT)
)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P999: 이게 아까 그 화면 방향 이슈 해결하려고 쓴 코드인 것? 이거 쓰면 화면이 안돌아가나용?
image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵넵!!

setContent {
CherrishTheme {
val appState = rememberMainAppState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.cherrish.android.presentation.calendar.navigation.navigateToCalendar
import com.cherrish.android.presentation.calendar.navigation.navigateToProcedure
import com.cherrish.android.presentation.challenge.navigation.navigateToChallenge
import com.cherrish.android.presentation.home.navigation.navigateToHome
import com.cherrish.android.presentation.mypage.navigation.navigateToMyPage
import com.cherrish.android.presentation.onboarding.navigation.navigateToOnboarding
import com.cherrish.android.presentation.onboarding.navigation.navigateToOnboardingInformation
import com.cherrish.android.presentation.splash.navigation.Splash
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
Expand All @@ -27,6 +30,17 @@ class MainAppState(
) {
val startDestination = Splash

private val clearStackNavOptions = navOptions {
popUpTo(0) { inclusive = true }
launchSingleTop = true
restoreState = false
}

private val keepStackNavOptions = navOptions {
launchSingleTop = true
restoreState = true
}

private val currentDestination = navController.currentBackStackEntryFlow
.map { it.destination }
.stateIn(
Expand Down Expand Up @@ -79,6 +93,18 @@ class MainAppState(
}
}

fun navigateToOnboarding(navOptions: NavOptions? = clearStackNavOptions) {
navController.navigateToOnboarding(navOptions)
}

fun navigateToOnboardingInformation(navOptions: NavOptions? = clearStackNavOptions) {
navController.navigateToOnboardingInformation(navOptions)
}

fun navigateToHome(navOptions: NavOptions? = clearStackNavOptions) {
navController.navigateToHome(navOptions)
}

fun navigateUp() {
navController.navigateUp()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import com.cherrish.android.presentation.challenge.navigation.challengeNavGraph
import com.cherrish.android.presentation.home.navigation.homeNavGraph
import com.cherrish.android.presentation.main.component.MainBottomBar
import com.cherrish.android.presentation.mypage.navigation.myPageNavGraph
import com.cherrish.android.presentation.onboarding.navigation.onboardingInformationNavGraph
import com.cherrish.android.presentation.onboarding.navigation.onboardingNavGraph
import com.cherrish.android.presentation.splash.navigation.splashNavGraph
import kotlinx.collections.immutable.toPersistentList

Expand Down Expand Up @@ -41,10 +43,20 @@ fun MainScreen(
startDestination = appState.startDestination
) {
splashNavGraph(
navigateToOnboarding = {}, // TODO: 로직 넣어서 바꿀 예정
navigateToOnboarding = appState::navigateToOnboarding,
paddingValues = innerPadding
)

onboardingNavGraph(
paddingValues = innerPadding,
navigateToOnboardingInformation = appState::navigateToOnboardingInformation
)

onboardingInformationNavGraph(
paddingValues = innerPadding,
navigateToHome = appState::navigateToHome
)

homeNavGraph(paddingValues = innerPadding)

calendarNavGraph(
Expand Down
Loading