From b719cce98d914f92d0eecd4c660701b2d80fe75a Mon Sep 17 00:00:00 2001 From: Erik Cavazos Date: Sat, 29 Jul 2023 00:55:07 -0600 Subject: [PATCH] WIP barra colapsable en pantalla de perfil y trae informacion de perfil --- .../java/com/isolaatti/home/FeedFragment.kt | 26 +++ .../domain/use_case/GetProfilePosts.kt | 13 ++ .../profile/presentation/ProfileViewModel.kt | 25 +- .../isolaatti/profile/ui/ProfileActivity.kt | 62 +++-- app/src/main/res/layout/activity_profile.xml | 219 ++++++++---------- app/src/main/res/values/themes.xml | 3 + 6 files changed, 197 insertions(+), 151 deletions(-) create mode 100644 app/src/main/java/com/isolaatti/profile/domain/use_case/GetProfilePosts.kt diff --git a/app/src/main/java/com/isolaatti/home/FeedFragment.kt b/app/src/main/java/com/isolaatti/home/FeedFragment.kt index 45fc04f..c333752 100644 --- a/app/src/main/java/com/isolaatti/home/FeedFragment.kt +++ b/app/src/main/java/com/isolaatti/home/FeedFragment.kt @@ -15,6 +15,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.constraintlayout.widget.ConstraintLayout import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels +import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import com.isolaatti.BuildConfig import com.isolaatti.R @@ -25,6 +26,9 @@ import com.isolaatti.posting.PostViewerActivity import com.isolaatti.posting.posts.presentation.PostsViewModel import com.isolaatti.posting.comments.presentation.BottomSheetPostComments import com.isolaatti.posting.common.domain.OnUserInteractedWithPostCallback +import com.isolaatti.posting.common.options_bottom_sheet.domain.OptionClicked +import com.isolaatti.posting.common.options_bottom_sheet.domain.Options +import com.isolaatti.posting.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel import com.isolaatti.posting.common.options_bottom_sheet.ui.BottomSheetPostOptionsFragment import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter import com.isolaatti.posting.posts.ui.CreatePostActivity @@ -45,11 +49,14 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { companion object { fun newInstance() = FeedFragment() + const val CALLER_ID = 20 } private val viewModel: PostsViewModel by activityViewModels() private val errorViewModel: ErrorMessageViewModel by activityViewModels() private val screenViewModel: FeedViewModel by viewModels() + val optionsViewModel: BottomSheetPostOptionsViewModel by activityViewModels() + private lateinit var viewBinding: FragmentFeedBinding private lateinit var adapter: PostsRecyclerViewAdapter @@ -59,6 +66,22 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { } } + val optionsObserver: Observer = Observer { + if(it.callerId == CALLER_ID) { + when(it.optionId) { + Options.Option.OPTION_DELETE -> { + + } + Options.Option.OPTION_EDIT -> { + + } + Options.Option.OPTION_REPORT -> { + + } + } + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -175,6 +198,8 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { } } screenViewModel.getProfile() + + optionsViewModel.optionClicked.observe(viewLifecycleOwner, optionsObserver) } fun onNewMenuItemClicked(v: View) { @@ -187,6 +212,7 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { override fun onUnLiked(postId: Long) = viewModel.unLikePost(postId) override fun onOptions(postId: Long) { + optionsViewModel.setOptions(Options.postOptions, CALLER_ID) val modalBottomSheet = BottomSheetPostOptionsFragment() modalBottomSheet.show(requireActivity().supportFragmentManager, BottomSheetPostOptionsFragment.TAG) } diff --git a/app/src/main/java/com/isolaatti/profile/domain/use_case/GetProfilePosts.kt b/app/src/main/java/com/isolaatti/profile/domain/use_case/GetProfilePosts.kt new file mode 100644 index 0000000..60e847d --- /dev/null +++ b/app/src/main/java/com/isolaatti/profile/domain/use_case/GetProfilePosts.kt @@ -0,0 +1,13 @@ +package com.isolaatti.profile.domain.use_case + +import com.isolaatti.posting.posts.data.remote.FeedDto +import com.isolaatti.posting.posts.data.remote.FeedFilterDto +import com.isolaatti.posting.posts.domain.PostsRepository +import com.isolaatti.utils.Resource +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetProfilePosts @Inject constructor(private val postsRepository: PostsRepository) { + operator fun invoke(userId: Int, lastId: Long, olderFirst: Boolean, filter: FeedFilterDto): Flow> = + postsRepository.getProfilePosts(userId, lastId, olderFirst, filter) +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt b/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt index b626f2e..f16b793 100644 --- a/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt +++ b/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt @@ -3,17 +3,40 @@ package com.isolaatti.profile.presentation import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.isolaatti.posting.posts.data.remote.FeedDto import com.isolaatti.profile.data.remote.UserProfileDto import com.isolaatti.profile.domain.ProfileRepository +import com.isolaatti.profile.domain.use_case.GetProfile +import com.isolaatti.profile.domain.use_case.GetProfilePosts +import com.isolaatti.utils.Resource import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class ProfileViewModel @Inject constructor(private val profileRepository: ProfileRepository) : ViewModel() { +class ProfileViewModel @Inject constructor(private val getProfileUseCase: GetProfile, private val getProfilePosts: GetProfilePosts) : ViewModel() { private val _profile = MutableLiveData() val profile: LiveData get() = _profile + private val _posts = MutableLiveData() + val posts: LiveData get() = _posts + fun getProfile(profileId: Int) { + viewModelScope.launch { + getProfileUseCase(profileId).onEach { + if(it is Resource.Success) { + _profile.postValue(it.data!!) + } + }.flowOn(Dispatchers.IO).launchIn(this) + } + } + + fun getPosts(profileId: Int, refresh: Boolean) { } } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/profile/ui/ProfileActivity.kt b/app/src/main/java/com/isolaatti/profile/ui/ProfileActivity.kt index d852eb0..80b1461 100644 --- a/app/src/main/java/com/isolaatti/profile/ui/ProfileActivity.kt +++ b/app/src/main/java/com/isolaatti/profile/ui/ProfileActivity.kt @@ -3,6 +3,7 @@ package com.isolaatti.profile.ui import android.content.Context import android.content.Intent import android.os.Bundle +import android.util.Log import androidx.activity.addCallback import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity @@ -13,6 +14,8 @@ import androidx.lifecycle.ViewModelProvider import androidx.viewpager.widget.PagerAdapter import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentViewHolder +import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener import com.google.android.material.tabs.TabLayoutMediator import com.isolaatti.R import com.isolaatti.databinding.ActivityProfileBinding @@ -24,35 +27,19 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class ProfileActivity : AppCompatActivity() { - class ViewPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) { - override fun getItemCount(): Int = 3 - - override fun createFragment(position: Int): Fragment { - return when(position) { - 0 -> { - DiscussionsFragment() - } - 1 -> { - AudiosFragment() - } - 2 -> { - ImagesFragment() - } - else -> {Fragment()} - } - } - - } - lateinit var viewBinding: ActivityProfileBinding private val viewModel: ProfileViewModel by viewModels() + private var userId: Int? = null + + private var title = "" private val profileObserver = Observer { profile -> Picasso.get() .load(UrlGen.userProfileImage(profile.id)) .into(viewBinding.profileImageView) + title = profile.name viewBinding.textViewUsername.text = profile.name viewBinding.textViewDescription.text = profile.descriptionText } @@ -60,27 +47,34 @@ class ProfileActivity : AppCompatActivity() { super.onCreate(savedInstanceState) viewBinding = ActivityProfileBinding.inflate(layoutInflater) setContentView(viewBinding.root) + userId = intent.extras?.getInt(EXTRA_USER_ID) + var scrollRange = -1 + var isShow = false + viewBinding.topAppBarLayout.addOnOffsetChangedListener(object: OnOffsetChangedListener { + + + override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) { + if (scrollRange == -1) scrollRange = appBarLayout.totalScrollRange + if(scrollRange + verticalOffset == 0) { + viewBinding.collapsingToolbarLayout.title = title + isShow = true + } else if(isShow) { + viewBinding.collapsingToolbarLayout.title = " " + } + + } + + }) - viewBinding.profileViewPager2.adapter = ViewPagerAdapter(this) viewBinding.topAppBar.setNavigationOnClickListener { finish() } - TabLayoutMediator(viewBinding.profileTabLayout, viewBinding.profileViewPager2) {tab, position -> - when(position) { - 0 -> { - tab.text = getText(R.string.discussions) - } - 1 -> { - tab.text = getText(R.string.audios) - } - 2 -> { - tab.text = getText(R.string.images) - } - } - }.attach() viewModel.profile.observe(this, profileObserver) + + userId?.let { viewModel.getProfile(it) } + } companion object { diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 9d3ff3c..35f163f 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -1,5 +1,5 @@ - - - + + android:layout_height="410dp" + app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" + app:contentScrim="@color/purple"> + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index fad1d58..c75ea0a 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -13,4 +13,7 @@ 50% + \ No newline at end of file