From 01e35c7e8ecbb61011823d05d2e5ff1499664cf9 Mon Sep 17 00:00:00 2001 From: gmin Date: Fri, 30 Jan 2026 21:50:30 +0900 Subject: [PATCH 1/9] =?UTF-8?q?=F0=9F=93=A6=20feature/file=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B3=80=EA=B2=BD:?= =?UTF-8?q?=20foundation-layout=EC=9D=84=20foundation=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `feature/file/build.gradle.kts`에서 `androidx.compose.foundation.layout` 의존성을 `androidx.compose.foundation`으로 변경 --- feature/file/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/file/build.gradle.kts b/feature/file/build.gradle.kts index 7355fce..7be8d8f 100644 --- a/feature/file/build.gradle.kts +++ b/feature/file/build.gradle.kts @@ -53,7 +53,7 @@ dependencies { implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) implementation(libs.androidx.navigation.compose) - implementation(libs.androidx.compose.foundation.layout) + implementation(libs.androidx.compose.foundation) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) From 50a844eb37dba359cfd15e706e9dab95857e91bc Mon Sep 17 00:00:00 2001 From: gmin Date: Mon, 2 Feb 2026 19:30:55 +0900 Subject: [PATCH 2/9] =?UTF-8?q?=E2=9C=A8=20feature/file:=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=82=AD=EC=A0=9C=20=EB=AA=A8=EB=8B=AC=20=EB=AC=B8?= =?UTF-8?q?=EA=B5=AC=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=AF=B8=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EC=9E=84=ED=8F=AC=ED=8A=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `LinksGrid.kt` 내 삭제 확인 모달의 버튼 텍스트를 "삭제" -> "삭제하기", "취소" -> "취소하기"로 변경 - 미사용 임포트(`lifecycleScope`, `rememberCoroutineScope`, `launch` 등) 제거 및 임포트 최적화 --- .../java/com/example/file/ui/content/LinksGrid.kt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/feature/file/src/main/java/com/example/file/ui/content/LinksGrid.kt b/feature/file/src/main/java/com/example/file/ui/content/LinksGrid.kt index 179d243..91591ab 100644 --- a/feature/file/src/main/java/com/example/file/ui/content/LinksGrid.kt +++ b/feature/file/src/main/java/com/example/file/ui/content/LinksGrid.kt @@ -1,6 +1,5 @@ package com.example.file.ui.content -import androidx.lifecycle.lifecycleScope import android.util.Log import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement @@ -12,7 +11,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -28,16 +26,15 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.cheonjaeung.compose.grid.SimpleGridCells import com.cheonjaeung.compose.grid.VerticalGrid +import com.example.design.modifier.noRippleClickable import com.example.file.FileViewModel import com.example.file.R -import com.example.design.modifier.noRippleClickable import com.example.file.ui.item.LinkItemLayout import com.example.file.ui.modal.FileModalWindow -import com.example.file.viewmodel.folder.state.FolderStateViewModel import com.example.file.ui.theme.Black import com.example.file.ui.theme.DefaultFont import com.example.file.ui.theme.Gray600 -import kotlinx.coroutines.launch +import com.example.file.viewmodel.folder.state.FolderStateViewModel @Composable fun LinksGrid( @@ -164,8 +161,8 @@ fun LinksGrid( }, onDismiss = { deleteModalWindowVisible = false }, title = "해당 링크를 삭제하시겠습니까?", - positiveText = "삭제", - negativeText = "취소" + positiveText = "삭제하기", + negativeText = "취소하기" ) { Text( text = "삭제 시 해당 링크가 영구적으로 제거되며\n복구가 불가능합니다.", From 1326445a4a34ad579927e3f9427b513d04b2881e Mon Sep 17 00:00:00 2001 From: gmin Date: Mon, 2 Feb 2026 19:33:19 +0900 Subject: [PATCH 3/9] =?UTF-8?q?=E2=9C=A8=20feature/file:=20FileBottomSheet?= =?UTF-8?q?=20UI=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B0=B0=EA=B2=BD=20=EB=94=A4(scrim)=20=ED=9A=A8?= =?UTF-8?q?=EA=B3=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `FileBottomSheet`에 0.5 투명도의 블랙 딤 컬러(`scrimColor`) 적용 - 텍스트 간격 조정을 위해 `Spacer` 추가 및 불필요한 `lineHeight`, `padding` 제거 --- .../file/ui/bottom/sheet/FileBottomSheet.kt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/feature/file/src/main/java/com/example/file/ui/bottom/sheet/FileBottomSheet.kt b/feature/file/src/main/java/com/example/file/ui/bottom/sheet/FileBottomSheet.kt index 97b93ce..1cc305b 100644 --- a/feature/file/src/main/java/com/example/file/ui/bottom/sheet/FileBottomSheet.kt +++ b/feature/file/src/main/java/com/example/file/ui/bottom/sheet/FileBottomSheet.kt @@ -10,7 +10,6 @@ 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.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -38,9 +37,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.example.file.R import com.example.design.modifier.noRippleClickable import com.example.design.theme.color.Basic +import com.example.file.R import com.example.file.ui.theme.Black import com.example.file.ui.theme.DefaultFont import com.example.file.ui.theme.Gray300 @@ -73,6 +72,9 @@ fun FileBottomSheet( color = Basic.gray[300] ) }, + + // 딤 효과 수치 + scrimColor = Basic.black.copy(alpha = 0.5f), sheetState = sheetState, onDismissRequest = onDismiss, tonalElevation = 8.dp, @@ -85,26 +87,29 @@ fun FileBottomSheet( .padding(bottom = 20.dp) .padding(horizontal = 20.dp), ) { + Text( modifier = Modifier .padding(start = 10.dp), text = title, fontSize = 18.sp, - lineHeight = 22.sp, fontFamily = DefaultFont, fontWeight = FontWeight(500), color = Black, ) + + Spacer(modifier = Modifier.height(11.dp)) + Text( modifier = Modifier - .padding(start = 10.dp, top = 14.dp), + .padding(start = 10.dp), text = body, fontSize = 15.sp, - lineHeight = 22.sp, fontFamily = DefaultFont, fontWeight = FontWeight.Normal, color = Gray600, ) + Spacer(modifier = Modifier.height(24.dp)) content() From 69c19e0ff1d0119b8f9da7d4f70fa84559b29aa6 Mon Sep 17 00:00:00 2001 From: gmin Date: Mon, 2 Feb 2026 19:34:09 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20feature/file:=20TextFi?= =?UTF-8?q?eldFileBottomSheet=20=ED=99=94=EC=82=B4=ED=91=9C=20=ED=9A=8C?= =?UTF-8?q?=EC=A0=84=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=9D=BC=EB=B2=A8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `animateFloatAsState`의 `label` 파라미터에 "화살표 회전 애니메이션" 명시 및 `targetValue` 네임드 파라미터 적용 --- .../example/file/ui/bottom/sheet/TextFieldFileBottomSheet.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/feature/file/src/main/java/com/example/file/ui/bottom/sheet/TextFieldFileBottomSheet.kt b/feature/file/src/main/java/com/example/file/ui/bottom/sheet/TextFieldFileBottomSheet.kt index 81c74d2..ff546f4 100644 --- a/feature/file/src/main/java/com/example/file/ui/bottom/sheet/TextFieldFileBottomSheet.kt +++ b/feature/file/src/main/java/com/example/file/ui/bottom/sheet/TextFieldFileBottomSheet.kt @@ -185,7 +185,10 @@ fun TextFieldFileBottomSheet( ) } - val rotation by animateFloatAsState(if (expanded) 180f else 0f, label = "") + val rotation by animateFloatAsState( + targetValue = if (expanded) 180f else 0f, + label = "화살표 회전 애니메이션" + ) val modifier = if(expanded) Modifier .padding(start = 10.dp) From 6d04654c309959f35c08bfdb2f5383c92e32c5b9 Mon Sep 17 00:00:00 2001 From: gmin Date: Mon, 2 Feb 2026 19:36:05 +0900 Subject: [PATCH 5/9] =?UTF-8?q?=E2=9C=A8=20feature/file:=20LinkItemLayout?= =?UTF-8?q?=20UI=20=EB=B0=8F=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `LinkItemLayout`에 그림자 효과(`shadow`)를 적용하고 기존 `shadowElevation` 속성 제거 - 태그 UI 레이아웃 수정: `padding` 값 조정, 폰트 크기 변경(10sp -> 12sp), `includeFontPadding = false` 적용 - 컴포넌트 간 간격 조정을 위해 `Spacer` 추가 및 기존 `padding` 로직 수정 - 불필요한 `showDialog` 상태 및 미사용 import 제거 - 클릭 이벤트 로직 내 불필요한 null safety 체크 최적화 --- .../example/file/ui/item/LinkItemLayout.kt | 89 ++++++++++--------- 1 file changed, 49 insertions(+), 40 deletions(-) diff --git a/feature/file/src/main/java/com/example/file/ui/item/LinkItemLayout.kt b/feature/file/src/main/java/com/example/file/ui/item/LinkItemLayout.kt index 306ae4e..8bc9fb3 100644 --- a/feature/file/src/main/java/com/example/file/ui/item/LinkItemLayout.kt +++ b/feature/file/src/main/java/com/example/file/ui/item/LinkItemLayout.kt @@ -6,6 +6,8 @@ import android.util.Log import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -18,7 +20,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape @@ -28,25 +29,24 @@ import androidx.compose.material3.Icon import androidx.compose.material3.Surface import androidx.compose.material3.Text 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.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.ExperimentalTextApi +import androidx.compose.ui.text.PlatformTextStyle +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.compose.rememberNavController import coil3.compose.AsyncImage import coil3.request.ImageRequest import coil3.request.crossfade @@ -54,8 +54,6 @@ import coil3.request.error import coil3.request.fallback import coil3.request.placeholder import com.example.core.model.LinkItemInfo -import com.example.design.modifier.noRippleClickable -import com.example.file.FileViewModel import com.example.file.R import com.example.file.ui.theme.Black import com.example.file.ui.theme.DefaultFont @@ -66,11 +64,12 @@ import com.example.file.ui.theme.Gray600 import com.example.file.ui.theme.Gray800 import com.example.file.ui.theme.White import com.example.file.ui.theme.domainLogoPainterOrNull -import androidx.compose.foundation.combinedClickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import java.time.OffsetDateTime -@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) +@OptIn( + ExperimentalMaterial3Api::class, + ExperimentalFoundationApi::class, + ExperimentalTextApi::class +) @Composable fun LinkItemLayout( link: LinkItemInfo? = null, @@ -78,7 +77,6 @@ fun LinkItemLayout( onLongClick: (Long) -> Unit = {}, ) { val tags = link?.tags?:emptyList() - var showDialog by remember { mutableStateOf(false) } val domainIcon = link?.let{ domainLogoPainterOrNull(it.url) } @@ -99,28 +97,38 @@ fun LinkItemLayout( Box ( // 태그 배경: 크기 wrap, 둥근 모서리(6dp), Gray100 배경색 modifier = Modifier - .wrapContentSize() .background( shape = RoundedCornerShape(size = 6.dp), color = Gray100 - ), + ) + .padding(horizontal = 6.dp, vertical = 1.dp), + contentAlignment = Alignment.Center ) { + // 태그 텍스트 Text( - // 태그 텍스트를 Box 중앙에 정렬, 내부 여백(가로 6dp, 세로 3dp) + // 태그 텍스트를 Box 중앙에 정렬, 내부 여백(가로 1dp, 세로 2dp) modifier = Modifier - .align(Alignment.Center) - .padding(horizontal = 6.dp, vertical = 1.dp), + .padding(horizontal = 1.dp, vertical = 2.dp), text = tag, - // 폰트 크기(10sp) - fontSize = 10.sp, + // 폰트 크기(12sp) + fontSize = 12.sp, // 폰트 fontFamily = DefaultFont, // 폰트 굵기(Normal) fontWeight = FontWeight.Normal, // 글자색(Gray600) color = Gray600, + + textAlign = TextAlign.Center, + + style = TextStyle( + platformStyle = PlatformTextStyle( + includeFontPadding = false + ) + ) ) + } } @@ -128,7 +136,7 @@ fun LinkItemLayout( indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = { - link?.linkuId?.let { + link.linkuId.let { Log.d("LinkItemLayout", "아이템 클릭: \"savelinkresult/${it}\"") onClick(link) } @@ -144,21 +152,17 @@ fun LinkItemLayout( // 카드 크기: 가로 181dp, 세로 267dp modifier = Modifier .width(181.dp) - //.height(267.dp) - then(modifier) - /*.pointerInput(Unit) { - detectTapGestures( - onLongPress = { - showDialog = true // 꾹 누르면 Dialog 띄우기 - } - ) - }*/, + .then(modifier) + .shadow( + elevation = 4.dp, + shape = RoundedCornerShape(18.dp) + ), // 모서리 둥글게(18dp) - shape = RoundedCornerShape(18.dp), + //shape = RoundedCornerShape(18.dp), // 카드 배경색(White) color = White, // 그림자(입체감) 효과(20dp) - shadowElevation = 5.dp//(if(painter == null) 0 else 5).dp, + //shadowElevation = 5.dp//(if(painter == null) 0 else 5).dp, ) { // 내용 전체를 세로로 배치하는 Column Column ( @@ -197,11 +201,13 @@ fun LinkItemLayout( } } + // 링크 메인 이미지, 제목 사이 간격 + Spacer(modifier = Modifier.height(10.dp)) + // (2) 링크 제목 Text( // 위쪽 여백(10dp) - modifier = Modifier - .padding(top = 10.dp), + modifier = Modifier, text = link?.title?:"제목", // 폰트 크기(15sp) fontSize = 15.sp, @@ -215,12 +221,14 @@ fun LinkItemLayout( overflow = TextOverflow.Ellipsis // 잘리면 ... 표시 ) + // 링크 제목, 태그 사이 간격 + Spacer(modifier = Modifier.height(1.dp)) + // (3) 링크 분류 태그(여러 개를 Row에 배치) LazyRow( // 가로 전체 채우기, 위쪽 여백(8dp) modifier = Modifier - .height(30.dp) - .padding(top = 8.dp), + .height(30.dp), // 태그 간 5dp 간격, 왼쪽 정렬 horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.Start), // 세로 중앙 정렬 @@ -232,8 +240,8 @@ fun LinkItemLayout( } } - // (4) 남은 공간 모두 차지하는 Spacer (아래로 밀어내기) - Spacer(modifier = Modifier.height(8.dp)) + // 링크 태그, 설명 프레임 사이 간격 + Spacer(modifier = Modifier.height(5.dp)) // (5) 링크 설명 프레임 (도메인, 아이콘 등) Row( @@ -300,7 +308,7 @@ private fun LinkItemTest() { contentAlignment = Alignment.TopCenter ){ Box( - modifier = Modifier.alpha(0.35f), + //modifier = Modifier.alpha(0.35f), ){ LinkItemLayout( link = null @@ -323,5 +331,6 @@ private fun LinkItemTest() { textAlign = TextAlign.Center, ) } -} + LinkItemLayout { } +} \ No newline at end of file From b27b3ed32a7343c638920d0ef5d82d2fb38cc88b Mon Sep 17 00:00:00 2001 From: gmin Date: Mon, 2 Feb 2026 19:38:40 +0900 Subject: [PATCH 6/9] =?UTF-8?q?=E2=9C=A8=20=EB=A7=81=ED=81=AC=20=EB=B6=84?= =?UTF-8?q?=EB=A5=98=20=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20UI=20?= =?UTF-8?q?=EB=B0=8F=20=EC=84=A0=ED=83=9D=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `selectedLinks`를 `mutableStateListOf`로 변경하여 상태 추적 지원 - 바텀시트 '추가' 버튼 활성화 상태(`isReady`) 조건 추가 (선택된 링크가 있을 때만 활성화) - 링크 아이템 레이아웃 수정: `offset`, `padding`, `shape` 및 정렬 조정 - 체크박스 미선택 시 색상(`uncheckedColor`) 변경 - 링크 선택 시 데이터 정합성을 위해 `onOkay` 콜백 내 `selectedLinks.clear()` 로직 추가 --- .../sheet/LinkCategorizationBottomSheet.kt | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/feature/file/src/main/java/com/example/file/ui/bottom/sheet/LinkCategorizationBottomSheet.kt b/feature/file/src/main/java/com/example/file/ui/bottom/sheet/LinkCategorizationBottomSheet.kt index ffe5148..5d04405 100644 --- a/feature/file/src/main/java/com/example/file/ui/bottom/sheet/LinkCategorizationBottomSheet.kt +++ b/feature/file/src/main/java/com/example/file/ui/bottom/sheet/LinkCategorizationBottomSheet.kt @@ -12,7 +12,7 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -25,6 +25,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -45,6 +46,7 @@ import com.example.core.model.LinkItemInfo import com.example.file.FileViewModel import com.example.file.R import com.example.design.modifier.noRippleClickable +import com.example.design.theme.color.Basic import com.example.file.ui.theme.Black import com.example.file.ui.theme.DefaultFont import com.example.file.ui.theme.Gray100 @@ -62,9 +64,9 @@ fun LinkCategorizationBottomSheet( ) { val links by fileViewModel.notCategorizationLinks.collectAsStateWithLifecycle() - var link by remember { mutableStateOf(null) } + //var link by remember { mutableStateOf(null) } - var selectedLinks = mutableListOf() + val selectedLinks = remember { mutableStateListOf() } val scope = rememberCoroutineScope() @@ -75,15 +77,17 @@ fun LinkCategorizationBottomSheet( title = "${folderStateViewModel.selectedTopFolder?.folderName?:""} 폴더의 미분류 링크 목록", body = "하위폴더에 추가하실 링크를 선택해주세요!", buttonText = "추가", + isReady = selectedLinks.isNotEmpty(), visible = folderStateViewModel.linkCategorizationBottomSheetVisible, onOkay = { scope.launch{ - selectedLinks.map { - fileViewModel.updateLinkFolder( - it, - folderStateViewModel.selectedBottomFolder?.folderId!! - ) + val folderId = requireNotNull(folderStateViewModel.selectedBottomFolder?.folderId) + + selectedLinks.forEach { + fileViewModel.updateLinkFolder(it, folderId) } + + selectedLinks.clear() } }, onDismiss = { folderStateViewModel.updateLinkCategorizationBottomSheetVisible(false) } @@ -95,7 +99,7 @@ fun LinkCategorizationBottomSheet( verticalArrangement = Arrangement.spacedBy(10.dp) ) { items(links) { - val l = it + val link = it val title = it.title val url = it.url val icon = domainLogoPainterOrNull(it.url)?:painterResource(R.drawable.link_categorization_default) @@ -104,64 +108,71 @@ fun LinkCategorizationBottomSheet( var checked by remember { mutableStateOf(false)} Row( modifier = Modifier - //.height(60.dp) + .height(60.dp) + .offset(x = (-20).dp) .noRippleClickable{ if(checked){ Log.d("LinkCategorizationBottomSheet", "checked: $it") - selectedLinks.remove(l) - checked = selectedLinks.contains(l) + selectedLinks.remove(link) + checked = selectedLinks.contains(link) } else { Log.d("LinkCategorizationBottomSheet", "checked: $it") - selectedLinks.add(l) - checked = selectedLinks.contains(l) + selectedLinks.add(link) + checked = selectedLinks.contains(link) } }, - horizontalArrangement = Arrangement.spacedBy(14.dp) + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalAlignment = Alignment.CenterVertically ) { Checkbox( - modifier = Modifier - .clip(RoundedCornerShape(18.dp)), checked = checked, onCheckedChange = { if(checked){ Log.d("LinkCategorizationBottomSheet", "checked: $it") - selectedLinks.remove(l) - checked = selectedLinks.contains(l) + selectedLinks.remove(link) + checked = selectedLinks.contains(link) } else { Log.d("LinkCategorizationBottomSheet", "checked: $it") - selectedLinks.add(l) - checked = selectedLinks.contains(l) + selectedLinks.add(link) + checked = selectedLinks.contains(link) } }, colors = CheckboxDefaults.colors( checkedColor = Purple200, + uncheckedColor = Basic.gray[200], ) ) Box( modifier = Modifier - .height(60.dp) - .background(Gray100), + //.height(60.dp) + .background( + color = Gray100, + shape = RoundedCornerShape(18.dp) + ) + /*.clip(RoundedCornerShape(18.dp))*/, contentAlignment = Alignment.Center ) { Image( modifier = Modifier - .fillMaxHeight() - .clip(RoundedCornerShape(18.dp)), + .fillMaxHeight(), painter = img, contentDescription = null ) } + Column( - modifier = Modifier - .fillMaxHeight() - .padding(vertical = 8.dp), + modifier = Modifier.fillMaxHeight(), + //verticalArrangement = Arrangement.SpaceBetween + ) { + // 링크 상단 패딩 + Spacer(modifier = Modifier.height(7.dp)) + Text( text = title, fontSize = 15.sp, - lineHeight = 22.sp, fontFamily = DefaultFont, fontWeight = FontWeight(500), color = Black, @@ -194,7 +205,6 @@ fun LinkCategorizationBottomSheet( Text( text = url, fontSize = 12.sp, - lineHeight = 14.sp, fontFamily = DefaultFont, fontWeight = FontWeight(400), color = Gray800, @@ -202,7 +212,10 @@ fun LinkCategorizationBottomSheet( overflow = TextOverflow.Ellipsis ) } + // 링크 하단 패딩 + Spacer(modifier = Modifier.height(7.dp)) } + } } } From e9fbcb649a14b2792b9ea7e851302ad9fa32ea44 Mon Sep 17 00:00:00 2001 From: gmin Date: Mon, 2 Feb 2026 19:39:07 +0900 Subject: [PATCH 7/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20feature/file:=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=BB=B4=ED=8F=AC=EC=A0=80?= =?UTF-8?q?=EB=B8=94=20=EC=A0=91=EA=B7=BC=20=EC=A0=9C=ED=95=9C=EC=9E=90=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(`internal`=20=EC=B6=94=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `ShareFolderIcon`, `LockFolderIcon`, `PencilIcon`, `BookMarkStar` 함수에 `internal` 접근 제한자 적용 --- .../main/java/com/example/file/ui/content/FolderIcons.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/feature/file/src/main/java/com/example/file/ui/content/FolderIcons.kt b/feature/file/src/main/java/com/example/file/ui/content/FolderIcons.kt index 5cd753a..65b6cd0 100644 --- a/feature/file/src/main/java/com/example/file/ui/content/FolderIcons.kt +++ b/feature/file/src/main/java/com/example/file/ui/content/FolderIcons.kt @@ -19,7 +19,7 @@ import com.example.file.ui.theme.White // 공유 폴더 사람 아이콘 @Composable -fun ShareFolderIcon( +internal fun ShareFolderIcon( tint: Color ) { Icon( @@ -31,7 +31,7 @@ fun ShareFolderIcon( // 잠금 폴더 자물쇠 아이콘 @Composable -fun LockFolderIcon( +internal fun LockFolderIcon( tint: Color ) { Icon( @@ -43,7 +43,7 @@ fun LockFolderIcon( // 수정 연필 아이콘 @Composable -fun PencilIcon( +internal fun PencilIcon( tint: Color ) { Icon( @@ -55,7 +55,7 @@ fun PencilIcon( // 북마크 별 아이콘 @Composable -fun BookMarkStar( +internal fun BookMarkStar( isBookmarked: Boolean ) { val modifier = if(isBookmarked) Modifier From 5af7142d5a859cf1ab82c7fe763fad181378650b Mon Sep 17 00:00:00 2001 From: gmin Date: Tue, 3 Feb 2026 17:50:33 +0900 Subject: [PATCH 8/9] =?UTF-8?q?=F0=9F=90=9B=20=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95:=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=8B=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `LaunchedEffect`의 key를 `text`에서 `Unit`으로 변경하여, 컴포저블이 처음 생성될 때만 검색 로직 관련 Flow가 생성되도록 수정했습니다. 이를 통해 불필요한 초기 호출을 방지합니다. --- .../design/top/search/SearchBarTopSheet.kt | 2 +- .../com/example/curation/ui/CurationScreen.kt | 10 +--------- .../src/main/java/com/example/file/FileScreen.kt | 2 +- .../java/com/example/home/screen/HomeScreen.kt | 16 +--------------- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/design/src/main/java/com/example/design/top/search/SearchBarTopSheet.kt b/design/src/main/java/com/example/design/top/search/SearchBarTopSheet.kt index 0e06fad..da8cb6e 100644 --- a/design/src/main/java/com/example/design/top/search/SearchBarTopSheet.kt +++ b/design/src/main/java/com/example/design/top/search/SearchBarTopSheet.kt @@ -146,7 +146,7 @@ fun SearchBarTopSheet( * - 350ms 디바운스 * - 동일 값 중복 호출 방지 */ - LaunchedEffect(text) { + LaunchedEffect(Unit) { snapshotFlow { text } .map { it.trim() } .filter { it.length >= 2 } diff --git a/feature/curation/src/main/java/com/example/curation/ui/CurationScreen.kt b/feature/curation/src/main/java/com/example/curation/ui/CurationScreen.kt index 8fb8404..1fd4561 100644 --- a/feature/curation/src/main/java/com/example/curation/ui/CurationScreen.kt +++ b/feature/curation/src/main/java/com/example/curation/ui/CurationScreen.kt @@ -4,17 +4,14 @@ package com.example.curation.ui import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize 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.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -27,9 +24,7 @@ import com.example.curation.R import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.width import androidx.compose.material3.Scaffold @@ -37,7 +32,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp @@ -46,8 +40,6 @@ import com.example.curation.CurationViewModel import com.example.curation.ui.list_card.LikedCurationCard import com.example.curation.Paperlogy import com.example.design.theme.LocalColorTheme -import com.example.design.theme.color.Basic -import com.example.design.R as Res import java.time.LocalDate import java.time.format.DateTimeFormatter import java.util.Locale @@ -306,7 +298,7 @@ fun CurationScreen( onQueryDelete = { viewModel.removeRecentQuery(it) }, onQueryClear = { viewModel.clearRecentQuery() }, fastSearchItems = viewModel.fastSearchItems.collectAsState().value, - recentQuerys = viewModel.recentQueryList.collectAsState().value.map{it.text} + recentQueries = viewModel.recentQueryList.collectAsState().value.map{it.text} ) } diff --git a/feature/file/src/main/java/com/example/file/FileScreen.kt b/feature/file/src/main/java/com/example/file/FileScreen.kt index 8c12897..117ab9d 100644 --- a/feature/file/src/main/java/com/example/file/FileScreen.kt +++ b/feature/file/src/main/java/com/example/file/FileScreen.kt @@ -284,7 +284,7 @@ fun FileScreen( onQueryDelete = { fileViewModel.removeRecentQuery(it) }, onQueryClear = { fileViewModel.clearRecentQuery() }, fastSearchItems = fileViewModel.fastSearchItems.collectAsState().value, - recentQuerys = fileViewModel.recentQueryList.collectAsState().value.map{it.text} + recentQueries = fileViewModel.recentQueryList.collectAsState().value.map{it.text} ) } diff --git a/feature/home/src/main/java/com/example/home/screen/HomeScreen.kt b/feature/home/src/main/java/com/example/home/screen/HomeScreen.kt index bc89c14..1b3bc03 100644 --- a/feature/home/src/main/java/com/example/home/screen/HomeScreen.kt +++ b/feature/home/src/main/java/com/example/home/screen/HomeScreen.kt @@ -1,8 +1,5 @@ package com.example.home.screen -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.expandVertically -import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -16,8 +13,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -25,7 +20,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -38,17 +32,13 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.zIndex @@ -56,20 +46,16 @@ import coil3.compose.AsyncImage import com.example.core.model.LinkSimpleInfo import com.example.design.BrushText import com.example.design.top.search.SearchBarTopSheet -import com.example.design.modifier.noRippleClickable import com.example.design.theme.LocalColorTheme import com.example.design.theme.LocalFontTheme import com.example.design.theme.color.Basic import com.example.design.util.DesignSystemBars -import com.example.file.ui.theme.FileTopBarLinkUFont -import com.example.file.ui.theme.MainColor import com.example.home.HomeViewModel import com.example.home.R import com.example.home.component.ClipboardLinkPasteBanner import com.example.home.component.rememberClipboardUrl import com.example.home.ui.top.bar.HomeTopBar import kotlinx.coroutines.launch -import com.example.design.R as Res data class LinkItem( val imageResId: Int?, // 링크 대표 이미지 @@ -525,7 +511,7 @@ fun HomeScreen( onQueryDelete = { homeViewModel.removeRecentQuery(it) }, onQueryClear = { homeViewModel.clearRecentQuery() }, fastSearchItems = homeViewModel.fastSearchItems.collectAsState().value, - recentQuerys = homeViewModel.recentQueryList.collectAsState().value.map{it.text} + recentQueries = homeViewModel.recentQueryList.collectAsState().value.map{it.text} ) } From 1b6b50286ae091372ae13ae4c21f8cb250be515d Mon Sep 17 00:00:00 2001 From: gmin Date: Tue, 3 Feb 2026 20:37:46 +0900 Subject: [PATCH 9/9] =?UTF-8?q?=E2=9C=A8=20EmailLoginScreen=20UI=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=EC=84=A0:=20=ED=95=98=EB=8B=A8?= =?UTF-8?q?=20=EB=A9=94=EB=89=B4=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(Box=20->=20Row)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 비밀번호 재설정, 구분선, 회원가입 버튼의 배치를 `Box`의 오프셋 방식에서 `Row`를 사용한 정렬 방식으로 변경 - `Arrangement.spacedBy`를 사용하여 요소 간 간격 조정 및 중앙 정렬 적용 --- .../login/ui/screen/EmailLoginScreen.kt | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/feature/login/src/main/java/com/example/login/ui/screen/EmailLoginScreen.kt b/feature/login/src/main/java/com/example/login/ui/screen/EmailLoginScreen.kt index 16e41c8..9c36140 100644 --- a/feature/login/src/main/java/com/example/login/ui/screen/EmailLoginScreen.kt +++ b/feature/login/src/main/java/com/example/login/ui/screen/EmailLoginScreen.kt @@ -237,28 +237,26 @@ fun EmailLoginScreen( val dividerStartPos = (220.scaler) // | 시작점 val signUpStartPos = (247.scaler) // 회원가입 시작점 - Box( + Row( modifier = Modifier + .align(Alignment.CenterHorizontally) .fillMaxWidth() .height((30.scaler)), // 클릭 영역 확보를 위한 높이 - contentAlignment = Alignment.CenterStart //세로 중앙 정렬 - ) { - // 1. 비밀번호 재설정 + horizontalArrangement = Arrangement.spacedBy(25.dp, alignment = Alignment.CenterHorizontally), + verticalAlignment = Alignment.CenterVertically + ){ Text( text = "비밀번호 재설정", fontSize = 15.sp, fontFamily = Paperlogy.font, color = Color(0xFF87898F), modifier = Modifier - .offset(x = resetStartPos) // 항상 101/412 지점 .noRippleClickable { //if (loginState !is LoginState.Loading) { -> 혹시 나중에 로딩중이 길어지면 사용해주세요. navigator.navigate("resetPassword") //} } ) - - // 2. 구분선 (|) // TODO : 비밀번호 재설정, 회원가입 대비 내려가서 부득이하게 약간 위로 올림. 다현이랑 조절해보기. Text( text = "|", fontSize = 14.sp, @@ -266,30 +264,23 @@ fun EmailLoginScreen( color = Color(0xFF87898F), style = TextStyle( baselineShift = BaselineShift(0.3f) // 약간 위로 올림 - ), - //style = TextStyle(baselineShift = BaselineShift(0.15f)), - modifier = Modifier - .offset(x = dividerStartPos) // 항상 220/412 지점 + ) ) - - // 3. 회원가입 Text( text = "회원가입", fontSize = 15.sp, fontFamily = Paperlogy.font, color = Color(0xFF87898F), modifier = Modifier - .offset(x = signUpStartPos) // 항상 247/412 지점 .noRippleClickable { focusManager.clearFocus() onSignUpClick() } ) } - - } } } +}