diff --git a/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorCard.kt b/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorCard.kt index 963475bd..278bc019 100644 --- a/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorCard.kt +++ b/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorCard.kt @@ -2,80 +2,143 @@ package com.droidknights.app2023.feature.home import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle import com.droidknights.app2023.core.designsystem.component.KnightsCard import com.droidknights.app2023.core.designsystem.component.NetworkImage import com.droidknights.app2023.core.designsystem.theme.KnightsTheme import com.droidknights.app2023.core.model.Sponsor +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive + +private const val SCROLL_DELAY_MILLIS = 20L +private const val SCROLL_PIXEL_UNIT = 4f @Composable fun SponsorCard( // TODO: 실제 데이터와 연결 - uiState: SponsorsUiState = SponsorsUiState(emptyList()), + uiState: SponsorsUiState = + listOf( + Sponsor( + name = "Sponsor1", + homepage = "https://www.instagram.com/droid_knights", + grade = Sponsor.Grade.GOLD, + imageUrl = "https://picsum.photos/id/237/200/200", + ), + Sponsor( + name = "Sponsor2", + homepage = "https://www.instagram.com/droid_knights", + grade = Sponsor.Grade.PLATINUM, + imageUrl = "https://picsum.photos/id/204/200/200", + ), + Sponsor( + name = "Sponsor3", + homepage = "https://www.instagram.com/droid_knights", + grade = Sponsor.Grade.PLATINUM, + imageUrl = "https://picsum.photos/id/203/200/200", + ), + Sponsor( + name = "Sponsor4", + homepage = "https://www.instagram.com/droid_knights", + grade = Sponsor.Grade.PLATINUM, + imageUrl = "https://picsum.photos/id/202/200/200", + ), + Sponsor( + name = "Sponsor5", + homepage = "https://www.instagram.com/droid_knights", + grade = Sponsor.Grade.PLATINUM, + imageUrl = "https://picsum.photos/id/201/200/200", + ), + Sponsor( + name = "Sponsor6", + homepage = "https://www.instagram.com/droid_knights", + grade = Sponsor.Grade.PLATINUM, + imageUrl = "https://picsum.photos/id/200/200/200", + ), + ).let(::SponsorsUiState), ) { KnightsCard { Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) + modifier = Modifier.fillMaxWidth() ) { - Text( - text = stringResource(id = R.string.sponsor_card_title), - style = KnightsTheme.typography.headlineSmallBL, - color = Color(0xFF000000), - modifier = Modifier.padding(top = 24.dp), - ) - Text( - text = stringResource( - id = R.string.sponsor_card_description, - uiState.platinumCount, - uiState.goldCount - ), - style = KnightsTheme.typography.titleSmallR, - color = Color(0xFF868686), - modifier = Modifier.padding(top = 8.dp), - ) - SponsorGroup(uiState.sponsors) + Column(modifier = Modifier.padding(horizontal = 24.dp)) { + Text( + text = stringResource(id = R.string.sponsor_card_title), + style = KnightsTheme.typography.headlineSmallBL, + color = Color(0xFF000000), + modifier = Modifier.padding(top = 24.dp), + ) + Text( + text = stringResource( + id = R.string.sponsor_card_description, + uiState.platinumCount, + uiState.goldCount + ), + style = KnightsTheme.typography.titleSmallR, + color = Color(0xFF868686), + modifier = Modifier.padding(top = 8.dp), + ) + } + if (uiState.isNotEmpty()) { + SponsorGroup(uiState.sponsors) + } } } } -// TODO: 이미지 연결 및 동적으로 배치 +// TODO: 세로 두 줄 고정 필요 @Composable private fun SponsorGroup( sponsors: List, ) { - Row( - horizontalArrangement = Arrangement - .spacedBy( - space = 8.dp, - alignment = Alignment.CenterHorizontally, - ), + val scrollState = rememberLazyListState() + val lifecycleOwner = LocalLifecycleOwner.current + + LazyRow( + state = scrollState, + horizontalArrangement = Arrangement.spacedBy( + space = 14.dp, + alignment = Alignment.CenterHorizontally, + ), + userScrollEnabled = false, modifier = Modifier - .fillMaxWidth() - .padding(24.dp), + .padding(vertical = 24.dp) + .fillMaxWidth(), ) { - sponsors.forEach { - SponsorLogo(it) + items(count = Int.MAX_VALUE) { index -> + SponsorLogo(sponsor = sponsors[index % sponsors.size]) + } + } + LaunchedEffect(Unit) { + lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) { + while (isActive) { + scrollState.scrollBy(SCROLL_PIXEL_UNIT) + delay(SCROLL_DELAY_MILLIS) + } } } } diff --git a/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorsUiState.kt b/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorsUiState.kt index 912d9675..0147bb31 100644 --- a/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorsUiState.kt +++ b/feature/home/src/main/java/com/droidknights/app2023/feature/home/SponsorsUiState.kt @@ -8,4 +8,6 @@ data class SponsorsUiState(val sponsors: List) { val goldCount: Int get() = sponsors.count { it.grade == Sponsor.Grade.GOLD } + + fun isNotEmpty() = sponsors.isNotEmpty() }