This commit is contained in:
Universall 2025-02-20 11:41:48 +03:00
parent aecbab7cd3
commit 277db36d79
9 changed files with 89 additions and 97 deletions

View File

@ -7,21 +7,25 @@ import androidx.annotation.Nullable;
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;
import com.displaynone.acss.components.auth.models.AuthTokenPair;
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO;
import com.google.gson.Gson;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.Optional;
public class UserManager {
// Preferences
private static final String _PREFERENCES_FILENAME = "userData";
private final SharedPreferences _preferences;
// Utils
private static final Gson gson = new Gson();
// Keys
private static final String _KEY_USER = "user";
// Cache
private UserDTO userDTO;
private static final String ACCESS_KEY = "user";
private Gson gson = new Gson();
public UserManager(Context context) {
this._preferences = this._createEncryptedPreferences(context);
@ -40,23 +44,24 @@ public class UserManager {
throw new RuntimeException(e);
}
}
public void saveDto(UserDTO userDTO) {
this.userDTO = userDTO;
_preferences.edit()
.putString(ACCESS_KEY,toJson(userDTO))
.putString(_KEY_USER, toJson(userDTO))
.apply();
}
public @Nullable UserDTO getDto() {
if (this.userDTO != null) return this.userDTO;
UserDTO userDTO = fromJson( _preferences.getString(ACCESS_KEY, null));
return userDTO;
}
private UserDTO fromJson(String userJSON){
UserDTO userDTO = gson.fromJson(userJSON, UserDTO.class);
return userDTO;
}
private String toJson(UserDTO userDTO){
return gson.toJson(userDTO);
return fromJson(_preferences.getString(_KEY_USER, null));
}
private UserDTO fromJson(String userJSON) {
return gson.fromJson(userJSON, UserDTO.class);
}
private String toJson(UserDTO userDTO) {
return gson.toJson(userDTO);
}
}

View File

@ -1,5 +1,5 @@
package com.displaynone.acss.config
object Constants {
const val serverUrl = "http://192.168.136.38:8086"
const val serverUrl = "http://192.168.56.1:8086"
}

View File

@ -46,7 +46,7 @@ class AdminFragment : Fragment(R.layout.fragment_admin) {
}
if (state is AdminViewModel.State.Error){
val errorMessage = state.errorMessage
binding.loginSearch.setError(errorMessage)
binding.loginSearch.error = errorMessage
}
}
}

View File

