Added start logic for visits pagination, changed visits logic, changed Dto objects, added password in login, bug fixes,
This commit is contained in:
		
							parent
							
								
									12c6b6e1c2
								
							
						
					
					
						commit
						961c37d265
					
				| @ -39,7 +39,7 @@ android { | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
| 
 | ||||
|     implementation("androidx.paging:paging-runtime:3.3.2") | ||||
|     val cameraX = "1.3.4" | ||||
|     implementation("androidx.camera:camera-core:$cameraX") | ||||
|     implementation("androidx.camera:camera-camera2:$cameraX") | ||||
|  | ||||
| @ -6,5 +6,5 @@ data class UserEntity( | ||||
|     val name: String, | ||||
|     val photo: String, | ||||
|     val position: String, | ||||
|     val lastVisit: String, | ||||
| //    val lastVisit: String, | ||||
| ) | ||||
| @ -10,7 +10,7 @@ class UserMapper { | ||||
|             login = userDTO.login, | ||||
|             position = userDTO.position, | ||||
|             name = userDTO.name, | ||||
|             lastVisit = userDTO.lastVisit, | ||||
| //            lastVisit = userDTO.lastVisit, | ||||
|             photo = userDTO.photo | ||||
|         ) | ||||
|         return userEntity | ||||
| @ -22,7 +22,7 @@ class UserMapper { | ||||
|             name = userEntity.name, | ||||
|             photo = userEntity.photo, | ||||
|             position = userEntity.position, | ||||
|             lastVisit = userEntity.lastVisit, | ||||
| //            lastVisit = userEntity.lastVisit, | ||||
|         ) | ||||
|         return userDto | ||||
|     } | ||||
|  | ||||
| @ -3,7 +3,9 @@ package com.displaynone.acss.components.auth.models.user | ||||
| import android.content.Context | ||||
| import com.displaynone.acss.components.auth.internal_utils.AuthTokenManager | ||||
| import com.displaynone.acss.components.auth.models.user.repository.UserRepository | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.LastVisitsDto | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.VisitDto | ||||
| 
 | ||||
| 
 | ||||
