Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ plugins {
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.kotlinxSerialization)
alias(libs.plugins.kapt)
alias(libs.plugins.compose.compiler)
}

android {
Expand Down Expand Up @@ -34,6 +35,7 @@ android {
}
buildFeatures {
viewBinding true
compose true
}
}

Expand All @@ -55,14 +57,17 @@ dependencies {
implementation libs.lifecycle.runtime.ktx
implementation libs.navigation.fragment.ktx
implementation libs.navigation.ui.ktx
implementation libs.coil
implementation libs.coil.compose
implementation libs.gson
implementation libs.bundles.network
implementation libs.kotlin.serialization
implementation libs.kotlinx.serializationJson
implementation libs.androidx.datastore
implementation libs.androidx.datastore.preferences

implementation platform(libs.compose.bom)
implementation libs.bundles.compose

implementation libs.dagger
kapt libs.daggerCompiler

Expand Down
58 changes: 48 additions & 10 deletions app/src/main/java/ru/otus/marketsample/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,64 @@
package ru.otus.marketsample

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
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.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode.Companion.Screen
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.core.os.bundleOf
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.createGraph
import androidx.navigation.findNavController
import androidx.navigation.toRoute
import ru.otus.marketsample.databinding.ActivityMainBinding
import ru.otus.marketsample.details.feature.DetailsViewModel
import ru.otus.marketsample.details.feature.di.DaggerDetailsComponent
import ru.otus.marketsample.products.feature.ProductListViewModel
import ru.otus.marketsample.products.feature.ProductsScreen
import ru.otus.marketsample.products.feature.di.DaggerProductListComponent
import ru.otus.marketsample.promo.feature.PromosScreen

class MainActivity : AppCompatActivity() {
sealed class ScreenRoute(val route: String, val title: String, val icon: ImageVector) {
object Products: ScreenRoute("products_screen", "Products", Icons.Default.Home)
object Promos: ScreenRoute("promos_screen", "Promos", Icons.Default.Settings)
}

private lateinit var binding: ActivityMainBinding
class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

ViewCompat.setOnApplyWindowInsetsListener(binding.container) { view, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
enableEdgeToEdge()
setContent {
MaterialTheme {
MainNavigation()
}
}
}
}
135 changes: 135 additions & 0 deletions app/src/main/java/ru/otus/marketsample/MainNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package ru.otus.marketsample

import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.core.os.bundleOf
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.viewModelFactory
import androidx.navigation.NavController
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.findNavController
import ru.otus.common.di.findDependencies
import ru.otus.marketsample.products.feature.ProductListViewModel
import ru.otus.marketsample.products.feature.ProductsScreen
import ru.otus.marketsample.products.feature.di.DaggerProductListComponent
import ru.otus.marketsample.products.feature.di.ProductListComponentDependencies
import ru.otus.marketsample.promo.feature.PromoListViewModel
import ru.otus.marketsample.promo.feature.PromosScreen
import ru.otus.marketsample.promo.feature.di.DaggerPromoComponent
import ru.otus.marketsample.promo.feature.di.PromoComponentDependencies

@Composable
fun MainNavigation() {
val navController = rememberNavController()

Scaffold(
bottomBar = {
NavigationBar {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination

listOf(ScreenRoute.Products, ScreenRoute.Promos).forEach { screen ->
NavigationBarItem(
icon = {
Icon(screen.icon, contentDescription = screen.title)
},
label = { Text(screen.title) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(
navController = navController,
startDestination = ScreenRoute.Products.route,
modifier = Modifier.padding(innerPadding)
) {
composable(ScreenRoute.Products.route) {
ProductListScreenContent()
}
composable(ScreenRoute.Promos.route) {
PromoListScreenContent()
}
}
}
}

data class NavigationItem(
val title: String,
val icon: ImageVector,
val route: String
)

@Composable
fun ProductListScreenContent() {
val dependencies = LocalContext.current.findDependencies<ProductListComponentDependencies>()
val component = DaggerProductListComponent.factory().create(dependencies)
val viewModel: ProductListViewModel = viewModel(factory = component.viewModelFactory())
val state by viewModel.state.collectAsState()
ProductsScreen(
state = state,
onRefresh = { viewModel.refresh() },
onItemClicked = { productId ->
// requireActivity().findNavController(R.id.nav_host_activity_main)
// .navigate(
// resId = R.id.action_main_to_details,
// args = bundleOf("productId" to productId),
// )
},
onErrorShown = { viewModel.errorHasShown() }
)
}

@Composable
fun PromoListScreenContent() {
val dependencies = LocalContext.current.findDependencies<PromoComponentDependencies>()
val component = DaggerPromoComponent.factory().create(dependencies)
val viewModel: PromoListViewModel = viewModel(factory = component.viewModelFactory())
val state by viewModel.state.collectAsState()

PromosScreen(
state = state,
onRefresh = { viewModel.refresh() },
onItemClicked = { productId ->
// requireActivity().findNavController(R.id.nav_host_activity_main)
// .navigate(
// resId = R.id.action_main_to_details,
// args = bundleOf("productId" to productId),
// )
},
onErrorShown = { viewModel.errorHasShown() }
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ class DetailsFragment : Fragment() {
override fun onAttach(context: Context) {
super.onAttach(context)

DaggerDetailsComponent.factory()
.create(
dependencies = findDependencies(),
productId = productId,
)
.inject(this)
// DaggerDetailsComponent.factory()
// .create(
// dependencies = findDependencies(),
// productId = productId,
// )
// .inject(this)
}

override fun onCreateView(
Expand Down
Loading