Skip to content

Commit d060ae2

Browse files
committed
Merge branch 'develop' into BOOK-225-feature/#111
# Conflicts: # feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt
2 parents 30cc067 + bf6dc12 commit d060ae2

File tree

8 files changed

+167
-34
lines changed

8 files changed

+167
-34
lines changed

.github/workflows/android-cd.yml

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: Android CD
2+
3+
env:
4+
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false"
5+
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
6+
7+
on:
8+
pull_request:
9+
branches:
10+
- main
11+
12+
jobs:
13+
cd-build:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
with:
20+
# 최근 태그를 확인하기 위해 필요
21+
fetch-depth: 0
22+
23+
- name: Set up JDK 17
24+
uses: actions/setup-java@v4
25+
with:
26+
distribution: 'corretto'
27+
java-version: 17
28+
29+
- name: Generate reed.jks
30+
run: echo '${{ secrets.REED_JAVA_KEYSTORE }}' | base64 -d > ./reed.jks
31+
32+
- name: Generate local.properties
33+
run: echo '${{ secrets.LOCAL_PROPERTIES }}' | base64 -d > ./local.properties
34+
35+
- name: Generate keystore.properties
36+
run: echo '${{ secrets.KEYSTORE_PROPERTIES }}' | base64 -d > ./keystore.properties
37+
38+
- name: Generate google-services.json
39+
run: echo '${{ secrets.GOOGLE_SERVICES }}' | base64 -d > ./app/google-services.json
40+
41+
- name: Extract Version Name from ApplicationConstants.kt
42+
run: |
43+
set -euo pipefail
44+
VERSION=$(grep "VERSION_NAME" build-logic/src/main/kotlin/com/ninecraft/booket/convention/ApplicationConstants.kt | sed -E 's/.*VERSION_NAME\s*=\s*"([^"]+)".*/\1/')
45+
if [[ -z "$VERSION" ]]; then
46+
echo "Error: ApplicationConstants.kt에서 VERSION_NAME 값을 추출하지 못했습니다." >&2
47+
exit 1
48+
fi
49+
echo "version=v${VERSION}" >> "$GITHUB_OUTPUT"
50+
echo "Version extracted from ApplicationConstants.kt: v${VERSION}"
51+
id: extract_version
52+
53+
- name: Generate Firebase Release Note
54+
id: firebase_release_note
55+
env:
56+
PR_TITLE: ${{ github.event.pull_request.title }}
57+
run: |
58+
# PR_TITLE은 env에서 안전하게 전달됨
59+
# 가장 최근 태그 찾기 (현재 버전 이전의 태그)
60+
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
61+
62+
# 릴리스 노트 내용 생성
63+
NOTES="## 🚀 변경사항: ${PR_TITLE}\n\n"
64+
65+
if [ -n "$LATEST_TAG" ]; then
66+
NOTES="${NOTES}### 이전 버전($LATEST_TAG)부터의 변경사항:\n"
67+
# 최근 태그부터 현재까지의 커밋만 가져옴
68+
COMMITS=$(git log --pretty=format:"- %h %s (%an)" ${LATEST_TAG}..HEAD --no-merges)
69+
NOTES="${NOTES}${COMMITS}"
70+
else
71+
NOTES="${NOTES}### 커밋 내역:\n"
72+
# 태그가 없는 경우 최근 10개 커밋만 표시
73+
COMMITS=$(git log --pretty=format:"- %h %s (%an)" --no-merges -n 10)
74+
NOTES="${NOTES}${COMMITS}\n\n(이전 릴리스 태그가 없어 최근 10개 커밋만 표시)"
75+
fi
76+
77+
# 환경 변수로 저장
78+
echo "notes<<EOF" >> $GITHUB_OUTPUT
79+
echo -e "$NOTES" >> $GITHUB_OUTPUT
80+
echo "EOF" >> $GITHUB_OUTPUT
81+
82+
- name: Build Release AAB
83+
run: |
84+
./gradlew :app:bundleRelease
85+
86+
- name: Upload Release Build to Artifacts
87+
uses: actions/upload-artifact@v4
88+
with:
89+
name: release-artifacts
90+
path: app/build/outputs/bundle/release/
91+
if-no-files-found: error
92+
93+
- name: Create Github Release
94+
uses: softprops/action-gh-release@v2
95+
with:
96+
tag_name: ${{ steps.extract_version.outputs.version }}
97+
release_name: ${{ steps.extract_version.outputs.version }}
98+
generate_release_notes: true
99+
100+
- name: Upload artifact to Firebase App Distribution
101+
uses: wzieba/Firebase-Distribution-Github-Action@v1
102+
with:
103+
appId: ${{secrets.FIREBASE_RELEASE_APP_ID}}
104+
serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }}
105+
groups: testers
106+
file: app/build/outputs/bundle/release/app-release.aab
107+
releaseNotes: ${{ steps.firebase_release_note.outputs.notes }}

