-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Home feed item transformation, modules restructuring.
- Loading branch information
1 parent
04b06f5
commit 6edda72
Showing
20 changed files
with
277 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 1 addition & 2 deletions
3
...oid/common/ui/feed/DisplayableFeedItem.kt → ...ned/kmp/model/feed/DisplayableFeedItem.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
plugins { | ||
id("kstreamlined.kmp.common") | ||
id("kstreamlined.kmp.test") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
...onMain/kotlin/io/github/reactivecircus/kstreamlined/kmp/presentation/home/HomeFeedItem.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package io.github.reactivecircus.kstreamlined.kmp.presentation.home | ||
|
||
import io.github.reactivecircus.kstreamlined.kmp.model.feed.DisplayableFeedItem | ||
import io.github.reactivecircus.kstreamlined.kmp.model.feed.FeedItem | ||
|
||
internal sealed interface HomeFeedItem { | ||
data class SectionHeader(val title: String) : HomeFeedItem | ||
data class Item(val displayableFeedItem: DisplayableFeedItem<FeedItem>) : HomeFeedItem | ||
} |
32 changes: 32 additions & 0 deletions
32
.../kotlin/io/github/reactivecircus/kstreamlined/kmp/presentation/home/HomeFeedItemMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package io.github.reactivecircus.kstreamlined.kmp.presentation.home | ||
|
||
import io.github.reactivecircus.kstreamlined.kmp.model.feed.FeedItem | ||
import io.github.reactivecircus.kstreamlined.kmp.model.feed.toDisplayable | ||
import io.github.reactivecircus.kstreamlined.kmp.prettytime.timeAgo | ||
import io.github.reactivecircus.kstreamlined.kmp.prettytime.weeksAgo | ||
import kotlinx.datetime.Clock | ||
import kotlinx.datetime.TimeZone | ||
|
||
internal fun List<FeedItem>.toHomeFeedItems( | ||
clock: Clock = Clock.System, | ||
timeZone: TimeZone = TimeZone.currentSystemDefault(), | ||
): List<HomeFeedItem> { | ||
val homeFeedItems = mutableListOf<HomeFeedItem>() | ||
var currentSectionHeader: String? = null | ||
|
||
// assume items are already sorted by publish time in descending order | ||
forEach { feedItem -> | ||
val sectionHeader = feedItem.publishTime.weeksAgo(clock) | ||
println("${feedItem.publishTime}: \"$sectionHeader\" for item: $feedItem") | ||
if (sectionHeader != currentSectionHeader) { | ||
homeFeedItems.add(HomeFeedItem.SectionHeader(sectionHeader)) | ||
currentSectionHeader = sectionHeader | ||
} | ||
val displayableFeedItem = feedItem.toDisplayable( | ||
feedItem.publishTime.timeAgo(clock, timeZone) | ||
) | ||
homeFeedItems.add(HomeFeedItem.Item(displayableFeedItem)) | ||
} | ||
|
||
return homeFeedItems | ||
} |
193 changes: 193 additions & 0 deletions
193
...lin/io/github/reactivecircus/kstreamlined/kmp/presentation/home/HomeFeedItemMapperTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package io.github.reactivecircus.kstreamlined.kmp.presentation.home | ||
|
||
import io.github.reactivecircus.kstreamlined.kmp.model.feed.DisplayableFeedItem | ||
import io.github.reactivecircus.kstreamlined.kmp.model.feed.FeedItem | ||
import kotlinx.datetime.Clock | ||
import kotlinx.datetime.Instant | ||
import kotlinx.datetime.TimeZone | ||
import kotlinx.datetime.toInstant | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
|
||
class HomeFeedItemMapperTest { | ||
|
||
@Test | ||
fun `transformed HomeFeedItems are grouped by weeks with expected displayable time`() { | ||
val fixedClock = object : Clock { | ||
override fun now(): Instant { | ||
return "2023-12-03T03:10:54Z".toInstant() | ||
} | ||
} | ||
val timeZone = TimeZone.UTC | ||
|
||
val feedItems = listOf( | ||
// this week | ||
// moments ago | ||
FeedItem.KotlinBlog( | ||
id = "1", | ||
title = "Kotlin Blog 1", | ||
publishTime = "2023-12-03T03:10:00Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
featuredImageUrl = "feature-image-url", | ||
), | ||
// 30 minutes ago | ||
FeedItem.KotlinYouTube( | ||
id = "2", | ||
title = "Kotlin YouTube 1", | ||
publishTime = "2023-12-03T02:40:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
thumbnailUrl = "thumbnail-url", | ||
description = "description", | ||
), | ||
// 5 hours ago | ||
FeedItem.KotlinWeekly( | ||
id = "3", | ||
title = "Kotlin Weekly 1", | ||
publishTime = "2023-12-02T22:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
), | ||
// yesterday | ||
FeedItem.TalkingKotlin( | ||
id = "4", | ||
title = "Talking Kotlin 1", | ||
publishTime = "2023-12-02T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
podcastLogoUrl = "podcast-logo-url", | ||
), | ||
// 5 days ago | ||
FeedItem.KotlinBlog( | ||
id = "5", | ||
title = "Kotlin Blog 2", | ||
publishTime = "2023-11-28T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
featuredImageUrl = "feature-image-url", | ||
), | ||
// last week | ||
// 12 days ago | ||
FeedItem.KotlinYouTube( | ||
id = "6", | ||
title = "Kotlin YouTube 2", | ||
publishTime = "2023-11-21T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
thumbnailUrl = "thumbnail-url", | ||
description = "description", | ||
), | ||
// earlier | ||
// 20 days ago | ||
FeedItem.KotlinWeekly( | ||
id = "7", | ||
title = "Kotlin Weekly 2", | ||
publishTime = "2023-11-13T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
), | ||
) | ||
|
||
val expectedHomeFeedItems = listOf( | ||
HomeFeedItem.SectionHeader("This week"), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.KotlinBlog( | ||
id = "1", | ||
title = "Kotlin Blog 1", | ||
publishTime = "2023-12-03T03:10:00Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
featuredImageUrl = "feature-image-url", | ||
), | ||
displayablePublishTime = "Moments ago", | ||
) | ||
), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.KotlinYouTube( | ||
id = "2", | ||
title = "Kotlin YouTube 1", | ||
publishTime = "2023-12-03T02:40:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
thumbnailUrl = "thumbnail-url", | ||
description = "description", | ||
), | ||
displayablePublishTime = "30 minutes ago", | ||
) | ||
), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.KotlinWeekly( | ||
id = "3", | ||
title = "Kotlin Weekly 1", | ||
publishTime = "2023-12-02T22:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
), | ||
displayablePublishTime = "5 hours ago", | ||
) | ||
), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.TalkingKotlin( | ||
id = "4", | ||
title = "Talking Kotlin 1", | ||
publishTime = "2023-12-02T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
podcastLogoUrl = "podcast-logo-url", | ||
), | ||
displayablePublishTime = "Yesterday", | ||
) | ||
), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.KotlinBlog( | ||
id = "5", | ||
title = "Kotlin Blog 2", | ||
publishTime = "2023-11-28T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
featuredImageUrl = "feature-image-url", | ||
), | ||
displayablePublishTime = "5 days ago", | ||
) | ||
), | ||
HomeFeedItem.SectionHeader("Last week"), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.KotlinYouTube( | ||
id = "6", | ||
title = "Kotlin YouTube 2", | ||
publishTime = "2023-11-21T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
thumbnailUrl = "thumbnail-url", | ||
description = "description", | ||
), | ||
displayablePublishTime = "21 Nov 2023", | ||
) | ||
), | ||
HomeFeedItem.SectionHeader("Earlier"), | ||
HomeFeedItem.Item( | ||
displayableFeedItem = DisplayableFeedItem( | ||
FeedItem.KotlinWeekly( | ||
id = "7", | ||
title = "Kotlin Weekly 2", | ||
publishTime = "2023-11-13T03:10:54Z".toInstant(), | ||
contentUrl = "content-url", | ||
savedForLater = false, | ||
), | ||
displayablePublishTime = "13 Nov 2023", | ||
) | ||
), | ||
) | ||
|
||
val actualHomeFeedItems = feedItems.toHomeFeedItems(fixedClock, timeZone) | ||
|
||
assertEquals(expectedHomeFeedItems, actualHomeFeedItems) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.