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
13 changes: 13 additions & 0 deletions 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)
}

android {
Expand Down Expand Up @@ -34,6 +35,11 @@ android {
}
buildFeatures {
viewBinding true
compose = true
}
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
}

Expand All @@ -55,15 +61,22 @@ dependencies {
implementation libs.lifecycle.runtime.ktx
implementation libs.navigation.fragment.ktx
implementation libs.navigation.ui.ktx
implementation libs.navigation.compose
implementation libs.coil
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 libs.compose.ui
implementation libs.androidx.material3
implementation libs.compose.foundation
implementation libs.coil.compose

implementation libs.dagger
implementation libs.androidx.runtime
implementation libs.androidx.foundation.layout
kapt libs.daggerCompiler

testImplementation libs.junit
Expand Down
19 changes: 4 additions & 15 deletions app/src/main/java/ru/otus/marketsample/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
package ru.otus.marketsample

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import ru.otus.marketsample.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

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
val appComponent = (applicationContext as MarketSampleApp).appComponent
setContent {
MainContent(appComponent)
}
}
}
112 changes: 112 additions & 0 deletions app/src/main/java/ru/otus/marketsample/MainContent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package ru.otus.marketsample

import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
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.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
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 ru.otus.marketsample.common.Screen
import ru.otus.marketsample.details.feature.DetailsScreen
import ru.otus.marketsample.di.AppComponent
import ru.otus.marketsample.products.feature.ProductsScreen
import ru.otus.marketsample.promo.feature.PromoScreen

@Composable
fun MainContent(appComponent: AppComponent) {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val items = listOf(Screen.Products, Screen.Promo)
Scaffold(
bottomBar = {
if (currentRoute != Screen.Details.route) {
BottomBar(
navController = navController,
items = items,
)
}
}
) { innerPadding ->
NavHost(
navController = navController,
startDestination = Screen.Products.route,
modifier = Modifier.padding(innerPadding)
) {
composable(Screen.Products.route) {
ProductsScreen(
appComponent = appComponent,
navController = navController,
)
}
composable(Screen.Promo.route) {
PromoScreen(appComponent)
}
composable(Screen.Details.route) { backStackEntry ->
val productId = backStackEntry.arguments?.getString(Screen.Details.PRODUCT_ID) ?: ""
DetailsScreen(
appComponent = appComponent,
productId = productId
)
}
}
}
}
@Composable
fun BottomBar(
items: List<Screen>,
navController: NavController,
) {
NavigationBar {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination

items.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
ImageVector.vectorResource(
screen.iconRes
),
modifier = Modifier.size(24.dp),
contentDescription = null
)
},
label = { Text(stringResource(screen.titleRes)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
colors = NavigationBarItemDefaults.colors(
selectedIconColor = colorResource(id = ru.otus.common.ui.R.color.purple_500),
selectedTextColor = colorResource(id = ru.otus.common.ui.R.color.purple_500),
indicatorColor = Color.Transparent,
unselectedIconColor = Color.Black,
unselectedTextColor = Color.Black,
),
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) { saveState = true }
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
49 changes: 0 additions & 49 deletions app/src/main/java/ru/otus/marketsample/MainFragment.kt

This file was deleted.

73 changes: 73 additions & 0 deletions app/src/main/java/ru/otus/marketsample/common/DiscountBadge.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ru.otus.marketsample.common

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

@Composable
fun DiscountBadge(
modifier: Modifier = Modifier,
discountText: String,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

по конвенции, аргументы без дефолтного значения должны идти первыми

) {
val purple200 = colorResource(id = ru.otus.common.ui.R.color.purple_200)
val purple500 = colorResource(id = ru.otus.common.ui.R.color.purple_500)
Box(
modifier = modifier
.padding(8.dp)
.drawWithCache {
val cornerRadius = 40.dp.toPx()
val topRightRadius = 10.dp.toPx()
val outlinePath = Path().apply {
addRoundRect(
RoundRect(
rect = Rect(Offset.Zero, size),
topLeft = CornerRadius(cornerRadius),
topRight = CornerRadius(topRightRadius),
bottomRight = CornerRadius(cornerRadius),
bottomLeft = CornerRadius(cornerRadius)
)
)
}
val gradientBrush = Brush.linearGradient(
colors = listOf(purple200, purple500),
start = Offset(0f, size.height),
end = Offset(size.width, 0f)
)

onDrawWithContent {
drawPath(path = outlinePath, brush = gradientBrush)
drawPath(
path = outlinePath,
color = Color.White,
style = Stroke(width = 2.dp.toPx())
)
drawContent()
}
},
contentAlignment = Alignment.Center
) {
Text(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp),
text = discountText,
color = Color.White,
fontSize = 14.sp,
fontWeight = FontWeight.Bold,
)
}
}
20 changes: 20 additions & 0 deletions app/src/main/java/ru/otus/marketsample/common/Loader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.otus.marketsample.common

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

@Composable
fun Loader(
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/ru/otus/marketsample/common/Screen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.otus.marketsample.common

import ru.otus.marketsample.R

sealed class Screen(val route: String, val titleRes: Int, val iconRes: Int) {
object Products : Screen("products_fragment", R.string.title_products, ru.otus.common.ui.R.drawable.ic_list)
object Promo : Screen("promo_fragment", R.string.title_promo, ru.otus.common.ui.R.drawable.ic_discount)
object Details : Screen("details/{productId}", 0, 0) {
const val PRODUCT_ID = "productId"
fun createRoute(productId: String) = "details/$productId"
}
}
Loading