.github/workflows/android-ci.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ jobs:
3636
gradle-home-cache-cleanup: true
3737

3838
- name: Generate local.properties
39-
run: |
40-
echo '${{ secrets.LOCAL_PROPERTIES }}' >> ./local.properties
39+
run: echo '${{ secrets.LOCAL_PROPERTIES }}' | base64 -d > ./local.properties
4140

4241
- name: Generate keystore.properties
43-
run: |
44-
echo '${{ secrets.KEYSTORE_PROPERTIES }}' >> ./keystore.properties
42+
run: echo '${{ secrets.KEYSTORE_PROPERTIES }}' | base64 -d > ./keystore.properties
4543

4644
- name: Generate google-services.json
4745
run: echo '${{ secrets.GOOGLE_SERVICES }}' | base64 -d > ./app/google-services.json

build-logic/src/main/kotlin/AndroidRetrofitConventionPlugin.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,6 @@ internal class AndroidRetrofitConventionPlugin : Plugin<Project> {
1717
"booket.kotlin.library.serialization",
1818
)
1919

20-
extensions.configure<LibraryExtension> {
21-
configureAndroid(this)
22-
23-
defaultConfig.apply {
24-
targetSdk = ApplicationConstants.TARGET_SDK
25-
}
26-
}
27-
2820
dependencies {
2921
implementation(libs.retrofit)
3022
implementation(libs.retrofit.kotlinx.serialization.converter)

feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
1212
import androidx.compose.foundation.layout.height
1313
import androidx.compose.foundation.layout.padding
1414
import androidx.compose.foundation.layout.size
15+
import androidx.compose.foundation.layout.statusBarsPadding
1516
import androidx.compose.foundation.pager.HorizontalPager
1617
import androidx.compose.foundation.pager.rememberPagerState
1718
import androidx.compose.foundation.shape.CircleShape
@@ -46,8 +47,6 @@ internal fun HomeUi(
4647
state: HomeUiState,
4748
modifier: Modifier = Modifier,
4849
) {
49-
HandleHomeSideEffects(state = state)
50-
5150
// TODO: Android 15에서 statusBar 색상 적용 안되는 문제 있음. 해결 예정.
5251
val systemUiController = rememberSystemUiController()
5352

@@ -64,20 +63,23 @@ internal fun HomeUi(
6463
}
6564
}
6665

66+
HandleHomeSideEffects(state = state)
67+
6768
Column(
68-
modifier = modifier.fillMaxSize(),
69+
modifier = modifier
70+
.fillMaxSize()
71+
.background(HomeBg)
72+
.statusBarsPadding(),
6973
) {
7074
HomeHeader(
7175
onSettingsClick = {
7276
state.eventSink(HomeUiEvent.OnSettingsClick)
7377
},
74-
modifier = modifier,
7578
)
7679
HomeBanner(
7780
onBookRegisterClick = {
7881
state.eventSink(HomeUiEvent.OnBookRegisterClick)
7982
},
80-
modifier = modifier,
8183
)
8284
HomeContent(
8385
state = state,

feature/library/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ ksp {
1717
dependencies {
1818
implementations(
1919
libs.logger,
20+
21+
libs.compose.system.ui.controller,
2022
)
2123
}

feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryUi.kt

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import androidx.compose.foundation.layout.Spacer
88
import androidx.compose.foundation.layout.fillMaxSize
99
import androidx.compose.foundation.layout.fillMaxWidth
1010
import androidx.compose.foundation.layout.height
11+
import androidx.compose.foundation.layout.statusBarsPadding
1112
import androidx.compose.foundation.lazy.items
1213
import androidx.compose.material3.CircularProgressIndicator
1314
import androidx.compose.material3.Text
1415
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.DisposableEffect
1517
import androidx.compose.ui.Alignment
1618
import androidx.compose.ui.Modifier
1719
import androidx.compose.ui.res.stringResource
@@ -21,6 +23,7 @@ import com.ninecraft.booket.core.designsystem.component.button.ReedButton
2123
import com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle
2224
import com.ninecraft.booket.core.designsystem.component.button.largeButtonStyle
2325
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
26+
import com.ninecraft.booket.core.designsystem.theme.White
2427
import com.ninecraft.booket.core.model.LibraryBookSummaryModel
2528
import com.ninecraft.booket.core.ui.component.InfinityLazyColumn
2629
import com.ninecraft.booket.core.ui.component.LoadStateFooter
@@ -31,21 +34,44 @@ import com.ninecraft.booket.feature.screens.LibraryScreen
3134
import com.slack.circuit.codegen.annotations.CircuitInject
3235
import dagger.hilt.android.components.ActivityRetainedComponent
3336
import kotlinx.collections.immutable.persistentListOf
37+
import tech.thdev.compose.exteions.system.ui.controller.rememberSystemUiController
3438

3539
@CircuitInject(LibraryScreen::class, ActivityRetainedComponent::class)
3640
@Composable
3741
internal fun LibraryUi(
3842
state: LibraryUiState,
3943
modifier: Modifier = Modifier,
4044
) {
45+
// TODO: Android 15에서 statusBar 색상 적용 안되는 문제 있음. 해결 예정.
46+
val systemUiController = rememberSystemUiController()
47+
48+
DisposableEffect(systemUiController) {
49+
systemUiController.setStatusBarColor(
50+
color = White,
51+
darkIcons = true,
52+
)
53+
onDispose {}
54+
}
55+
4156
HandleLibrarySideEffects(
4257
state = state,
4358
eventSink = state.eventSink,
4459
)
4560

4661
Column(
47-
modifier = modifier.fillMaxSize(),
62+
modifier = modifier
63+
.fillMaxSize()
64+
.statusBarsPadding(),
4865
) {
66+
LibraryHeader(
67+
onSearchClick = {
68+
state.eventSink(LibraryUiEvent.OnLibrarySearchClick)
69+
},
70+
onSettingClick = {
71+
state.eventSink(LibraryUiEvent.OnSettingsClick)
72+
},
73+
)
74+
4975
LibraryContent(
5076
state = state,
5177
modifier = modifier,
@@ -63,14 +89,6 @@ internal fun LibraryContent(
6389
horizontalAlignment = Alignment.CenterHorizontally,
6490
verticalArrangement = Arrangement.Center,
6591
) {
66-
LibraryHeader(
67-
onSearchClick = {
68-
state.eventSink(LibraryUiEvent.OnLibrarySearchClick)
69-
},
70-
onSettingClick = {
71-
state.eventSink(LibraryUiEvent.OnSettingsClick)
72-
},
73-
)
7492
FilterChipGroup(
7593
filterList = state.filterChips,
7694
selectedChipOption = state.currentFilter,

feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/bottomnavigation/BottomNavigation.kt renamed to feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/bottomnavigation/BottomNavigationUi.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package com.ninecraft.booket.feature.main.bottomnavigation
22

3+
import androidx.compose.foundation.layout.WindowInsets
34
import androidx.compose.foundation.layout.fillMaxSize
45
import androidx.compose.foundation.layout.padding
56
import androidx.compose.runtime.Composable
67
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.unit.dp
79
import com.ninecraft.booket.core.ui.ReedScaffold
810
import com.ninecraft.booket.feature.main.component.MainBottomBar
911
import com.ninecraft.booket.feature.main.component.MainTab
@@ -15,7 +17,7 @@ import kotlinx.collections.immutable.toImmutableList
1517

1618
@CircuitInject(BottomNavigationScreen::class, ActivityRetainedComponent::class)
1719
@Composable
18-
fun BottomNavigation(
20+
fun BottomNavigationUi(
1921
state: BottomNavigationUiState,
2022
modifier: Modifier = Modifier,
2123
) {
@@ -30,6 +32,7 @@ fun BottomNavigation(
3032
},
3133
)
3234
},
35+
contentWindowInsets = WindowInsets(top = 0.dp),
3336
) { innerPadding ->
3437
NavigableCircuitContent(
3538
navigator = state.navigator,

feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,22 @@ import androidx.compose.foundation.layout.Column
1919
import androidx.compose.foundation.layout.PaddingValues
2020
import androidx.compose.foundation.layout.Row
2121
import androidx.compose.foundation.layout.Spacer
22+
import androidx.compose.foundation.layout.WindowInsets
23+
import androidx.compose.foundation.layout.aspectRatio
2224
import androidx.compose.foundation.layout.fillMaxSize
2325
import androidx.compose.foundation.layout.fillMaxWidth
2426
import androidx.compose.foundation.layout.height
2527
import androidx.compose.foundation.layout.offset
2628
import androidx.compose.foundation.layout.padding
2729
import androidx.compose.foundation.layout.size
30+
import androidx.compose.foundation.layout.systemBarsPadding
2831
import androidx.compose.foundation.layout.width
2932
import androidx.compose.foundation.lazy.LazyColumn
3033
import androidx.compose.foundation.shape.CircleShape
3134
import androidx.compose.material3.Button
3235
import androidx.compose.material3.ButtonDefaults
3336
import androidx.compose.material3.Icon
37+
import androidx.compose.material3.Scaffold
3438
import androidx.compose.material3.Text
3539
import androidx.compose.runtime.Composable
3640
import androidx.compose.runtime.DisposableEffect
@@ -59,7 +63,6 @@ import com.ninecraft.booket.core.designsystem.theme.ReedTheme
5963
import com.ninecraft.booket.core.designsystem.theme.White
6064
import com.ninecraft.booket.core.ui.component.ReedCloseTopAppBar
6165
import com.ninecraft.booket.core.ui.component.ReedDialog
62-
import com.ninecraft.booket.core.ui.component.ReedFullScreen
6366
import com.ninecraft.booket.feature.record.R
6467
import com.ninecraft.booket.feature.record.ocr.component.CameraFrame
6568
import com.ninecraft.booket.feature.record.ocr.component.SentenceBox
@@ -75,10 +78,16 @@ internal fun Ocr(
7578
state: OcrUiState,
7679
modifier: Modifier = Modifier,
7780
) {
78-
ReedFullScreen {
79-
when (state.currentUi) {
80-
OcrUi.CAMERA -> CameraPreview(state = state, modifier = modifier)
81-
OcrUi.RESULT -> TextScanResult(state = state, modifier = modifier)
81+
Scaffold(contentWindowInsets = WindowInsets(0.dp)) { innerPadding ->
82+
Box(
83+
modifier = modifier
84+
.fillMaxSize()
85+
.padding(innerPadding),
86+
) {
87+
when (state.currentUi) {
88+
OcrUi.CAMERA -> CameraPreview(state = state, modifier = modifier)
89+
OcrUi.RESULT -> TextScanResult(state = state, modifier = modifier)
90+
}
8291
}
8392
}
8493
}
@@ -168,7 +177,8 @@ private fun CameraPreview(
168177
Box(
169178
modifier = modifier
170179
.fillMaxSize()
171-
.background(Neutral950),
180+
.background(Neutral950)
181+
.systemBarsPadding(),
172182
) {
173183
ReedCloseTopAppBar(
174184
modifier = Modifier
@@ -275,7 +285,8 @@ private fun TextScanResult(
275285
Column(
276286
modifier = modifier
277287
.fillMaxSize()
278-
.background(White),
288+
.background(White)
289+
.systemBarsPadding(),
279290
) {
280291
ReedCloseTopAppBar(
281292
title = stringResource(R.string.ocr_sentence_selection),

0 commit comments

Comments
 (0)