Skip to content

Commit

Permalink
add profile scree, refactor navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Nov 28, 2023
1 parent f4fde81 commit f3d2ecd
Show file tree
Hide file tree
Showing 38 changed files with 497 additions and 58 deletions.
1 change: 1 addition & 0 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ kotlin {
implementation(project(":core:ui"))
implementation(project(":feature:feed"))
implementation(project(":feature:film"))
implementation(project(":feature:profile"))
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion composeApp/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.stslex.core.network.di.networkModule
import com.stslex.core.ui.theme.AppTheme
import com.stslex.feature.feed.di.feedModule
import com.stslex.feature.film.di.filmModule
import com.stslex.feature.profile.di.profileModule
import di.appModule
import org.koin.compose.KoinApplication
import org.koin.dsl.KoinAppDeclaration
Expand Down Expand Up @@ -34,7 +35,8 @@ private fun setupModules(): KoinAppDeclaration = {
coreModule,
networkModule,
feedModule,
filmModule
filmModule,
profileModule,
)
)
}
5 changes: 4 additions & 1 deletion composeApp/src/commonMain/kotlin/InitialApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.transitions.SlideTransition
import main_screen.MainScreen

@Composable
Expand All @@ -22,7 +23,9 @@ fun InitialApp(
modifier = Modifier.fillMaxSize()
.padding(paddingValues)
) {
Navigator(MainScreen)
Navigator(MainScreen) {
SlideTransition(it)
}
}
}
}
3 changes: 3 additions & 0 deletions composeApp/src/commonMain/kotlin/main_screen/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ 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.TabNavigator
import com.stslex.core.ui.mvi.setupNavigator
import main_screen.bottom_nav_bar.BottomNavigationBar
import main_screen.bottom_nav_bar.FeedTab

