diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml index e6f581c..0d5fb65 100644 --- a/.idea/navEditor.xml +++ b/.idea/navEditor.xml @@ -37,6 +37,40 @@ + + + + + + + @@ -135,8 +169,8 @@ @@ -147,20 +181,44 @@ - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - @@ -241,8 +275,8 @@ diff --git a/app/src/main/java/com/isolaatti/followers/presentation/FollowersViewModel.kt b/app/src/main/java/com/isolaatti/followers/presentation/FollowersViewModel.kt new file mode 100644 index 0000000..0da6380 --- /dev/null +++ b/app/src/main/java/com/isolaatti/followers/presentation/FollowersViewModel.kt @@ -0,0 +1,16 @@ +package com.isolaatti.followers.presentation + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.isolaatti.profile.data.remote.ProfileListItemDto +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class FollowersViewModel @Inject constructor() : ViewModel() { + + val followers: MutableLiveData> = MutableLiveData() + val followings: MutableLiveData> = MutableLiveData() + + +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/followers/presentation/FollowersViewPagerAdapter.kt b/app/src/main/java/com/isolaatti/followers/presentation/FollowersViewPagerAdapter.kt new file mode 100644 index 0000000..68b3978 --- /dev/null +++ b/app/src/main/java/com/isolaatti/followers/presentation/FollowersViewPagerAdapter.kt @@ -0,0 +1,18 @@ +package com.isolaatti.followers.presentation + +import androidx.fragment.app.Fragment +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.isolaatti.followers.ui.FollowersFragment +import com.isolaatti.followers.ui.FollowingFragment + +class FollowersViewPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { + override fun getItemCount(): Int = 2 + + override fun createFragment(position: Int): Fragment { + if(position == 0) { + return FollowersFragment() + } + + return FollowingFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/followers/ui/FollowersFragment.kt b/app/src/main/java/com/isolaatti/followers/ui/FollowersFragment.kt new file mode 100644 index 0000000..27a13a4 --- /dev/null +++ b/app/src/main/java/com/isolaatti/followers/ui/FollowersFragment.kt @@ -0,0 +1,24 @@ +package com.isolaatti.followers.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import com.isolaatti.databinding.FragmentFollowersBinding +import com.isolaatti.followers.presentation.FollowersViewModel + +class FollowersFragment : Fragment() { + private lateinit var binding: FragmentFollowersBinding + private val viewModel: FollowersViewModel by viewModels({ requireParentFragment() }) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentFollowersBinding.inflate(inflater) + return binding.root + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/followers/ui/FollowingFragment.kt b/app/src/main/java/com/isolaatti/followers/ui/FollowingFragment.kt new file mode 100644 index 0000000..3f22d08 --- /dev/null +++ b/app/src/main/java/com/isolaatti/followers/ui/FollowingFragment.kt @@ -0,0 +1,24 @@ +package com.isolaatti.followers.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import com.isolaatti.databinding.FragmentFollowersBinding +import com.isolaatti.followers.presentation.FollowersViewModel + +class FollowingFragment : Fragment() { + private lateinit var binding: FragmentFollowersBinding + private val viewModel: FollowersViewModel by viewModels({ requireParentFragment() }) + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentFollowersBinding.inflate(inflater) + return binding.root + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/followers/ui/MainFollowersFragment.kt b/app/src/main/java/com/isolaatti/followers/ui/MainFollowersFragment.kt new file mode 100644 index 0000000..78f3146 --- /dev/null +++ b/app/src/main/java/com/isolaatti/followers/ui/MainFollowersFragment.kt @@ -0,0 +1,43 @@ +package com.isolaatti.followers.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import com.google.android.material.tabs.TabLayoutMediator +import com.isolaatti.R +import com.isolaatti.databinding.FragmentFollowersMainBinding +import com.isolaatti.followers.presentation.FollowersViewModel +import com.isolaatti.followers.presentation.FollowersViewPagerAdapter +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MainFollowersFragment : Fragment() { + + private lateinit var binding: FragmentFollowersMainBinding + private val viewModel: FollowersViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentFollowersMainBinding.inflate(inflater) + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.viewPagerFollowersMain.adapter = FollowersViewPagerAdapter(this) + TabLayoutMediator(binding.tabLayoutFollowers, binding.viewPagerFollowersMain) { tab, position -> + when(position) { + 0 -> tab.text = getText(R.string.followers) + 1 -> tab.text = getText(R.string.followings) + } + }.attach() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/home/FeedFragment.kt b/app/src/main/java/com/isolaatti/home/FeedFragment.kt index c960bc1..ceeb6a1 100644 --- a/app/src/main/java/com/isolaatti/home/FeedFragment.kt +++ b/app/src/main/java/com/isolaatti/home/FeedFragment.kt @@ -3,7 +3,6 @@ package com.isolaatti.home import android.app.Activity import android.content.Intent import android.os.Bundle -import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View @@ -14,7 +13,6 @@ import android.widget.Toast 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 @@ -31,7 +29,6 @@ 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.presentation.UpdateEvent import com.isolaatti.posting.posts.ui.CreatePostActivity import com.isolaatti.profile.ui.ProfileActivity import com.isolaatti.settings.ui.SettingsActivity @@ -201,7 +198,7 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { override fun onUnLiked(postId: Long) = viewModel.unLikePost(postId) override fun onOptions(postId: Long) { - optionsViewModel.setOptions(Options.postOptions, CALLER_ID) + optionsViewModel.setOptions(Options.myPostOptions, CALLER_ID) val modalBottomSheet = BottomSheetPostOptionsFragment() modalBottomSheet.show(requireActivity().supportFragmentManager, BottomSheetPostOptionsFragment.TAG) } diff --git a/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt b/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt index 0e7ddab..56c9575 100644 --- a/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt +++ b/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.Observer @@ -12,9 +11,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.dialog.MaterialDialogs -import com.isolaatti.R import com.isolaatti.databinding.BottomSheetPostCommentsBinding import com.isolaatti.posting.common.domain.OnUserInteractedCallback import com.isolaatti.posting.common.options_bottom_sheet.domain.OptionClicked @@ -120,7 +116,7 @@ class BottomSheetPostComments() : BottomSheetDialogFragment(), OnUserInteractedC override fun onOptions(postId: Long) { - optionsViewModel.setOptions(Options.commentOptions, CALLER_ID) + optionsViewModel.setOptions(Options.myCommentOptions, CALLER_ID) val fragment = BottomSheetPostOptionsFragment() fragment.show(parentFragmentManager, BottomSheetPostOptionsFragment.TAG) } diff --git a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt index cc31233..93ede8b 100644 --- a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt +++ b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt @@ -21,15 +21,23 @@ data class Options( } companion object { + val myPostOptions = Options(R.string.post_options_title, listOf( + Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), + Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT), + Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) + )) + val postOptions = Options(R.string.post_options_title, listOf( + Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) + )) + + val myCommentOptions = Options(R.string.post_options_title, listOf( Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT), Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) )) val commentOptions = Options(R.string.post_options_title, listOf( - Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), - Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT), Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) )) } diff --git a/app/src/main/java/com/isolaatti/profile/ui/MainFollowersFragment.kt b/app/src/main/java/com/isolaatti/profile/ui/MainFollowersFragment.kt deleted file mode 100644 index 8c184bc..0000000 --- a/app/src/main/java/com/isolaatti/profile/ui/MainFollowersFragment.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.isolaatti.profile.ui - -import androidx.fragment.app.Fragment -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class MainFollowersFragment : Fragment() { -} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt index ed8e1ba..dba7cbb 100644 --- a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt +++ b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt @@ -5,12 +5,16 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.content.res.ResourcesCompat +import androidx.core.content.res.ResourcesCompat.ThemeCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.Observer import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.R.color.m3_icon_button_icon_color_selector +import com.google.android.material.button.MaterialButton import com.isolaatti.BuildConfig import com.isolaatti.R import com.isolaatti.databinding.FragmentDiscussionsBinding @@ -51,7 +55,6 @@ class ProfileMainFragment : Fragment() { private var scrollRange = -1 private var isShow = false - private val profileObserver = Observer { profile -> Picasso.get() .load(UrlGen.userProfileImage(profile.id)) @@ -60,6 +63,12 @@ class ProfileMainFragment : Fragment() { title = profile.name viewBinding.textViewUsername.text = profile.name viewBinding.textViewDescription.text = profile.descriptionText + + viewBinding.goToFollowersBtn.text = getString( + R.string.go_to_followers_btn_text, + profile.numberOfFollowers.toString(), + profile.numberOfFollowing.toString() + ) } private val postsObserver: Observer?> = Observer { @@ -74,18 +83,22 @@ class ProfileMainFragment : Fragment() { FollowingState.FollowingThisUser -> { viewBinding.textViewFollowingState.setText(R.string.following_user) viewBinding.followButton.setText(R.string.unfollow) + viewBinding.followButton.isChecked = true } FollowingState.MutuallyFollowing -> { viewBinding.textViewFollowingState.setText(R.string.mutually_following) viewBinding.followButton.setText(R.string.unfollow) + viewBinding.followButton.isChecked = true } FollowingState.ThisUserIsFollowingMe -> { viewBinding.textViewFollowingState.setText(R.string.following_you) viewBinding.followButton.setText(R.string.follow) + viewBinding.followButton.isChecked = false } FollowingState.NotMutuallyFollowing -> { viewBinding.textViewFollowingState.text = "" viewBinding.followButton.setText(R.string.follow) + viewBinding.followButton.isChecked = false } } } @@ -128,6 +141,10 @@ class ProfileMainFragment : Fragment() { } } + viewBinding.goToFollowersBtn.setOnClickListener { + findNavController().navigate(ProfileMainFragmentDirections.actionDiscussionsFragmentToMainFollowersFragment()) + } + viewBinding.feedRecyclerView.adapter = postsAdapter viewBinding.feedRecyclerView.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) @@ -191,7 +208,7 @@ class ProfileMainFragment : Fragment() { } override fun onOptions(postId: Long) { - optionsViewModel.setOptions(Options.postOptions, FeedFragment.CALLER_ID) + optionsViewModel.setOptions(Options.myPostOptions, FeedFragment.CALLER_ID) val modalBottomSheet = BottomSheetPostOptionsFragment() modalBottomSheet.show(requireActivity().supportFragmentManager, BottomSheetPostOptionsFragment.TAG) } diff --git a/app/src/main/res/layout/fragment_discussions.xml b/app/src/main/res/layout/fragment_discussions.xml index 3ca52ba..e64c54d 100644 --- a/app/src/main/res/layout/fragment_discussions.xml +++ b/app/src/main/res/layout/fragment_discussions.xml @@ -33,6 +33,18 @@ app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar" tools:srcCompat="@tools:sample/avatars" /> + + - + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + style="@style/Widget.Material3.Button.TextButton" + app:layout_constraintTop_toBottomOf="@id/text_view_description"/> + + + app:layout_constraintTop_toBottomOf="@id/go_to_followers_btn" /> diff --git a/app/src/main/res/layout/fragment_followers.xml b/app/src/main/res/layout/fragment_followers.xml new file mode 100644 index 0000000..77d9ef6 --- /dev/null +++ b/app/src/main/res/layout/fragment_followers.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_followers_main.xml b/app/src/main/res/layout/fragment_followers_main.xml new file mode 100644 index 0000000..be2d0b6 --- /dev/null +++ b/app/src/main/res/layout/fragment_followers_main.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_followings.xml b/app/src/main/res/layout/fragment_followings.xml new file mode 100644 index 0000000..77d9ef6 --- /dev/null +++ b/app/src/main/res/layout/fragment_followings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/profile_navigation.xml b/app/src/main/res/navigation/profile_navigation.xml index b97f639..e91005b 100644 --- a/app/src/main/res/navigation/profile_navigation.xml +++ b/app/src/main/res/navigation/profile_navigation.xml @@ -49,6 +49,6 @@ android:label="UserLinkFragment" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 54a5a9d..c3ef012 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,6 +51,7 @@ Report profile Block profile Sort + Followers Following Following @@ -59,4 +60,7 @@ User link Follow Unfollow + Followers: %s Following: %s + K + M \ No newline at end of file