Skip to content

Commit

Permalink
Merge pull request #4 from stslex/dev
Browse files Browse the repository at this point in the history
Feed
  • Loading branch information
stslex authored Nov 26, 2023
2 parents f86e9bd + 02ca5c8 commit be51fdf
Show file tree
Hide file tree
Showing 44 changed files with 740 additions and 212 deletions.
2 changes: 1 addition & 1 deletion composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ kotlin {
commonMain.dependencies {
implementation(project(":core:core"))
implementation(project(":core:ui"))
implementation(project(":feature:home"))
implementation(project(":feature:feed"))
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions composeApp/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import androidx.compose.runtime.Composable
import com.stslex.core.core.coreModule
import com.stslex.core.ui.theme.AppTheme
import com.stslex.feature.home.di.homeModule
import com.stslex.feature.feed.di.feedModule
import di.appModule
import org.koin.compose.KoinApplication
import org.koin.dsl.KoinAppDeclaration
Expand Down Expand Up @@ -30,7 +30,7 @@ private fun setupModules(): KoinAppDeclaration = {
listOf(
appModule,
coreModule,
homeModule,
feedModule,
)
)
}
4 changes: 2 additions & 2 deletions composeApp/src/commonMain/kotlin/InitialApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.navigator.Navigator
import com.stslex.feature.home.ui.HomeScreen
import main_screen.MainScreen

@Composable
fun InitialApp(
Expand All @@ -22,7 +22,7 @@ fun InitialApp(
modifier = Modifier.fillMaxSize()
.padding(paddingValues)
) {
Navigator(HomeScreen)
Navigator(MainScreen)
}
}
}
2 changes: 1 addition & 1 deletion composeApp/src/commonMain/kotlin/di/appModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package di

import AppNavigatorImpl
import navigator.AppNavigatorImpl
import com.stslex.core.ui.navigation.AppNavigator
import org.koin.dsl.module

Expand Down
33 changes: 33 additions & 0 deletions composeApp/src/commonMain/kotlin/main_screen/FeedTab.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main_screen

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.List
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import com.stslex.feature.feed.ui.FeedScreenSetup

object FeedTab : Tab {

override val options: TabOptions
@Composable
get() {
val title = "feed"
val icon = rememberVectorPainter(Icons.Default.List)

return remember {
TabOptions(
index = 0u,
title = title,
icon = icon
)
}
}

@Composable
override fun Content() {
FeedScreenSetup()
}
}
63 changes: 63 additions & 0 deletions composeApp/src/commonMain/kotlin/main_screen/MainScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main_screen

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.tab.CurrentTab
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabNavigator

object MainScreen : Screen {

@Composable
override fun Content() {
TabNavigator(FeedTab) {
Scaffold(
content = { paddingValues ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
CurrentTab()
}
},
bottomBar = {
NavigationBar {
TabNavigationItem(FeedTab)
TabNavigationItem(ProfileTab)
}
}
)
}
}
}

@Composable
private fun RowScope.TabNavigationItem(tab: Tab) {
val tabNavigator = LocalTabNavigator.current

NavigationBarItem(
selected = tabNavigator.current == tab,
onClick = { tabNavigator.current = tab },
label = { Text(tab.options.title) },
alwaysShowLabel = false,
icon = {
Icon(
painter = checkNotNull(tab.options.icon),
contentDescription = tab.options.title
)
}
)
}

33 changes: 33 additions & 0 deletions composeApp/src/commonMain/kotlin/main_screen/ProfileTab.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main_screen

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountBox
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions

