Merge remote-tracking branch 'origin/main'

This commit is contained in:
Juja2025 2025-02-19 18:58:02 +03:00
commit bfe0546c4a
8 changed files with 238 additions and 15 deletions

View File

@ -23,6 +23,8 @@ import ru.myitschool.work.ui.searchuser.SearchUserDestination
import ru.myitschool.work.ui.searchuser.SearchUserFragment import ru.myitschool.work.ui.searchuser.SearchUserFragment
import ru.myitschool.work.ui.splash.SplashDestination import ru.myitschool.work.ui.splash.SplashDestination
import ru.myitschool.work.ui.splash.SplashFragment import ru.myitschool.work.ui.splash.SplashFragment
import ru.myitschool.work.ui.userInfo.UserInfoDestination
import ru.myitschool.work.ui.userInfo.UserInfoFragment
@AndroidEntryPoint @AndroidEntryPoint
class RootActivity : AppCompatActivity() { class RootActivity : AppCompatActivity() {
@ -45,6 +47,7 @@ class RootActivity : AppCompatActivity() {
fragment<QrScanFragment, QrScanDestination>() fragment<QrScanFragment, QrScanDestination>()
fragment<EntryListFragment, EntryListDestination>() fragment<EntryListFragment, EntryListDestination>()
fragment<SearchUserFragment, SearchUserDestination>() fragment<SearchUserFragment, SearchUserDestination>()
fragment<UserInfoFragment, UserInfoDestination>()
} }
} }

View File

@ -99,7 +99,7 @@ class ProfileFragment : Fragment(R.layout.fragment_profile) {
is ProfileViewModel.Action.OpenSearch -> { is ProfileViewModel.Action.OpenSearch -> {
findNavController().navigate(SearchUserDestination) { findNavController().navigate(SearchUserDestination) {
popUpTo<SearchUserFragment> { inclusive = true } popUpTo<SearchUserDestination> { inclusive = true }
} }
} }

View File

@ -1,28 +1,52 @@
package ru.myitschool.work.ui.searchuser package ru.myitschool.work.ui.searchuser
import androidx.fragment.app.viewModels
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.serialization.Serializable
import ru.myitschool.work.R import ru.myitschool.work.R
import ru.myitschool.work.databinding.FragmentSearchUserBinding
import ru.myitschool.work.ui.profile.ProfileDestination
import ru.myitschool.work.utils.collectWhenStarted
@Serializable
@AndroidEntryPoint @AndroidEntryPoint
class SearchUserFragment : Fragment(R.layout.fragment_search_user) { class SearchUserFragment : Fragment(R.layout.fragment_search_user) {
companion object { private var _binding: FragmentSearchUserBinding? = null
fun newInstance() = SearchUserFragment() private val binding: FragmentSearchUserBinding get() = _binding!!
}
private val viewModel: SearchUserViewModel by viewModels() private val viewModel: SearchUserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentSearchUserBinding.bind(view)
// TODO: Use the ViewModel initCallback()
subscribe()
}
private fun initCallback() {
binding.floatingActionButton2.setOnClickListener { viewModel.closeSearchUser() }
} }
}
private fun subscribe() {
viewModel.action.collectWhenStarted(this) { action ->
when (action) {
is SearchUserViewModel.Action.OpenProfile -> {
findNavController().navigate(ProfileDestination) {
popUpTo<ProfileDestination> { inclusive = true }
}
}
}
}
}
}

View File

@ -2,13 +2,27 @@ package ru.myitschool.work.ui.searchuser
import android.content.Context import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import ru.myitschool.work.utils.MutablePublishFlow
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class SearchUserViewModel @Inject constructor( class SearchUserViewModel @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
) : ViewModel() { ) : ViewModel() {
// TODO: Implement the ViewModel private val _action = MutablePublishFlow<Action>()
val action = _action.asSharedFlow()
fun closeSearchUser(){
viewModelScope.launch {
_action.emit(Action.OpenProfile)
}
}
sealed interface Action {
data object OpenProfile: Action
}
} }

View File

@ -0,0 +1,6 @@
package ru.myitschool.work.ui.userInfo
import kotlinx.serialization.Serializable
@Serializable
data object UserInfoDestination

View File

@ -0,0 +1,58 @@
package ru.myitschool.work.ui.userInfo
import ru.myitschool.work.ui.searchuser.SearchUserViewModel
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import dagger.hilt.android.AndroidEntryPoint
import ru.myitschool.work.R
import ru.myitschool.work.databinding.FragmentSearchUserBinding
import ru.myitschool.work.databinding.FragmentUserInfoBinding
import ru.myitschool.work.ui.profile.ProfileDestination
import ru.myitschool.work.ui.searchuser.SearchUserDestination
import ru.myitschool.work.utils.collectWhenStarted
@AndroidEntryPoint
class UserInfoFragment : Fragment(R.layout.fragment_user_info) {
private var _binding: FragmentUserInfoBinding? = null
private val binding: FragmentUserInfoBinding get() = _binding!!
private val viewModel: UserInfoViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentUserInfoBinding.bind(view)
initCallback()
subscribe()
}
private fun initCallback() {
binding.floatingActionButton2.setOnClickListener { viewModel.closeSearchUser() }
}
private fun subscribe() {
viewModel.action.collectWhenStarted(this) { action ->
when (action) {
is UserInfoViewModel.Action.OpenProfile -> {
findNavController().navigate(SearchUserDestination) {
popUpTo<SearchUserDestination> { inclusive = true }
}
}
}
}
}
}

View File

@ -0,0 +1,28 @@
package ru.myitschool.work.ui.userInfo
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import ru.myitschool.work.utils.MutablePublishFlow
import javax.inject.Inject
@HiltViewModel
class UserInfoViewModel @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
private val _action = MutablePublishFlow<Action>()
val action = _action.asSharedFlow()
fun closeSearchUser(){
viewModelScope.launch {
_action.emit(Action.OpenProfile)
}
}
sealed interface Action {
data object OpenProfile: Action
}
}

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:padding="16dp"
android:orientation="vertical"
android:layout_height="match_parent">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton2"
style="@style/Theme.UiTemplate.FAB.Gray"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:src="@drawable/ic_back" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="120dp"
android:layout_gravity="center"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/photo2"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_margin="5dp"
android:elevation="10dp"
app:cardCornerRadius="12dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/photo"
style="@style/roundedImageView"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginBottom="16dp"
android:contentDescription="@null"
tools:src="@tools:sample/avatars" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/fullname"
style="@style/Theme.UiTemplate.TextH3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/photo2"
tools:text="@tools:sample/full_names" />
<TextView
android:id="@+id/position"
style="@style/Theme.UiTemplate.TextH4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="16dp"
tools:text="@tools:sample/cities" />
<TextView
android:id="@+id/lastEntry"
style="@style/Theme.UiTemplate.TextH4_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:layout_gravity="center"
tools:text="@tools:sample/date/hhmm" />
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Theme.UiTemplate.OutlineButton.Error"
android:layout_marginTop="100dp"
android:layout_gravity="center"
android:text="@string/admin_block" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>