diff --git a/app/src/main/java/com/example/myapplication/api/ApiStatus.kt b/app/src/main/java/com/example/myapplication/api/ApiStatus.kt new file mode 100644 index 0000000..3952e73 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/api/ApiStatus.kt @@ -0,0 +1,5 @@ +package com.example.myapplication.api + +enum class ApiStatus { + LOADING, ERROR, DONE +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeList.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeList.kt index 6168a4e..1dd164f 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeList.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeList.kt @@ -29,6 +29,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -55,11 +56,15 @@ fun BikeList( currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory) ) { var getUser by remember { mutableStateOf(currentUserViewModel.user) } + val bikePagingItems = viewModel.bikePagingFlowState.flow.collectAsLazyPagingItems() + + LaunchedEffect(getUser?.uid) { + viewModel.refresh() + } // Проверяем, есть ли у пользователя uid if (getUser?.uid != null) { val coroutineScope = rememberCoroutineScope() - val bikePagingItems = viewModel.bikeListUiState.collectAsLazyPagingItems() Scaffold( topBar = {}, diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeListViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeListViewModel.kt index b370abd..8b85cef 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeListViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeListViewModel.kt @@ -1,17 +1,37 @@ 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.viewModelScope import androidx.paging.PagingData +import androidx.paging.cachedIn import com.example.myapplication.database.entities.model.Bike import com.example.myapplication.database.entities.repository.BikeRepository import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow class BikeListViewModel( private val bikeRepository: BikeRepository -) : ViewModel() { - val bikeListUiState: Flow> = bikeRepository.getAllBikes() +) : LoadingViewModel() { + var bikePagingFlowState by mutableStateOf(BikePagingFlowState()) + private set + + fun refresh() { + runInScope(actionSuccess = { + val pagingSource = bikeRepository.getAllBikes() + bikePagingFlowState = BikePagingFlowState(pagingSource.cachedIn(viewModelScope)) + }) + } suspend fun deleteBike(bike: Bike) { - bikeRepository.deleteBike(bike) + runInScope(actionSuccess = { + bikeRepository.deleteBike(bike) + }) } -} \ No newline at end of file +} + +data class BikePagingFlowState( + val flow: Flow> = emptyFlow(), +) \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeView.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeView.kt index 805c602..874755c 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeView.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeView.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController +import com.example.myapplication.api.ApiStatus import com.example.myapplication.composeui.navigation.Screen import com.example.myapplication.database.entities.model.Bike @@ -50,7 +51,8 @@ fun BikeView( LaunchedEffect(Unit) { viewModel.refreshState() } - + when (viewModel.apiStatus) { + ApiStatus.DONE -> { Column( modifier = Modifier .padding(16.dp) @@ -148,3 +150,12 @@ fun BikeView( } } } + + ApiStatus.LOADING -> LoadingPage() + else -> ErrorPage( + message = viewModel.apiError, + onBack = { navController.popBackStack() } + ) + } +} + diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeViewModel.kt index 35a6527..9d90e19 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/BikeViewModel.kt @@ -10,7 +10,7 @@ import com.example.myapplication.database.entities.repository.BikeRepository class BikeViewModel( savedStateHandle: SavedStateHandle, private val bikeRepository: BikeRepository -) : ViewModel() { +) : LoadingViewModel() { private val bikeUid: Int = checkNotNull(savedStateHandle["id"]) var bikeUiState by mutableStateOf(BikeUiState()) @@ -18,7 +18,11 @@ class BikeViewModel( suspend fun refreshState() { if (bikeUid > 0) { - bikeUiState = BikeUiState(bikeRepository.getBike(bikeUid)) + runInScope(actionSuccess = { + bikeUiState = BikeUiState(bikeRepository.getBike(bikeUid)) + }, actionError = { + bikeUiState = BikeUiState() + }) } } diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/CartViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/CartViewModel.kt index 7c4ec52..1abff97 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/CartViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/CartViewModel.kt @@ -20,7 +20,7 @@ class CartViewModel( private val rentRepository: RentRepository, private val rentItemRepository: RentItemRepository, private val userRepository: UserRepository, -) : ViewModel() { +) : LoadingViewModel() { //private val userUid: Int = 1 var cartUiState by mutableStateOf(CartUiState()) private set diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/CurrentUserViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/CurrentUserViewModel.kt index a851ba1..ba68fed 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/CurrentUserViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/CurrentUserViewModel.kt @@ -9,7 +9,7 @@ import com.example.myapplication.database.entities.model.User import com.example.myapplication.database.entities.repository.UserRepository import kotlinx.coroutines.launch -class CurrentUserViewModel(private val userRepository: UserRepository) : ViewModel(){ +class CurrentUserViewModel(private val userRepository: UserRepository) : LoadingViewModel(){ val argument = mutableStateOf(null) private val userid = mutableStateOf(null) var user by mutableStateOf(null) diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/EntryUserViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/EntryUserViewModel.kt index 8fb5e9c..aac3c27 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/EntryUserViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/EntryUserViewModel.kt @@ -9,7 +9,7 @@ import com.example.myapplication.database.entities.model.User import com.example.myapplication.database.entities.repository.UserRepository import kotlinx.coroutines.launch -class EntryUserViewModel(private val userRepository: UserRepository) : ViewModel() { +class EntryUserViewModel(private val userRepository: UserRepository) : LoadingViewModel() { var userList by mutableStateOf>(emptyList()) fun setUserList() { diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/ItemListViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/ItemListViewModel.kt index 0c1556f..66681dd 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/ItemListViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/ItemListViewModel.kt @@ -10,7 +10,7 @@ import com.example.myapplication.database.entities.repository.UserItemRepository class ItemListViewModel( private val itemRepository: ItemRepository, private val userItemRepository: UserItemRepository -) : ViewModel() { +) : LoadingViewModel() { suspend fun deleteItem(item: ItemFromBike) { itemRepository.deleteItem( Item( diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/LoadingPage.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/LoadingPage.kt new file mode 100644 index 0000000..bc7999c --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/LoadingPage.kt @@ -0,0 +1,64 @@ +package com.example.myapplication.database.entities.composeui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.TextUnitType +import androidx.compose.ui.unit.dp +import com.example.myapplication.R + +@Composable +fun LoadingPage() { + Column( + modifier = Modifier + .fillMaxSize() + .padding(10.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + fontSize = TextUnit(value = 25F, type = TextUnitType.Sp), + text = stringResource(id = R.string.loading) + ) + } +} + +@Composable +fun ErrorPage(message: String, onBack: () -> Unit) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(10.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + fontSize = TextUnit(value = 20F, type = TextUnitType.Sp), + text = message, + color = Color(0xFFFF1744) + ) + Spacer(modifier = Modifier.padding(bottom = 10.dp)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = { onBack() } + ) { + Text(stringResource(id = R.string.back)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/LoadingViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/LoadingViewModel.kt new file mode 100644 index 0000000..4f5c1f9 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/LoadingViewModel.kt @@ -0,0 +1,50 @@ +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.viewModelScope +import com.example.myapplication.api.ApiStatus +import kotlinx.coroutines.launch +import retrofit2.HttpException +import java.io.IOException + +open class LoadingViewModel : ViewModel() { + var apiStatus by mutableStateOf(ApiStatus.DONE) + private set + + var apiError by mutableStateOf("") + private set + + fun runInScope( + actionSuccess: suspend () -> Unit, + actionError: suspend () -> Unit, + needLoadingScreen: Boolean = true, + ) { + viewModelScope.launch { + if (needLoadingScreen) + apiStatus = ApiStatus.LOADING + runCatching { + actionSuccess() + apiStatus = ApiStatus.DONE + apiError = "" + }.onFailure { e: Throwable -> + when (e) { + is IOException, + is HttpException -> { + actionError() + apiStatus = ApiStatus.ERROR + apiError = e.localizedMessage ?: e.toString() + } + + else -> throw e + } + } + } + } + + fun runInScope(actionSuccess: suspend () -> Unit) { + runInScope(actionSuccess, actionError = {}) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/RegisterUserViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/RegisterUserViewModel.kt index 9caf4d3..940a369 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/RegisterUserViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/RegisterUserViewModel.kt @@ -8,7 +8,7 @@ import com.example.myapplication.database.entities.model.User import com.example.myapplication.database.entities.repository.UserRepository import kotlinx.coroutines.launch -class RegisterUserViewModel(private val userRepository: UserRepository) : ViewModel() { +class RegisterUserViewModel(private val userRepository: UserRepository) : LoadingViewModel() { private val _users = MutableLiveData>() val users: LiveData> get() = _users diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/RentListViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/RentListViewModel.kt index 6fd11e7..93b7ae5 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/RentListViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/RentListViewModel.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.flatMapLatest class RentListViewModel( private val rentRepository: RentRepository -) : ViewModel() { +) : LoadingViewModel() { private val _userId = MutableStateFlow(null) val userId: StateFlow get() = _userId diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/RentViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/RentViewModel.kt index 11335e7..c2b69a2 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/RentViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/RentViewModel.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.stateIn class RentViewModel( savedStateHandle: SavedStateHandle, private val rentRepository: RentRepository -) : ViewModel() { +) : LoadingViewModel() { private val rentUid: Int = checkNotNull(savedStateHandle["id"]) val rentUiState: StateFlow = flow{emit(rentRepository.getRent(rentUid))} .map { diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/ReportViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/ReportViewModel.kt index eb82ac2..13e14a7 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/ReportViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/ReportViewModel.kt @@ -15,7 +15,7 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -class ReportViewModel(private val itemRespository: RestItemRepository): ViewModel() { +class ReportViewModel(private val itemRespository: RestItemRepository): LoadingViewModel() { var reportPageUiState by mutableStateOf(ReportPageUiState()) private set diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEdit.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEdit.kt index c5bf3bc..1ac4564 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEdit.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEdit.kt @@ -19,7 +19,10 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.myapplication.R +import com.example.myapplication.api.ApiStatus import com.example.myapplication.database.entities.composeui.AppViewModelProvider +import com.example.myapplication.database.entities.composeui.ErrorPage +import com.example.myapplication.database.entities.composeui.LoadingPage import com.example.myapplication.ui.theme.PmudemoTheme import kotlinx.coroutines.launch @@ -29,7 +32,8 @@ fun BikeEdit( viewModel: BikeEditViewModel = viewModel(factory = AppViewModelProvider.Factory), ) { val coroutineScope = rememberCoroutineScope() - + when (viewModel.apiStatus) { + ApiStatus.DONE -> { BikeEdit( bikeUiState = viewModel.bikeUiState, onClick = { @@ -40,6 +44,13 @@ fun BikeEdit( }, onUpdate = viewModel::updateUiState, ) + } + ApiStatus.LOADING -> LoadingPage() + else -> ErrorPage( + message = viewModel.apiError, + onBack = { navController.popBackStack() } + ) + } } @Composable diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEditViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEditViewModel.kt index c311fff..7850084 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEditViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/BikeEditViewModel.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.example.myapplication.database.entities.composeui.LoadingViewModel import com.example.myapplication.database.entities.model.Bike import com.example.myapplication.database.entities.model.BikeWithItems import com.example.myapplication.database.entities.model.ItemFromBike @@ -15,7 +16,7 @@ import kotlinx.coroutines.launch class BikeEditViewModel( savedStateHandle: SavedStateHandle, private val bikeRepository: BikeRepository -) : ViewModel() { +) : LoadingViewModel() { var bikeUiState by mutableStateOf(BikeUiState()) private set @@ -23,10 +24,15 @@ class BikeEditViewModel( init { viewModelScope.launch { - if (bikeUid > 0) { - bikeUiState = bikeRepository.getBike(bikeUid) - .toUiState(true) - } + runInScope( + actionSuccess = { + bikeUiState = bikeRepository.getBike(bikeUid) + .toUiState(true) + }, + actionError = { + bikeUiState = BikeUiState() + } + ) } } @@ -39,11 +45,15 @@ class BikeEditViewModel( suspend fun saveBike() { if (validateInput()) { - if (bikeUid > 0) { - bikeRepository.updateBike(bikeUiState.bikeDetails.toBike(bikeUid)) - } else { - bikeRepository.insertBike(bikeUiState.bikeDetails.toBike()) - } + runInScope( + actionSuccess = { + if (bikeUid > 0) { + bikeRepository.updateBike(bikeUiState.bikeDetails.toBike(bikeUid)) + } else { + bikeRepository.insertBike(bikeUiState.bikeDetails.toBike()) + } + } + ) } } diff --git a/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/ItemEditViewModel.kt b/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/ItemEditViewModel.kt index 30fe2aa..d7d842d 100644 --- a/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/ItemEditViewModel.kt +++ b/app/src/main/java/com/example/myapplication/database/entities/composeui/edit/ItemEditViewModel.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.example.myapplication.database.entities.composeui.LoadingViewModel import com.example.myapplication.database.entities.model.Item import com.example.myapplication.database.entities.repository.ItemRepository import kotlinx.coroutines.launch @@ -14,7 +15,7 @@ import org.threeten.bp.LocalDateTime class ItemEditViewModel( savedStateHandle: SavedStateHandle, private val itemRepository: ItemRepository -) : ViewModel() { +) : LoadingViewModel() { var itemUiState by mutableStateOf(ItemUiState()) private set diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f32b9ba..33d2c02 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,4 +21,6 @@ Велосипед не указан Размер загруженного изображения: %1$dx%2$d Загрузите изображение + Загрузка… + Назад \ No newline at end of file