From 5c4c6508c4e99c754089f5fdbd3191e3fb3ba4c7 Mon Sep 17 00:00:00 2001 From: devfeijoa Date: Wed, 29 Jul 2026 22:30:57 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EC=BB=AC=EB=A0=89=EC=85=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=82=B4=20=EC=9E=91=ED=92=88=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EB=82=B4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `CollectionNovelSearchScreen.kt`: 작품 검색을 위한 임시 화면 및 레이아웃 구현 - `CollectionNovelSearchAppBar.kt`: 작품 검색 화면 전용 앱바 추가 - `CollectionNovelSection.kt`: 작품 추가 카드 클릭 시 `onAddNovelClick` 콜백이 실행되도록 수정하고, 클릭 피드백을 위한 `clickable` 및 `clip` 속성 적용 - `CollectionNavHost.kt`: 작품 검색 경로(`COLLECTION_NOVEL_SEARCH_ROUTE`) 정의 및 내비게이션 그래프 내 화면 추가 --- .../collection/CollectionCreateScreen.kt | 7 +- .../feature/collection/CollectionNavHost.kt | 9 +++ .../collection/CollectionNovelSearchScreen.kt | 61 ++++++++++++++++ .../component/CollectionNovelSearchAppBar.kt | 71 +++++++++++++++++++ .../component/CollectionNovelSection.kt | 18 ++++- 5 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt create mode 100644 feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt index 2a43e11ae..adb21c92f 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt @@ -24,6 +24,7 @@ import com.into.websoso.feature.collection.component.CollectionPrivacySetting @Composable internal fun CollectionCreateScreen( onNavigateBack: () -> Unit, + onNavigateToNovelSearch: () -> Unit, modifier: Modifier = Modifier, ) { var isPrivate by rememberSaveable { mutableStateOf(false) } @@ -60,6 +61,7 @@ internal fun CollectionCreateScreen( ), ) CollectionNovelSection( + onAddNovelClick = onNavigateToNovelSearch, modifier = Modifier.padding( start = 20.dp, top = 30.dp, @@ -73,6 +75,9 @@ internal fun CollectionCreateScreen( @Composable private fun CollectionCreateScreenPreview() { WebsosoTheme { - CollectionCreateScreen(onNavigateBack = {}) + CollectionCreateScreen( + onNavigateBack = {}, + onNavigateToNovelSearch = {}, + ) } } diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt index 4086532e1..cdcae84e5 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt @@ -8,6 +8,7 @@ import androidx.navigation.compose.rememberNavController private const val COLLECTION_ROUTE = "collection" private const val COLLECTION_CREATE_ROUTE = "collection/create" +private const val COLLECTION_NOVEL_SEARCH_ROUTE = "collection/create/novel-search" @Composable fun CollectionNavHost( @@ -32,6 +33,14 @@ fun CollectionNavHost( composable(route = COLLECTION_CREATE_ROUTE) { CollectionCreateScreen( onNavigateBack = navController::popBackStack, + onNavigateToNovelSearch = { + navController.navigate(COLLECTION_NOVEL_SEARCH_ROUTE) + }, + ) + } + composable(route = COLLECTION_NOVEL_SEARCH_ROUTE) { + CollectionNovelSearchScreen( + onNavigateBack = navController::popBackStack, ) } } diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt new file mode 100644 index 000000000..fef0e03b0 --- /dev/null +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt @@ -0,0 +1,61 @@ +package com.into.websoso.feature.collection + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.into.websoso.core.designsystem.theme.Black +import com.into.websoso.core.designsystem.theme.Gray200 +import com.into.websoso.core.designsystem.theme.WebsosoTheme +import com.into.websoso.core.designsystem.theme.White +import com.into.websoso.feature.collection.component.CollectionNovelSearchAppBar + +@Composable +internal fun CollectionNovelSearchScreen( + onNavigateBack: () -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .fillMaxSize() + .background(White) + .statusBarsPadding(), + ) { + CollectionNovelSearchAppBar(onNavigateBack = onNavigateBack) + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text( + text = "작품 검색", + color = Black, + style = WebsosoTheme.typography.headline1, + ) + Text( + text = "임시화면", + color = Gray200, + style = WebsosoTheme.typography.body2, + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +private fun CollectionNovelSearchScreenPreview() { + WebsosoTheme { + CollectionNovelSearchScreen(onNavigateBack = {}) + } +} diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt new file mode 100644 index 000000000..b0db5e284 --- /dev/null +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt @@ -0,0 +1,71 @@ +package com.into.websoso.feature.collection.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.into.websoso.core.designsystem.theme.Black +import com.into.websoso.core.designsystem.theme.Primary100 +import com.into.websoso.core.designsystem.theme.WebsosoTheme +import com.into.websoso.core.designsystem.theme.White +import com.into.websoso.core.resource.R.drawable.ic_navigate_left + +@Composable +internal fun CollectionNovelSearchAppBar( + onNavigateBack: () -> Unit, + modifier: Modifier = Modifier, +) { + Box( + modifier = modifier + .fillMaxWidth() + .height(44.dp) + .background(White), + contentAlignment = Alignment.Center, + ) { + IconButton( + onClick = onNavigateBack, + modifier = Modifier + .align(Alignment.CenterStart) + .padding(start = 6.dp) + .size(44.dp), + ) { + Image( + painter = painterResource(id = ic_navigate_left), + contentDescription = null, + modifier = Modifier.size(24.dp), + ) + } + Text( + text = "작품 리스트", + color = Black, + style = WebsosoTheme.typography.title2, + ) + Text( + text = "완료", + color = Primary100, + style = WebsosoTheme.typography.title2, + modifier = Modifier + .align(Alignment.CenterEnd) + .padding(horizontal = 20.dp), + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun CollectionNovelSearchAppBarPreview() { + WebsosoTheme { + CollectionNovelSearchAppBar(onNavigateBack = {}) + } +} diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSection.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSection.kt index 4366857ff..f5dfffa7f 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSection.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSection.kt @@ -1,6 +1,7 @@ package com.into.websoso.feature.collection.component import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -12,7 +13,9 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.res.painterResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle @@ -26,7 +29,12 @@ import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.resource.R.drawable.ic_plus_novel @Composable -internal fun CollectionNovelSection(modifier: Modifier = Modifier) { +internal fun CollectionNovelSection( + onAddNovelClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val addCardShape = RoundedCornerShape(8.dp) + Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(12.dp), @@ -54,9 +62,13 @@ internal fun CollectionNovelSection(modifier: Modifier = Modifier) { Column( modifier = Modifier .size(width = 103.dp, height = 160.dp) + .clip(addCardShape) .background( color = Gray50, - shape = RoundedCornerShape(8.dp), + shape = addCardShape, + ).clickable( + onClick = onAddNovelClick, + role = Role.Button, ), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -81,6 +93,6 @@ internal fun CollectionNovelSection(modifier: Modifier = Modifier) { @Composable private fun CollectionNovelSectionPreview() { WebsosoTheme { - CollectionNovelSection() + CollectionNovelSection(onAddNovelClick = {}) } } From 66f75e169aca1223e947e6810924150517b3a129 Mon Sep 17 00:00:00 2001 From: devfeijoa Date: Thu, 30 Jul 2026 00:09:35 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=EC=BB=AC=EB=A0=89=EC=85=98=20?= =?UTF-8?q?=EC=9E=91=ED=92=88=20=EA=B2=80=EC=83=89=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EB=82=B4=20=EA=B2=80=EC=83=89=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20UI=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `CollectionNovelSearchField.kt`: 작품 제목 및 작가 검색을 위한 검색 필드 컴포저블 구현 - `CollectionNovelSearchAppBar.kt`: 완료 버튼의 활성화 상태에 따른 색상 변경 로직 추가 및 `isCompleteEnabled` 파라미터 정의 --- .../collection/CollectionNovelSearchScreen.kt | 41 ++++-------- .../component/CollectionNovelSearchAppBar.kt | 9 ++- .../component/CollectionNovelSearchField.kt | 65 +++++++++++++++++++ 3 files changed, 86 insertions(+), 29 deletions(-) create mode 100644 feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt index fef0e03b0..1b549ef32 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt @@ -1,21 +1,18 @@ package com.into.websoso.feature.collection import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview -import com.into.websoso.core.designsystem.theme.Black -import com.into.websoso.core.designsystem.theme.Gray200 +import androidx.compose.ui.unit.dp import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.designsystem.theme.White import com.into.websoso.feature.collection.component.CollectionNovelSearchAppBar +import com.into.websoso.feature.collection.component.CollectionNovelSearchField @Composable internal fun CollectionNovelSearchScreen( @@ -28,27 +25,17 @@ internal fun CollectionNovelSearchScreen( .background(White) .statusBarsPadding(), ) { - CollectionNovelSearchAppBar(onNavigateBack = onNavigateBack) - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center, - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - Text( - text = "작품 검색", - color = Black, - style = WebsosoTheme.typography.headline1, - ) - Text( - text = "임시화면", - color = Gray200, - style = WebsosoTheme.typography.body2, - ) - } - } + CollectionNovelSearchAppBar( + onNavigateBack = onNavigateBack, + isCompleteEnabled = false, + ) + CollectionNovelSearchField( + modifier = Modifier.padding( + start = 20.dp, + top = 10.dp, + end = 20.dp, + ), + ) } } diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt index b0db5e284..c88cecd9a 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.into.websoso.core.designsystem.theme.Black +import com.into.websoso.core.designsystem.theme.Gray100 import com.into.websoso.core.designsystem.theme.Primary100 import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.designsystem.theme.White @@ -24,6 +25,7 @@ import com.into.websoso.core.resource.R.drawable.ic_navigate_left @Composable internal fun CollectionNovelSearchAppBar( onNavigateBack: () -> Unit, + isCompleteEnabled: Boolean, modifier: Modifier = Modifier, ) { Box( @@ -53,7 +55,7 @@ internal fun CollectionNovelSearchAppBar( ) Text( text = "완료", - color = Primary100, + color = if (isCompleteEnabled) Primary100 else Gray100, style = WebsosoTheme.typography.title2, modifier = Modifier .align(Alignment.CenterEnd) @@ -66,6 +68,9 @@ internal fun CollectionNovelSearchAppBar( @Composable private fun CollectionNovelSearchAppBarPreview() { WebsosoTheme { - CollectionNovelSearchAppBar(onNavigateBack = {}) + CollectionNovelSearchAppBar( + onNavigateBack = {}, + isCompleteEnabled = false, + ) } } diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt new file mode 100644 index 000000000..cb206734a --- /dev/null +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt @@ -0,0 +1,65 @@ +package com.into.websoso.feature.collection.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.into.websoso.core.designsystem.theme.Gray100 +import com.into.websoso.core.designsystem.theme.Gray70New +import com.into.websoso.core.designsystem.theme.WebsosoTheme +import com.into.websoso.core.resource.R.drawable.ic_common_search + +@Composable +internal fun CollectionNovelSearchField(modifier: Modifier = Modifier) { + Row( + modifier = modifier + .fillMaxWidth() + .height(42.dp) + .border( + width = 1.dp, + color = Gray70New, + shape = RoundedCornerShape(14.dp), + ).padding( + start = 16.dp, + end = 10.dp, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = "작품 제목, 작가를 검색하세요", + color = Gray100, + style = WebsosoTheme.typography.body4, + modifier = Modifier.weight(1f), + ) + Box( + modifier = Modifier.size(36.dp), + contentAlignment = Alignment.Center, + ) { + Image( + painter = painterResource(id = ic_common_search), + contentDescription = null, + modifier = Modifier.size(width = 25.dp, height = 26.dp), + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun CollectionNovelSearchFieldPreview() { + WebsosoTheme { + CollectionNovelSearchField(modifier = Modifier.padding(20.dp)) + } +} From 7618ed91eb41c234ead54b801df7bc14445270af Mon Sep 17 00:00:00 2001 From: devfeijoa Date: Thu, 30 Jul 2026 00:32:50 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EC=BB=AC=EB=A0=89=EC=85=98=20?= =?UTF-8?q?=EC=9E=91=ED=92=88=20=EA=B2=80=EC=83=89=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EB=B0=8F=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=ED=8F=AC=EC=BB=A4=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `CollectionNovelSearchField.kt`: 기존의 정적 텍스트를 `BasicTextField`로 교체하여 실제 입력이 가능하도록 수정하고, 검색어 삭제를 위한 클리어 버튼 추가 - `CollectionNovelSearchScreen.kt`: `searchQuery` 상태 관리 로직을 추가하고, `LaunchedEffect`를 통해 화면 진입 시 검색 필드 자동 포커스 및 키보드 노출 기능 구현 --- .../collection/CollectionNovelSearchScreen.kt | 24 +++++++ .../component/CollectionNovelSearchField.kt | 67 +++++++++++++++++-- 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt index 1b549ef32..1311c8017 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt @@ -6,7 +6,16 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.into.websoso.core.designsystem.theme.WebsosoTheme @@ -19,6 +28,17 @@ internal fun CollectionNovelSearchScreen( onNavigateBack: () -> Unit, modifier: Modifier = Modifier, ) { + var searchQuery by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue()) + } + val searchFocusRequester = remember { FocusRequester() } + val keyboardController = LocalSoftwareKeyboardController.current + + LaunchedEffect(Unit) { + searchFocusRequester.requestFocus() + keyboardController?.show() + } + Column( modifier = modifier .fillMaxSize() @@ -30,6 +50,10 @@ internal fun CollectionNovelSearchScreen( isCompleteEnabled = false, ) CollectionNovelSearchField( + value = searchQuery, + onValueChange = { searchQuery = it }, + onClearClick = { searchQuery = TextFieldValue() }, + focusRequester = searchFocusRequester, modifier = Modifier.padding( start = 20.dp, top = 10.dp, diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt index cb206734a..e0a8bcc56 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt @@ -9,20 +9,38 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.into.websoso.core.designsystem.theme.Black import com.into.websoso.core.designsystem.theme.Gray100 import com.into.websoso.core.designsystem.theme.Gray70New +import com.into.websoso.core.designsystem.theme.Primary100 import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.resource.R.drawable.ic_common_search +import com.into.websoso.core.resource.R.drawable.ic_common_search_clear @Composable -internal fun CollectionNovelSearchField(modifier: Modifier = Modifier) { +internal fun CollectionNovelSearchField( + value: TextFieldValue, + onValueChange: (TextFieldValue) -> Unit, + onClearClick: () -> Unit, + focusRequester: FocusRequester, + modifier: Modifier = Modifier, +) { Row( modifier = modifier .fillMaxWidth() @@ -37,12 +55,41 @@ internal fun CollectionNovelSearchField(modifier: Modifier = Modifier) { ), verticalAlignment = Alignment.CenterVertically, ) { - Text( - text = "작품 제목, 작가를 검색하세요", - color = Gray100, - style = WebsosoTheme.typography.body4, - modifier = Modifier.weight(1f), + BasicTextField( + value = value, + onValueChange = onValueChange, + modifier = Modifier + .weight(1f) + .focusRequester(focusRequester), + singleLine = true, + textStyle = WebsosoTheme.typography.body4.copy(color = Black), + cursorBrush = SolidColor(Primary100), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), + decorationBox = { innerTextField -> + Box { + if (value.text.isEmpty()) { + Text( + text = "작품 제목, 작가를 검색하세요", + color = Gray100, + style = WebsosoTheme.typography.body4, + ) + } + innerTextField() + } + }, ) + if (value.text.isNotEmpty()) { + IconButton( + onClick = onClearClick, + modifier = Modifier.size(36.dp), + ) { + Image( + painter = painterResource(id = ic_common_search_clear), + contentDescription = "검색어 지우기", + modifier = Modifier.size(36.dp), + ) + } + } Box( modifier = Modifier.size(36.dp), contentAlignment = Alignment.Center, @@ -60,6 +107,12 @@ internal fun CollectionNovelSearchField(modifier: Modifier = Modifier) { @Composable private fun CollectionNovelSearchFieldPreview() { WebsosoTheme { - CollectionNovelSearchField(modifier = Modifier.padding(20.dp)) + CollectionNovelSearchField( + value = TextFieldValue(), + onValueChange = {}, + onClearClick = {}, + focusRequester = remember { FocusRequester() }, + modifier = Modifier.padding(20.dp), + ) } } From 5ca78ec1dcbde28b770c447af7cfacf5e9c2572a Mon Sep 17 00:00:00 2001 From: devfeijoa Date: Fri, 31 Jul 2026 17:05:59 +0900 Subject: [PATCH 4/4] refactor: consolidate collection app bars --- .../collection/CollectionCreateScreen.kt | 7 +- .../collection/CollectionNovelSearchScreen.kt | 8 +- .../feature/collection/CollectionScreen.kt | 5 +- .../collection/component/CollectionAppBar.kt | 33 ++++++-- .../component/CollectionCreateAppBar.kt | 65 ---------------- .../component/CollectionNovelSearchAppBar.kt | 76 ------------------- 6 files changed, 41 insertions(+), 153 deletions(-) delete mode 100644 feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateAppBar.kt delete mode 100644 feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt index adb21c92f..7d17230e3 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.designsystem.theme.White -import com.into.websoso.feature.collection.component.CollectionCreateAppBar +import com.into.websoso.feature.collection.component.CollectionAppBar import com.into.websoso.feature.collection.component.CollectionDescriptionInput import com.into.websoso.feature.collection.component.CollectionNameInput import com.into.websoso.feature.collection.component.CollectionNovelSection @@ -37,7 +37,10 @@ internal fun CollectionCreateScreen( .background(White) .statusBarsPadding(), ) { - CollectionCreateAppBar(onNavigateBack = onNavigateBack) + CollectionAppBar( + actionLabel = "완료", + onNavigateBack = onNavigateBack, + ) CollectionPrivacySetting( isPrivate = isPrivate, onPrivateChange = { isPrivate = it }, diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt index 1311c8017..183f65357 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.designsystem.theme.White -import com.into.websoso.feature.collection.component.CollectionNovelSearchAppBar +import com.into.websoso.feature.collection.component.CollectionAppBar import com.into.websoso.feature.collection.component.CollectionNovelSearchField @Composable @@ -45,9 +45,11 @@ internal fun CollectionNovelSearchScreen( .background(White) .statusBarsPadding(), ) { - CollectionNovelSearchAppBar( + CollectionAppBar( + title = "작품 리스트", + actionLabel = "완료", onNavigateBack = onNavigateBack, - isCompleteEnabled = false, + isActionEnabled = false, ) CollectionNovelSearchField( value = searchQuery, diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt index d6cac2e39..23c2cecd2 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt @@ -34,7 +34,10 @@ fun CollectionScreen( .background(White) .statusBarsPadding(), ) { - CollectionAppBar(onNavigateBack = onNavigateBack) + CollectionAppBar( + title = "컬렉션", + onNavigateBack = onNavigateBack, + ) CollectionTabRow( selectedTab = selectedTab, onTabSelected = { selectedTab = it }, diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt index 3c6e7d8aa..d8fdb7b43 100644 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt +++ b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt @@ -16,13 +16,18 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.into.websoso.core.designsystem.theme.Black +import com.into.websoso.core.designsystem.theme.Gray100 +import com.into.websoso.core.designsystem.theme.Primary100 import com.into.websoso.core.designsystem.theme.WebsosoTheme import com.into.websoso.core.designsystem.theme.White import com.into.websoso.core.resource.R.drawable.ic_navigate_left @Composable internal fun CollectionAppBar( + title: String? = null, + actionLabel: String? = null, onNavigateBack: () -> Unit, + isActionEnabled: Boolean = false, modifier: Modifier = Modifier, ) { Box( @@ -45,11 +50,23 @@ internal fun CollectionAppBar( modifier = Modifier.size(24.dp), ) } - Text( - text = "컬렉션", - color = Black, - style = WebsosoTheme.typography.title2, - ) + title?.let { + Text( + text = it, + color = Black, + style = WebsosoTheme.typography.title2, + ) + } + actionLabel?.let { + Text( + text = it, + color = if (isActionEnabled) Primary100 else Gray100, + style = WebsosoTheme.typography.title2, + modifier = Modifier + .align(Alignment.CenterEnd) + .padding(horizontal = 20.dp), + ) + } } } @@ -57,6 +74,10 @@ internal fun CollectionAppBar( @Composable private fun CollectionAppBarPreview() { WebsosoTheme { - CollectionAppBar(onNavigateBack = {}) + CollectionAppBar( + title = "작품 리스트", + actionLabel = "완료", + onNavigateBack = {}, + ) } } diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateAppBar.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateAppBar.kt deleted file mode 100644 index 5f7f0f561..000000000 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateAppBar.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.into.websoso.feature.collection.component - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.into.websoso.core.designsystem.theme.Gray100 -import com.into.websoso.core.designsystem.theme.WebsosoTheme -import com.into.websoso.core.designsystem.theme.White -import com.into.websoso.core.resource.R.drawable.ic_navigate_left - -@Composable -internal fun CollectionCreateAppBar( - onNavigateBack: () -> Unit, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier - .fillMaxWidth() - .height(44.dp) - .background(White), - contentAlignment = Alignment.Center, - ) { - IconButton( - onClick = onNavigateBack, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(start = 6.dp) - .size(44.dp), - ) { - Image( - painter = painterResource(id = ic_navigate_left), - contentDescription = null, - modifier = Modifier.size(24.dp), - ) - } - Text( - text = "완료", - color = Gray100, - style = WebsosoTheme.typography.title2, - modifier = Modifier - .align(Alignment.CenterEnd) - .padding(horizontal = 20.dp), - ) - } -} - -@Preview(showBackground = true) -@Composable -private fun CollectionCreateAppBarPreview() { - WebsosoTheme { - CollectionCreateAppBar(onNavigateBack = {}) - } -} diff --git a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt b/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt deleted file mode 100644 index c88cecd9a..000000000 --- a/feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchAppBar.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.into.websoso.feature.collection.component - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.into.websoso.core.designsystem.theme.Black -import com.into.websoso.core.designsystem.theme.Gray100 -import com.into.websoso.core.designsystem.theme.Primary100 -import com.into.websoso.core.designsystem.theme.WebsosoTheme -import com.into.websoso.core.designsystem.theme.White -import com.into.websoso.core.resource.R.drawable.ic_navigate_left - -@Composable -internal fun CollectionNovelSearchAppBar( - onNavigateBack: () -> Unit, - isCompleteEnabled: Boolean, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier - .fillMaxWidth() - .height(44.dp) - .background(White), - contentAlignment = Alignment.Center, - ) { - IconButton( - onClick = onNavigateBack, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(start = 6.dp) - .size(44.dp), - ) { - Image( - painter = painterResource(id = ic_navigate_left), - contentDescription = null, - modifier = Modifier.size(24.dp), - ) - } - Text( - text = "작품 리스트", - color = Black, - style = WebsosoTheme.typography.title2, - ) - Text( - text = "완료", - color = if (isCompleteEnabled) Primary100 else Gray100, - style = WebsosoTheme.typography.title2, - modifier = Modifier - .align(Alignment.CenterEnd) - .padding(horizontal = 20.dp), - ) - } -} - -@Preview(showBackground = true) -@Composable -private fun CollectionNovelSearchAppBarPreview() { - WebsosoTheme { - CollectionNovelSearchAppBar( - onNavigateBack = {}, - isCompleteEnabled = false, - ) - } -}