diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_notification_add_outlined.xml b/composeApp/src/commonMain/composeResources/drawable/ic_notification_add_outlined.xml new file mode 100644 index 0000000..a745721 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_notification_add_outlined.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_notifications_active.xml b/composeApp/src/commonMain/composeResources/drawable/ic_notifications_active.xml new file mode 100644 index 0000000..9890419 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_notifications_active.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_notifications_add.xml b/composeApp/src/commonMain/composeResources/drawable/ic_notifications_add.xml new file mode 100644 index 0000000..fc0ceb1 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_notifications_add.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_notifications_none.xml b/composeApp/src/commonMain/composeResources/drawable/ic_notifications_none.xml new file mode 100644 index 0000000..e5e2603 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_notifications_none.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/HomeScreen.kt index 1674b0a..837fd25 100644 --- a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/HomeScreen.kt @@ -32,7 +32,7 @@ fun HomeScreenRoot( innerPadding: PaddingValues, onSettingClick: () -> Unit = {}, ) { - val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() val state by viewModel.state.collectAsStateWithLifecycle() val keyboardController = LocalSoftwareKeyboardController.current @@ -69,8 +69,7 @@ fun HomeScreenRoot( HomeScreen( modifier = Modifier .fillMaxWidth() - .padding(innerPadding) - .verticalScroll(rememberScrollState()), + .padding(innerPadding), state = state, onAction = { action -> viewModel.onAction(action) @@ -87,12 +86,11 @@ private fun HomeScreen( onAction: (HomeAction) -> Unit = {} ) { Column(modifier = modifier) { - UpcomingContestCardMostRecent() ContestHorizontalPager( onAction = { onAction(it) }, - state = state + state = state, ) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/ContestHorizontalPager.kt b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/ContestHorizontalPager.kt index 1caa79a..bcf7f05 100644 --- a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/ContestHorizontalPager.kt +++ b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/ContestHorizontalPager.kt @@ -1,12 +1,12 @@ package org.onedroid.greedycoder.app.presentation.home.components import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.RoundedCornerShape @@ -19,12 +19,10 @@ 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.text.font.FontWeight import androidx.compose.ui.unit.dp import org.onedroid.greedycoder.app.presentation.home.HomeAction import org.onedroid.greedycoder.app.presentation.home.HomeState -import org.onedroid.greedycoder.core.theme.extraSmall -import org.onedroid.greedycoder.core.theme.small @Composable fun ContestHorizontalPager( @@ -39,13 +37,18 @@ fun ContestHorizontalPager( onAction(HomeAction.OnTabSelected(pagerState.currentPage)) } Column( - modifier = Modifier.fillMaxWidth().padding(16.dp), + modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { TabRow( modifier = Modifier - .padding(horizontal = extraSmall) - .clip(RoundedCornerShape(8.dp)) + .padding(horizontal = 16.dp, vertical = 8.dp) + .clip(RoundedCornerShape(12.dp)) + .border( + 1.dp, + MaterialTheme.colorScheme.outline.copy(alpha = 0.1f), + RoundedCornerShape(12.dp) + ) .fillMaxWidth(), selectedTabIndex = state.selectedTabIndex, containerColor = MaterialTheme.colorScheme.surfaceContainer, @@ -74,7 +77,8 @@ fun ContestHorizontalPager( .align(Alignment.Center) .padding(vertical = 12.dp), text = "Upcoming", - style = MaterialTheme.typography.labelLarge + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold ) } } @@ -101,27 +105,24 @@ fun ContestHorizontalPager( .align(Alignment.Center) .padding(vertical = 12.dp), text = "Completed", - style = MaterialTheme.typography.labelLarge + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold ) } } } HorizontalPager( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.padding().fillMaxWidth(), state = pagerState ) { pageIndex -> - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - when (pageIndex) { - 0 -> { - Text(text = "Upcoming") - } - 1 -> { - Text(text = "Completed") - } + when (pageIndex) { + 0 -> { + UpComingContestList() + } + + 1 -> { + Text(text = "Completed") } } } diff --git a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/UpcomingContest.kt b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/UpcomingContest.kt index a1971c5..b40f11b 100644 --- a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/UpcomingContest.kt +++ b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/home/components/UpcomingContest.kt @@ -1,39 +1,57 @@ package org.onedroid.greedycoder.app.presentation.home.components import androidx.compose.foundation.background +import androidx.compose.foundation.border 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.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +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.layout.width -import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Notifications import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import greedycoder.composeapp.generated.resources.Res +import greedycoder.composeapp.generated.resources.ic_notification_add_outlined +import greedycoder.composeapp.generated.resources.ic_notifications_active +import greedycoder.composeapp.generated.resources.ic_notifications_add +import org.jetbrains.compose.resources.painterResource @Composable fun UpcomingContestCardMostRecent() { Card( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 4.dp), + .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) + .border( + 1.dp, + MaterialTheme.colorScheme.outline.copy(alpha = 0.1f), + RoundedCornerShape(12.dp) + ), shape = RoundedCornerShape(12.dp), colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.surfaceContainer - ) + ), + //elevation = CardDefaults.cardElevation(1.dp) ) { Column( modifier = Modifier @@ -47,7 +65,7 @@ fun UpcomingContestCardMostRecent() { Column { Text( text = "Upcoming Contest", - color = Color.Gray, + color = MaterialTheme.colorScheme.onSecondaryContainer, style = MaterialTheme.typography.bodySmall ) Spacer(modifier = Modifier.height(4.dp)) @@ -64,23 +82,26 @@ fun UpcomingContestCardMostRecent() { } } - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(12.dp)) // Title Text( text = "Codeforces Round 1003 (Div. 4)", color = MaterialTheme.colorScheme.onSurface, - style = MaterialTheme.typography.titleMedium, + style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(10.dp)) // Difficulty and Tags Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier - .background(Color(0xFF2E2E2E), RoundedCornerShape(12.dp)) + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + RoundedCornerShape(12.dp) + ) .padding(horizontal = 8.dp, vertical = 4.dp) .padding(end = 4.dp) ) { @@ -93,7 +114,10 @@ fun UpcomingContestCardMostRecent() { Spacer(modifier = Modifier.width(5.dp)) Box( modifier = Modifier - .background(Color(0xFF2E2E2E), RoundedCornerShape(12.dp)) + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + RoundedCornerShape(12.dp) + ) .padding(horizontal = 8.dp, vertical = 4.dp) .padding(end = 4.dp) ) { @@ -106,7 +130,10 @@ fun UpcomingContestCardMostRecent() { Spacer(modifier = Modifier.width(5.dp)) Box( modifier = Modifier - .background(Color(0xFF2E2E2E), RoundedCornerShape(12.dp)) + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + RoundedCornerShape(12.dp) + ) .padding(horizontal = 8.dp, vertical = 4.dp) .padding(end = 4.dp) ) { @@ -126,13 +153,140 @@ fun TimerDisplay(value: Int, unit: String) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( text = value.toString().padStart(2, '0'), - color = Color.White, + color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.labelLarge ) Text( text = unit, - color = Color.Gray, + color = MaterialTheme.colorScheme.onSecondaryContainer, style = MaterialTheme.typography.bodySmall ) } -} \ No newline at end of file +} + +@Composable +fun UpComingContestCard() { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) + .border( + 1.dp, + MaterialTheme.colorScheme.outline.copy(alpha = 0.1f), + RoundedCornerShape(12.dp) + ), + shape = RoundedCornerShape(12.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainer + ), + //elevation = CardDefaults.cardElevation(1.dp) + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + // Header + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = "Upcoming Contest", + color = MaterialTheme.colorScheme.onSecondaryContainer, + style = MaterialTheme.typography.bodySmall + ) + Column { + Text( + text = "Feb, 09, 2025 10:30 PM", + color = MaterialTheme.colorScheme.onSecondaryContainer, + style = MaterialTheme.typography.bodySmall + ) + } + } + + Spacer(modifier = Modifier.height(12.dp)) + + // Title + Text( + text = "Codeforces Round 1003 (Div. 4)", + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold + ) + + Spacer(modifier = Modifier.height(10.dp)) + + // Difficulty and Tags + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + RoundedCornerShape(12.dp) + ) + .padding(horizontal = 8.dp, vertical = 4.dp) + .padding(end = 4.dp) + ) { + Text( + text = "Type: ICPC", + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.labelSmall + ) + } + Spacer(modifier = Modifier.width(5.dp)) + Box( + modifier = Modifier + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + RoundedCornerShape(12.dp) + ) + .padding(horizontal = 8.dp, vertical = 4.dp) + .padding(end = 4.dp) + ) { + Text( + text = "Duration 2 Hrs", + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.labelSmall + ) + } + } + + IconButton( + colors = IconButtonDefaults.iconButtonColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer + ), + onClick = {}, + modifier = Modifier + ) { + Icon( + modifier = Modifier.size(25.dp).padding(2.dp), + painter = painterResource(Res.drawable.ic_notification_add_outlined), + contentDescription = null, + tint = MaterialTheme.colorScheme.onSecondaryContainer + ) + } + } + } + } +} + +@Composable +fun UpComingContestList() { + LazyColumn( + modifier = Modifier.fillMaxSize(), + ) { + item { + UpcomingContestCardMostRecent() + } + items(3) { + UpComingContestCard() + } + } +} + diff --git a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/profile/components/ProfileSection.kt b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/profile/components/ProfileSection.kt index 343bcca..656039a 100644 --- a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/profile/components/ProfileSection.kt +++ b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/app/presentation/profile/components/ProfileSection.kt @@ -38,12 +38,13 @@ fun ProfileSection( avatar: String, ) { Card( - modifier = modifier.fillMaxWidth().padding(top = 4.dp), + modifier = modifier.fillMaxWidth().padding(top = 4.dp) + .border(1.dp, MaterialTheme.colorScheme.outline.copy(alpha = 0.1f), RoundedCornerShape(8.dp)), colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.surfaceContainer, ), shape = RoundedCornerShape(8.dp), - elevation = CardDefaults.cardElevation(0.5.dp) + //elevation = CardDefaults.cardElevation(0.5.dp) ) { Row( modifier = Modifier.fillMaxWidth() diff --git a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/core/components/Feed.kt b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/core/components/Feed.kt new file mode 100644 index 0000000..eaa8a48 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/core/components/Feed.kt @@ -0,0 +1,225 @@ +package org.onedroid.greedycoder.core.components + +import androidx.compose.foundation.focusGroup +import androidx.compose.foundation.gestures.FlingBehavior +import androidx.compose.foundation.gestures.ScrollableDefaults +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.GridItemSpan +import androidx.compose.foundation.lazy.grid.LazyGridItemScope +import androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope +import androidx.compose.foundation.lazy.grid.LazyGridState +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun Feed( + modifier: Modifier = Modifier, + columns: GridCells = GridCells.Fixed(1), + state: LazyGridState = rememberLazyGridState(), + contentPadding: PaddingValues = PaddingValues(0.dp), + verticalArrangement: Arrangement.Vertical = Arrangement.Top, + horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, + flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), + content: @ExtensionFunctionType FeedScope.() -> Unit +) { + val feedScope = FeedScopeImpl().apply(content) + LazyVerticalGrid( + columns = columns, + modifier = modifier, + state = state, + contentPadding = contentPadding, + verticalArrangement = verticalArrangement, + horizontalArrangement = horizontalArrangement, + flingBehavior = flingBehavior + ) { + feedScope.items.forEach { feedItem -> + items( + count = feedItem.count, + key = feedItem.key, + contentType = feedItem.contentType, + span = feedItem.span, + itemContent = feedItem.itemContent + ) + } + } +} + +interface FeedScope { + fun item( + key: Any? = null, + span: (@ExtensionFunctionType LazyGridItemSpanScope.() -> GridItemSpan)? = null, + contentType: Any? = null, + content: @Composable LazyGridItemScope.() -> Unit + ) + + fun items( + count: Int, + key: ((index: Int) -> Any)? = null, + span: (@ExtensionFunctionType LazyGridItemSpanScope.(index: Int) -> GridItemSpan)? = null, + contentType: (index: Int) -> Any? = { null }, + itemContent: @Composable LazyGridItemScope.(index: Int) -> Unit + ) +} + +inline fun FeedScope.items( + items: List, + noinline key: ((item: T) -> Any)? = null, + noinline span: (@ExtensionFunctionType LazyGridItemSpanScope.(item: T) -> GridItemSpan)? = null, + noinline contentType: (item: T) -> Any? = { null }, + crossinline itemContent: @Composable LazyGridItemScope.(item: T) -> Unit +) = items( + count = items.size, + key = if (key != null) { + { index: Int -> key(items[index]) } + } else { + null + }, + span = if (span != null) { + { index: Int -> span(items[index]) } + } else { + null + }, + contentType = { index: Int -> contentType(items[index]) } +) { index -> + itemContent(items[index]) +} + +inline fun FeedScope.itemsIndexed( + items: List, + noinline key: ((index: Int, item: T) -> Any)? = null, + noinline span: (@ExtensionFunctionType LazyGridItemSpanScope.(index: Int, item: T) -> GridItemSpan)? = null, + noinline contentType: (index: Int, item: T) -> Any? = { _, _ -> null }, + crossinline itemContent: @Composable LazyGridItemScope.(index: Int, item: T) -> Unit +) = items( + count = items.size, + key = if (key != null) { + { index: Int -> key(index, items[index]) } + } else { + null + }, + span = if (span != null) { + { index: Int -> span(index, items[index]) } + } else { + null + }, + contentType = { index: Int -> contentType(index, items[index]) } +) { index -> + itemContent(index, items[index]) +} + +inline fun FeedScope.items( + items: Array, + noinline key: ((item: T) -> Any)? = null, + noinline span: (@ExtensionFunctionType LazyGridItemSpanScope.(item: T) -> GridItemSpan)? = null, + noinline contentType: (item: T) -> Any? = { null }, + crossinline itemContent: @Composable LazyGridItemScope.(item: T) -> Unit +) = items( + count = items.size, + key = if (key != null) { + { index: Int -> key(items[index]) } + } else { + null + }, + span = if (span != null) { + { index: Int -> span(items[index]) } + } else { + null + }, + contentType = { index: Int -> contentType(items[index]) } +) { index -> + itemContent(items[index]) +} + +inline fun FeedScope.itemsIndexed( + items: Array, + noinline key: ((index: Int, item: T) -> Any)? = null, + noinline span: (@ExtensionFunctionType LazyGridItemSpanScope.(index: Int, item: T) -> GridItemSpan)? = null, + noinline contentType: (index: Int, item: T) -> Any? = { _, _ -> null }, + crossinline itemContent: @Composable LazyGridItemScope.(index: Int, item: T) -> Unit +) = items( + count = items.size, + key = if (key != null) { + { index: Int -> key(index, items[index]) } + } else { + null + }, + span = if (span != null) { + { index: Int -> span(index, items[index]) } + } else { + null + }, + contentType = { index: Int -> contentType(index, items[index]) } +) { index -> + itemContent(index, items[index]) +} + +inline fun FeedScope.row( + key: Any? = null, + contentType: Any? = null, + crossinline content: @Composable LazyGridItemScope.() -> Unit +) = item( + key = key, + span = { GridItemSpan(maxLineSpan) }, + contentType = contentType +) { + content() +} + +inline fun FeedScope.title( + key: Any? = null, + contentType: Any? = null, + crossinline content: @Composable LazyGridItemScope.() -> Unit +) = row(key = key, contentType = contentType) { content() } + +inline fun FeedScope.action( + key: Any? = null, + contentType: Any? = null, + horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, + crossinline content: @Composable RowScope.() -> Unit +) = row( + key = key, + contentType = contentType +) { + Row( + modifier = Modifier + .focusGroup() + .horizontalScroll(rememberScrollState()), + horizontalArrangement = horizontalArrangement + ) { + content() + } +} + +inline fun FeedScope.single( + key: Any? = null, + contentType: Any? = null, + crossinline content: @Composable LazyGridItemScope.() -> Unit +) = item( + key = key, + span = { GridItemSpan(maxLineSpan) }, + contentType = contentType +) { + content() +} + + +inline fun FeedScope.footer( + key: Any? = null, + contentType: Any? = null, + crossinline content: @Composable LazyGridItemScope.() -> Unit +) = item( + key = key, + span = { GridItemSpan(maxLineSpan) }, + contentType = contentType +) { + content() +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/core/components/FeedScopeImpl.kt b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/core/components/FeedScopeImpl.kt new file mode 100644 index 0000000..3c3a027 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/onedroid/greedycoder/core/components/FeedScopeImpl.kt @@ -0,0 +1,61 @@ +package org.onedroid.greedycoder.core.components + + +import androidx.compose.foundation.lazy.grid.GridItemSpan +import androidx.compose.foundation.lazy.grid.LazyGridItemScope +import androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope +import androidx.compose.runtime.Composable + +internal class FeedScopeImpl : FeedScope { + val items = mutableListOf() + override fun item( + key: Any?, + span: (LazyGridItemSpanScope.() -> GridItemSpan)?, + contentType: Any?, + content: @Composable LazyGridItemScope.() -> Unit + ) { + items.add( + FeedItem( + count = 1, + key = if (key != null) { + { key } + } else { + null + }, + span = if (span != null) { + { span() } + } else { + null + }, + contentType = { contentType }, + itemContent = { content() } + ) + ) + } + + override fun items( + count: Int, + key: ((index: Int) -> Any)?, + span: (LazyGridItemSpanScope.(index: Int) -> GridItemSpan)?, + contentType: (index: Int) -> Any?, + itemContent: @Composable LazyGridItemScope.(index: Int) -> Unit + ) { + items.add( + FeedItem( + count = count, + key = key, + span = span, + contentType = contentType, + itemContent = itemContent + ) + ) + } +} + +internal data class FeedItem( + val count: Int, + val key: ((index: Int) -> Any)?, + val span: (LazyGridItemSpanScope.(index: Int) -> GridItemSpan)?, + val contentType: (index: Int) -> Any?, + val itemContent: @Composable LazyGridItemScope.(index: Int) -> Unit +) \ No newline at end of file