object ProfileTab : Tab {

override val options: TabOptions
@Composable
get() {
val title = "profile"
val icon = rememberVectorPainter(Icons.Default.AccountBox)

return remember {
TabOptions(
index = 1u,
title = title,
icon = icon
)
}
}

@Composable
override fun Content() {
Text("Profile")
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package navigator

import cafe.adriel.voyager.navigator.Navigator
import com.stslex.core.ui.navigation.AppNavigator
import com.stslex.core.ui.navigation.AppScreen
import com.stslex.feature.home.ui.HomeScreen
import com.stslex.feature.home.ui.SecondScreen
import main_screen.MainScreen

class AppNavigatorImpl(
private val navigator: Lazy<Navigator>
Expand All @@ -12,8 +13,7 @@ class AppNavigatorImpl(
screen: AppScreen
) {
when (screen) {
AppScreen.Home -> navigator.value.push(HomeScreen)
is AppScreen.SecondScreen -> navigator.value.push(SecondScreen(screen.text))
AppScreen.Main -> navigator.value.push(MainScreen)
}
}
}
1 change: 1 addition & 0 deletions core/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ kotlin {
implementation(compose.foundation)
api(libs.koin.core)
api(libs.koin.compose)
api(libs.kotlinx.collections.immutable)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
Expand Down
3 changes: 3 additions & 0 deletions core/ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ kotlin {
api(libs.koin.android)
api(libs.koin.androidx.compose)
}
dependencies {
debugApi(libs.compose.ui.tooling)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
Expand Down Expand Up @@ -43,15 +45,16 @@ abstract class BaseStore<S : State, E : Event, A : Action, N : Navigation>(
}
}

val event: MutableSharedFlow<E> = MutableSharedFlow()
private val _event: MutableSharedFlow<E> = MutableSharedFlow()
val event: SharedFlow<E> = _event.asSharedFlow()

fun updateState(update: (S) -> S) {
_state.update(update)
}

fun sendEvent(event: E) {
scope.launch(appDispatcher.default) {
this@BaseStore.event.emit(event)
this@BaseStore._event.emit(event)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@ package com.stslex.core.ui.navigation

sealed interface AppScreen {

data object Home : AppScreen

data class SecondScreen(val text: String) : AppScreen
data object Main : AppScreen
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ kotlin {
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "home"
baseName = "feed"
isStatic = true
}
}
Expand All @@ -38,7 +38,7 @@ kotlin {
}

android {
namespace = "com.stslex.feature.home"
namespace = "com.stslex.feature.feed"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.stslex.feature.feed.data.model

data class FeedDataModel(
val films: List<FilmDataModel>,
val hasNextPage: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.feature.feed.data.model

data class FilmDataModel(
val id: String,
val title: String,
val description: String,
val imageUrl: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.feature.feed.data.repository

import com.stslex.feature.feed.data.model.FeedDataModel

interface FeedRepository {

suspend fun getFeed(page: Int, pageSize: Int): FeedDataModel
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.stslex.feature.feed.data.repository

import com.stslex.feature.feed.data.model.FeedDataModel

class FeedRepositoryImpl : FeedRepository {
override suspend fun getFeed(page: Int, pageSize: Int): FeedDataModel {
TODO("Not yet implemented")
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.stslex.feature.feed.data.repository

import com.stslex.core.core.Logger
import com.stslex.feature.feed.data.model.FeedDataModel
import com.stslex.feature.feed.data.model.FilmDataModel
import kotlinx.coroutines.delay

class MockFeedRepositoryImpl : FeedRepository {

override suspend fun getFeed(
page: Int,
pageSize: Int
): FeedDataModel {
Logger.debug("getFeed page: $page, pageSize: $pageSize")
delay(3000)
return FeedDataModel(
films = Array(pageSize) { index ->
val itemIndex = page.dec() * pageSize + index
FilmDataModel(
id = itemIndex.toString(),
title = "Title $itemIndex",
description = "Description $itemIndex",
imageUrl = "https://picsum.photos/200/300"
)
}.toList(),
hasNextPage = true
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.stslex.feature.feed.di

import com.stslex.core.ui.base.viewModelDefinition
import com.stslex.feature.feed.data.repository.FeedRepository
import com.stslex.feature.feed.data.repository.MockFeedRepositoryImpl
import com.stslex.feature.feed.domain.interactor.FeedInteractor
import com.stslex.feature.feed.domain.interactor.FeedInteractorImpl
import com.stslex.feature.feed.navigation.FeedScreenRouter
import com.stslex.feature.feed.navigation.FeedScreenRouterImpl
import com.stslex.feature.feed.ui.store.FeedScreenStore
import org.koin.dsl.module

val feedModule = module {
viewModelDefinition {
FeedScreenStore(
interactor = get(),
appDispatcher = get(),
router = get()
)
}

factory<FeedScreenRouter> { FeedScreenRouterImpl(get()) }
factory<FeedInteractor> { FeedInteractorImpl(get()) }
factory<FeedRepository> { MockFeedRepositoryImpl() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.feature.feed.domain.interactor

import com.stslex.feature.feed.domain.model.FeedDomainModel

interface FeedInteractor {

suspend fun getFeed(page: Int, pageSize: Int): FeedDomainModel
}
Loading

0 comments on commit be51fdf

Please sign in to comment.