object MainScreen : Screen {

@Composable
override fun Content() {
setupNavigator()

TabNavigator(
tab = FeedTab,
) { tabNavigator ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ package main_screen.bottom_nav_bar

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.core.screen.Screen
import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import com.stslex.feature.profile.ui.ProfileScreen

object ProfileTab : Tab {

Expand All @@ -33,11 +32,3 @@ object ProfileTab : Tab {
Navigator(ProfileScreen)
}
}

object ProfileScreen : Screen {

@Composable
override fun Content() {
Text("Profile")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ import co.touchlab.kermit.Logger as Log

object Logger {

const val DEFAULT_TAG = "WIZARD"
private const val DEFAULT_TAG = "WIZARD"

fun exception(
throwable: Throwable,
tag: String? = null,
message: String? = null
) {
// TODO check build config if (BuildConfig.DEBUG.not()) return
val currentTag = "$DEFAULT_TAG:${tag.orEmpty()}"
Log.e(
tag = currentTag,
tag = tag ?: DEFAULT_TAG,
throwable = throwable,
messageString = message ?: throwable.message.orEmpty(),
)
Expand All @@ -25,9 +24,8 @@ object Logger {
tag: String? = null,
) {
// TODO check build config if (BuildConfig.DEBUG.not()) return
val currentTag = "$DEFAULT_TAG:${tag.orEmpty()}"
Log.d(
tag = currentTag,
tag = tag ?: DEFAULT_TAG,
messageString = message
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package com.stslex.core.network.clients.film.client

import com.stslex.core.network.clients.film.model.FilmFeedResponse
import com.stslex.core.network.clients.film.model.FilmResponse
import kotlinx.coroutines.flow.Flow

interface FilmClient {

suspend fun getFeedFilms(page: Int, pageSize: Int): FilmFeedResponse

fun getFilm(id: String): Flow<FilmResponse>
suspend fun getFilm(id: String): FilmResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import com.stslex.core.network.clients.film.model.FilmResponse
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

class FilmClientImpl(
private val client: NetworkClient
Expand All @@ -22,14 +20,9 @@ class FilmClientImpl(
}.body()
}

override fun getFilm(
id: String
): Flow<FilmResponse> = flow {
val film: FilmResponse = client.request {
get("feed") {
parameter("id", id)
}.body()
}
emit(film)
override suspend fun getFilm(id: String): FilmResponse = client.request {
get("feed") {
parameter("id", id)
}.body()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import com.stslex.core.core.Logger
import com.stslex.core.network.clients.film.model.FilmFeedResponse
import com.stslex.core.network.clients.film.model.FilmResponse
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

class MockFilmClientImpl : FilmClient {

Expand All @@ -24,11 +22,7 @@ class MockFilmClientImpl : FilmClient {
)
}

override fun getFilm(
id: String
): Flow<FilmResponse> = flow {
emit(getFilmById(id.toInt()))
}
override suspend fun getFilm(id: String): FilmResponse = getFilmById(id.toInt())

private fun getFilmById(id: Int) = filmsList[id % filmsList.size].copy(
id = id.toString()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.stslex.core.network.clients.profile.client

import com.stslex.core.network.clients.profile.model.ProfileResponse
import kotlinx.coroutines.delay

class MockProfileClientImpl : ProfileClient {

override suspend fun getProfile(uuid: String): ProfileResponse {
delay(2000)
return ProfileResponse(
uuid = "uuid",
username = "John Doe",
avatarUrl = "https://avatars.githubusercontent.com/u/139426?s=460&u=8f6b6e2e4e9e4b0e9b5b5e4e9b5b5e4e9b5b5e4e&v=4",
bio = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec auctor, nisl eu ultricies tincidunt, nisl nisl aliquam nisl,",
followers = 100,
following = 93,
favouriteCount = 873
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.core.network.clients.profile.client

import com.stslex.core.network.clients.profile.model.ProfileResponse

interface ProfileClient {

suspend fun getProfile(uuid: String): ProfileResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.stslex.core.network.clients.profile.client

import com.stslex.core.network.client.NetworkClient
import com.stslex.core.network.clients.profile.model.ProfileResponse
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter

class ProfileClientImpl(
private val client: NetworkClient
) : ProfileClient {

override suspend fun getProfile(
uuid: String
): ProfileResponse = client.request {
get("profile") {
parameter("uuid", uuid)
}.body()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.stslex.core.network.clients.profile.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ProfileResponse(
@SerialName("uuid")
val uuid: String,
@SerialName("username")
val username: String,
@SerialName("avatar_url")
val avatarUrl: String,
@SerialName("bio")
val bio: String,
@SerialName("followers")
val followers: Int,
@SerialName("following")
val following: Int,
@SerialName("favourite_count")
val favouriteCount: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import com.stslex.core.network.client.NetworkClient
import com.stslex.core.network.client.NetworkClientImpl
import com.stslex.core.network.clients.film.client.FilmClient
import com.stslex.core.network.clients.film.client.MockFilmClientImpl
import com.stslex.core.network.clients.profile.client.MockProfileClientImpl
import com.stslex.core.network.clients.profile.client.ProfileClient
import org.koin.dsl.module

val networkModule = module {
single<NetworkClient> {
NetworkClientImpl(appDispatcher = get())
}
single<FilmClient> { MockFilmClientImpl() }
single<ProfileClient> { MockProfileClientImpl() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.stslex.core.core.Logger as Log

object KtorLogger : Logger {

private const val TAG = Log.DEFAULT_TAG + ":KtorLogger"
private const val TAG = "KTOR_LOGGER"

override fun log(message: String) {
Log.debug(message, TAG)
Expand Down
10 changes: 3 additions & 7 deletions core/ui/src/commonMain/kotlin/com/stslex/core/ui/mvi/StoreExt.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
package com.stslex.core.ui.mvi

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import androidx.compose.runtime.LaunchedEffect
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import com.stslex.core.ui.navigation.AppNavigator
import org.koin.compose.getKoin

@Composable
inline fun <reified S : ScreenModel> Screen.getScreenStore(): S {
fun setupNavigator() {
val navigator = LocalNavigator.currentOrThrow
val koin = getKoin()
remember(navigator) {
LaunchedEffect(navigator.hashCode()) {
koin.get<AppNavigator>().setNavigator(navigator)
}
return getScreenModel<S>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.screen.Screen
import com.stslex.core.ui.mvi.getScreenStore
import cafe.adriel.voyager.koin.getScreenModel
import com.stslex.feature.feed.ui.components.FeedScreenContent
import com.stslex.feature.feed.ui.components.FeedScreenError
import com.stslex.feature.feed.ui.components.FeedScreenLoading
Expand All @@ -23,7 +23,7 @@ object FeedScreen : Screen {

@Composable
override fun Content() {
val store = getScreenStore<FeedScreenStore>()
val store = getScreenModel<FeedScreenStore>()
val state by remember { store.state }.collectAsState()
LaunchedEffect(Unit) {
store.event.collect { event ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ import com.stslex.core.network.clients.film.client.FilmClient
import com.stslex.feature.film.data.model.FilmData
import com.stslex.feature.film.data.model.toData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.flow

class FilmRepositoryImpl(
private val client: FilmClient
) : FilmRepository {

override fun getFilm(
id: String
): Flow<FilmData> = client
.getFilm(id = id)
.map { response ->
response.toData()
}
override fun getFilm(id: String): Flow<FilmData> = flow {
val film = client.getFilm(id = id).toData()
emit(film)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.screen.Screen
import com.stslex.core.ui.mvi.getScreenStore
import cafe.adriel.voyager.koin.getScreenModel
import com.stslex.core.ui.mvi.setupNavigator
import com.stslex.feature.film.ui.components.FilmContentScreen
import com.stslex.feature.film.ui.store.FilmScreenState
import com.stslex.feature.film.ui.store.FilmStore
Expand All @@ -26,7 +27,9 @@ data class FilmScreen(

@Composable
override fun Content() {
val store = getScreenStore<FilmStore>()
setupNavigator()

val store = getScreenModel<FilmStore>()
LaunchedEffect(Unit) {
store.sendAction(Action.Init(id))
}
Expand Down
Loading

0 comments on commit f3d2ecd

Please sign in to comment.