поиск

This commit is contained in:
dasha 2023-12-17 17:13:27 +04:00
parent 3dc39aa82f
commit 55a0ac8581
9 changed files with 74924 additions and 49 deletions

View File

@ -1,6 +1,5 @@
package com.example.myapplication.api.cinema package com.example.myapplication.api.cinema
import android.util.Log
import androidx.paging.ExperimentalPagingApi import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
@ -24,11 +23,7 @@ class RestCinemaRepository(
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase private val database: AppDatabase
) : CinemaRepository { ) : CinemaRepository {
override fun getAllCinemas(): Flow<PagingData<Cinema>> { override fun getAllCinemas(name: String): Flow<PagingData<Cinema>> {
Log.d(RestCinemaRepository::class.simpleName, "Get cinemas")
val pagingSourceFactory = { dbCinemaRepository.getAllCinemasPagingSource() }
@OptIn(ExperimentalPagingApi::class) @OptIn(ExperimentalPagingApi::class)
return Pager( return Pager(
config = PagingConfig( config = PagingConfig(
@ -42,8 +37,13 @@ class RestCinemaRepository(
dbRemoteKeyRepository, dbRemoteKeyRepository,
database, database,
), ),
pagingSourceFactory = pagingSourceFactory ) {
).flow if (name.isEmpty()) {
dbCinemaRepository.getAllCinemasPagingSource()
} else {
dbCinemaRepository.getAllCinemasPagingSource(name)
}
}.flow
} }
override suspend fun getCinema(uid: Int): CinemaWithSessions { override suspend fun getCinema(uid: Int): CinemaWithSessions {

View File

@ -0,0 +1,63 @@
package com.example.myapplication.composeui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun Search(
initValue: String,
onDone: (String) -> Unit,
modifier: Modifier
) {
val maxLength = 20
val (value, setValue) = remember { mutableStateOf(initValue) }
fun clear() {
setValue("")
onDone("")
}
fun handleChange(newValue: String) {
if (newValue.length > maxLength) {
return
} else if (newValue.isEmpty()) {
clear()
}
setValue(newValue)
}
fun handleDone() {
onDone(value)
}
BasicTextField(
value = value,
onValueChange = { handleChange(it) },
modifier = modifier,
singleLine = true,
keyboardActions = KeyboardActions(
onDone = { handleDone() }
)
)
Spacer(modifier = Modifier.width(16.dp))
Icon(
imageVector = Icons.Default.Search,
contentDescription = null,
modifier = Modifier
.size(30.dp)
.clickable { handleDone() },
tint = MaterialTheme.colorScheme.secondary,
)
}

View File

@ -12,13 +12,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
@ -29,9 +25,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -49,6 +42,7 @@ import androidx.navigation.navArgument
import com.example.myapplication.LiveStore import com.example.myapplication.LiveStore
import com.example.myapplication.composeui.Cart import com.example.myapplication.composeui.Cart
import com.example.myapplication.composeui.Report import com.example.myapplication.composeui.Report
import com.example.myapplication.composeui.Search
import com.example.myapplication.database.entities.composeui.CinemaList import com.example.myapplication.database.entities.composeui.CinemaList
import com.example.myapplication.database.entities.composeui.CinemaView import com.example.myapplication.database.entities.composeui.CinemaView
import com.example.myapplication.database.entities.composeui.OrderList import com.example.myapplication.database.entities.composeui.OrderList
@ -64,7 +58,6 @@ fun Topbar(
navController: NavHostController, navController: NavHostController,
currentScreen: Screen? currentScreen: Screen?
) { ) {
var searchQuery by remember { mutableStateOf("") }
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -100,9 +93,12 @@ fun Topbar(
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
BasicTextField( if (currentScreen?.route == Screen.CinemaList.route) {
value = searchQuery, Search(
onValueChange = { newValue -> searchQuery = newValue }, initValue = LiveStore.searchRequest.value ?: "",
onDone = {
LiveStore.searchRequest.value = it
},
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.height(36.dp) .height(36.dp)
@ -110,28 +106,12 @@ fun Topbar(
color = MaterialTheme.colorScheme.onPrimary, color = MaterialTheme.colorScheme.onPrimary,
RoundedCornerShape(18.dp) RoundedCornerShape(18.dp)
) )
.padding(start = 13.dp, top = 8.dp), .padding(start = 13.dp, top = 8.dp)
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = androidx.compose.ui.text.input.ImeAction.Search
),
keyboardActions = KeyboardActions(
onSearch = { }
)
)
Spacer(modifier = Modifier.width(16.dp))
Icon(
imageVector = Icons.Default.Search,
contentDescription = null,
modifier = Modifier
.size(30.dp)
.clickable { },
tint = MaterialTheme.colorScheme.secondary
) )
} }
} }
} }
}
@Composable @Composable
fun Navbar( fun Navbar(

View File

@ -26,6 +26,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -48,8 +49,13 @@ fun CinemaList(
viewModel: CinemaListViewModel = viewModel(factory = AppViewModelProvider.Factory) viewModel: CinemaListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val cinemaPagingItems = viewModel.cinemaListUiState.collectAsLazyPagingItems() val cinemaPagingItems = viewModel.cinemaPagingFlow.flow.collectAsLazyPagingItems()
val user = LiveStore.user.observeAsState() val user = LiveStore.user.observeAsState()
val searchPattern = LiveStore.searchRequest.observeAsState("")
LaunchedEffect(searchPattern.value) {
viewModel.refresh()
}
Scaffold( Scaffold(
topBar = {}, topBar = {},

View File

@ -1,17 +1,35 @@
package com.example.myapplication.database.entities.composeui package com.example.myapplication.database.entities.composeui
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.example.myapplication.LiveStore
import com.example.myapplication.database.entities.model.Cinema import com.example.myapplication.database.entities.model.Cinema
import com.example.myapplication.database.entities.repository.CinemaRepository import com.example.myapplication.database.entities.repository.CinemaRepository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
class CinemaListViewModel( class CinemaListViewModel(
private val cinemaRepository: CinemaRepository private val cinemaRepository: CinemaRepository
) : ViewModel() { ) : ViewModel() {
val cinemaListUiState: Flow<PagingData<Cinema>> = cinemaRepository.getAllCinemas() var cinemaPagingFlow by mutableStateOf(ProductPagingFlowState())
private set
fun refresh() {
val name = "%${LiveStore.searchRequest.value}%"
val pagingSource = cinemaRepository.getAllCinemas(name)
cinemaPagingFlow = ProductPagingFlowState(pagingSource.cachedIn(viewModelScope))
}
suspend fun deleteCinema(cinema: Cinema) { suspend fun deleteCinema(cinema: Cinema) {
cinemaRepository.deleteCinema(cinema) cinemaRepository.deleteCinema(cinema)
} }
} }
data class ProductPagingFlowState(
val flow: Flow<PagingData<Cinema>> = emptyFlow(),
)

View File

@ -14,6 +14,8 @@ import kotlinx.coroutines.flow.Flow
interface CinemaDao { interface CinemaDao {
@Query("select * from cinemas order by name") @Query("select * from cinemas order by name")
fun getAll(): PagingSource<Int, Cinema> fun getAll(): PagingSource<Int, Cinema>
@Query("select * from cinemas where cinemas.name like :name order by name collate nocase asc")
fun getAll(name: String): PagingSource<Int, Cinema>
@Query( @Query(
"SELECT c.*, s.uid as session_uid, s.date_time, s.price, s.max_count-IFNULL(SUM(os.count), 0) as available_count, c.uid as cinema_id " + "SELECT c.*, s.uid as session_uid, s.date_time, s.price, s.max_count-IFNULL(SUM(os.count), 0) as available_count, c.uid as cinema_id " +

View File

@ -6,7 +6,7 @@ import com.example.myapplication.database.entities.model.CinemaWithSessions
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface CinemaRepository { interface CinemaRepository {
fun getAllCinemas(): Flow<PagingData<Cinema>> fun getAllCinemas(name: String): Flow<PagingData<Cinema>>
suspend fun getCinema(uid: Int): CinemaWithSessions suspend fun getCinema(uid: Int): CinemaWithSessions
suspend fun insertCinema(cinema: Cinema) suspend fun insertCinema(cinema: Cinema)
suspend fun updateCinema(cinema: Cinema) suspend fun updateCinema(cinema: Cinema)

View File

@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaRepository { class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaRepository {
override fun getAllCinemas(): Flow<PagingData<Cinema>> = Pager( override fun getAllCinemas(name: String): Flow<PagingData<Cinema>> = Pager(
config = PagingConfig( config = PagingConfig(
pageSize = AppContainer.LIMIT, pageSize = AppContainer.LIMIT,
enablePlaceholders = false enablePlaceholders = false
@ -21,6 +21,7 @@ class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaReposito
pagingSourceFactory = cinemaDao::getAll pagingSourceFactory = cinemaDao::getAll
).flow ).flow
override suspend fun getCinema(uid: Int): CinemaWithSessions { override suspend fun getCinema(uid: Int): CinemaWithSessions {
val item = cinemaDao.getByUid(uid) val item = cinemaDao.getByUid(uid)
.map { map -> .map { map ->
@ -43,6 +44,8 @@ class OfflineCinemaRepository(private val cinemaDao: CinemaDao) : CinemaReposito
fun getAllCinemasPagingSource(): PagingSource<Int, Cinema> = cinemaDao.getAll() fun getAllCinemasPagingSource(): PagingSource<Int, Cinema> = cinemaDao.getAll()
fun getAllCinemasPagingSource(name: String): PagingSource<Int, Cinema> = cinemaDao.getAll(name)
suspend fun insertCinemas(cinemas: List<Cinema>) = suspend fun insertCinemas(cinemas: List<Cinema>) =
cinemaDao.insert(*cinemas.toTypedArray()) cinemaDao.insert(*cinemas.toTypedArray())

File diff suppressed because it is too large Load Diff