Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 5 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.google.devtools.ksp.gradle.KspExtension
import com.ninecraft.booket.convention.getLocalProperty
import org.gradle.kotlin.dsl.configure
import java.util.Properties

Expand Down Expand Up @@ -32,6 +32,7 @@ android {
getByName("debug") {
isDebuggable = true
applicationIdSuffix = ".dev"
buildConfigField("String", "GOOGLE_WEB_CLIENT_ID", getLocalProperty("DEBUG_GOOGLE_WEB_CLIENT_ID"))
manifestPlaceholders += mapOf(
"appName" to "@string/app_name_dev",
)
Expand All @@ -42,6 +43,7 @@ android {
isMinifyEnabled = true
isShrinkResources = true
signingConfig = signingConfigs.getByName("release")
buildConfigField("String", "GOOGLE_WEB_CLIENT_ID", getLocalProperty("RELEASE_GOOGLE_WEB_CLIENT_ID"))
manifestPlaceholders += mapOf(
"appName" to "@string/app_name",
)
Expand All @@ -53,8 +55,8 @@ android {
}

defaultConfig {
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", getApiKey("KAKAO_NATIVE_APP_KEY"))
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = getApiKey("KAKAO_NATIVE_APP_KEY").trim('"')
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", getLocalProperty("KAKAO_NATIVE_APP_KEY"))
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = getLocalProperty("KAKAO_NATIVE_APP_KEY").trim('"')
}

buildFeatures {
Expand Down Expand Up @@ -109,7 +111,3 @@ dependencies {
api(libs.circuit.codegen.annotation)
ksp(libs.circuit.codegen.ksp)
}

fun getApiKey(propertyKey: String): String {
return gradleLocalProperties(rootDir, providers).getProperty(propertyKey)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ninecraft.booket.convention

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the
Expand All @@ -10,3 +11,7 @@ internal val Project.libs
internal fun Project.applyPlugins(vararg plugins: String) {
plugins.forEach(pluginManager::apply)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

👍👍👍

fun Project.getLocalProperty(propertyKey: String): String {
return gradleLocalProperties(rootDir, providers).getProperty(propertyKey)
}
10 changes: 3 additions & 7 deletions core/network/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.ninecraft.booket.convention.getLocalProperty


plugins {
Expand All @@ -18,11 +18,11 @@ android {

buildTypes {
debug {
buildConfigField("String", "SERVER_BASE_URL", getServerBaseUrl("DEBUG_SERVER_BASE_URL"))
buildConfigField("String", "SERVER_BASE_URL", getLocalProperty("DEBUG_SERVER_BASE_URL"))
}

release {
buildConfigField("String", "SERVER_BASE_URL", getServerBaseUrl("RELEASE_SERVER_BASE_URL"))
buildConfigField("String", "SERVER_BASE_URL", getLocalProperty("RELEASE_SERVER_BASE_URL"))
}
}
}
Expand All @@ -36,7 +36,3 @@ dependencies {
libs.logger,
)
}

fun getServerBaseUrl(propertyKey: String): String {
return gradleLocalProperties(rootDir, providers).getProperty(propertyKey)
}
9 changes: 2 additions & 7 deletions core/ocr/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties

import com.ninecraft.booket.convention.getLocalProperty

plugins {
alias(libs.plugins.booket.android.library)
Expand All @@ -13,7 +12,7 @@ android {
namespace = "com.ninecraft.booket.core.ocr"

defaultConfig {
buildConfigField("String", "CLOUD_VISION_API_KEY", getApiKey("CLOUD_VISION_API_KEY"))
buildConfigField("String", "CLOUD_VISION_API_KEY", getLocalProperty("CLOUD_VISION_API_KEY"))
}

buildFeatures {
Expand All @@ -30,7 +29,3 @@ dependencies {
libs.logger,
)
}

fun getApiKey(propertyKey: String): String {
return gradleLocalProperties(rootDir, providers).getProperty(propertyKey)
}
16 changes: 16 additions & 0 deletions feature/login/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.ninecraft.booket.convention.getLocalProperty

plugins {
alias(libs.plugins.booket.android.feature)
alias(libs.plugins.kotlin.serialization)
Expand All @@ -8,6 +10,20 @@ plugins {

android {
namespace = "com.ninecraft.booket.feature.login"

buildTypes {
getByName("debug") {
buildConfigField("String", "GOOGLE_WEB_CLIENT_ID", getLocalProperty("DEBUG_GOOGLE_WEB_CLIENT_ID"))
}

getByName("release") {
buildConfigField("String", "GOOGLE_WEB_CLIENT_ID", getLocalProperty("RELEASE_GOOGLE_WEB_CLIENT_ID"))
}
}

buildFeatures {
buildConfig = true
}
}

dependencies {
Expand Down
4 changes: 2 additions & 2 deletions feature/onboarding/stability/onboarding.stability
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ internal fun com.ninecraft.booket.feature.onboarding.OnboardingUi(state: com.nin
- modifier: STABLE (marked @Stable or @Immutable)

@Composable
internal fun com.ninecraft.booket.feature.onboarding.component.OnboardingPage(imageRes: kotlin.Int, titleRes: kotlin.Int, highlightTextRes: kotlin.Int, descriptionRes: kotlin.Int, modifier: androidx.compose.ui.Modifier): kotlin.Unit
internal fun com.ninecraft.booket.feature.onboarding.component.OnboardingPage(imageRes: kotlin.Int, titleRes: kotlin.Int, highlightTextRes: kotlin.Int?, descriptionRes: kotlin.Int, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
- imageRes: STABLE (primitive type)
- titleRes: STABLE (primitive type)
- highlightTextRes: STABLE (primitive type)
- highlightTextRes: STABLE (class with no mutable properties)
- descriptionRes: STABLE (primitive type)
- modifier: STABLE (marked @Stable or @Immutable)

Expand Down
11 changes: 11 additions & 0 deletions feature/search/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.ninecraft.booket.convention.getLocalProperty


plugins {
alias(libs.plugins.booket.android.feature)
alias(libs.plugins.kotlin.serialization)
Expand All @@ -8,6 +11,14 @@ plugins {

android {
namespace = "com.ninecraft.booket.feature.search"

buildFeatures {
buildConfig = true
}

defaultConfig {
buildConfigField("String", "REED_KAKAOTALK_CHANNEL_URL", getLocalProperty("REED_KAKAOTALK_CHANNEL_URL"))
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class BookSearchPresenter(
override fun present(): BookSearchUiState {
val scope = rememberCoroutineScope()
val userState by authRepository.userState.collectAsRetainedState(initial = UserState.Guest)
var uiState by rememberRetained { mutableStateOf<UiState>(UiState.Idle) }
var searchUiState by rememberRetained { mutableStateOf<SearchUiState>(SearchUiState.Idle) }
var footerState by rememberRetained { mutableStateOf<FooterState>(FooterState.Idle) }
val queryState = rememberTextFieldState()
val recentSearches by repository.bookRecentSearches.collectAsRetainedState(initial = emptyList())
Expand All @@ -86,7 +86,7 @@ class BookSearchPresenter(
fun searchBooks(query: String, startIndex: Int = START_INDEX) {
scope.launch {
if (startIndex == START_INDEX) {
uiState = UiState.Loading
searchUiState = SearchUiState.Loading
} else {
footerState = FooterState.Loading
}
Expand All @@ -108,7 +108,7 @@ class BookSearchPresenter(
isLastPage = result.lastPage

if (startIndex == START_INDEX) {
uiState = UiState.Success
searchUiState = SearchUiState.Success
analyticsHelper.logEvent(SEARCH_BOOK_RESULT)
} else {
footerState = if (isLastPage) FooterState.End else FooterState.Idle
Expand All @@ -119,7 +119,7 @@ class BookSearchPresenter(
analyticsHelper.logEvent(ERROR_SEARCH_LOADING)
val errorMessage = exception.message ?: "알 수 없는 오류가 발생했습니다."
if (startIndex == START_INDEX) {
uiState = UiState.Error(exception)
searchUiState = SearchUiState.Error(exception)
} else {
footerState = FooterState.Error(errorMessage)
}
Expand Down Expand Up @@ -260,6 +260,10 @@ class BookSearchPresenter(
is BookSearchUiEvent.OnBookRegisterSuccessCancelButtonClick -> {
isBookRegisterSuccessBottomSheetVisible = false
}

is BookSearchUiEvent.OnInquireClick -> {
sideEffect = BookSearchSideEffect.NavigateToKakaoTalkChannel
}
}
}

Expand All @@ -268,7 +272,7 @@ class BookSearchPresenter(
}

return BookSearchUiState(
uiState = uiState,
searchUiState = searchUiState,
footerState = footerState,
queryState = queryState,
recentSearches = recentSearches.toImmutableList(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import com.ninecraft.booket.core.common.constants.BookStatus
import com.ninecraft.booket.core.common.extensions.toErrorType
import com.ninecraft.booket.core.designsystem.DevicePreview
import com.ninecraft.booket.core.designsystem.component.ReedDivider
import com.ninecraft.booket.core.designsystem.component.button.ReedButton
import com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle
import com.ninecraft.booket.core.designsystem.component.button.smallButtonStyle
import com.ninecraft.booket.core.designsystem.component.textfield.ReedTextField
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
import com.ninecraft.booket.core.designsystem.theme.White
Expand Down Expand Up @@ -114,19 +117,19 @@ internal fun BookSearchContent(
ReedDivider()
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing2))

when (state.uiState) {
is UiState.Loading -> {
when (state.searchUiState) {
is SearchUiState.Loading -> {
ReedLoadingIndicator()
}

is UiState.Error -> {
is SearchUiState.Error -> {
ReedErrorUi(
errorType = state.uiState.exception.toErrorType(),
errorType = state.searchUiState.exception.toErrorType(),
onRetryClick = { state.eventSink(BookSearchUiEvent.OnRetryClick) },
)
}

is UiState.Idle -> {
is SearchUiState.Idle -> {
if (state.recentSearches.isEmpty()) {
Box(
modifier = Modifier.fillMaxSize(),
Expand Down Expand Up @@ -173,17 +176,33 @@ internal fun BookSearchContent(
}
}

is UiState.Success -> {
is SearchUiState.Success -> {
if (state.isEmptySearchResult) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Text(
text = stringResource(R.string.empty_results),
color = ReedTheme.colors.contentSecondary,
style = ReedTheme.typography.body1Medium,
)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = stringResource(R.string.empty_results_title),
color = ReedTheme.colors.contentPrimary,
style = ReedTheme.typography.headline1SemiBold,
)
Text(
text = stringResource(R.string.empty_results_description),
color = ReedTheme.colors.contentSecondary,
style = ReedTheme.typography.body1Medium,
)
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
ReedButton(
onClick = { state.eventSink(BookSearchUiEvent.OnInquireClick) },
text = stringResource(R.string.inquire),
sizeStyle = smallButtonStyle,
colorStyle = ReedButtonColorStyle.SECONDARY,
)
}
}
} else {
Row(
Expand Down Expand Up @@ -294,7 +313,7 @@ internal fun BookSearchContent(

@DevicePreview
@Composable
private fun BookSearchPreview() {
private fun BookRecentSearchPreview() {
ReedTheme {
BookSearchUi(
state = BookSearchUiState(
Expand All @@ -303,3 +322,16 @@ private fun BookSearchPreview() {
)
}
}

@DevicePreview
@Composable
private fun BookSearchEmptyResultPreview() {
ReedTheme {
BookSearchContent(
state = BookSearchUiState(
searchUiState = SearchUiState.Success,
eventSink = {},
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import kotlinx.collections.immutable.persistentListOf
import java.util.UUID

@Immutable
sealed interface UiState {
data object Idle : UiState
data object Loading : UiState
data object Success : UiState
data class Error(val exception: Throwable) : UiState
sealed interface SearchUiState {
data object Idle : SearchUiState
data object Loading : SearchUiState
data object Success : SearchUiState
data class Error(val exception: Throwable) : SearchUiState
}

data class BookSearchUiState(
val uiState: UiState = UiState.Idle,
val searchUiState: SearchUiState = SearchUiState.Idle,
val footerState: FooterState = FooterState.Idle,
val queryState: TextFieldState = TextFieldState(),
val recentSearches: ImmutableList<String> = persistentListOf(),
Expand All @@ -37,7 +37,7 @@ data class BookSearchUiState(
val sideEffect: BookSearchSideEffect? = null,
val eventSink: (BookSearchUiEvent) -> Unit,
) : CircuitUiState {
val isEmptySearchResult: Boolean get() = uiState is UiState.Success && searchResult.totalResults == 0
val isEmptySearchResult: Boolean get() = searchUiState is SearchUiState.Success && searchResult.totalResults == 0
}

@Immutable
Expand All @@ -46,6 +46,8 @@ sealed interface BookSearchSideEffect {
val message: UiText,
private val key: String = UUID.randomUUID().toString(),
) : BookSearchSideEffect

data object NavigateToKakaoTalkChannel : BookSearchSideEffect
}

sealed interface BookSearchUiEvent : CircuitUiEvent {
Expand All @@ -64,4 +66,5 @@ sealed interface BookSearchUiEvent : CircuitUiEvent {
data object OnBookRegisterButtonClick : BookSearchUiEvent
data object OnBookRegisterSuccessOkButtonClick : BookSearchUiEvent
data object OnBookRegisterSuccessCancelButtonClick : BookSearchUiEvent
data object OnInquireClick : BookSearchUiEvent
}
Loading
Loading