рефакторинг

This commit is contained in:
dasha 2023-12-16 21:00:28 +04:00
parent aab18402b5
commit 3dc39aa82f
40 changed files with 62106 additions and 169 deletions

View File

@ -3,16 +3,12 @@ package com.example.myapplication
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import com.example.myapplication.composeui.Authenticator import com.example.myapplication.composeui.Authenticator
import com.example.myapplication.composeui.navigation.MainNavbar import com.example.myapplication.composeui.navigation.MainNavbar
import com.example.myapplication.datastore.DataStoreManager import com.example.myapplication.datastore.DataStoreManager

View File

@ -1,18 +1,18 @@
package com.example.myapplication.api package com.example.myapplication.api
import androidx.room.TypeConverters import kotlinx.serialization.KSerializer
import com.example.myapplication.database.entities.model.LocalDateTimeConverter import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.* import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.* import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalDateTime
import org.threeten.bp.DateTimeUtils.toLocalDateTime
import org.threeten.bp.format.DateTimeFormatter import org.threeten.bp.format.DateTimeFormatter
@Serializer(forClass = LocalDateTime::class) @kotlinx.serialization.ExperimentalSerializationApi
object LocalDateTimeSerializer : KSerializer<LocalDateTime> { object LocalDateTimeSerializer : KSerializer<LocalDateTime> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDateTime) { override fun serialize(encoder: Encoder, value: LocalDateTime) {
val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm") val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")

View File

@ -1,8 +1,8 @@
package com.example.myapplication.api package com.example.myapplication.api
import com.example.myapplication.api.cinema.CinemaRemote import com.example.myapplication.api.cinema.CinemaRemote
import com.example.myapplication.api.order.OrderRemote
import com.example.myapplication.api.cinema.CinemaWithSessionsRemote import com.example.myapplication.api.cinema.CinemaWithSessionsRemote
import com.example.myapplication.api.order.OrderRemote
import com.example.myapplication.api.session.ReportRemote import com.example.myapplication.api.session.ReportRemote
import com.example.myapplication.api.session.SessionFromCinemaRemote import com.example.myapplication.api.session.SessionFromCinemaRemote
import com.example.myapplication.api.session.SessionRemote import com.example.myapplication.api.session.SessionRemote
@ -11,6 +11,7 @@ import com.example.myapplication.api.user.UserRemote
import com.example.myapplication.api.user.UserSessionRemote import com.example.myapplication.api.user.UserSessionRemote
import com.example.myapplication.api.user.UserSessionWithSessionRemote import com.example.myapplication.api.user.UserSessionWithSessionRemote
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual import kotlinx.serialization.modules.contextual
@ -31,9 +32,6 @@ interface MyServerService {
@GET("orders") @GET("orders")
suspend fun getOrders(): List<OrderRemote> suspend fun getOrders(): List<OrderRemote>
@GET("users")
suspend fun getUsers(): List<UserRemote>
@GET("cinemas") @GET("cinemas")
suspend fun getCinemas( suspend fun getCinemas(
@Query("_page") page: Int, @Query("_page") page: Int,
@ -163,6 +161,7 @@ interface MyServerService {
@Volatile @Volatile
private var INSTANCE: MyServerService? = null private var INSTANCE: MyServerService? = null
@OptIn(ExperimentalSerializationApi::class)
fun getInstance(): MyServerService { fun getInstance(): MyServerService {
return INSTANCE ?: synchronized(this) { return INSTANCE ?: synchronized(this) {
val logger = HttpLoggingInterceptor() val logger = HttpLoggingInterceptor()

View File

@ -79,8 +79,8 @@ class CinemaRemoteMediator(
dbCinemaRepository.insertCinemas(cinemas) dbCinemaRepository.insertCinemas(cinemas)
sessionsFromCinemas.forEach { sessionsFromCinemas.forEach {
try { try {
dbSessionRepository.insertSessions(it) dbSessionRepository.insertSessions(it)
} catch(_:Exception) { } catch (_: Exception) {
} }
} }

View File

@ -52,8 +52,10 @@ class OrderRemoteMediator(
} }
try { try {
val orders = service.getOrders(LiveStore.user.value?.uid ?: 0, val orders = service.getOrders(
page, state.config.pageSize).map { it.toOrder() } LiveStore.user.value?.uid ?: 0,
page, state.config.pageSize
).map { it.toOrder() }
val endOfPaginationReached = orders.isEmpty() val endOfPaginationReached = orders.isEmpty()
database.withTransaction { database.withTransaction {
if (loadType == LoadType.REFRESH) { if (loadType == LoadType.REFRESH) {

View File

@ -1,19 +1,16 @@
package com.example.myapplication.api.order package com.example.myapplication.api.order
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
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.myapplication.api.MyServerService import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.cinema.toCinemaRemote
import com.example.myapplication.api.session.toSessionFromOrder import com.example.myapplication.api.session.toSessionFromOrder
import com.example.myapplication.database.AppContainer import com.example.myapplication.database.AppContainer
import com.example.myapplication.database.AppDatabase import com.example.myapplication.database.AppDatabase
import com.example.myapplication.database.entities.model.Order import com.example.myapplication.database.entities.model.Order
import com.example.myapplication.database.entities.model.OrderSessionCrossRef import com.example.myapplication.database.entities.model.OrderSessionCrossRef
import com.example.myapplication.database.entities.model.SessionFromOrder import com.example.myapplication.database.entities.model.SessionFromOrder
import com.example.myapplication.database.entities.repository.OfflineCinemaRepository
import com.example.myapplication.database.entities.repository.OfflineOrderRepository import com.example.myapplication.database.entities.repository.OfflineOrderRepository
import com.example.myapplication.database.entities.repository.OfflineOrderSessionRepository import com.example.myapplication.database.entities.repository.OfflineOrderSessionRepository
import com.example.myapplication.database.entities.repository.OrderRepository import com.example.myapplication.database.entities.repository.OrderRepository
@ -23,14 +20,11 @@ import kotlinx.coroutines.flow.Flow
class RestOrderRepository( class RestOrderRepository(
private val service: MyServerService, private val service: MyServerService,
private val dbOrderRepository: OfflineOrderRepository, private val dbOrderRepository: OfflineOrderRepository,
private val dbCinemaRepository: OfflineCinemaRepository,
private val dbOrderSessionRepository: OfflineOrderSessionRepository, private val dbOrderSessionRepository: OfflineOrderSessionRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase private val database: AppDatabase
) : OrderRepository { ) : OrderRepository {
override fun getAllOrders(userId: Int?): Flow<PagingData<Order>> { override fun getAllOrders(userId: Int): Flow<PagingData<Order>> {
Log.d(RestOrderRepository::class.simpleName, "Get orders")
val pagingSourceFactory = { dbOrderRepository.getAllOrdersPagingSource(userId) } val pagingSourceFactory = { dbOrderRepository.getAllOrdersPagingSource(userId) }
@OptIn(ExperimentalPagingApi::class) @OptIn(ExperimentalPagingApi::class)

View File

@ -2,7 +2,6 @@ package com.example.myapplication.api.ordersession
import com.example.myapplication.api.MyServerService import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.session.SessionFromOrderRemote import com.example.myapplication.api.session.SessionFromOrderRemote
import com.example.myapplication.api.session.toSession
import com.example.myapplication.database.entities.model.OrderSessionCrossRef import com.example.myapplication.database.entities.model.OrderSessionCrossRef
import com.example.myapplication.database.entities.repository.OfflineOrderSessionRepository import com.example.myapplication.database.entities.repository.OfflineOrderSessionRepository
import com.example.myapplication.database.entities.repository.OrderSessionRepository import com.example.myapplication.database.entities.repository.OrderSessionRepository

View File

@ -1,20 +0,0 @@
package com.example.myapplication.api.session
import com.example.myapplication.api.cinema.CinemaRemote
import com.example.myapplication.api.cinema.toCinema
import com.example.myapplication.database.entities.model.SessionFromCart
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.threeten.bp.LocalDateTime
@Serializable
class SessionFromCartRemote(
val id: Int = 0,
var count: Int = 0,
var cinemaId: Int = 0,
)
fun SessionFromCartRemote.toSessionFromCart(cinema: CinemaRemote, dateTime: LocalDateTime, price: Double, availableCount: Int): SessionFromCart =
SessionFromCart(
id, dateTime, price, availableCount, count, cinema.id, cinema.toCinema()
)

View File

@ -10,7 +10,8 @@ import org.threeten.bp.LocalDateTime
@Serializable @Serializable
class SessionFromOrderRemote( class SessionFromOrderRemote(
val id: Int = 0, val id: Int = 0,
@Contextual val dateTime: LocalDateTime = LocalDateTime.MIN, @Contextual
val dateTime: LocalDateTime = LocalDateTime.MIN,
val frozenPrice: Double = 0.0, val frozenPrice: Double = 0.0,
val count: Int = 0, val count: Int = 0,
val cinemaId: Int = 0, val cinemaId: Int = 0,

View File

@ -1,7 +1,5 @@
package com.example.myapplication.api.session package com.example.myapplication.api.session
import com.example.myapplication.api.cinema.CinemaRemote
import com.example.myapplication.api.cinema.toCinema
import com.example.myapplication.database.entities.model.Session import com.example.myapplication.database.entities.model.Session
import kotlinx.serialization.Contextual import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -3,8 +3,6 @@ package com.example.myapplication.api.user
import android.util.Log import android.util.Log
import com.example.myapplication.api.MyServerService import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.cinema.toCinema import com.example.myapplication.api.cinema.toCinema
import com.example.myapplication.api.cinema.toCinemaRemote
import com.example.myapplication.api.session.toSessionFromCart
import com.example.myapplication.database.entities.model.SessionFromCart import com.example.myapplication.database.entities.model.SessionFromCart
import com.example.myapplication.database.entities.model.User import com.example.myapplication.database.entities.model.User
import com.example.myapplication.database.entities.model.UserSessionCrossRef import com.example.myapplication.database.entities.model.UserSessionCrossRef
@ -44,7 +42,8 @@ class RestUserRepository(
it.toSessionFromCart( it.toSessionFromCart(
it.session.maxCount - service.getOrders().flatMap { order -> it.session.maxCount - service.getOrders().flatMap { order ->
order.sessions.filter { session -> session.id == it.id } order.sessions.filter { session -> session.id == it.id }
}.sumOf { session -> session.count }, cinema.toCinema()) }.sumOf { session -> session.count }, cinema.toCinema()
)
} }
} }

View File

@ -1,8 +1,5 @@
package com.example.myapplication.api.user package com.example.myapplication.api.user
import com.example.myapplication.api.session.SessionFromCartRemote
import com.example.myapplication.api.session.SessionRemote
import com.example.myapplication.database.entities.model.Session
import com.example.myapplication.database.entities.model.User import com.example.myapplication.database.entities.model.User
import com.example.myapplication.database.entities.model.UserRole import com.example.myapplication.database.entities.model.UserRole
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,13 +1,9 @@
package com.example.myapplication.api.user package com.example.myapplication.api.user
import com.example.myapplication.api.session.SessionRemote
import com.example.myapplication.database.entities.model.Cinema
import com.example.myapplication.database.entities.model.SessionFromCart
import com.example.myapplication.database.entities.model.User
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class UserSessionRemote ( data class UserSessionRemote(
val id: Int = 0, val id: Int = 0,
val userId: Int = 0, val userId: Int = 0,
val sessionId: Int = 0, val sessionId: Int = 0,

View File

@ -6,7 +6,7 @@ import com.example.myapplication.database.entities.model.SessionFromCart
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class UserSessionWithSessionRemote ( data class UserSessionWithSessionRemote(
val id: Int = 0, val id: Int = 0,
val userId: Int = 0, val userId: Int = 0,
val sessionId: Int = 0, val sessionId: Int = 0,
@ -14,7 +14,10 @@ data class UserSessionWithSessionRemote (
val session: SessionRemote, val session: SessionRemote,
) )
fun UserSessionWithSessionRemote.toSessionFromCart(availableCount: Int = 0, cinema: Cinema): SessionFromCart = SessionFromCart( fun UserSessionWithSessionRemote.toSessionFromCart(
availableCount: Int = 0,
cinema: Cinema
): SessionFromCart = SessionFromCart(
sessionId, sessionId,
session.dateTime, session.dateTime,
session.price, session.price,

View File

@ -1,8 +1,6 @@
package com.example.myapplication.api.usersession package com.example.myapplication.api.usersession
import com.example.myapplication.api.MyServerService import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.session.SessionFromCartRemote
import com.example.myapplication.api.session.toSession
import com.example.myapplication.api.user.UserSessionRemote import com.example.myapplication.api.user.UserSessionRemote
import com.example.myapplication.database.entities.model.UserSessionCrossRef import com.example.myapplication.database.entities.model.UserSessionCrossRef
import com.example.myapplication.database.entities.repository.OfflineUserSessionRepository import com.example.myapplication.database.entities.repository.OfflineUserSessionRepository
@ -18,17 +16,22 @@ class RestUserSessionRepository(
if (session.sessionId == userSessionCrossRef.sessionId) if (session.sessionId == userSessionCrossRef.sessionId)
return return
} }
service.createUserSession(UserSessionRemote(id = 0, service.createUserSession(
userId = userSessionCrossRef.userId, UserSessionRemote(
sessionId = userSessionCrossRef.sessionId, id = 0,
count = userSessionCrossRef.count userId = userSessionCrossRef.userId,
)) sessionId = userSessionCrossRef.sessionId,
count = userSessionCrossRef.count
)
)
dbUserSessionRepository.insertUserSession(userSessionCrossRef) dbUserSessionRepository.insertUserSession(userSessionCrossRef)
} }
override suspend fun updateUserSession(userSessionCrossRef: UserSessionCrossRef) { override suspend fun updateUserSession(userSessionCrossRef: UserSessionCrossRef) {
val userSessionRemote = service.getUserSession(userSessionCrossRef.userId, val userSessionRemote = service.getUserSession(
userSessionCrossRef.sessionId).first() userSessionCrossRef.userId,
userSessionCrossRef.sessionId
).first()
if (userSessionCrossRef.count <= 0) { if (userSessionCrossRef.count <= 0) {
service.deleteUserSession(userSessionRemote.id) service.deleteUserSession(userSessionRemote.id)
dbUserSessionRepository.deleteUserSession(userSessionCrossRef) dbUserSessionRepository.deleteUserSession(userSessionCrossRef)
@ -40,8 +43,10 @@ class RestUserSessionRepository(
} }
override suspend fun deleteUserSession(userSessionCrossRef: UserSessionCrossRef) { override suspend fun deleteUserSession(userSessionCrossRef: UserSessionCrossRef) {
val userSessionRemote = service.getUserSession(userSessionCrossRef.userId, val userSessionRemote = service.getUserSession(
userSessionCrossRef.sessionId).first() userSessionCrossRef.userId,
userSessionCrossRef.sessionId
).first()
service.deleteUserSession(userSessionRemote.id) service.deleteUserSession(userSessionRemote.id)
dbUserSessionRepository.deleteUserSession(userSessionCrossRef) dbUserSessionRepository.deleteUserSession(userSessionCrossRef)
} }

View File

@ -3,7 +3,6 @@ package com.example.myapplication.composeui
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.myapplication.LiveStore import com.example.myapplication.LiveStore
import com.example.myapplication.database.entities.composeui.AppViewModelProvider import com.example.myapplication.database.entities.composeui.AppViewModelProvider

View File

@ -2,8 +2,6 @@ package com.example.myapplication.composeui
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -11,7 +9,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
@ -20,33 +17,23 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.DismissDirection import androidx.compose.material3.DismissDirection
import androidx.compose.material3.DismissState import androidx.compose.material3.DismissState
import androidx.compose.material3.DismissValue
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberDismissState import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
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.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource

View File

@ -15,7 +15,6 @@ import com.example.myapplication.database.entities.repository.OrderSessionReposi
import com.example.myapplication.database.entities.repository.UserRepository import com.example.myapplication.database.entities.repository.UserRepository
import com.example.myapplication.database.entities.repository.UserSessionRepository import com.example.myapplication.database.entities.repository.UserSessionRepository
import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalDateTime
import java.util.LinkedList
class CartViewModel( class CartViewModel(
private val userSessionRepository: UserSessionRepository, private val userSessionRepository: UserSessionRepository,
@ -23,28 +22,14 @@ class CartViewModel(
private val orderSessionRepository: OrderSessionRepository, private val orderSessionRepository: OrderSessionRepository,
private val userRepository: UserRepository, private val userRepository: UserRepository,
) : ViewModel() { ) : ViewModel() {
private val requestQueue: LinkedList<suspend () -> Unit> = LinkedList() private var isLoading: Boolean = false
private var isProcessingQueue: Boolean = false
private suspend fun processQueue() {
isProcessingQueue = true
while (requestQueue.isNotEmpty()) {
val request = requestQueue.poll()
request.invoke()
refreshState()
}
isProcessingQueue = false
}
var isLoading: Boolean = false
var cartUiState by mutableStateOf(CartUiState()) var cartUiState by mutableStateOf(CartUiState())
private set private set
suspend fun refreshState() { suspend fun refreshState() {
val userId: Int = LiveStore.user.value?.uid ?: return val userId: Int = LiveStore.user.value?.uid ?: 0
val cart = userRepository.getCartByUser(userId) val cart = userRepository.getCartByUser(userId)
cartUiState = CartUiState(cart) cartUiState = CartUiState(cart)
isLoading = false
} }
suspend fun addToOrder(sessions: List<SessionFromCart>) { suspend fun addToOrder(sessions: List<SessionFromCart>) {
@ -70,22 +55,14 @@ class CartViewModel(
} }
suspend fun removeFromCart(session: Session, count: Int = 0) { suspend fun removeFromCart(session: Session, count: Int = 0) {
if (isLoading)
return
isLoading = true
val userId: Int = LiveStore.user.value?.uid ?: return val userId: Int = LiveStore.user.value?.uid ?: return
userSessionRepository.deleteUserSession(UserSessionCrossRef(userId, session.uid, count)) userSessionRepository.deleteUserSession(UserSessionCrossRef(userId, session.uid, count))
refreshState() refreshState()
} }
suspend fun updateFromCart(session: Session, count: Int, availableCount: Int) suspend fun updateFromCart(session: Session, count: Int, availableCount: Int): Boolean {
: Boolean {
if (isLoading)
return false
isLoading = true
val userId: Int = LiveStore.user.value?.uid ?: return false val userId: Int = LiveStore.user.value?.uid ?: return false
if (count == 0) { if (count == 0) {
isLoading = false
removeFromCart(session, count) removeFromCart(session, count)
return false return false
} }

View File

@ -111,7 +111,7 @@ fun CardScreen(reportData: List<ReportRemote>) {
Text(text = "Фильм: $cinemaName") Text(text = "Фильм: $cinemaName")
Text(text = "Сеанс: ${dateFormatter.format(ticketDateTime)}") Text(text = "Сеанс: ${dateFormatter.format(ticketDateTime)}")
Text(text = "Стоимость: $ticketPrice") Text(text = "Стоимость: $ticketPrice")
Text(text = "Максимальное количество билетов: $ticketQuantity") Text(text = "Максимальное кол-во билетов: $ticketQuantity")
Text(text = "Купили: $ticketsPurchased") Text(text = "Купили: $ticketsPurchased")
Text(text = "Выручка: $revenue") Text(text = "Выручка: $revenue")
} }

View File

@ -80,7 +80,6 @@ class AppDataContainer(private val context: Context) : AppContainer {
RestOrderRepository( RestOrderRepository(
MyServerService.getInstance(), MyServerService.getInstance(),
orderRepository, orderRepository,
cinemaRepository,
orderSessionRepository, orderSessionRepository,
remoteKeyRepository, remoteKeyRepository,
AppDatabase.getInstance(context) AppDatabase.getInstance(context)

View File

@ -25,7 +25,6 @@ import com.example.myapplication.database.remotekeys.model.RemoteKeys
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.threeten.bp.LocalDateTime
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@Database( @Database(

View File

@ -6,7 +6,6 @@ import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.myapplication.CinemaApplication import com.example.myapplication.CinemaApplication
import com.example.myapplication.composeui.Authenticator
import com.example.myapplication.composeui.AuthenticatorViewModel import com.example.myapplication.composeui.AuthenticatorViewModel
import com.example.myapplication.composeui.CartViewModel import com.example.myapplication.composeui.CartViewModel
import com.example.myapplication.composeui.ReportViewModel import com.example.myapplication.composeui.ReportViewModel
@ -66,7 +65,7 @@ object AppViewModelProvider {
cinemaApplication().container.userRestRepository, cinemaApplication().container.userRestRepository,
) )
} }
initializer { initializer {
AuthenticatorViewModel(cinemaApplication().container.userRestRepository) AuthenticatorViewModel(cinemaApplication().container.userRestRepository)
} }
initializer { initializer {

View File

@ -1,7 +1,6 @@
package com.example.myapplication.database.entities.composeui package com.example.myapplication.database.entities.composeui
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.util.Log
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -27,7 +26,6 @@ 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

View File

@ -1,16 +1,10 @@
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.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
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

View File

@ -10,15 +10,13 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -28,6 +26,7 @@ import androidx.navigation.NavController
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemContentType import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey import androidx.paging.compose.itemKey
import com.example.myapplication.LiveStore
import com.example.myapplication.composeui.navigation.Screen import com.example.myapplication.composeui.navigation.Screen
import com.example.myapplication.ui.theme.PmudemoTheme import com.example.myapplication.ui.theme.PmudemoTheme
import org.threeten.bp.format.DateTimeFormatter import org.threeten.bp.format.DateTimeFormatter
@ -37,15 +36,21 @@ fun OrderList(
navController: NavController?, navController: NavController?,
viewModel: OrderListViewModel = viewModel(factory = AppViewModelProvider.Factory) viewModel: OrderListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
val user = LiveStore.user.observeAsState()
val ordersUiState = viewModel.orderListUiState.collectAsLazyPagingItems() val ordersUiState = viewModel.orderListUiState.collectAsLazyPagingItems()
LaunchedEffect(user.value?.uid) {
viewModel.refreshState(user.value?.uid ?: 0)
}
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(all = 10.dp) .padding(all = 10.dp)
) { ) {
items(count = ordersUiState.itemCount, items(
count = ordersUiState.itemCount,
key = ordersUiState.itemKey(), key = ordersUiState.itemKey(),
contentType = ordersUiState.itemContentType()) { index -> contentType = ordersUiState.itemContentType()
) { index ->
val order = ordersUiState[index] val order = ordersUiState[index]
val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm") val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
val orderId = Screen.OrderView.route.replace("{id}", order!!.uid.toString()) val orderId = Screen.OrderView.route.replace("{id}", order!!.uid.toString())
@ -67,7 +72,10 @@ fun OrderList(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
Text("Заказ №${order.uid}, ${formattedDate}", color = MaterialTheme.colorScheme.onSecondary) Text(
"Заказ №${order.uid}, ${formattedDate}",
color = MaterialTheme.colorScheme.onSecondary
)
} }
} }
} }

View File

@ -1,18 +1,18 @@
package com.example.myapplication.database.entities.composeui package com.example.myapplication.database.entities.composeui
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.paging.PagingData import androidx.paging.PagingData
import com.example.myapplication.LiveStore
import com.example.myapplication.database.entities.model.Order import com.example.myapplication.database.entities.model.Order
import com.example.myapplication.database.entities.repository.OrderRepository import com.example.myapplication.database.entities.repository.OrderRepository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
class OrderListViewModel( class OrderListViewModel(
private val orderRepository: OrderRepository private val orderRepository: OrderRepository
) : ViewModel() { ) : ViewModel() {
val orderListUiState: Flow<PagingData<Order>> = var orderListUiState: Flow<PagingData<Order>> = emptyFlow()
orderRepository.getAllOrders(LiveStore.user.value?.uid ?: 0)
}
data class OrderListUiState(val orderList: List<Order> = listOf()) fun refreshState(userId: Int = 0) {
orderListUiState = orderRepository.getAllOrders(userId)
}
}

View File

@ -4,7 +4,6 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.myapplication.database.AppContainer import com.example.myapplication.database.AppContainer
import com.example.myapplication.database.AppDataContainer
import com.example.myapplication.database.entities.model.SessionFromOrder import com.example.myapplication.database.entities.model.SessionFromOrder
import com.example.myapplication.database.entities.repository.OrderRepository import com.example.myapplication.database.entities.repository.OrderRepository
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@ -19,13 +18,14 @@ class OrderViewModel(
) : ViewModel() { ) : ViewModel() {
private val orderUid: Int = checkNotNull(savedStateHandle["id"]) private val orderUid: Int = checkNotNull(savedStateHandle["id"])
val orderUiState: StateFlow<OrderUiState> = flow{emit(orderRepository.getOrder(orderUid))} .map { val orderUiState: StateFlow<OrderUiState> =
OrderUiState(it) flow { emit(orderRepository.getOrder(orderUid)) }.map {
}.stateIn( OrderUiState(it)
scope = viewModelScope, }.stateIn(
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppContainer.TIMEOUT), scope = viewModelScope,
initialValue = OrderUiState() started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppContainer.TIMEOUT),
) initialValue = OrderUiState()
)
} }
data class OrderUiState(val sessionList: List<SessionFromOrder> = listOf()) data class OrderUiState(val sessionList: List<SessionFromOrder> = listOf())

View File

@ -34,7 +34,6 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.myapplication.LiveStore import com.example.myapplication.LiveStore
import com.example.myapplication.composeui.navigation.Screen
import com.example.myapplication.datastore.DataStoreManager import com.example.myapplication.datastore.DataStoreManager
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -173,7 +172,7 @@ fun UserProfile(
onClick = { onClick = {
coroutine.launch { coroutine.launch {
if (viewModel.signIn(dataStoreManager)) { if (viewModel.signIn(dataStoreManager)) {
navController.navigate(Screen.CinemaList.route) navController.popBackStack()
} }
} }
}, },

View File

@ -1,6 +1,5 @@
package com.example.myapplication.database.entities.composeui package com.example.myapplication.database.entities.composeui
import android.content.Context
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
@ -68,7 +67,8 @@ class UserProfileViewModel(
} else if (details.password.isBlank()) { } else if (details.password.isBlank()) {
R.string.err_02 R.string.err_02
} else if (details.passwordConfirm.isBlank() } else if (details.passwordConfirm.isBlank()
|| details.password != details.passwordConfirm) { || details.password != details.passwordConfirm
) {
R.string.err_05 R.string.err_05
} else { } else {
null null

View File

@ -10,8 +10,6 @@ import com.example.myapplication.database.entities.model.Cinema
import com.example.myapplication.database.entities.model.CinemaWithSessions import com.example.myapplication.database.entities.model.CinemaWithSessions
import com.example.myapplication.database.entities.model.SessionFromCinema import com.example.myapplication.database.entities.model.SessionFromCinema
import com.example.myapplication.database.entities.repository.CinemaRepository import com.example.myapplication.database.entities.repository.CinemaRepository
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class CinemaEditViewModel( class CinemaEditViewModel(

View File

@ -8,8 +8,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.myapplication.database.entities.model.Session import com.example.myapplication.database.entities.model.Session
import com.example.myapplication.database.entities.repository.SessionRepository import com.example.myapplication.database.entities.repository.SessionRepository
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalDateTime

View File

@ -2,7 +2,6 @@ package com.example.myapplication.database.entities.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import org.threeten.bp.LocalDateTime import org.threeten.bp.LocalDateTime

View File

@ -38,7 +38,7 @@ data class SessionFromCinema(
} }
} }
fun SessionFromCinema.toSession(): Session = Session ( fun SessionFromCinema.toSession(): Session = Session(
uid, uid,
dateTime, dateTime,
price, price,

View File

@ -1,7 +1,6 @@
package com.example.myapplication.database.entities.repository package com.example.myapplication.database.entities.repository
import androidx.paging.PagingData import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.myapplication.database.entities.model.Cinema import com.example.myapplication.database.entities.model.Cinema
import com.example.myapplication.database.entities.model.CinemaWithSessions import com.example.myapplication.database.entities.model.CinemaWithSessions
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

View File

@ -11,7 +11,7 @@ import com.example.myapplication.database.entities.model.SessionFromOrder
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
class OfflineOrderRepository(private val orderDao: OrderDao) : OrderRepository { class OfflineOrderRepository(private val orderDao: OrderDao) : OrderRepository {
override fun getAllOrders(userId: Int?): Flow<PagingData<Order>> = Pager( override fun getAllOrders(userId: Int): Flow<PagingData<Order>> = Pager(
config = PagingConfig( config = PagingConfig(
pageSize = AppContainer.LIMIT, pageSize = AppContainer.LIMIT,
enablePlaceholders = false enablePlaceholders = false

View File

@ -6,7 +6,7 @@ import com.example.myapplication.database.entities.model.SessionFromOrder
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
interface OrderRepository { interface OrderRepository {
fun getAllOrders(userId: Int?): Flow<PagingData<Order>> fun getAllOrders(userId: Int): Flow<PagingData<Order>>
suspend fun getOrder(uid: Int): List<SessionFromOrder> suspend fun getOrder(uid: Int): List<SessionFromOrder>
suspend fun insertOrder(order: Order): Long suspend fun insertOrder(order: Order): Long
} }

View File

@ -1,7 +1,6 @@
package com.example.myapplication.database.entities.repository package com.example.myapplication.database.entities.repository
import com.example.myapplication.database.entities.model.Session import com.example.myapplication.database.entities.model.Session
import kotlinx.coroutines.flow.Flow
interface SessionRepository { interface SessionRepository {
suspend fun getSession(uid: Int): Session suspend fun getSession(uid: Int): Session

View File

@ -3,15 +3,12 @@ package com.example.myapplication.datastore
import android.content.Context import android.content.Context
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("data_store")
class DataStoreManager(private val context: Context) { class DataStoreManager(private val context: Context) {
companion object { companion object {

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<network-security-config> <network-security-config>
<domain-config cleartextTrafficPermitted="true"> <domain-config cleartextTrafficPermitted="true">
<!-- <domain includeSubdomains="true">192.168.154.166</domain>--> <!-- <domain includeSubdomains="true">192.168.154.166</domain>-->
<domain includeSubdomains="true">192.168.0.101</domain> <domain includeSubdomains="true">192.168.0.101</domain>
</domain-config> </domain-config>
</network-security-config> </network-security-config>

File diff suppressed because it is too large Load Diff