@ -80,10 +80,6 @@ class InitFragment : Fragment(R.layout.fragment_init) {
return false
}
private fun getCachedUser(): UserDTO? {
return UserServiceST.getInstance().getUserDTO();
}
private fun isUserAuthenticated(): Boolean {
return UserServiceST.getInstance().hasTokens()
}
@ -91,4 +87,9 @@ class InitFragment : Fragment(R.layout.fragment_init) {
private fun handleError(string: Int) {
binding.error.text = requireContext().getString(string)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -11,8 +11,8 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.displaynone.acss.R
import com.displaynone.acss.components.auth.models.user.UserServiceST
import com.displaynone.acss.components.acs.models.visit.VisitAdapter
import com.displaynone.acss.components.auth.models.user.UserServiceST
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
@ -20,7 +20,7 @@ import com.displaynone.acss.ui.scan.QrScanDestination
import com.displaynone.acss.util.collectWithLifecycle
import com.displaynone.acss.util.navigateTo
class ProfileFragment: Fragment(R.layout.fragment_profile) {
class ProfileFragment : Fragment(R.layout.fragment_profile) {
private var _binding: FragmentProfileBinding? = null
private val binding: FragmentProfileBinding get() = _binding!!
@ -33,29 +33,28 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
checkForAdmin()
binding.swipeRefresh.setOnRefreshListener {
if (getIsMe()){
refreshData()
} else{
showData(getUserDto()!!)
}
if (getIsMe()) refreshData() else showData(getUserDto()!!);
}
binding.logout.setOnClickListener{
binding.logout.setOnClickListener {
logout()
}
binding.scan.setOnClickListener{
binding.scan.setOnClickListener {
navigateTo(view, R.id.action_profileFragment_to_qrScanFragment)
}
binding.buttonSearch.setOnClickListener{
binding.buttonSearch.setOnClickListener {
navigateTo(view, R.id.action_profileFragment_to_adminFragment)
}
binding.recyclerViewLogs.adapter = adapter
if (getIsMe()) {
refreshData()
viewModel.visitListState.collectWithLifecycle(this) { data ->
adapter.submitData(data)
}
viewModel.visitListState.collectWithLifecycle(this) { data -> adapter.submitData(data) }
waitForQRScanResult()
} else{
} else {
showData(getUserDto()!!)
Log.d("ProfileFragment", "set login")
viewModel.visitListStateFromLogin.collectWithLifecycle(this) { data ->
@ -66,72 +65,66 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
}
subscribe()
binding.recyclerViewLogs.layoutManager = LinearLayoutManager(requireContext())
// viewModel.visitListStateFromLogin.collectWithLifecycle(this) { data ->
// adapter.submitData(data)
// }
}
private fun checkForAdmin() {
Log.d("check", "cheking for roles")
val userDTO = UserServiceST.getInstance().getUserDTO() ?: return
val userDTO = UserServiceST.getInstance().getUserDTO()
if (userDTO != null) {
if (userDTO.roles.any { it.name == "ROLE_ADMIN" }) {
Log.d("adminlog", "i'm admin")
binding.buttonSearch.visibility = View.VISIBLE
binding.rightsUsingSmartphone.text = "Пропуск действителен"
}
if (userDTO.roles.any { it.name == "ROLE_USER" }) {
Log.d("userlog", "i'm user")
binding.rightsUsingSmartphone.text = "Пропуск действителен"
}
if (userDTO.roles.any { it.name == "ROLE_ADMIN" }) {
binding.buttonSearch.visibility = View.VISIBLE
binding.rightsUsingSmartphone.text = "Пропуск действителен"
}
if (userDTO.roles.any { it.name == "ROLE_USER" }) {
binding.rightsUsingSmartphone.text = "Пропуск действителен"
}
}
private fun hideButtons() {
binding.logout.visibility = View.GONE
binding.scan.visibility = View.GONE
binding.buttonSearch.visibility = View.GONE
}
fun showMyData(userDTO: UserDTO){
private fun showMyData(userDTO: UserDTO) {
binding.fio.text = userDTO.name
binding.position.text = userDTO.position
setAvatar(userDTO.photo)
}
fun showData(userDTO: UserDTO){
private fun showData(userDTO: UserDTO) {
binding.fio.text = userDTO.name
binding.position.text = userDTO.position
viewModel.setLogin(login1 = userDTO.login)
Log.d("ProfileFragment", userDTO.login)
// binding.lastEntry.text = userDTO.lastVisit
setAvatar(userDTO.photo)
}
private fun refreshData() {
Log.d("ProfileFragment", "Refreshed")
viewModel.getInfo()
subscribeToGetData()
}
fun subscribe() {
private fun subscribe() {
viewModel.action.collectWithLifecycle(this) { action ->
if (action is Action.GoToAuth) {
view?.let { navigateTo(it, R.id.action_profileFragment_to_authFragment) } ?: throw IllegalStateException("View is null")
view?.let { navigateTo(it, R.id.action_profileFragment_to_authFragment) }
?: throw IllegalStateException("View is null")
}
if (action is Action.GoToScan) {
view?.let { navigateTo(it, R.id.action_profileFragment_to_qrResultFragment) }?: throw IllegalStateException("View is null")
view?.let { navigateTo(it, R.id.action_profileFragment_to_qrResultFragment) }
?: throw IllegalStateException("View is null")
}
}
}
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(
viewLifecycleOwner,
object : OnBackPressedCallback(true) {
@ -145,20 +138,19 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
)?.observe(viewLifecycleOwner) { bundle ->
val qrCode = bundle.getString("key_qr")
if (!qrCode.isNullOrEmpty()) view?.let {
val bundle = Bundle().apply {
putString("qrCode", qrCode)
}
navigateTo(it, R.id.action_profileFragment_to_qrResultFragment, bundle)
val newBundle = Bundle().apply { putString("qrCode", qrCode) }
navigateTo(it, R.id.action_profileFragment_to_qrResultFragment, newBundle)
}
}
}
private fun logout() {
viewModel.logout()
viewModel.openAuth()
Toast.makeText(activity, "LOGOUT", Toast.LENGTH_SHORT).show()
}
private fun subscribeToGetData(){
private fun subscribeToGetData() {
viewModel.state.collectWithLifecycle(this) { state ->
if (state is ProfileViewModel.State.Show) {
val userDto: UserDTO = state.item

View File

@ -1,13 +1,9 @@
package com.displaynone.acss.ui.result
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.displaynone.acss.R
import com.displaynone.acss.databinding.FragmentQrResultBinding
import com.displaynone.acss.util.collectWithLifecycle
@ -21,34 +17,37 @@ class QrResultFragment : Fragment(R.layout.fragment_qr_result) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d("QrResultFragment", getQrCode())
_binding = FragmentQrResultBinding.bind(view)
binding.close.setOnClickListener(this::closeQrScanFragment)
this.openDoor()
viewModel.state.collectWithLifecycle(this){ state ->
if (state is QrResultViewModel.State.Result){
if (state.resultCode == 200) {
setResult(getString(R.string.success))
} else if (state.resultCode == 400) {
setResult(getString(R.string.wrong))
} else if (state.resultCode == 401) {
setResult(getString(R.string.cancel))
viewModel.state.collectWithLifecycle(this) { state ->
if (state is QrResultViewModel.State.Result) {
when (state.resultCode) {
200 -> {
setResult(getString(R.string.success))
}
400 -> {
setResult(getString(R.string.wrong))
}
401 -> {
setResult(getString(R.string.cancel))
}
}
}
if (state is QrResultViewModel.State.Error){
setResult(state.errorMessage)
}
if (state is QrResultViewModel.State.Error) setResult(state.errorMessage)
}
}
private fun openDoor() {
val qrValue = getQrCode() ?: return
val qrCodeValueLong: Long
try {
qrCodeValueLong = getQrCode().toLong()
qrCodeValueLong = qrValue.toLong()
} catch (exception: Exception) {
when (exception) {
is NumberFormatException, is IllegalArgumentException -> setResult(getString(R.string.wrong))
@ -60,8 +59,8 @@ class QrResultFragment : Fragment(R.layout.fragment_qr_result) {
viewModel.openDoor(qrCodeValueLong)
}
private fun getQrCode(): String {
return arguments?.getString("qrCode") ?: "No QR Code Provided"
private fun getQrCode(): String? {
return arguments?.getString("qrCode")
}
private fun closeQrScanFragment(view: View) {

View File

@ -61,9 +61,7 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
viewModel.action.collectWhenStarted(this) { action ->
when (action) {
is QrScanViewModel.Action.RequestPermission -> requestPermission(action.permission)
is QrScanViewModel.Action.CloseWithCancel -> {
goBack()
}
is QrScanViewModel.Action.CloseWithCancel -> goBack()
is QrScanViewModel.Action.CloseWithResult -> {
sendResult(QrScanDestination.packToBundle(action.result))
goBack()
@ -82,9 +80,7 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
val previewView: PreviewView = binding.viewFinder
val executor = ContextCompat.getMainExecutor(context)
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
val options = BarcodeScannerOptions.Builder().setBarcodeFormats(Barcode.FORMAT_QR_CODE).build()
val barcodeScanner = BarcodeScanning.getClient(options)
this.barcodeScanner = barcodeScanner

View File

@ -1,7 +1,5 @@
package com.displaynone.acss.ui.scan
import androidx.lifecycle.ViewModel
import android.Manifest
import android.app.Application
import android.content.pm.PackageManager
@ -80,6 +78,7 @@ class QrScanViewModel(
data class RequestPermission(
val permission: String
) : Action
data object CloseWithCancel : Action
data class CloseWithResult(
val result: String

View File

@ -17,7 +17,7 @@
<fragment
android:id="@+id/nav_profile"
android:name="com.displaynone.acss.ui.profile.ProfileFragment"
android:label="@string/profile"
android:label="@string/title_profile"
tools:layout="@layout/fragment_profile">
<action
android:id="@+id/action_profileFragment_to_authFragment"