| class UserServiceST( | ||||
| @ -28,13 +30,34 @@ class UserServiceST( | ||||
|             return instance ?: throw RuntimeException("null instance") | ||||
|         } | ||||
|     } | ||||
|     suspend fun login(login: String): Result<Unit>{ | ||||
|     suspend fun login(login: String, password:String): Result<Unit>{ | ||||
|         return runCatching { | ||||
|             userRepository.login(login = login).getOrThrow().let { data -> | ||||
|             userRepository.login(login = login, password).getOrThrow().let { data -> | ||||
|                 tokenManager.saveTokens(data) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     suspend fun getMyLastVisits(pageNum: Int, | ||||
|                                 pageSize: Int): Result<List<VisitDto>> { | ||||
|         if (!tokenManager.hasTokens()) { | ||||
|             throw RuntimeException("access token is null") | ||||
|         } | ||||
| 
 | ||||
|         return userRepository.getMyLastVisits( | ||||
|             pageNum = pageNum, | ||||
|             pageSize = pageSize, | ||||
|             token = tokenManager.authTokenPair!!.accessToken | ||||
|         ).map { pagingDto -> pagingDto.content | ||||
|         } | ||||
|     } | ||||
|     suspend fun getLastVisitsByLogin(pageNum: Int, | ||||
|                                      pageSize: Int, | ||||
|                                      login: String): Result<List<VisitDto>> { | ||||
|         if (!tokenManager.hasTokens()) { | ||||
|             throw RuntimeException("access token is null") | ||||
|         } | ||||
|         return userRepository.getLastVisitsByLogin(pageNum, pageSize, tokenManager.authTokenPair!!.accessToken, login).map { pagingDto -> pagingDto.content } | ||||
|     } | ||||
|     fun logout(){ | ||||
|         tokenManager.clear() | ||||
|     } | ||||
|  | ||||
| @ -2,10 +2,12 @@ package com.displaynone.acss.components.auth.models.user.repository | ||||
| 
 | ||||
| import android.util.Log | ||||
| import com.displaynone.acss.components.auth.models.AuthTokenPair | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.LastVisitsDto | ||||
| import com.displaynone.acss.config.Constants.serverUrl | ||||
| import com.displaynone.acss.config.Network | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.RegisterUserDto | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.UserLoginDto | ||||
| import io.ktor.client.call.body | ||||
| import io.ktor.client.request.get | ||||
| import io.ktor.client.request.headers | ||||
| @ -33,13 +35,14 @@ class UserRepository( | ||||
|             result.status != HttpStatusCode.OK | ||||
|         } | ||||
|     } | ||||
|     suspend fun login(login: String): Result<AuthTokenPair> = withContext(Dispatchers.IO) { | ||||
|     suspend fun login(login: String, password: String): Result<AuthTokenPair> = withContext(Dispatchers.IO) { | ||||
|         runCatching { | ||||
|             val result = Network.client.post("$serverUrl/api/auth/login") { | ||||
|                 headers { | ||||
|                     append(HttpHeaders.ContentType, ContentType.Application.Json.toString()) | ||||
|                 } | ||||
|                 setBody("""{ "login": "$login" }""") | ||||
|                 contentType(ContentType.Application.Json) | ||||
|                 setBody(UserLoginDto(login, password)) | ||||
|             } | ||||
|             if (result.status != HttpStatusCode.OK) { | ||||
|                 error("Status ${result.status}: ${result.body<String>()}") | ||||
| @ -99,6 +102,57 @@ class UserRepository( | ||||
|             result.body() | ||||
|         } | ||||
|     } | ||||
|     suspend fun getMyLastVisits(pageNum: Int, | ||||
|                                 pageSize: Int, | ||||
|                                 token: String): Result<LastVisitsDto> = withContext(Dispatchers.IO){ | ||||
|         runCatching { | ||||
|             val result = Network.client.get("$serverUrl/api/acs/visits/me?page=$pageNum&size=$pageSize") { | ||||
|                 headers { | ||||
|                     append(HttpHeaders.Authorization, "Bearer $token") | ||||
|                 } | ||||
|             } | ||||
|             Log.d("UserRepository", result.bodyAsText()) | ||||
|             if (result.status != HttpStatusCode.OK) { | ||||
|                 error("Status ${result.status}: ${result.body<String>()}") | ||||
|             } | ||||
| 
 | ||||
|             result.body() | ||||
|         } | ||||
|     } | ||||
|     suspend fun getLastVisitsByLogin(pageNum: Int, | ||||
|                                      pageSize: Int, | ||||
|                                      token: String, login: String): Result<LastVisitsDto> = withContext(Dispatchers.IO){ | ||||
|         runCatching { | ||||
|             val encodedLogin = login.encodeURLPath() | ||||
|             val result = Network.client.get("$serverUrl/api/acs/login/${encodedLogin}?page=$pageNum&size=$pageSize") { | ||||
|                 headers { | ||||
|                     append(HttpHeaders.Authorization, "Bearer $token") | ||||
|                 } | ||||
|                 setBody("""{ "login": "$encodedLogin" }""") | ||||
|             } | ||||
|             if (result.status != HttpStatusCode.OK) { | ||||
|                 error("Status ${result.status}: ${result.body<String>()}") | ||||
|             } | ||||
|             Log.d("UserRepository", result.bodyAsText()) | ||||
|             result.body() | ||||
|         } | ||||
|     } | ||||
|     suspend fun getAllLastVisitsAsAdmin(token: String, login: String): Result<UserDTO> = withContext(Dispatchers.IO){ | ||||
|         runCatching { | ||||
|             val encodedLogin = login.encodeURLPath() | ||||
|             val result = Network.client.get("$serverUrl/api/users/login/$encodedLogin") { | ||||
|                 headers { | ||||
|                     append(HttpHeaders.Authorization, "Bearer $token") | ||||
|                 } | ||||
|                 setBody("""{ "code": "$encodedLogin" }""") | ||||
|             } | ||||
|             if (result.status != HttpStatusCode.OK) { | ||||
|                 error("Status ${result.status}: ${result.body<String>()}") | ||||
|             } | ||||
|             Log.d("UserRepository", result.bodyAsText()) | ||||
|             result.body() | ||||
|         } | ||||
|     } | ||||
|     suspend fun openDoor(token: String, code: Long): Result<Unit> = withContext(Dispatchers.IO) { | ||||
|         runCatching { | ||||
|             val result = Network.client.patch("$serverUrl/api/open") { | ||||
|  | ||||
| @ -0,0 +1,55 @@ | ||||
| package com.displaynone.acss.components.auth.models.user.repository | ||||
| 
 | ||||
| import android.graphics.Color | ||||
| import android.view.LayoutInflater | ||||
| import android.view.ViewGroup | ||||
| import androidx.paging.PagingDataAdapter | ||||
| import androidx.recyclerview.widget.DiffUtil | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.bumptech.glide.Glide | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.VisitDto | ||||
| import com.displaynone.acss.databinding.ItemScannerViewBinding | ||||
| 
 | ||||
| class VisitAdapter: PagingDataAdapter<VisitDto, VisitAdapter.ViewHolder>(VisitDiff) { | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { | ||||
|         return ViewHolder( | ||||
|             ItemScannerViewBinding.inflate( | ||||
|                 LayoutInflater.from(parent.context), | ||||
|                 parent, | ||||
|                 false | ||||
|             ) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override fun onBindViewHolder(holder: ViewHolder, position: Int) { | ||||
|         holder.bind(getItem(position) ?: | ||||
|         VisitDto( | ||||
|             id = -1, | ||||
|             userId = -1, | ||||
|             gateId = -1, | ||||
|             createdAt = "Loading...", | ||||
|         )) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     class ViewHolder( | ||||
|         private val binding: ItemScannerViewBinding | ||||
|     ): RecyclerView.ViewHolder(binding.root) { | ||||
|         fun bind(item: VisitDto){ | ||||
|             binding.scanTime.text = item.createdAt | ||||
|             binding.scannerId.text = item.gateId.toString() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     object VisitDiff : DiffUtil.ItemCallback<VisitDto>() { | ||||
|         override fun areItemsTheSame(oldItem: VisitDto, newItem: VisitDto): Boolean { | ||||
|             return oldItem.id == newItem.id | ||||
|         } | ||||
| 
 | ||||
|         override fun areContentsTheSame(oldItem: VisitDto, newItem: VisitDto): Boolean { | ||||
|             return oldItem == newItem | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,35 @@ | ||||
| package com.displaynone.acss.components.auth.models.user.repository | ||||
| 
 | ||||
| import androidx.paging.PagingSource | ||||
| import androidx.paging.PagingState | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.VisitDto | ||||
| 
 | ||||
| class VisitListPagingSource( | ||||
|     private val request: suspend (pageNum: Int, pageSize: Int) -> Result<List<VisitDto>> | ||||
| ) : PagingSource<Int, VisitDto>() { | ||||
|     override fun getRefreshKey(state: PagingState<Int, VisitDto>): Int? { | ||||
|         return state.anchorPosition?.let { | ||||
|             state.closestPageToPosition(it)?.prevKey?.plus(1) | ||||
|                 ?: state.closestPageToPosition(it)?.nextKey?.minus(1) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(params: LoadParams<Int>): LoadResult<Int, VisitDto> { | ||||
|         val pageNum = params.key ?: 0 | ||||
|         return request.invoke( | ||||
|             pageNum, | ||||
|             params.loadSize | ||||
|         ).fold( | ||||
|             onSuccess = { value -> | ||||
|                 LoadResult.Page( | ||||
|                     data = value, | ||||
|                     prevKey = (pageNum - 1).takeIf { it >= 0 }, | ||||
|                     nextKey = (pageNum + 1).takeIf { value.size == params.loadSize } | ||||
|                 ) | ||||
|             }, | ||||
|             onFailure = { error -> | ||||
|                 LoadResult.Error(error) | ||||
|             } | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| package com.displaynone.acss.components.auth.models.user.repository.dto | ||||
| 
 | ||||
| import kotlinx.serialization.SerialName | ||||
| import kotlinx.serialization.Serializable | ||||
| 
 | ||||
| 
 | ||||
| @Serializable | ||||
| data class LastVisitsDto( | ||||
|     @SerialName("content") | ||||
|     val content: List<VisitDto> | ||||
| ) { | ||||
| } | ||||
| @ -21,6 +21,6 @@ data class UserDTO ( | ||||
|     @SerialName("position") | ||||
|     val position: String, | ||||
| 
 | ||||
|     @SerialName("lastVisit") | ||||
|     val lastVisit: String, | ||||
| //    @SerialName("lastVisit") | ||||
| //    val lastVisit: String, | ||||
| ) : java.io.Serializable | ||||
| @ -0,0 +1,13 @@ | ||||
| package com.displaynone.acss.components.auth.models.user.repository.dto | ||||
| 
 | ||||
| import kotlinx.serialization.SerialName | ||||
| import kotlinx.serialization.Serializable | ||||
| 
 | ||||
| @Serializable | ||||
| data class UserLoginDto( | ||||
|     @SerialName("login") | ||||
|     val login: String, | ||||
|     @SerialName("password") | ||||
|     val password: String, | ||||
| ) { | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| package com.displaynone.acss.components.auth.models.user.repository.dto | ||||
| 
 | ||||
| import kotlinx.serialization.SerialName | ||||
| import kotlinx.serialization.Serializable | ||||
| 
 | ||||
| @Serializable | ||||
| data class VisitDto( | ||||
|     @SerialName("id") | ||||
|     val id: Long, | ||||
|     @SerialName("userId") | ||||
|     val userId: Long, | ||||
|     @SerialName("gateId") | ||||
|     val gateId: Long, | ||||
|     @SerialName("createdAt") | ||||
|     val createdAt: String, | ||||
| ) { | ||||
| } | ||||
| @ -40,9 +40,14 @@ class AdminFragment : Fragment(R.layout.fragment_admin) { | ||||
|                 val userDto = state.item | ||||
|                 val bundle = Bundle().apply{ | ||||
|                     putSerializable("user", userDto) | ||||
|                     putBoolean("isMe", false) | ||||
|                 } | ||||
|                 navigateTo(view, R.id.action_adminFragment_to_profileFragment, bundle) | ||||
|             } | ||||
|             if (state is AdminViewModel.State.Error){ | ||||
|                 val errorMessage = state.errorMessage | ||||
|                 binding.loginSearch.setError(errorMessage) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -5,7 +5,6 @@ import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.displaynone.acss.components.auth.models.user.UserServiceST | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO | ||||
| import com.displaynone.acss.ui.profile.ProfileViewModel.State | ||||
| import kotlinx.coroutines.flow.MutableStateFlow | ||||
| import kotlinx.coroutines.flow.asStateFlow | ||||
| import kotlinx.coroutines.launch | ||||
| @ -20,7 +19,8 @@ class AdminViewModel: ViewModel() { | ||||
|                     _state.emit(State.Show(item = dto)) | ||||
|                 }, | ||||
|                 onFailure = { error -> | ||||
|                     error.message?.let { error(it) } | ||||
| //                    error.message?.let { error(it) } | ||||
|                     _state.emit(State.Error(error.message.toString())) | ||||
|                     Log.e("AdminViewModel", error.message.toString()) } | ||||
|             ) | ||||
|         } | ||||
| @ -30,6 +30,9 @@ class AdminViewModel: ViewModel() { | ||||
|         data class Show( | ||||
|             val item: UserDTO | ||||
|             ): State | ||||
|         data class Error( | ||||
|             val errorMessage: String | ||||
|         ): State | ||||
|         data object Loading : State | ||||
|     } | ||||
| } | ||||
| @ -59,6 +59,7 @@ class AuthFragment: Fragment(R.layout.fragment_auth) { | ||||
|                 val username = s.toString() | ||||
|                 val valid = isUsernameValid(username) | ||||
| 
 | ||||
| 
 | ||||
|                 binding.hint.visibility = if(valid) View.INVISIBLE else View.VISIBLE | ||||
|                 binding.next.isEnabled = valid | ||||
|                 val color = if (valid) R.color.primary else R.color.secondary | ||||
| @ -67,6 +68,35 @@ class AuthFragment: Fragment(R.layout.fragment_auth) { | ||||
| 
 | ||||
|             override fun afterTextChanged(s: Editable?) {} | ||||
|         }) | ||||
| //        binding.password.addTextChangedListener(object : TextWatcher { | ||||
| //            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} | ||||
| //            @SuppressLint("ResourceAsColor") | ||||
| //            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { | ||||
| //                binding.error.visibility = View.GONE | ||||
| //                val username = s.toString() | ||||
| //                val valid = isPasswordValid(username) | ||||
| // | ||||
| //                binding.hint.visibility = if(valid) View.INVISIBLE else View.VISIBLE | ||||
| //                if (!valid){ | ||||
| //                    val errorMessage = getPasswordValidError(s.toString()) | ||||
| //                    binding.password.setError(errorMessage) | ||||
| //                } | ||||
| //                binding.next.isEnabled = valid | ||||
| //                val color = if (valid) R.color.primary else R.color.secondary | ||||
| //                binding.next.backgroundTintList = ContextCompat.getColorStateList(requireContext(), color) | ||||
| //            } | ||||
| // | ||||
| //            override fun afterTextChanged(s: Editable?) {} | ||||
| //        }) | ||||
|     } | ||||
|     private fun getPasswordValidError(password: String): String { | ||||
|         if (password.length < 8){ return "LenError" } | ||||
|         val letterRegex = Regex("^(?=.*[A-Z]).+$") | ||||
|         if(!letterRegex.matches(password)){ return "UpperCaseError"} | ||||
|         val digitRegex = Regex("^(?=.*\\\\d).+$") | ||||
|         if(!digitRegex.matches(password)){ return "DigitCaseError"} | ||||
| 
 | ||||
|         return "NoErrors" | ||||
|     } | ||||
| 
 | ||||
|     private fun isUsernameValid(username: String): Boolean { | ||||
| @ -76,6 +106,10 @@ class AuthFragment: Fragment(R.layout.fragment_auth) { | ||||
|                 !username[0].isDigit() && | ||||
|                 alf.matches(username) | ||||
|     } | ||||
|     private fun isPasswordValid(password: String): Boolean { | ||||
|         return password.isNotEmpty() && | ||||
|                 password.length >= 8 | ||||
|     } | ||||
| //    private fun subscribe() { | ||||
| //        viewModel.state.collectWhenStarted(this) { state -> | ||||
| //            binding.login.setOnClickListener(this::onLoginButtonClicked) | ||||
| @ -84,8 +118,9 @@ class AuthFragment: Fragment(R.layout.fragment_auth) { | ||||
| 
 | ||||
|     private fun onLoginButtonClicked(view: View) { | ||||
|         val login = binding.login.text.toString() | ||||
|         val password = binding.password.text.toString() | ||||
|         if (login.isEmpty()) return | ||||
|         viewModel.login(login) | ||||
|         viewModel.login(login, password) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -22,10 +22,10 @@ class AuthViewModel(): ViewModel() { | ||||
|     private val _errorState = MutableStateFlow<String?>(null) | ||||
|     val errorState: StateFlow<String?> = _errorState.asStateFlow() | ||||
| 
 | ||||
|     fun login(login: String){ | ||||
|     fun login(login: String, password:String){ | ||||
|         viewModelScope.launch { | ||||
|             try { | ||||
|                 UserServiceST.getInstance().login(login).fold( | ||||
|                 UserServiceST.getInstance().login(login, password).fold( | ||||
|                     onSuccess = { openProfile() }, | ||||
|                     onFailure = { error -> | ||||
|                         Log.e("AuthViewModel", "Login failed: ${error.message ?: "Unknown error"}") | ||||
|  | ||||
| @ -10,6 +10,7 @@ import androidx.fragment.app.viewModels | ||||
| import androidx.navigation.fragment.findNavController | ||||
| import com.bumptech.glide.Glide | ||||
| import com.displaynone.acss.R | ||||
| import com.displaynone.acss.components.auth.models.user.repository.VisitAdapter | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO | ||||
| import com.displaynone.acss.databinding.FragmentProfileBinding | ||||
| import com.displaynone.acss.ui.profile.ProfileViewModel.Action | ||||
| @ -27,31 +28,58 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) { | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|         _binding = FragmentProfileBinding.bind(view) | ||||
| 
 | ||||
|         binding.swipeRefresh.setOnRefreshListener { | ||||
|             refreshData() | ||||
|         } | ||||
| // | ||||
| //        binding.swipeRefresh.setOnRefreshListener { | ||||
| //            if (getIsMe()){ | ||||
| //                refreshData() | ||||
| //            } else{ | ||||
| //                showData(getUserDto()!!) | ||||
| //            } | ||||
| //        } | ||||
|         binding.logout.setOnClickListener{ | ||||
|             logout() | ||||
|         } | ||||
|         binding.scan.setOnClickListener{ | ||||
|             viewModel.openScan() | ||||
|         } | ||||
|         val user = getUserDto() | ||||
|         if (user == null) { | ||||
|         val adapter = VisitAdapter() | ||||
|         binding.recyclerViewLogs.adapter = adapter | ||||
|         if (getIsMe()) { | ||||
|             refreshData() | ||||
| //            viewModel.visitListState.collectWithLifecycle(this) { data -> | ||||
| //                adapter.submitData(data) | ||||
| //            } | ||||
|             waitForQRScanResult() | ||||
|         } else{ | ||||
|             showData(user) // TODO()  не показывать кнопки | ||||
|             showData(getUserDto()!!) | ||||
|             hideButtons() | ||||
| 
 | ||||
|         } | ||||
|         subscribe() | ||||
| 
 | ||||
|         viewModel.visitListState.collectWithLifecycle(this) { data -> | ||||
|             adapter.submitData(data) | ||||
|             Log.d("ProfileFragment", "submitted data") | ||||
|         } | ||||
| //        viewModel.visitListStateFromLogin.collectWithLifecycle(this) { data -> | ||||
| //            adapter.submitData(data) | ||||
| //        } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private fun hideButtons() { | ||||
|         binding.logout.visibility = View.INVISIBLE | ||||
|         binding.scan.visibility = View.INVISIBLE | ||||
|     } | ||||
| 
 | ||||
|     fun showData(userDTO: UserDTO){ | ||||
|         binding.fio.text = userDTO.name | ||||
|         binding.position.text = userDTO.position | ||||
|         binding.lastEntry.text = userDTO.lastVisit | ||||
|         viewModel.setLogin(login1 = userDTO.login) | ||||
| //        binding.lastEntry.text = userDTO.lastVisit | ||||
| //        viewModel.visitListStateFromLogin.collectWithLifecycle(this){ | ||||
| // | ||||
| //        } | ||||
|         setAvatar(userDTO.photo) | ||||
|     } | ||||
|     private fun refreshData() { | ||||
| @ -72,6 +100,10 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) { | ||||
|     private fun getUserDto(): UserDTO? { | ||||
|         return arguments?.getSerializable("user") as? UserDTO | ||||
|     } | ||||
|     private fun getIsMe(): Boolean { | ||||
|         return arguments?.getBoolean("isMe", true) ?: true | ||||
|     } | ||||
| 
 | ||||
|     private fun waitForQRScanResult() { | ||||
| 
 | ||||
|         requireActivity().onBackPressedDispatcher.addCallback( | ||||
|  | ||||
| @ -3,7 +3,12 @@ package com.displaynone.acss.ui.profile | ||||
| import android.util.Log | ||||
| import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import androidx.paging.Pager | ||||
| import androidx.paging.PagingConfig | ||||
| import androidx.paging.cachedIn | ||||
| import androidx.paging.log | ||||
| import com.displaynone.acss.components.auth.models.user.UserServiceST | ||||
| import com.displaynone.acss.components.auth.models.user.repository.VisitListPagingSource | ||||
| import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO | ||||
| import kotlinx.coroutines.channels.BufferOverflow | ||||
| import kotlinx.coroutines.channels.Channel | ||||
| @ -17,10 +22,31 @@ class ProfileViewModel(): ViewModel() { | ||||
|         capacity = Channel.BUFFERED, | ||||
|         onBufferOverflow = BufferOverflow.DROP_OLDEST, | ||||
|     ) | ||||
|     private var login: String = "" // FIXME() | ||||
|     fun setLogin(login1: String){ | ||||
|         login = login1 | ||||
|     } | ||||
|     val action = _action.receiveAsFlow() | ||||
|     val _state = MutableStateFlow<State>(State.Loading) | ||||
|     val state = _state.asStateFlow() | ||||
| 
 | ||||
|     val visitListState = Pager( | ||||
|         config = PagingConfig(pageSize = 20, | ||||
|             enablePlaceholders = false, | ||||
|             maxSize = 100 | ||||
|         ) | ||||
|     ) { | ||||
|         VisitListPagingSource(UserServiceST.getInstance()::getMyLastVisits) | ||||
|     }.flow | ||||
|         .cachedIn(viewModelScope) | ||||
| 
 | ||||
|     val visitListStateFromLogin = Pager( | ||||
|         config = PagingConfig(pageSize = 20, enablePlaceholders = false, maxSize = 100) | ||||
|     ) { | ||||
|         VisitListPagingSource { pageNum, pageSize -> | ||||
|             UserServiceST.getInstance().getLastVisitsByLogin(pageNum,pageSize, login) | ||||
|         } | ||||
|     }.flow.cachedIn(viewModelScope) | ||||
| 
 | ||||
|     fun logout(){ | ||||
|         UserServiceST.getInstance().logout() | ||||
| @ -48,6 +74,7 @@ class ProfileViewModel(): ViewModel() { | ||||
|             _action.send(Action.GoToScan) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     sealed interface State { | ||||
|         data object Loading : State | ||||
|         data class Show( | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user