From 941c88f1a70b66ad936815c114a28f68bcb389a2 Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Sat, 22 Nov 2025 18:53:05 +0900 Subject: [PATCH 01/15] =?UTF-8?q?:bug:=20Fix(#103):=20=EB=9D=BC=EB=B2=A8?= =?UTF-8?q?=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=ED=99=94=EB=A9=B4=20=EC=98=A8?= =?UTF-8?q?=EB=B3=B4=EB=94=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelListOnboardingState.kt | 2 + .../presentation/label/LabelListViewModel.kt | 37 ++++++++++++++++++- .../com/umc/edison/ui/label/LabelTabScreen.kt | 30 +++++++-------- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/umc/edison/presentation/label/LabelListOnboardingState.kt b/app/src/main/java/com/umc/edison/presentation/label/LabelListOnboardingState.kt index b6ae0c8ca..559015521 100644 --- a/app/src/main/java/com/umc/edison/presentation/label/LabelListOnboardingState.kt +++ b/app/src/main/java/com/umc/edison/presentation/label/LabelListOnboardingState.kt @@ -5,11 +5,13 @@ import com.umc.edison.presentation.onboarding.OnboardingPositionState data class LabelListOnboardingState( val show: Boolean, val labelBound: OnboardingPositionState, + val draggedIndex: Int, ) { companion object { val DEFAULT = LabelListOnboardingState( show = false, labelBound = OnboardingPositionState.DEFAULT, + draggedIndex = -1, ) } } diff --git a/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt b/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt index 320dffa30..f6a5f54db 100644 --- a/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt +++ b/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt @@ -16,6 +16,7 @@ import com.umc.edison.presentation.base.BaseViewModel import com.umc.edison.presentation.model.LabelModel import com.umc.edison.presentation.model.toPresentation import com.umc.edison.presentation.onboarding.OnboardingPositionState +import com.umc.edison.ui.theme.Aqua100 import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -43,6 +44,7 @@ class LabelListViewModel @Inject constructor( companion object { const val SCREEN_NAME = "label_list" + const val TEMP_LABEL_ID = "-1" } init { @@ -82,6 +84,11 @@ class LabelListViewModel @Inject constructor( val labelsWithId = _uiState.value.labels.filter { !it.id.isNullOrEmpty() } var completedCount = 0 + if (labelsWithId.isEmpty()) { + handleOnboardingState() + return + } + labelsWithId.forEach { label -> collectDataResource( flow = getBubblesByLabelUseCase(label.id!!), @@ -110,6 +117,7 @@ class LabelListViewModel @Inject constructor( ) ) } + handleOnboardingState() } } ) @@ -130,6 +138,9 @@ class LabelListViewModel @Inject constructor( ) } fetchBubblesByLabel() + }, + onComplete = { + handleOnboardingState() } ) } @@ -193,7 +204,16 @@ class LabelListViewModel @Inject constructor( collectDataResource( flow = setHasSeenOnboardingUseCase(SCREEN_NAME), onSuccess = { - _onboardingState.update { it.copy(show = false) } + _onboardingState.update { it.copy(show = false, draggedIndex = -1) } + + // 온보딩 종료 시 temp label만 제거 (default label은 유지) + if (_uiState.value.labels.any { it.id == TEMP_LABEL_ID }) { + _uiState.update { uiState -> + uiState.copy( + labels = uiState.labels.filter { it.id != TEMP_LABEL_ID } + ) + } + } } ) } @@ -201,4 +221,19 @@ class LabelListViewModel @Inject constructor( fun setLabelListItemBound(offset: Offset, size: IntSize) { _onboardingState.update { it.copy(labelBound = OnboardingPositionState(offset, size)) } } + + private fun handleOnboardingState() { + if (_onboardingState.value.show) { + val currentLabels = _uiState.value.labels + + val hasAdditionalLabels = currentLabels.any { !it.id.isNullOrEmpty() } + + if (!hasAdditionalLabels) { + val tempLabel = LabelModel(id = TEMP_LABEL_ID, name = "감상", color = Aqua100, bubbleCnt = 7) + _uiState.update { it.copy(labels = it.labels + listOf(tempLabel)) } + } + + _onboardingState.update { it.copy(draggedIndex = 1) } + } + } } diff --git a/app/src/main/java/com/umc/edison/ui/label/LabelTabScreen.kt b/app/src/main/java/com/umc/edison/ui/label/LabelTabScreen.kt index c37d05bc2..d0294edfb 100644 --- a/app/src/main/java/com/umc/edison/ui/label/LabelTabScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/label/LabelTabScreen.kt @@ -39,7 +39,6 @@ import com.umc.edison.ui.components.LabelListItem import com.umc.edison.ui.components.LabelModalContent import com.umc.edison.ui.navigation.NavRoute import com.umc.edison.ui.onboarding.LabelListOnboardingScreen -import com.umc.edison.ui.theme.Aqua100 import com.umc.edison.ui.theme.Gray600 @OptIn(ExperimentalMaterial3Api::class) @@ -125,15 +124,14 @@ fun LabelTabScreen( viewModel.updateEditMode(LabelEditMode.ADD) } ) - val labels = if (uiState.labels.isEmpty() && onboardingState.show) { - listOf(LabelModel(id = "", name = "감상", color = Aqua100, bubbleCnt = 7)) - } else { - uiState.labels - } LabelList( - labels = labels, - draggedIndex = draggedIndex.intValue, + labels = uiState.labels, + draggedIndex = if (onboardingState.show) { + onboardingState.draggedIndex + } else { + draggedIndex.intValue + }, onLabelClick = { labelId -> navHostController.navigate(NavRoute.LabelDetail.createRoute(labelId)) }, @@ -146,10 +144,14 @@ fun LabelTabScreen( viewModel.updateSelectedLabel(uiState.labels[index]) }, onDrag = { index -> - draggedIndex.intValue = index + if (!onboardingState.show) { + draggedIndex.intValue = index + } }, resetDrag = { - draggedIndex.intValue = -1 + if (!onboardingState.show) { + draggedIndex.intValue = -1 + } }, setLabelItemPosition = { offset, size -> viewModel.setLabelListItemBound(offset, size) @@ -159,12 +161,6 @@ fun LabelTabScreen( } if (onboardingState.show) { - if (uiState.labels.isNotEmpty()) { - draggedIndex.intValue = 1 - } else { - draggedIndex.intValue = 0 - } - LabelListOnboardingScreen( onDismiss = { viewModel.setHasSeenOnboarding() @@ -190,7 +186,7 @@ fun LabelList( ) { Column { labels.forEachIndexed { index, label -> - val modifier = if ((labels.size > 1 && index == 1) || index == 0) { + val modifier = if (showOnboarding && index == draggedIndex) { Modifier.onGloballyPositioned { coordinates -> setLabelItemPosition( coordinates.positionOnScreen(), From 3328466115eca9bce3c96e51e193f2b47cfaf9f2 Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Sat, 22 Nov 2025 19:10:04 +0900 Subject: [PATCH 02/15] =?UTF-8?q?:bug:=20Feature(#103):=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EC=97=90=EB=94=94=EC=8A=A8=20=EC=98=A8=EB=B3=B4?= =?UTF-8?q?=EB=94=A9=20=EB=9D=BC=EB=B2=A8=ED=83=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edison/MyEdisonOnboardingState.kt | 2 +- .../presentation/edison/MyEdisonViewModel.kt | 1 - .../ui/bubblestorage/BubbleStorageScreen.kt | 4 +- .../umc/edison/ui/edison/MyEdisonScreen.kt | 40 ++++++++++++++----- .../ui/onboarding/BubbleStorageOnboarding.kt | 2 +- .../onboarding/LabelListOnboardingScreen.kt | 10 +++-- .../ui/onboarding/MyEdisonOnboardingScreen.kt | 28 ++++++++++--- 7 files changed, 62 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonOnboardingState.kt b/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonOnboardingState.kt index 7bcc2b8c3..9263ce7c6 100644 --- a/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonOnboardingState.kt +++ b/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonOnboardingState.kt @@ -11,7 +11,7 @@ data class MyEdisonOnboardingState( val DEFAULT = MyEdisonOnboardingState( show = false, bubbleInputBound = OnboardingPositionState.DEFAULT, - myEdisonNavBarBounds = List(2) { OnboardingPositionState.DEFAULT }, + myEdisonNavBarBounds = List(3) { OnboardingPositionState.DEFAULT }, ) } } diff --git a/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonViewModel.kt b/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonViewModel.kt index 5cc69442a..e5310422d 100644 --- a/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonViewModel.kt +++ b/app/src/main/java/com/umc/edison/presentation/edison/MyEdisonViewModel.kt @@ -3,7 +3,6 @@ package com.umc.edison.presentation.edison import androidx.compose.ui.geometry.Offset import androidx.compose.ui.unit.IntSize import com.umc.edison.domain.usecase.bubble.GetAllRecentBubblesUseCase -import com.umc.edison.domain.usecase.bubble.SearchBubblesUseCase import com.umc.edison.domain.usecase.onboarding.GetHasSeenOnboardingUseCase import com.umc.edison.domain.usecase.onboarding.SetHasSeenOnboardingUseCase import com.umc.edison.presentation.ToastManager diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index f6e800e65..db0413284 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -39,7 +39,7 @@ import com.umc.edison.ui.components.BubblesLayout import com.umc.edison.ui.components.LabelTagList import com.umc.edison.ui.components.calculateBubbleSize import com.umc.edison.ui.navigation.NavRoute -import com.umc.edison.ui.onboarding.BubbleStorageOnboarding +import com.umc.edison.ui.onboarding.EdisonNavBarOnboarding import com.umc.edison.ui.theme.Gray300 import com.umc.edison.ui.theme.Gray800 import com.umc.edison.ui.theme.Gray900 @@ -284,7 +284,7 @@ fun BubbleStorageScreen( } if (!onboardingState.edisonOnboardingShow && onboardingState.show && uiState.bubbles.isNotEmpty()) { - BubbleStorageOnboarding( + EdisonNavBarOnboarding( onboardingState = onboardingState, onDismiss = { viewModel.setHasSeenOnboarding() diff --git a/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt b/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt index 79fc99607..6f4d906bc 100644 --- a/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.positionOnScreen import androidx.compose.ui.platform.LocalContext @@ -92,8 +93,6 @@ fun MyEdisonScreen( modifier = Modifier.fillMaxSize(), ) { page -> when (page) { - - 0 -> { Column( modifier = Modifier @@ -101,7 +100,6 @@ fun MyEdisonScreen( .background(Color.White), horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(modifier = Modifier.weight(0.6f)) BubbleInput( @@ -121,11 +119,11 @@ fun MyEdisonScreen( 1 -> { if (onboardingState.show) { - val context = LocalContext.current - val imageRequest = ImageRequest.Builder(context) + val imageRequest = ImageRequest.Builder(LocalContext.current) .data(R.drawable.bubble_ex) .crossfade(true) .build() + AsyncImage( model = imageRequest, contentDescription = "Bubble Example", @@ -133,7 +131,7 @@ fun MyEdisonScreen( .fillMaxWidth() .wrapContentHeight(), alignment = Alignment.Center, - contentScale = androidx.compose.ui.layout.ContentScale.Crop, + contentScale = ContentScale.Crop, ) } else { BubbleStorageScreen( @@ -148,9 +146,26 @@ fun MyEdisonScreen( 2 -> { - LabelTabScreen( - navHostController = navController, - ) + if (onboardingState.show) { + val imageRequest = ImageRequest.Builder(LocalContext.current) + .data(R.drawable.bubble_ex) + .crossfade(true) + .build() + + AsyncImage( + model = imageRequest, + contentDescription = "Label Example", + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), + alignment = Alignment.Center, + contentScale = ContentScale.Crop, + ) + } else { + LabelTabScreen( + navHostController = navController, + ) + } } } } @@ -163,7 +178,6 @@ fun MyEdisonScreen( contentAlignment = Alignment.TopCenter ) { MyEdisonNavBar( - onBubbleClick = { coroutineScope.launch { pagerState.scrollToPage(0) @@ -182,7 +196,6 @@ fun MyEdisonScreen( } viewModel.resetSearchResults() }, - currentPage = pagerState.currentPage, isViewMode = isViewMode, setNavBarPosition = { idx: Int, offset: Offset, size: IntSize -> @@ -205,6 +218,11 @@ fun MyEdisonScreen( pagerState.scrollToPage(1) } }, + changeToLabelMode = { + coroutineScope.launch { + pagerState.scrollToPage(2) + } + }, changeToBubbleInputMode = { coroutineScope.launch { pagerState.scrollToPage(0) diff --git a/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt b/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt index d1d42ac05..7d25b1d1c 100644 --- a/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt +++ b/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt @@ -36,7 +36,7 @@ import com.umc.edison.ui.theme.White000 import kotlin.math.roundToInt @Composable -fun BubbleStorageOnboarding( +fun EdisonNavBarOnboarding( onboardingState: BubbleStorageOnboardingState, onDismiss: () -> Unit, ) { diff --git a/app/src/main/java/com/umc/edison/ui/onboarding/LabelListOnboardingScreen.kt b/app/src/main/java/com/umc/edison/ui/onboarding/LabelListOnboardingScreen.kt index 0091ad28a..9a55124ca 100644 --- a/app/src/main/java/com/umc/edison/ui/onboarding/LabelListOnboardingScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/onboarding/LabelListOnboardingScreen.kt @@ -113,12 +113,16 @@ fun LabelListOnboardingScreen( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { - val context = LocalContext.current + val imageRequest = ImageRequest.Builder(LocalContext.current) + .data(R.drawable.ic_up_slide) + .build() AsyncImage( - model = ImageRequest.Builder(context).data(R.drawable.ic_up_slide).build(), + model = imageRequest, contentDescription = "Slide Up Icon", - modifier = Modifier.rotate(-90f).size(44.dp) + modifier = Modifier + .rotate(-90f) + .size(44.dp) ) Spacer(modifier = Modifier.width(12.dp)) diff --git a/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt b/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt index fb2dda6c4..2614749e6 100644 --- a/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt @@ -39,7 +39,8 @@ import com.umc.edison.ui.theme.White000 import kotlin.math.roundToInt internal enum class MyEdisonOnboardingPage { - MY_EDISON_BOTTOM_TAB, BUBBLE_INPUT, BUBBLE_STORAGE, SPACE_BOTTOM_TAB, BUBBLE_BOTTOM_TAB, ART_LETTER_BOTTOM_TAB, MY_PAGE_BOTTOM_TAB, + MY_EDISON_BOTTOM_TAB, BUBBLE_INPUT, BUBBLE_STORAGE, BUBBLE_LABEL, + SPACE_BOTTOM_TAB, BUBBLE_BOTTOM_TAB, ART_LETTER_BOTTOM_TAB, MY_PAGE_BOTTOM_TAB, } @Composable @@ -47,6 +48,7 @@ fun MyEdisonOnboarding( onboardingState: MyEdisonOnboardingState, bottomNavBarBounds: List, changeToStorageMode: () -> Unit, + changeToLabelMode: () -> Unit, changeToBubbleInputMode: () -> Unit, onDismiss: () -> Unit, ) { @@ -78,20 +80,33 @@ fun MyEdisonOnboarding( } MyEdisonOnboardingPage.BUBBLE_STORAGE -> { - BubbleStorageOnboarding( + EdisonNavBarOnboarding( edisonNavBarComponent = onboardingState.myEdisonNavBarBounds[1], + onNextPage = { + currentPage = MyEdisonOnboardingPage.BUBBLE_LABEL + changeToLabelMode() + }, + statusBarHeightPx = statusBarHeightPx, + text = "일주일 간 작성한 버블을 모아볼 수 있어요." + ) + } + + MyEdisonOnboardingPage.BUBBLE_LABEL -> { + EdisonNavBarOnboarding( + edisonNavBarComponent = onboardingState.myEdisonNavBarBounds[2], onNextPage = { currentPage = MyEdisonOnboardingPage.SPACE_BOTTOM_TAB changeToBubbleInputMode() }, - statusBarHeightPx = statusBarHeightPx + statusBarHeightPx = statusBarHeightPx, + text = "라벨별로 버블을 모아볼 수 있어요." ) } MyEdisonOnboardingPage.SPACE_BOTTOM_TAB -> { BottomTabOnboarding( bottomTabComponent = bottomNavBarBounds[1], - description = "작성한 모든 버블들을 맵 형태로 확인해요.\n" + "라벨별 모아보기도 가능해요.", + description = "모든 버블을 맵 형태로 확인해요.\n" + "키워드 맵핑으로 지금 필요한 아이디어를 찾아보세요.", onNextPage = { currentPage = MyEdisonOnboardingPage.BUBBLE_BOTTOM_TAB }, statusBarHeightPx = statusBarHeightPx ) @@ -297,10 +312,11 @@ fun BubbleInputOnboarding( } @Composable -fun BubbleStorageOnboarding( +fun EdisonNavBarOnboarding( edisonNavBarComponent: OnboardingPositionState, onNextPage: () -> Unit, statusBarHeightPx: Int, + text: String, ) { val density = LocalDensity.current @@ -363,7 +379,7 @@ fun BubbleStorageOnboarding( .background(color = White000, shape = RoundedCornerShape(16)) ) { Text( - text = "작성한 버블은 이렇게 저장돼요!", + text = text, modifier = Modifier .padding(16.dp) .align(Alignment.Center), From 675da77a8a7261f6f185108a0337f8aa9847d9ad Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Sat, 22 Nov 2025 19:23:36 +0900 Subject: [PATCH 03/15] =?UTF-8?q?:sparkles:=20Feature(#127):=20=EC=8A=A4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=B7=B0=20=ED=94=84=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../umc/edison/ui/space/BubbleGraphScreen.kt | 249 ++++++------------ 1 file changed, 80 insertions(+), 169 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt b/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt index f4d820d2c..96b3277b3 100644 --- a/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt @@ -5,33 +5,15 @@ import android.graphics.BlurMaskFilter import android.graphics.LinearGradient import android.graphics.Paint import android.graphics.Shader -import androidx.compose.animation.animateContentSize -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.tween import androidx.compose.foundation.Canvas -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTransformGestures -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -42,8 +24,6 @@ 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.clip -import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color @@ -51,47 +31,31 @@ import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.drawIntoCanvas import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.graphics.lerp import androidx.compose.ui.graphics.nativeCanvas import androidx.compose.ui.graphics.toArgb +import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource -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.unit.Dp -import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import kotlin.math.sqrt import androidx.hilt.navigation.compose.hiltViewModel import com.umc.edison.R import com.umc.edison.presentation.model.BubbleModel -import com.umc.edison.presentation.model.KeywordBubbleModel import com.umc.edison.presentation.model.getDisplayTitle import com.umc.edison.presentation.space.BubbleGraphViewModel -import com.umc.edison.presentation.space.KeywordViewModel -import com.umc.edison.ui.components.BubblePreview -import com.umc.edison.ui.components.BubbleType -import com.umc.edison.ui.components.calculateBubblePreviewSize -import com.umc.edison.ui.components.extractPlainText import com.umc.edison.ui.theme.Gray100 import com.umc.edison.ui.theme.Gray300 -import com.umc.edison.ui.theme.Gray400 import com.umc.edison.ui.theme.Gray500 import com.umc.edison.ui.theme.Gray800 -import com.umc.edison.ui.theme.Gray900 -import kotlinx.coroutines.launch import kotlin.math.cos -import kotlin.math.min -import kotlin.math.roundToInt import kotlin.math.sin -import kotlin.random.Random @SuppressLint("UnusedBoxWithConstraintsScope") @Composable fun BubbleGraphScreen( - onShowKeywordMap :()->Unit, + onShowKeywordMap: () -> Unit, showBubble: (BubbleModel) -> Unit, viewModel: BubbleGraphViewModel = hiltViewModel(), ) { @@ -130,146 +94,98 @@ fun BubbleGraphScreen( } } - if (scale < 1.6f) { - Canvas( - modifier = Modifier - .fillMaxSize() - .graphicsLayer( - scaleX = scale, - scaleY = scale, - translationX = offset.x, - translationY = offset.y, - transformOrigin = TransformOrigin(0f, 0f) - ) - ) { - // 클러스터 구름 그리기 - uiState.clusters.forEach { cluster -> - if (cluster.colors.size <= 2) { - drawGradientBlurCircle( - center = cluster.position, - radius = cluster.radius, - colors = cluster.colors, - blurRadius = blurRadius, - ) - } else { - drawOverlappingBlurCircles( - center = cluster.position, - bigRadius = cluster.radius, - colors = cluster.colors, - blurRadius = blurRadius, - ) - } - } + Canvas( + modifier = Modifier + .fillMaxSize() + .graphicsLayer( + scaleX = scale, + scaleY = scale, + translationX = offset.x, + translationY = offset.y, + transformOrigin = TransformOrigin(0f, 0f), + ) + .pointerInput(uiState.bubbles, scale, offset) { + detectTapGestures { tapOffset -> + val transformedOffset = (tapOffset - offset) / scale - // 연결선 그리기 - uiState.edges.forEach { edge -> - val start = - uiState.bubbles.find { it.bubble.id == edge.startBubbleId }?.position - ?: Offset.Zero - val end = uiState.bubbles.find { it.bubble.id == edge.endBubbleId }?.position - ?: Offset.Zero - drawLine(color = Gray500, start = start, end = end, strokeWidth = 1.dp.toPx()) - } + val radius = 12f + uiState.bubbles.forEach { positionedBubble -> + val distance = sqrt( + (transformedOffset.x - positionedBubble.position.x) * (transformedOffset.x - positionedBubble.position.x) + + (transformedOffset.y - positionedBubble.position.y) * (transformedOffset.y - positionedBubble.position.y) + ) - // 버블 점 그리기 - val radius = 12f - uiState.bubbles.forEach { positionedBubble -> - val colors: List = positionedBubble.bubble.labels.map { it.color } - if (colors.size <= 1) { - drawCircle( - color = colors.firstOrNull() ?: Gray500, - radius = radius, - center = positionedBubble.position - ) - } else { - drawCircle( - brush = Brush.linearGradient( - colors, - start = positionedBubble.position - Offset(radius * 2, 0f), - end = positionedBubble.position + Offset(radius * 2, 0f), - ), - radius = radius, - center = positionedBubble.position - ) - } - drawContext.canvas.nativeCanvas.drawText( - positionedBubble.bubble.getDisplayTitle(), - positionedBubble.position.x, - positionedBubble.position.y + radius.dp.toPx() + 10.dp.toPx(), - Paint().apply { - color = Gray800.toArgb() - textSize = 35f - textAlign = Paint.Align.CENTER + if (distance <= radius) { + showBubble(positionedBubble.bubble) + return@detectTapGestures + } } + } + } + ) { + // 클러스터 구름 그리기 + uiState.clusters.forEach { cluster -> + if (cluster.colors.size <= 2) { + drawGradientBlurCircle( + center = cluster.position, + radius = cluster.radius, + colors = cluster.colors, + blurRadius = blurRadius, + ) + } else { + drawOverlappingBlurCircles( + center = cluster.position, + bigRadius = cluster.radius, + colors = cluster.colors, + blurRadius = blurRadius, ) } } - } else { - Canvas( - modifier = Modifier - .fillMaxSize() - ) { - // 클러스터 구름 그리기 - uiState.clusters.forEach { cluster -> - if (cluster.colors.size <= 2) { - drawGradientBlurCircle( - center = cluster.position * scale + offset, - radius = cluster.radius * scale, - colors = cluster.colors, - blurRadius = blurRadius, - ) - } else { - drawOverlappingBlurCircles( - center = cluster.position * scale + offset, - bigRadius = cluster.radius * scale, - colors = cluster.colors, - blurRadius = blurRadius, - ) - } - } - uiState.edges.forEach { edge -> - val startBubble = uiState.bubbles.find { it.bubble.id == edge.startBubbleId } - val endBubble = uiState.bubbles.find { it.bubble.id == edge.endBubbleId } - if (startBubble != null && endBubble != null) { - val start = startBubble.position * scale + offset - val end = endBubble.position * scale + offset - drawLine( - color = Gray500, - start = start, - end = end, - strokeWidth = 1.dp.toPx() - ) - } - } + // 연결선 그리기 + uiState.edges.forEach { edge -> + val start = + uiState.bubbles.find { it.bubble.id == edge.startBubbleId }?.position + ?: Offset.Zero + val end = uiState.bubbles.find { it.bubble.id == edge.endBubbleId }?.position + ?: Offset.Zero + drawLine(color = Gray500, start = start, end = end, strokeWidth = 1.dp.toPx()) } + // 버블 점 그리기 + val radius = 12f uiState.bubbles.forEach { positionedBubble -> - val screenPosition = positionedBubble.position * scale + offset - val previewSize = calculateBubblePreviewSize(positionedBubble.bubble) - Box( - modifier = Modifier - .offset { - IntOffset( - x = screenPosition.x.roundToInt() - (previewSize.size.roundToPx() / 2), - y = screenPosition.y.roundToInt() - (previewSize.size.roundToPx() / 2) - ) - } - .animateContentSize() - ) { - BubblePreview( - bubble = positionedBubble.bubble, - size = previewSize, - onClick = { - showBubble(positionedBubble.bubble) - }, + val colors: List = positionedBubble.bubble.labels.map { it.color } + if (colors.size <= 1) { + drawCircle( + color = colors.firstOrNull() ?: Gray500, + radius = radius, + center = positionedBubble.position + ) + } else { + drawCircle( + brush = Brush.linearGradient( + colors, + start = positionedBubble.position - Offset(radius * 2, 0f), + end = positionedBubble.position + Offset(radius * 2, 0f), + ), + radius = radius, + center = positionedBubble.position ) } + drawContext.canvas.nativeCanvas.drawText( + positionedBubble.bubble.getDisplayTitle(), + positionedBubble.position.x, + positionedBubble.position.y + radius.dp.toPx() + 10.dp.toPx(), + Paint().apply { + color = Gray800.toArgb() + textSize = 35f + textAlign = Paint.Align.CENTER + } + ) } - } - FloatingActionButton( onClick = onShowKeywordMap, modifier = Modifier @@ -285,11 +201,7 @@ fun BubbleGraphScreen( tint = Color.Unspecified ) } - } - - - } private fun DrawScope.drawGradientBlurCircle( @@ -359,4 +271,3 @@ private fun DrawScope.drawOverlappingBlurCircles( ) } } - From b88af58c0df3abdb57c5d11f7df8f2e3a3399aa6 Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Mon, 1 Dec 2025 01:02:48 +0900 Subject: [PATCH 04/15] =?UTF-8?q?:art:=20Feature(#127):=20=ED=95=98?= =?UTF-8?q?=EB=93=9C=20=EC=BD=94=EB=94=A9=EB=90=9C=20=EA=B0=92=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../umc/edison/presentation/label/LabelListViewModel.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt b/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt index f6a5f54db..4b802ddba 100644 --- a/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt +++ b/app/src/main/java/com/umc/edison/presentation/label/LabelListViewModel.kt @@ -45,6 +45,8 @@ class LabelListViewModel @Inject constructor( companion object { const val SCREEN_NAME = "label_list" const val TEMP_LABEL_ID = "-1" + private const val ONBOARDING_TEMP_LABEL_NAME = "감상" + private const val ONBOARDING_TEMP_LABEL_BUBBLE_COUNT = 7 } init { @@ -229,7 +231,12 @@ class LabelListViewModel @Inject constructor( val hasAdditionalLabels = currentLabels.any { !it.id.isNullOrEmpty() } if (!hasAdditionalLabels) { - val tempLabel = LabelModel(id = TEMP_LABEL_ID, name = "감상", color = Aqua100, bubbleCnt = 7) + val tempLabel = LabelModel( + id = TEMP_LABEL_ID, + name = ONBOARDING_TEMP_LABEL_NAME, + color = Aqua100, + bubbleCnt = ONBOARDING_TEMP_LABEL_BUBBLE_COUNT + ) _uiState.update { it.copy(labels = it.labels + listOf(tempLabel)) } } From 300f225671f044685cbd7635608fc62271e9b60a Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Mon, 1 Dec 2025 01:06:02 +0900 Subject: [PATCH 05/15] =?UTF-8?q?:art:=20Feature(#127):=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../umc/edison/ui/edison/MyEdisonScreen.kt | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt b/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt index 6f4d906bc..4e51d4393 100644 --- a/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt @@ -119,19 +119,9 @@ fun MyEdisonScreen( 1 -> { if (onboardingState.show) { - val imageRequest = ImageRequest.Builder(LocalContext.current) - .data(R.drawable.bubble_ex) - .crossfade(true) - .build() - - AsyncImage( - model = imageRequest, + OnboardingImagePlaceholder( contentDescription = "Bubble Example", - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight(), - alignment = Alignment.Center, - contentScale = ContentScale.Crop, + data = R.drawable.bubble_ex, ) } else { BubbleStorageScreen( @@ -147,21 +137,10 @@ fun MyEdisonScreen( 2 -> { if (onboardingState.show) { - val imageRequest = ImageRequest.Builder(LocalContext.current) - .data(R.drawable.bubble_ex) - .crossfade(true) - .build() - - AsyncImage( - model = imageRequest, + OnboardingImagePlaceholder( contentDescription = "Label Example", - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight(), - alignment = Alignment.Center, - contentScale = ContentScale.Crop, + data = R.drawable.bubble_ex, ) - } else { LabelTabScreen( navHostController = navController, ) @@ -234,3 +213,24 @@ fun MyEdisonScreen( ) } } + +@Composable +private fun OnboardingImagePlaceholder( + contentDescription: String, + data: Any, +) { + val imageRequest = ImageRequest.Builder(LocalContext.current) + .data(data) + .crossfade(true) + .build() + + AsyncImage( + model = imageRequest, + contentDescription = contentDescription, + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), + alignment = Alignment.Center, + contentScale = ContentScale.Crop, + ) +} \ No newline at end of file From b9edbe208a2bbd4ba3b03521917914369e011eb5 Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Mon, 1 Dec 2025 01:10:53 +0900 Subject: [PATCH 06/15] =?UTF-8?q?:art:=20Feature(#127):=20sqrt=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/umc/edison/ui/components/BubbleLayout.kt | 5 ++--- .../java/com/umc/edison/ui/space/BubbleGraphScreen.kt | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/components/BubbleLayout.kt b/app/src/main/java/com/umc/edison/ui/components/BubbleLayout.kt index 4d8c98244..30a1c33e0 100644 --- a/app/src/main/java/com/umc/edison/ui/components/BubbleLayout.kt +++ b/app/src/main/java/com/umc/edison/ui/components/BubbleLayout.kt @@ -33,7 +33,6 @@ import androidx.compose.ui.unit.min import com.umc.edison.presentation.model.BubbleModel import com.umc.edison.ui.theme.White000 import kotlinx.coroutines.android.awaitFrame -import kotlin.math.sqrt import kotlin.random.Random @SuppressLint("ConfigurationScreenWidthHeight") @@ -182,9 +181,9 @@ fun calculateGridOffset( fun isOverlapping(b1: PlacedBubble, b2: PlacedBubble): Boolean { val dx = (b1.x.value + b1.size.value / 2) - (b2.x.value + b2.size.value / 2) val dy = (b1.y.value + b1.size.value / 2) - (b2.y.value + b2.size.value / 2) - val distance = sqrt(dx * dx + dy * dy) + val distance = dx * dx + dy * dy val threshold = (b1.size.value + b2.size.value) / 2 + 4.dp.value - return distance < threshold + return distance < threshold * threshold } data class PlacedBubble(val x: Dp, val y: Dp, val size: Dp) diff --git a/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt b/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt index 96b3277b3..704c15ce2 100644 --- a/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/space/BubbleGraphScreen.kt @@ -39,7 +39,6 @@ import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import kotlin.math.sqrt import androidx.hilt.navigation.compose.hiltViewModel import com.umc.edison.R import com.umc.edison.presentation.model.BubbleModel @@ -110,12 +109,11 @@ fun BubbleGraphScreen( val radius = 12f uiState.bubbles.forEach { positionedBubble -> - val distance = sqrt( - (transformedOffset.x - positionedBubble.position.x) * (transformedOffset.x - positionedBubble.position.x) + - (transformedOffset.y - positionedBubble.position.y) * (transformedOffset.y - positionedBubble.position.y) - ) + val dx = transformedOffset.x - positionedBubble.position.x + val dy = transformedOffset.y - positionedBubble.position.y + val distanceSquared = dx * dx + dy * dy - if (distance <= radius) { + if (distanceSquared <= radius * radius) { showBubble(positionedBubble.bubble) return@detectTapGestures } From 861dd924fb09f0cae4678f69c010139981f40799 Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Mon, 1 Dec 2025 01:16:38 +0900 Subject: [PATCH 07/15] =?UTF-8?q?:truck:=20Rename(#127):=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=ED=95=A8=EC=88=98=20=EB=AA=85=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt | 4 ++-- .../com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt | 2 +- .../com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index db0413284..a4da79935 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -39,7 +39,7 @@ import com.umc.edison.ui.components.BubblesLayout import com.umc.edison.ui.components.LabelTagList import com.umc.edison.ui.components.calculateBubbleSize import com.umc.edison.ui.navigation.NavRoute -import com.umc.edison.ui.onboarding.EdisonNavBarOnboarding +import com.umc.edison.ui.onboarding.BubbleSpaceOnboarding import com.umc.edison.ui.theme.Gray300 import com.umc.edison.ui.theme.Gray800 import com.umc.edison.ui.theme.Gray900 @@ -284,7 +284,7 @@ fun BubbleStorageScreen( } if (!onboardingState.edisonOnboardingShow && onboardingState.show && uiState.bubbles.isNotEmpty()) { - EdisonNavBarOnboarding( + BubbleSpaceOnboarding( onboardingState = onboardingState, onDismiss = { viewModel.setHasSeenOnboarding() diff --git a/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt b/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt index 7d25b1d1c..75eb246c3 100644 --- a/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt +++ b/app/src/main/java/com/umc/edison/ui/onboarding/BubbleStorageOnboarding.kt @@ -36,7 +36,7 @@ import com.umc.edison.ui.theme.White000 import kotlin.math.roundToInt @Composable -fun EdisonNavBarOnboarding( +fun BubbleSpaceOnboarding( onboardingState: BubbleStorageOnboardingState, onDismiss: () -> Unit, ) { diff --git a/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt b/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt index 2614749e6..bf310cb07 100644 --- a/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt @@ -312,7 +312,7 @@ fun BubbleInputOnboarding( } @Composable -fun EdisonNavBarOnboarding( +private fun EdisonNavBarOnboarding( edisonNavBarComponent: OnboardingPositionState, onNextPage: () -> Unit, statusBarHeightPx: Int, From 05646c3c4a4c5922c0ca167fb20380480e9d35a8 Mon Sep 17 00:00:00 2001 From: OSSU <90602694+SuHyeon00@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:19:13 +0900 Subject: [PATCH 08/15] :recycle: Refactor(#127): string formatting Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt b/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt index bf310cb07..5af6d7954 100644 --- a/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/onboarding/MyEdisonOnboardingScreen.kt @@ -106,7 +106,7 @@ fun MyEdisonOnboarding( MyEdisonOnboardingPage.SPACE_BOTTOM_TAB -> { BottomTabOnboarding( bottomTabComponent = bottomNavBarBounds[1], - description = "모든 버블을 맵 형태로 확인해요.\n" + "키워드 맵핑으로 지금 필요한 아이디어를 찾아보세요.", + description = "모든 버블을 맵 형태로 확인해요.\n키워드 맵핑으로 지금 필요한 아이디어를 찾아보세요.", onNextPage = { currentPage = MyEdisonOnboardingPage.BUBBLE_BOTTOM_TAB }, statusBarHeightPx = statusBarHeightPx ) From 6a6e3af92bd6a42572c6f907fe901e85d232442a Mon Sep 17 00:00:00 2001 From: SuHyeon00 Date: Mon, 1 Dec 2025 01:23:09 +0900 Subject: [PATCH 09/15] =?UTF-8?q?:bug:=20Fix(#127):=20LabelTabScreen=20?= =?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=BB=A8=EB=94=94=EC=85=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt b/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt index 4e51d4393..98f8a2741 100644 --- a/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/edison/MyEdisonScreen.kt @@ -141,6 +141,7 @@ fun MyEdisonScreen( contentDescription = "Label Example", data = R.drawable.bubble_ex, ) + } else { LabelTabScreen( navHostController = navController, ) From 64d798427bbd91f6c215884a5fc315c889a29971 Mon Sep 17 00:00:00 2001 From: JaeminHwang49 Date: Sat, 13 Dec 2025 19:11:11 +0900 Subject: [PATCH 10/15] =?UTF-8?q?Feature(#132):=20MyEdisonNav=20=EB=9D=BC?= =?UTF-8?q?=EB=B2=A8=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/ic_label-playstore.png | Bin 0 -> 7459 bytes app/src/main/res/drawable/ic_label.xml | 21 +++--------------- .../main/res/mipmap-anydpi-v26/ic_label.xml | 5 +++++ .../res/mipmap-anydpi-v26/ic_label_round.xml | 5 +++++ app/src/main/res/mipmap-hdpi/ic_label.webp | Bin 0 -> 1512 bytes .../res/mipmap-hdpi/ic_label_foreground.webp | Bin 0 -> 1368 bytes .../main/res/mipmap-hdpi/ic_label_round.webp | Bin 0 -> 2566 bytes app/src/main/res/mipmap-mdpi/ic_label.webp | Bin 0 -> 1176 bytes .../res/mipmap-mdpi/ic_label_foreground.webp | Bin 0 -> 628 bytes .../main/res/mipmap-mdpi/ic_label_round.webp | Bin 0 -> 1646 bytes app/src/main/res/mipmap-xhdpi/ic_label.webp | Bin 0 -> 1568 bytes .../res/mipmap-xhdpi/ic_label_foreground.webp | Bin 0 -> 680 bytes .../main/res/mipmap-xhdpi/ic_label_round.webp | Bin 0 -> 3364 bytes app/src/main/res/mipmap-xxhdpi/ic_label.webp | Bin 0 -> 1830 bytes .../mipmap-xxhdpi/ic_label_foreground.webp | Bin 0 -> 702 bytes .../res/mipmap-xxhdpi/ic_label_round.webp | Bin 0 -> 4706 bytes app/src/main/res/mipmap-xxxhdpi/ic_label.webp | Bin 0 -> 2062 bytes .../mipmap-xxxhdpi/ic_label_foreground.webp | Bin 0 -> 788 bytes .../res/mipmap-xxxhdpi/ic_label_round.webp | Bin 0 -> 6714 bytes 19 files changed, 13 insertions(+), 18 deletions(-) create mode 100644 app/src/main/ic_label-playstore.png create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_label.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_label_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_label.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_label_foreground.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_label_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_label.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_label_foreground.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_label_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_label.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_label_foreground.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_label_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_label.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_label_foreground.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_label_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_label.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_label_foreground.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_label_round.webp diff --git a/app/src/main/ic_label-playstore.png b/app/src/main/ic_label-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5e38941ed5709fa496621192a80a34548aa7aa GIT binary patch literal 7459 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 j - - - - - + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_label.xml b/app/src/main/res/mipmap-anydpi-v26/ic_label.xml new file mode 100644 index 000000000..438ab2867 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_label.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_label_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_label_round.xml new file mode 100644 index 000000000..438ab2867 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_label_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-hdpi/ic_label.webp b/app/src/main/res/mipmap-hdpi/ic_label.webp new file mode 100644 index 0000000000000000000000000000000000000000..1671a8e86350f8ae33ad199458c78957348c43c3 GIT binary patch literal 1512 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 aICZAFd?gU))hN~iJEj8T)M%KwPa^_RU63XK literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_label_round.webp b/app/src/main/res/mipmap-hdpi/ic_label_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..bec242e4f612a689b03c840f68c06a6eb16e677e GIT binary patch literal 2566 zcmV+h3i<|BMM6+kP&iET2><{uN5Byf716%-|B&STV%xT}98Xsd*0yc$ z#>v{=O>$-1w(YFFJL<04IE zQM<9(v8~D?>baR*K#C;Ekrez<9fA8E0`=5#IwDs>BuS1W#Z^Yko_I~=2|ToiF2S~K z(~c_ty^r8KD%-Yg+qP}nU9fH2>OySW$-Cz+2X5O&lGLD?c4lwy?i+xrl^{f@1U3x? z0T@)M1V*JhOal;TsA3QppLI~ zDh*Cy5Xy0v;P(9K_W*<{w4G58prZB1>k4i~949GC6sdG>rd(Bib2h#A-cF{SRh(3u zO*yNoyRwt_vY@$hpJAeFfC~~fbwT9B|;J|36jV= z2*jF}H^s8@hP*wrgXVzvZ@ZBqh4^a+Q0}!Aw`xvdTHSdBakBv{Z#8!3wgQ-eonpE0 z+pDx!oTR+8wDw$#{*)t+WXUP-ES8sduLHf}r8G_j{CYaMA5*wGOH0&Yu}+p{v6*6b z=uBZ$0XH`mw;E1+RVrajtxQp5Pm(KNsUW>LE0*KH0Zh`p^4csQQu&JBX4A>YvOIURA2n`LsqbPj6z=#-I`v%*nMf0 zeMsTuWxwIDq1MaGu0!+2Y}{J}As$f$+>Tp_N;>D9?8(9pk=hNGBu$bf`IC{2k(FVK zp_3oJ`YKkUG33p{I;?iPJXkV7S>Br|tx8gq5OCy?Uy;1a(2YKlbjk2V8N*n_n8~L2aiLLCTSj^O z*OOTdWA(Cz1|^ln zMpU%efVXW#(IH^aK6W`>;&k+cFlkcUFn+5+A?1!?6fIbjcbvKjRkYTMK$OA?Bt;2v z2r1x0z%UMN_Tdw?!hC!*LQt=s=3IKu3eK&BrV#EktTKW!Sz5~oaxTB{9nP&s5JHMLZe09O^hRRG zuSt@m$!DExmdj9qQWdGQuKu?u`6(cP!9_5ExLG5 z?$pYZCaMrJN-@hz#785jR}Ti`z1e8jN*BnWvapvIqm=9^%gC#(njxUg$XRt{TGbD+ zOqwFKzNA%Ufi7xt{L?nStBRS#NFBJrAR&_tdQ?eA0yc( ztI9dWd&+x(4p2{kpin>Yb-B!PEc;g6DG-;>@}c@n=wNr zwFm(fB7*S1?iXuflD?9yhEDawlkO839F=o3%@&;qr zbwq63c%vjKmil&Rcjg$?_ru%>%+Q{HQ5U^-B894kRMsni-h0&;2UG1ujda*KG6K<$C=Ss$Z0` z=1&CmQ-c$<$O`6dzIbNK8Z=Kg-k7PVtnt_29?#-Nk8JU61Ara0bpRKF2Ijpz_g5)(%MC=OO2wDW{-bZMJy3N{>z7U>x;(ukABwz=RO!7h)f*4Djn8uaaH%zpJPy-!q zOr7Q7Wvb7L;IYBMgP>8AZbiH)KZb9Lt`KV0j3ueNwFnvq=Z{Auf#|?5AA)8PxXsy9 zeyoW#=n0`DJyFN=%(UJ1doh0c$rQlpzQDh1h*%YCmU`JYi>D!k8n?zxU1ce@waeOk z5I7xx+^~cog66WAk~oukO~N$6I-wzi((VuICs;{gV|p!1z6VuBcG&PEfS_r!&^y)c zL)Zpi6Kk4s2tUP*QpWJ^Q;X2&CmVhQ$QOWU23`aW5p*)=PFrjxScj^ifV$I9Qzd!y z9D>db>x%$Xh8cu)1oaWL=^DnS=w4Yjym`|;WW%$&VkyrjiWbAP*ETQ?L7V>;6@j7% z%&sAbpb3JG9mI0q+jpx@UgYJSnD)V%_J}g3%bVzM6Wq`jRT(9}C)!rlUBmK&;D10} zv0Vsj6JijwK+vU=SmeulV6n@w?Z6s5Z!(!=O}5=nCOYOjzj$(XgGQM*h(*_Q10(xz5 z=B1z2{snu--#Iu>2l_qzn73MlK=TmY9K<51UwaJ%O@CUW_Q`EPtnY84Z9WKicL$Es cficC?5ts<{;N=f zgUq{o*?`+fk|QZ=mP_~4gZJNt_l9b(?cQ}Kgh;YoE3@YZFc3Xt?+8E+0y5mY1Gn0? z<;nd&@dV=1LFts7%z@41Q!oK7BQSznN5z{Dx91B0pa29^fC3Ou0tV_6koiRXk$HbB z-T@zn-#HzLBnIbW9QKkpL zjQE?(FbTjGRDlbAxZ!O5QH4^2XqMK5D^SS$S*KS!qP=GyZbT5d|qcx+C>%B z-9NsU|1b7GzTS^|t*dqckwj~?1pu{6yVymwpoAE9>f)=OJ1cWEr^%V-|MUN2OX1X_ zN^2t;QLU-9ai*QxefDwuYF8jCsu8Kwf&ikRBBC16>5YmlfJIf(&iL=~-&Ij*ms889 zs;d?VBJB-e8;RC}L95dR#1;Y6q7>RCkWOoD7e%2KEecwbB7oZp1PM{DetlUf}1UAwv->)VG*=iL1A%ip!R9vfSN~pL@0w$pBE-M)d$*lQ=VEOy;~Q}Mdi{s|0RWAudAYBf?Je8xd#$@x zvu#wfZExAOZQJ&t*|zl$+}%U9-y`}z0pNeh8KFX(gZ7UBgOFhm7yz6c=TUZa0)Ub7 z4>-?vm`mMZfiqwvF<>DV4#p)ik~mVrv~nsXsWjlsEDb6%{CYl+za^F-F17X>HR>kMsvGa)`8d89d3hA$c_yWuTc_QP46qq_?G%dO9L57?>k{`9!HId9)#9k$(LS zZlh7+>#Ayjv3cd$MjFXybgUqbH9YD~tRz{-7(xQ8jwIF->8bKPV{Ac$9d|aLNJp}( z4wQ&zs(QqWKvBeKRVyMkkcDu~k^Fj$?uMWXh87UvhqSHMVo>#LB1T>EG6N``J#;|Gav?mv0<{N;=1 qPaofV_x=Ow$2&^$43N&`DkxG{$YlWX$iLG691#EW=P&L^@V^9vo;}_G literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_label_foreground.webp b/app/src/main/res/mipmap-mdpi/ic_label_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..5e4c45a6a2d468fe9b6ae11ea08e9809ee3a318e GIT binary patch literal 628 zcmV-)0*n1pNk&F&0ssJ4MM6+kP&iCq0ssInYrq;1zriSyBt^M<=^~ zJ80-H03$fmZmpw^AaGN?(QX2B2U881`fd4wbV9I3@L3X@8y!KUDqBY_^%Xt}&$G@T zcik1HrdCt7@KJu=H8<=-jP5m&qN*>DyW$E^QQZp9U-Uj{a)`TtmU-IxaocH1UEN}qO)VluL*4GSxxYTmfYpuq)HZ%huY89-+T6zN4`tyH% OdvK&J{kCd?paB55q$~CS literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_label_round.webp b/app/src/main/res/mipmap-mdpi/ic_label_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..649dce4091e84e03db51f81115d3bd026d40178a GIT binary patch literal 1646 zcmV-!29fzvNk&Fy1^@t8MM6+kP&iCl1^@srFTe{B^-!Ar|Bxj8&vTwxoosunD|2nz zw(Zk+*0yci-nQ+`to6Q$j;PG4%B)xLTmA=CvCXQ;h;f^F8r!yQ8^1Q-Mv`P%DgUj) z0n}#$9|?`yt?CD%Z6rZ*IMc7j6Vz!LX?2BLrb;>+_F#q*QY za^i9jRSOjl{q&G-xQ!d`JIec>@ao|0o#6LN-?2@5P5-A#*+3_N)GNFc~e};TPhE$oZ95b6nzs> zrYW|AQnrtc-IftB6EN)o+Ef{g2Kdp6`I?GHzC<|cHb3Lbg@Y>0^YZO%=oJT;AJ>^e63+P<%P~H>5VR)ac~g?`$>Na4!0R3L9JeU51|H|264_3D zt9-dz0i8xeXq~_nV)(3K>JN&mo}D@xrbg)VZjY&CPIOoaAALnY19%mDqi&A;n^cV9 zvktCGz}0mF1OdFqZ_LfTw>6dhQ`%XL;NH8t{z(M*@FC@f`8hk4T8+@&mq!kn0GByuHoCfhspLbT{xW?Hj-bPUGeVvCCfUW)ra+waRadqR4lpw>; zTt`AU009r(_QFc+x#8&lvPziY?xqNMLqX{-+Zj2?jM)3d3eNca-bDg#>UrQsz`T98 ziZV?#wZd@LRmmfThbh5S;}_k=sowm%9Sc_2ke91(->9aX{gQ#>7sQwtjNsn)>!<|2 z0?i2oe0SYFqHL!tW%tREjqEp-AB;5qsN>i6lt2JDp(bdh+jOg$M$@KBrwy!IEQm6= zQU+7Y9$OnrRe(ZR2jXeGd}|ykMWbXD4h^noN#t3~aOj5qXut z9Ukot&R5O6=l>=UeO`B|*M3bjdEvW4N$=UgSPdqPUw(I0{o85oJ3_#XK+=`(ckQ?a z+h99GR`}jj7IYKmHhw#A5J(=s*!*`Yg+R(#?_EA?GJ@^&rZU3UYS~1t)U@0VFY8qT zsVS9U-pUjLiD&N)?$`cOwkdm4i{VQfHf=Bl>fZ<5q2U%QK;ahPt}?9utTv}_u#I+h zt*N>2xtf~CAN9fUk;a#9?t*SmZNFH~cl^~C?gWAeWNo(FwbRb7@1PEczKO)W?&Opv zbxJ~)q~&4<*Q@=0Z#RMLzOTM;cY-V*0k;$ak<}n~)7_@+x2L=2*Xd={;cy(ET$p@Y z^o%Y>2h`V3-P7B5n`&HgCmZj#T%8RGcoB#okWn2QH`{I9rd{2kP3_`2c6s|o=Y2f3 zK3?G7e4~y}b?S|}de_`~7&H>dtQa}7CRh~xxqJm00XG8v6$BCqWL1Owb+LLIsM!~5 sbWmNL@>>tD$R*%r{LfLSa}Ust1^4#jM-uQM;5YdHk>gW4Ra)K&03gRcc>n+a literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_label.webp b/app/src/main/res/mipmap-xhdpi/ic_label.webp new file mode 100644 index 0000000000000000000000000000000000000000..e1d5effbf60ab235a083985440493f01f5de2688 GIT binary patch literal 1568 zcmV+*2H*KoNk&E(1^@t8MM6+kP&iBs1^@srU%(d-wT6PWZ6t?3?Cl;15itQSYYACf z8vXX#zF_=EM2;2YTHB^b${%m+?(XiMx$lw@ZiGgJT!Xt4Y3S|_kz4)Mhx>4-YO2ua zUw7Zy@i~whNs=TPe^kR~wco4Cqa-PkBuSFfDj8uh=XV$^gN0+;+Og;VUi`LgJ7$@c z3Fy;kvQnl`ohliPt;)9XewU5gHj=2B-EC9t^#fVkwx?~=e>N^Nw`1n53}a?y2po-> zcT{F(hTp=q)xarTPGmcBe8~-|`5FRAoA=K=4}!LBo0?wdjN7)61WZLUdvE_GW%4x0 z#%&`<+|XU9R)>26{b%hX@q-aP@}GbBmE=D2=rgA{*Tn3X0c7VT zhL?A9)@{|QTdQ8IdM2e|o7*|I0GN#AHFtHsJFp78fCU{I#@)el*Oa<6^b9}l4u`RR z_}M?+{%eq9ZurIS=r|!VGTwLdldSv2GO%E$j`AkR>o^2aT-89n5?n&?1GKOVT(t-JcHks}26TkhA6W4D#(WQN z+dclAp9c}2um8zm-D80*p$oQzRd`wtTaG#zAwW9qn*8pYEmhDJ-}TsPlpM3k5Mo0N zl8m|w#n2w3KOBQGqc{7`+yOCw9CIyuzQ(B_`(Z~gHk@b(T1RN|jGok$^+fH47(n;C zj#hfI&#%w*Q&r(>NLR2GG_65l-6s^ zpC6rQP+ADYZU-TLJIb-{2*Qdb(OqQuLKK9Q1dcX*qK!QP*@k2{nI;ku1YwI)evY@oCkRbBG!avN(&CWP2|jVn;qz5?^cQ271X#_FmswE^oaFs#FK18Xz5ddJW^3+jINHkIr zUW)%m;i1@dluI*|`iBZr%vkf)QEQ74go3yt;x|#0iNe`&=;)fGqgFO3{Thso7XUD0 z8`WuQ-WoS(+K8GxD6-+>^BqC~B7ei}cFf1QYxk&oxJ%;AGT91BYlX4N0sz(mpYJXm zFwOz;D=4Lmv8e(8R?&d;m52@(AngFc(?V4b!QpUB6|Wai0f3Kz@qQrviB$l`7ywuj zUC|(Z9g2;27Z63bAijq5HztcHA~kRP4~&ZqqDWp5#@qm4d9({5I_!sU2T(-#n~ay$ ziGtd~(I6OK0IEoush$)k#{IdtuJ{;U9Rh&>{|NKgF3r!yuA|QCLG)d#uV9S%M^fIS zyN{c$KCzFG(LBGQH@6*L!0o>-#)hxmJxunM0O)ZjiP{YZJXhA@`vuIhf>2?0B1s1G=p!@K8n>MK0 zK-4ybLiOTyPZ!BXyzsomnf79}(SbzkHy0q0IDjP+1d5eR?Ab1#TPJs3&kviAhwZ!f zM_sUHtl`Z^$=-*k^y{^?udi#X?JeoBY&d-P?aR4!va?w!VRA8%5Wt8ePJkulM|=@z z2ivihnd&x5r;$Z9j9l%>vzf>V$cs_P;mF2B8QCO^TspGD5#&2yG)Uuqptvw1b0z`^ zV2vXZLJlYaHK4A%@yQXdZ%*>ZtpnhIBZ5FI(HLS;#6<-XpPmjN{)48cr!n8*pD{x# S4wB9RP=Ku{&p+y*|4I?b8wh;> literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_label_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_label_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..f8729ad230381238bd5ce59d93ea1d319f4d140e GIT binary patch literal 680 zcmV;Z0$2S~Nk&GX0ssJ4MM6+kP&iDK0ssIn*T6LpzriSyBt^M<{=z2eZx@w|G%x_p-8eX zorj42Pk@T%6LxTcDQ2h(XSl*KcJK{V<&+iLI71!H6}C`DX<~{x`U$pB7J0!w>eBAx z3rZeuxI$eC6MREy;|){Pl{3LNlrUZ}MO|rE_=2)UA9Xap@PgL+9loOr?xR%EMjg!! z+6eyOJG$To$`dKZV1qWYdvuqeB+*74!429d|DZc=p$xIcur_GD-=e_}+@K4-)eNPF zH`GCI&<6T}y6`K8!cQnSbTE_++Mo>tld z4s?yGu-wqbTXBxDIiNuubPHt&PVrWpV+;;xPzRl$axOR2(GSislmi;n5p1D6!Cmx& zbM)ze26Y5`sJxUL?r@EMaE`Y+pg|qM1fNm1;2Ngr2Y=!b>54h(XeL-g<-Od%HB8Zu z_^+^rDrmWZ@34#I)x&30(UcpCw=u=|CHROc`f@|@HZCz9Q*5CsZMmU%4Ldl(C1zMG O!v`E-2WzM*=l^&1eoNB; literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_label_round.webp b/app/src/main/res/mipmap-xhdpi/ic_label_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..985d30752928f468d88f1afa8c7204fb9a9fbc8a GIT binary patch literal 3364 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_label.webp b/app/src/main/res/mipmap-xxhdpi/ic_label.webp new file mode 100644 index 0000000000000000000000000000000000000000..0b91c2a837be3722054331222b4ff57ae4053386 GIT binary patch literal 1830 zcmV+>2if>iNk&E<2LJ$9MM6+kP&iBy2LJ#skH8}kHHLz=ZJ3ll?Cy_1L`(ojWy*u5 z0j0xC^ws||NrhBoZU-gVwr$gPM&&uSZQHg}vTfFE+qP}nPBFFTi|^QR&fe$V8z*Z) zjwDG^_5TlF(Xc^?VnOSDD0AEW@0Wx5( z+8g)V3DDCJn|(m52xn#YHVi#p3_Xa)-E$utKn7&9zVfG@oqY#kl6WzRjhEfe%B2s) zV)XzD^sMU!c2(S@iH+B(TC58|cfl+IcEJ4XoOJ0%*;gbDaw3_LX0%8OFEy6`US(>Q zE&;PhLEmPBXl%NzfWDA`O`A(fQM6NmB7D*>$z5pXl#AXSw2VN+PFh5@gIUdYtk+e|~w;KgGRwgun zgI60P>jbzc?*Y7w=OJl*BWZDy&yXKUt0i(_-qn*SC3^*UjiH;v7Yq@C)pgVG?DZq=8ocU3TXUmHs z>7RtruILWnaglVciH;v7Yl7J)k{*|u0<@Gcn(>@U&I%~Skr?_j!AP2AmI$y+mK#YE z8enV_ojfHgq9kXzPXK?x)RIyj92*TvDW|#y??xpXB;$C&6)cPWVVJi6p;DR+#M!695U>M?4Z> zs*#iuZ%T1zNa~6RWej0ppYf|?C2rq~q(`z+fT_lZQtStSYJ~BX;zP+w?z*EIk{-!E z1EeIvQXE+U@V$ibsV2gb^@H118wPe&{Jh>#Gjz?Sg;3z@w!YW@!DUr3_a)1XXX($x zZ5jAjnD_cXv?H1H>?sICj~7D^;#T)oj~ehcQ11b5iUHQUxk(U4EnWgzcbuA@gWVJZ zuth^2f?!?FJL-dZEmqPI&?>NcdJI;dmykt(DxgEW#GiTvpM9{qT8P}$*;Ofawe3}V zhAubD*_sZo+jR0Qh>dd5=)^o!7|?hd`sFANonG03_YOH6JO=<@4jf>xEOf| z0kuc~0|%>k-k@mSV(0Jpw*8fsjtIhrH%CV4m`- z?L_r%l&bFU)Xi3j$fHcT@hF|%Pk%4YJ`eu)X1<&jie>Qg(}EO)KJDAAK!+G)i!N>O z;uyp+EX{Ve+UYIOL%@qx0;<}ypo#|~Qm&vxfru3Lpm2eR6a`eZ1W>U+Rci_~5)hHj z1w96+Y7YT7dJA-|-O_BwF%!oCyrN4RvJeCPU_|`-U8Ns;c5z4%!JcpbR;1 zAoAH*FAx9|B4B|FDM$-sA{wMc!37JVU_!vbh^PVq209pELQo(S(L}%m19V^?wp@&e Ur~(!sQ2?;0g65D$0r^9T0Lpw_d;kCd literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_label_foreground.webp b/app/src/main/res/mipmap-xxhdpi/ic_label_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..95488da6398f23ec6269d4eb2eacfcd3ede7f274 GIT binary patch literal 702 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_label.webp b/app/src/main/res/mipmap-xxxhdpi/ic_label.webp new file mode 100644 index 0000000000000000000000000000000000000000..e93b3a3e4ad203997630095860d0dc914e815033 GIT binary patch literal 2062 zcmV+p2=Vt)Nk&En2mk~+%FriB|xl47g;x9U0Y zRaQx4ys4U#7)g>M$?3Sth(iJ3nKXDg+qNB#bbJclWNh1r#$4N5Z^k_~yx#@EjU+`>1)tY;O{QEXGfVKgQ4HwM0{I?`8Iy*|ZE7939BVM?Yh}OOor5PVn@C#XVczHx|4Hmwv?$-CQUJbu~cDU2IqX8?xOqf z%W@Xyy2%`)!3;)oOqS&O((~yMfF}Fty*9rZ%gyGvbfzfGT5HU8`&EAwjnFR{b&by8 z+@&){Azy3^cMAcuXj*$2KsWk$gPScW=*Kv*7^DziDo+$hmqY-MCGRH45(QbS7!3=# ztBgrK-UqM%v?yBpB!Dq)}{-<-UPv?Oey)io9B6gpB~lm)O`S+fn%S^N84lw zmK(Xpu}vIqOpv`<#CFtVlTYUY08b~rd#MEA?X3gs>hWCUrP6)?@x2bRtH<180MVQ; zfYiSk}XAsjD9EJ_@M^Twm$15RFgV$Q2zTR3mAY5U&*$ z0r(REG#Y76_J$ar7{t>`9wNqWZNw2zDq=3%O*Bic=n$>z8c~GXIo0?CNobZ3H63(| zLvlJgi1ta_1j$1@_H^}%hv-oVkhq83UI{W%S#A)EjX4J5@W;?4al$9=AvYCSW$0Ed zSCE*n1c`f*y4XP07}i^$Ang({CGH{JhpaQKH&;O-oJl#jNEN)11~T7BB32vm$RGu2 z(hyVPz9aHbf(%OLD#QZAhgi(LVF|M1j)+8rCCK(2P4;H{j*gSH329GI#!t%HB9+NK zr1rzgL#nI|xnXa*1BBKLhp*`DD;gn9ZDWSJliCUKeBxB^0ub6QI?R+>B#$PrSV!q^j4fI9nPoFF2Z3(bYp_Ns3^qPgldO_(9Rl$8Bv`C8CvLw^EbBs-MKNz zL@fS0#tGjY&j_ua4okOx?r9JmmHrA6j~EOAO4ZuwuynhpfnM)3g%8m&Cro$nDYQpv zxMtcllbWe&B&vEtLxPLcj!Hc7rICc#i1vMx*VBG2c{NpBTwIMrfYF{qOH>-UhQ)oG+ErvY>)E759!o1nhGDEiHBmb z*8BxQqlVxC@IAz1YpDI;Y$~)E=Kj>79_<0}QV2jl16(eEyw&b0lQI}4Q!9Z(CmE`WzdGJp=?0!R;lVt{IZ)-UERPAt|K=|*$%^4L&b zUR3%z!~1%7DS2mgDB&K3N&uFtAQ-9v8UWhg=}wJM<|+{;Q(mvpRFMN-O@-7<71ETW z>NbV+RkgenvC34D5R#I--taB`k{7!30D(e(feXOe{G3!y0Wtsz1E3zDxg-QS?yddo z^!@N;_cA5kXqXKLyq+L6lPemIs+%AKl$8ddaUq0x-e{M;^gjQn|A%XGl%__Ov|qQKL~d^K{5|QY+jbIp zt;vBYiNPsj1u)8`hO6DT{r|%I{90aayKX57U21t~`y*!y+SAzqxB=2q0Ln^3eb7Mw zAW#xQB_VtW^j?9h>vqw)-H5~Ph>`2M5h7$6If;!RM=T@Av25f7ZiF~}HxdFP2p3wN zZnV}enx>b8@UGmTgFq@kSxQ!<#h%8W9smzOdWsvMwiL7k4#7YOm4x7?3k3LzLpqo`yP;y_Vi7(h|Tk#JN7kbmQX3}K|%5C8xG literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_label_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_label_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..cc9e33cdfbffa379c98787315596f109dbcf0144 GIT binary patch literal 788 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 Q14#`lkd&GfT#uG934k=}xc~qF literal 0 HcmV?d00001 From 517238aaea50e7301a2df25e17eb4495b72ebf37 Mon Sep 17 00:00:00 2001 From: JaeminHwang49 Date: Sat, 13 Dec 2025 20:02:20 +0900 Subject: [PATCH 11/15] =?UTF-8?q?Feat(#132):=20=EB=B9=88=20=EB=B2=84?= =?UTF-8?q?=EB=B8=94=20=EB=B3=B4=EA=B4=80=ED=95=A8=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80(=EB=B2=84=EB=B8=94=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=97=B0=EA=B2=B0=20X)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/bubblestorage/BubbleStorageScreen.kt | 84 +++++++++++++++++++ app/src/main/res/values/strings.xml | 5 +- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index a4da79935..c43d4c4d9 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -44,6 +44,17 @@ import com.umc.edison.ui.theme.Gray300 import com.umc.edison.ui.theme.Gray800 import com.umc.edison.ui.theme.Gray900 import com.umc.edison.ui.theme.White000 +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Surface +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import com.umc.edison.R +import com.umc.edison.ui.theme.EdisonTypography +import com.umc.edison.ui.theme.Gray500 +import com.umc.edison.ui.theme.Gray700 @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -99,6 +110,19 @@ fun BubbleStorageScreen( } }, ) { + + // ====== (추가) 버블이 없을 때 Empty 화면 출력 ====== + if (uiState.bubbles.isEmpty()) { + BubbleStorageEmptyView( + onCtaClick = { + // TODO: "찰나의 영감을 기록하기" 클릭 시 이동 로직 연결 + // (예: navHostController.navigate(...)) + } + ) + return@BaseContent + } + // =================================================== + var onBubbleClick: (BubbleModel) -> Unit = {} var onBubbleLongClick: (BubbleModel) -> Unit = {} @@ -293,3 +317,63 @@ fun BubbleStorageScreen( } } } + +@Composable +private fun BubbleStorageEmptyView( + onCtaClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val ctaTextBrush = Brush.linearGradient( + colors = listOf( + Color(0xFFF2F227), // #F2F227 + Color(0xFFFF87D5), // #FF87D5 + Color(0xFF5BADFF), // #5BADFF + ) + ) + + Column( + modifier = modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(R.string.bubble_storage_empty_title), + style = EdisonTypography.displayLarge, + color = Gray700, + textAlign = TextAlign.Center, + ) + + Spacer(modifier = Modifier.height(24.dp)) + + Text( + text = stringResource(R.string.bubble_storage_empty_subtitle), + style = EdisonTypography.bodyMedium, + color = Gray500, + textAlign = TextAlign.Center, + ) + + Spacer(modifier = Modifier.height(4.dp)) + + val ctaTextBrush = Brush.horizontalGradient( + colors = listOf( + Color(0xFFF2F227), + Color(0xFFFF87D5), + Color(0xFF5BADFF), + ) + ) + + Surface( + onClick = onCtaClick, + shape = RoundedCornerShape(100.dp), + color = Color(0xFFFFF7F7), + ) { + Text( + text = stringResource(R.string.bubble_storage_empty_cta), + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), + style = MaterialTheme.typography.displaySmall.copy(brush = ctaTextBrush), + color = Color.Unspecified, + textAlign = TextAlign.Center, + ) + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 802b06edf..2b5ce53ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -35,4 +35,7 @@ 3. 해당 계정으로 Edison에 재가입할 경우, 새로운 계정으로 간주됩니다. 안내 사항을 모두 확인하였으며, 이에 동의합니다. 로그인이 필요한 기능입니다 - \ No newline at end of file + 지난 한 달간 새로 작성한\n버블이 없어요! + 에디슨과 함께 + 찰나의 영감을 기록하기 + From 44243c4c4b09a649c5c14c4e3e3063989738da6a Mon Sep 17 00:00:00 2001 From: JaeminHwang49 Date: Sun, 14 Dec 2025 00:18:50 +0900 Subject: [PATCH 12/15] =?UTF-8?q?Feature(#132):=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=B2=84=EB=B8=94=20=EC=9E=85=EB=A0=A5=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EA=B3=BC=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edison/ui/bubblestorage/BubbleStorageScreen.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index c43d4c4d9..4d0ca0b7c 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -41,20 +41,18 @@ import com.umc.edison.ui.components.calculateBubbleSize import com.umc.edison.ui.navigation.NavRoute import com.umc.edison.ui.onboarding.BubbleSpaceOnboarding import com.umc.edison.ui.theme.Gray300 +import com.umc.edison.ui.theme.Gray500 +import com.umc.edison.ui.theme.Gray700 import com.umc.edison.ui.theme.Gray800 import com.umc.edison.ui.theme.Gray900 import com.umc.edison.ui.theme.White000 -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Surface -import androidx.compose.ui.graphics.BlendMode import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import com.umc.edison.R import com.umc.edison.ui.theme.EdisonTypography -import com.umc.edison.ui.theme.Gray500 -import com.umc.edison.ui.theme.Gray700 @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -110,18 +108,14 @@ fun BubbleStorageScreen( } }, ) { - - // ====== (추가) 버블이 없을 때 Empty 화면 출력 ====== if (uiState.bubbles.isEmpty()) { BubbleStorageEmptyView( onCtaClick = { - // TODO: "찰나의 영감을 기록하기" 클릭 시 이동 로직 연결 - // (예: navHostController.navigate(...)) + navHostController.navigate(NavRoute.BubbleEdit.createRoute("")) } ) return@BaseContent } - // =================================================== var onBubbleClick: (BubbleModel) -> Unit = {} var onBubbleLongClick: (BubbleModel) -> Unit = {} From 1e093e49e75973a6783a2777d69cd138c4025f35 Mon Sep 17 00:00:00 2001 From: JaeminHwang49 Date: Fri, 2 Jan 2026 17:02:59 +0900 Subject: [PATCH 13/15] =?UTF-8?q?Chore(#132):=20=EC=98=81=EA=B0=90?= =?UTF-8?q?=EC=9D=84=20=EA=B8=B0=EB=A1=9D=ED=95=98=EA=B8=B0=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index 4d0ca0b7c..e7ffda91d 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -365,7 +365,8 @@ private fun BubbleStorageEmptyView( text = stringResource(R.string.bubble_storage_empty_cta), modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), style = MaterialTheme.typography.displaySmall.copy(brush = ctaTextBrush), - color = Color.Unspecified, + + textAlign = TextAlign.Center, ) } From 8da779d233039662bc83393b23354e85a424a3ff Mon Sep 17 00:00:00 2001 From: JaeminHwang49 Date: Mon, 5 Jan 2026 17:22:34 +0900 Subject: [PATCH 14/15] =?UTF-8?q?Fix(#132):=20=EC=83=89=EC=83=81=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EC=97=90=20=EA=B7=B8=EB=9D=BC=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=EC=85=98,=20=EB=B0=B0=EA=B2=BD=20=EC=83=89=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/bubblestorage/BubbleStorageScreen.kt | 22 +++++++------------ .../java/com/umc/edison/ui/theme/Color.kt | 7 +++++- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index e7ffda91d..42a17c697 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -48,11 +48,14 @@ import com.umc.edison.ui.theme.Gray900 import com.umc.edison.ui.theme.White000 import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Surface -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import com.umc.edison.R import com.umc.edison.ui.theme.EdisonTypography +import com.umc.edison.ui.theme.EmptyViewCtaBg +import com.umc.edison.ui.theme.GradientBlue +import com.umc.edison.ui.theme.GradientPink +import com.umc.edison.ui.theme.GradientYellow @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -317,13 +320,6 @@ private fun BubbleStorageEmptyView( onCtaClick: () -> Unit, modifier: Modifier = Modifier, ) { - val ctaTextBrush = Brush.linearGradient( - colors = listOf( - Color(0xFFF2F227), // #F2F227 - Color(0xFFFF87D5), // #FF87D5 - Color(0xFF5BADFF), // #5BADFF - ) - ) Column( modifier = modifier.fillMaxSize(), @@ -350,23 +346,21 @@ private fun BubbleStorageEmptyView( val ctaTextBrush = Brush.horizontalGradient( colors = listOf( - Color(0xFFF2F227), - Color(0xFFFF87D5), - Color(0xFF5BADFF), + GradientYellow, + GradientPink, + GradientBlue, ) ) Surface( onClick = onCtaClick, shape = RoundedCornerShape(100.dp), - color = Color(0xFFFFF7F7), + color = EmptyViewCtaBg, ) { Text( text = stringResource(R.string.bubble_storage_empty_cta), modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), style = MaterialTheme.typography.displaySmall.copy(brush = ctaTextBrush), - - textAlign = TextAlign.Center, ) } diff --git a/app/src/main/java/com/umc/edison/ui/theme/Color.kt b/app/src/main/java/com/umc/edison/ui/theme/Color.kt index 843b73a9f..52cc47c7a 100644 --- a/app/src/main/java/com/umc/edison/ui/theme/Color.kt +++ b/app/src/main/java/com/umc/edison/ui/theme/Color.kt @@ -49,6 +49,11 @@ val Orange100 = Color(0xFFFFE2CD) val LightGreen100 = Color(0XFFD5FFAB) val LightBlue100 = Color(0XFFA8F4F7) +val EmptyViewCtaBg = Color(0xFFFFF7F7) +val GradientYellow = Color(0xFFF2F227) +val GradientPink = Color(0xFFFF87D5) +val GradientBlue = Color(0xFF5BADFF) + val ColorPickerList = listOf( Red100, Yellow100, @@ -62,4 +67,4 @@ val ColorPickerList = listOf( Green200, Purple100, Color(0xFFC9CBD3), -) \ No newline at end of file +) From e95440385ca592aeaf23b84ddff981f1c6d7642d Mon Sep 17 00:00:00 2001 From: JaeminHwang49 Date: Sat, 24 Jan 2026 13:59:35 +0900 Subject: [PATCH 15/15] =?UTF-8?q?Fix(#132):=20=EB=A9=94=EC=9D=B4=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt | 2 +- app/src/main/java/com/umc/edison/ui/navigation/NavRoute.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt index 42a17c697..54e3dc456 100644 --- a/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt +++ b/app/src/main/java/com/umc/edison/ui/bubblestorage/BubbleStorageScreen.kt @@ -114,7 +114,7 @@ fun BubbleStorageScreen( if (uiState.bubbles.isEmpty()) { BubbleStorageEmptyView( onCtaClick = { - navHostController.navigate(NavRoute.BubbleEdit.createRoute("")) + navHostController.navigate(NavRoute.BubbleEdit.createRoute()) } ) return@BaseContent diff --git a/app/src/main/java/com/umc/edison/ui/navigation/NavRoute.kt b/app/src/main/java/com/umc/edison/ui/navigation/NavRoute.kt index 91c63f22f..c1bd1ff9d 100644 --- a/app/src/main/java/com/umc/edison/ui/navigation/NavRoute.kt +++ b/app/src/main/java/com/umc/edison/ui/navigation/NavRoute.kt @@ -68,8 +68,8 @@ sealed class NavRoute(val route: String) { } data object BubbleEdit : NavRoute("$MY_EDISON_ROUTE/edit") { - fun createRoute(bubbleId: String?): String { - return if (bubbleId != null) { + fun createRoute(bubbleId: String? = null): String { + return if (!bubbleId.isNullOrEmpty()) { "$route?bubbleId=$bubbleId" } else { route