Skip to content
Snippets Groups Projects
Commit e7c1b0ca authored by Baryshnikov Oleg's avatar Baryshnikov Oleg
Browse files

Add the get character by id API method.

Add location and origin fields to the character info model.
Implement get character functions in repository and UI layers.
parent fb2b4114
Branches master
No related tags found
No related merge requests found
Showing
with 487 additions and 129 deletions
......@@ -55,20 +55,14 @@ fun MainScreen() {
modifier = Modifier.fillMaxSize(1f),
snackbarHost = { SnackbarHost(snackbarHostState) },
topBar = {
MyTopAppBar(selectedScreen, snackbarHostState)
MyTopAppBar(selectedScreen, {})
},
content = { innerPadding ->
NavHost(
MyNavHost(
navController,
startDestination = Screen.Characters.route,
snackbarHostState,
Modifier.padding(innerPadding)
) {
composable(Screen.Characters.route) {
CharacterListScreen(snackbarHostState)
}
composable(Screen.Favorite.route) { }
composable(Screen.CharacterDetail.route) { }
}
)
},
bottomBar = {
MyNavigationBar(navController, selectedScreen)
......
package cz.fel.barysole.ackeetesttask
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import cz.fel.barysole.ackeetesttask.ui.screen.Screen
import cz.fel.barysole.ackeetesttask.ui.screen.characterdetail.CharacterDetailScreen
import cz.fel.barysole.ackeetesttask.ui.screen.characterlist.CharacterListScreen
@Composable
fun MyNavHost(
navController: NavHostController,
snackbarHostState: SnackbarHostState,
modifier: Modifier
) {
NavHost(
navController,
startDestination = Screen.Characters.route,
modifier = modifier
) {
composable(Screen.Characters.route) {
CharacterListScreen(
snackbarHostState,
onItemSelected = { characterId ->
navController.navigate(Screen.CharacterDetail.routeWithoutArgument + "/" + characterId) {
launchSingleTop = true
}
}
)
}
composable(Screen.Favorite.route) { }
composable(
Screen.CharacterDetail.route,
arguments = listOf(navArgument("characterId") { type = NavType.LongType })
) { backStackEntry ->
CharacterDetailScreen(backStackEntry.arguments?.getLong("characterId"))
}
}
}
package cz.fel.barysole.ackeetesttask.api
import cz.fel.barysole.ackeetesttask.api.response.CharacterListResponse
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
interface RickAndMortyApi {
......@@ -20,4 +22,10 @@ interface RickAndMortyApi {
@Query("page") page: Int,
): CharacterListResponse
@GET("character/{id}")
suspend fun getCharacterById(
@Path("id") id: Long
): CharacterInfo
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ interface CharacterDao {
fun getAll(): PagingSource<Int, CharacterInfo>
@Query("SELECT * FROM CharacterInfo WHERE id=:id")
fun getById(id: Long): CharacterInfo?
suspend fun getById(id: Long): CharacterInfo?
@Query(
"SELECT * FROM CharacterInfo WHERE " +
......
package cz.fel.barysole.ackeetesttask.model
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.annotations.SerializedName
......@@ -16,8 +17,8 @@ data class CharacterInfo(
@field:SerializedName("species") val species: String?,
@field:SerializedName("type") val type: String?,
@field:SerializedName("gender") val gender: String?,
@field:SerializedName("origin.name") val origin: String?,
@field:SerializedName("location.name") val location: String?,
@field:SerializedName("origin") @Embedded val origin: Origin?,
@field:SerializedName("location") @Embedded val location: Location?,
// Locally saved favorite state
var isFavorite: Boolean = false,
)
package cz.fel.barysole.ackeetesttask.model
import com.google.gson.annotations.SerializedName
data class Location(
@field:SerializedName("name") val locationName: String?
)
package cz.fel.barysole.ackeetesttask.model
import com.google.gson.annotations.SerializedName
data class Origin(
@field:SerializedName("name") val originName: String?
)
\ No newline at end of file
package cz.fel.barysole.ackeetesttask.repository
class RepositoryResult {
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ import cz.fel.barysole.ackeetesttask.api.RickAndMortyApi
import cz.fel.barysole.ackeetesttask.db.room.AppDatabase
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
import cz.fel.barysole.ackeetesttask.model.PaginationInfo
import cz.fel.barysole.ackeetesttask.repository.characters.CharacterRepositoryImpl.Companion.insertCharacterItems
import cz.fel.barysole.ackeetesttask.repository.pagination.PaginationDataType
import retrofit2.HttpException
import java.io.IOException
......@@ -72,7 +73,7 @@ class CharacterRemoteMediator(
if (response.paginationInfo?.next == null) null else requiredPage + 1
)
)
insertCharacterItems(response.items)
insertCharacterItems(response.items, appDatabase.characterDao())
}
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (exception: IOException) {
......@@ -82,20 +83,6 @@ class CharacterRemoteMediator(
}
}
// Save isFavorite flag during items update in the DB
private suspend fun insertCharacterItems(items: List<CharacterInfo>) {
// clear the character table in the database
appDatabase.characterDao().deleteNotFavorite()
for (item in items) {
val itemInDb = appDatabase.characterDao().getById(item.id)
if (itemInDb?.isFavorite == true) {
appDatabase.characterDao().insert(item.copy(isFavorite = true))
} else {
appDatabase.characterDao().insert(item)
}
}
}
companion object {
const val STARTING_PAGE_NUMBER = 1
}
......
......@@ -10,4 +10,6 @@ interface CharacterRepository {
fun getCharactersFlow(): Flow<PagingData<CharacterInfo>>
suspend fun getCharacter(characterId: Long): CharacterInfo?
}
\ No newline at end of file
......@@ -4,10 +4,17 @@ import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import cz.fel.barysole.ackeetesttask.api.RickAndMortyApi
import cz.fel.barysole.ackeetesttask.db.room.AppDatabase
import cz.fel.barysole.ackeetesttask.db.room.dao.CharacterDao
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
import cz.fel.barysole.ackeetesttask.model.PaginationInfo
import cz.fel.barysole.ackeetesttask.repository.pagination.PaginationDataType
import kotlinx.coroutines.flow.Flow
import retrofit2.HttpException
import java.io.IOException
import javax.inject.Inject
import javax.inject.Singleton
......@@ -40,9 +47,31 @@ class CharacterRepositoryImpl @Inject constructor(
).flow
}
override suspend fun getCharacter(characterId: Long): CharacterInfo? {
val response = rickAndMortyApi.getCharacterById(characterId)
appDatabase.withTransaction {
insertCharacterItems(listOf(response), appDatabase.characterDao())
}
return appDatabase.characterDao().getById(characterId)
}
companion object {
//based on this description - https://rickandmortyapi.com/documentation/#info-and-pagination
const val NETWORK_PAGE_SIZE = 20
// Save isFavorite flag during items update in the DB
suspend fun insertCharacterItems(items: List<CharacterInfo>, characterDao: CharacterDao) {
// clear the character table in the database
characterDao.deleteNotFavorite()
for (item in items) {
val itemInDb = characterDao.getById(item.id)
if (itemInDb?.isFavorite == true) {
characterDao.insert(item.copy(isFavorite = true))
} else {
characterDao.insert(item)
}
}
}
}
}
\ No newline at end of file
......@@ -4,10 +4,10 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import cz.fel.barysole.ackeetesttask.R
sealed class Screen(val route: String, @StringRes val nameResId: Int, @DrawableRes val iconResId: Int? = null) {
sealed class Screen(val route: String, val nameResId: Int, @DrawableRes val iconResId: Int? = null, val routeWithoutArgument: String? = null) {
object Characters : Screen("characters", R.string.characters, R.drawable.ic_rick_face)
object Favorite : Screen("favorite", R.string.favorite, R.drawable.baseline_star_24)
object CharacterDetail : Screen("characterdetail", R.string.character_detail)
object CharacterDetail : Screen("characterdetail/{characterId}", R.string.character_detail, routeWithoutArgument = "characterdetail")
}
val appScreenList = listOf(
......
package cz.fel.barysole.ackeetesttask.ui.screen.characterdetail
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@Composable
fun CharacterDetailScreen(
characterId: Long?,
viewModel: CharacterDetailViewModel = hiltViewModel()
) {
viewModel.onRefreshData(characterId)
val characterDetailScreenState by viewModel.uiState.collectAsState()
Surface(
shape = MaterialTheme.shapes.large,
color = MaterialTheme.colorScheme.surface,
shadowElevation = 4.dp,
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 8.dp)
.fillMaxSize(1f)
) {
characterDetailScreenState.characterInfo?.let { character ->
CharacterInfo(character = character, 16.dp, 16.dp, 24.dp)
}
}
}
\ No newline at end of file
package cz.fel.barysole.ackeetesttask.ui.screen.characterdetail
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
import cz.fel.barysole.ackeetesttask.repository.characters.CharacterRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class CharacterDetailViewModel @Inject constructor(
private val characterRepository: CharacterRepository
) : ViewModel() {
// The UI state
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
fun showLoadingError(hasError: Boolean) {
_uiState.update { state -> state.copy(showError = hasError) }
}
fun onRefreshData(characterId: Long?) {
showLoadingError(false)
characterId?.let {
viewModelScope.launch {
_uiState.update { state ->
state.copy(
characterInfo = characterRepository.getCharacter(
characterId
)
)
}
}
}
}
data class UiState(
val showError: Boolean = false,
val characterInfo: CharacterInfo? = null
)
}
\ No newline at end of file
package cz.fel.barysole.ackeetesttask.ui.screen.characterdetail
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
import cz.fel.barysole.ackeetesttask.model.Location
import cz.fel.barysole.ackeetesttask.model.Origin
@Composable
@OptIn(ExperimentalGlideComposeApi::class)
fun CharacterInfo(character: CharacterInfo, startPaddingForElements: Dp = 0.dp, topPaddingForElements: Dp = 0.dp, itemSpaceSize: Dp = 0.dp) {
Column(
modifier = Modifier
.fillMaxWidth(1f)
) {
Row {
character.image?.let {
GlideImage(
model = it,
contentDescription = "Character image",
modifier = Modifier
.padding(top = topPaddingForElements, start = startPaddingForElements)
.size(128.dp)
.clip(MaterialTheme.shapes.small)
)
}
Column (modifier = Modifier.padding(top = topPaddingForElements, start = startPaddingForElements)) {
Text(
text = "Name",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
modifier = Modifier.padding(top = 8.dp),
text = "${character.name}",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(4.dp))
}
}
Divider(modifier = Modifier.padding(top = 16.dp, bottom = 16.dp))
Row (modifier = Modifier.padding(start = startPaddingForElements)) {
Column {
Text(
text = "Status",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = "${character.status}",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(itemSpaceSize))
Text(
text = "Type",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = if (character.type.isNullOrBlank()) "-" else character.type,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(itemSpaceSize))
Text(
text = "Gender",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = "${character.gender}",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(itemSpaceSize))
Text(
text = "Origin",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = "${character.origin?.originName}",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(itemSpaceSize))
Text(
text = "Location",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = "${character.location?.locationName}",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
}
}
}
@Preview
@Composable
fun CharacterInfoPreview() {
CharacterInfo(
character = CharacterInfo(
id = 2,
name = "Morty Smith",
status = "Alive",
species = "Human",
type = "",
gender = "Male",
origin = Origin("Earth"),
location = Location("Earth"),
image = "https://rickandmortyapi.com/api/character/avatar/2.jpeg"
)
)
}
\ No newline at end of file
......@@ -22,6 +22,7 @@ import cz.fel.barysole.ackeetesttask.ui.uielement.character.CharacterList
@Composable
fun CharacterListScreen(
snackbar: SnackbarHostState,
onItemSelected: (id: Long) -> Unit,
characterListViewModel: CharacterListViewModel = hiltViewModel()
) {
Surface(
......@@ -56,7 +57,7 @@ fun CharacterListScreen(
}
}
} else {
CharacterList(it)
CharacterList(it, onItemSelected)
}
}
}
......
package cz.fel.barysole.ackeetesttask.ui.uielement.character
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
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.clip
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.paging.compose.LazyPagingItems
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
@Composable
fun CharacterList(characterList: LazyPagingItems<CharacterInfo>) {
fun CharacterList(
characterList: LazyPagingItems<CharacterInfo>,
onItemSelected: (id: Long) -> Unit
) {
LazyColumn(modifier = Modifier.padding(vertical = 4.dp)) {
items(
count = characterList.itemCount,
contentType = { if (characterList[it] == null) 1 else 0 }
) { index ->
characterList[index]?.let {
CharacterListItem(it)
}
}
}
}
@OptIn(ExperimentalGlideComposeApi::class)
@Composable
fun CharacterListItem(character: CharacterInfo) {
Surface(
shape = MaterialTheme.shapes.large,
color = MaterialTheme.colorScheme.surface,
shadowElevation = 4.dp,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Row(
modifier = Modifier
.padding(all = 10.dp)
.fillMaxWidth(1f),
verticalAlignment = Alignment.CenterVertically
) {
character.image?.let {
GlideImage(
model = it,
contentDescription = "Character image",
modifier = Modifier
.size(48.dp)
.clip(MaterialTheme.shapes.small)
)
}
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
text = "${character.name}",
style = MaterialTheme.typography.titleMedium,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(4.dp))
character.status?.let {
Text(
text = character.status,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
CharacterListItem(it, onItemSelected)
}
}
}
......
package cz.fel.barysole.ackeetesttask.ui.uielement.character
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
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.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
import cz.fel.barysole.ackeetesttask.model.CharacterInfo
@OptIn(ExperimentalGlideComposeApi::class)
@Composable
fun CharacterListItem(character: CharacterInfo, onItemSelected: (id: Long) -> Unit) {
Surface(
shape = MaterialTheme.shapes.large,
color = MaterialTheme.colorScheme.surface,
shadowElevation = 4.dp,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp).clickable { onItemSelected(character.id) }
) {
Row(
modifier = Modifier
.padding(all = 10.dp)
.fillMaxWidth(1f),
verticalAlignment = Alignment.CenterVertically
) {
character.image?.let {
GlideImage(
model = it,
contentDescription = "Character image",
modifier = Modifier
.size(48.dp)
.clip(MaterialTheme.shapes.small)
)
}
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
text = "${character.name}",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(4.dp))
character.status?.let {
Text(
text = character.status,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
}
}
\ No newline at end of file
......@@ -23,39 +23,41 @@ fun MyNavigationBar(navController: NavController, selectedScreen: Screen?) {
Screen.Characters,
Screen.Favorite
)
NavigationBar(
modifier = Modifier.shadow(8.dp),
containerColor = MaterialTheme.colorScheme.surface,
tonalElevation = 0.dp
) {
navBarItems.forEach {screen ->
NavigationBarItem(
icon = {
if (screen.iconResId != null) {
Icon(
painterResource(screen.iconResId),
contentDescription = stringResource(screen.nameResId),
modifier = Modifier.size(24.dp)
)
}
},
label = { Text(stringResource(screen.nameResId)) },
selected = selectedScreen == screen,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
if (selectedScreen == Screen.Characters || selectedScreen == Screen.Favorite) {
NavigationBar(
modifier = Modifier.shadow(8.dp),
containerColor = MaterialTheme.colorScheme.surface,
tonalElevation = 0.dp
) {
navBarItems.forEach { screen ->
NavigationBarItem(
icon = {
if (screen.iconResId != null) {
Icon(
painterResource(screen.iconResId),
contentDescription = stringResource(screen.nameResId),
modifier = Modifier.size(24.dp)
)
}
},
label = { Text(stringResource(screen.nameResId)) },
selected = selectedScreen == screen,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
// Avoid multiple copies of the same destination when reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
)
}
}
}
}
\ No newline at end of file
......@@ -35,7 +35,7 @@ import kotlinx.coroutines.launch
@Composable
fun MySearchBar(
isSearchBarShowing: MutableState<Boolean>,
snackbar: SnackbarHostState,
onItemSelected: (id: Long) -> Unit,
characterSearchViewModel: CharacterSearchViewModel = hiltViewModel()
) {
val isSearchBarIsActive = rememberSaveable {
......@@ -87,7 +87,7 @@ fun MySearchBar(
Text("Data cannot be loaded!", style = MaterialTheme.typography.titleMedium, textAlign = TextAlign.Center)
}
} else {
CharacterList(it)
CharacterList(it, onItemSelected)
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment