2023-02-11 23:41:23 -06:00
|
|
|
package com.isolaatti.profile.ui
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
import android.content.Context
|
2024-04-21 14:17:41 -06:00
|
|
|
import android.content.Intent
|
2023-02-11 23:41:23 -06:00
|
|
|
import android.os.Bundle
|
2023-09-12 22:31:52 -06:00
|
|
|
import android.util.Log
|
2023-02-11 23:41:23 -06:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
|
import android.view.View
|
|
|
|
|
import android.view.ViewGroup
|
2023-08-27 23:03:40 -06:00
|
|
|
import android.widget.Toast
|
2023-12-20 23:06:01 -06:00
|
|
|
import androidx.appcompat.content.res.AppCompatResources
|
2023-02-11 23:41:23 -06:00
|
|
|
import androidx.fragment.app.Fragment
|
2023-08-06 22:11:28 -06:00
|
|
|
import androidx.fragment.app.activityViewModels
|
2023-07-31 00:25:25 -06:00
|
|
|
import androidx.fragment.app.viewModels
|
2023-09-10 13:17:50 -06:00
|
|
|
import androidx.lifecycle.Lifecycle
|
2023-07-31 00:25:25 -06:00
|
|
|
import androidx.lifecycle.Observer
|
2023-09-10 13:17:50 -06:00
|
|
|
import androidx.lifecycle.lifecycleScope
|
|
|
|
|
import androidx.lifecycle.repeatOnLifecycle
|
2023-07-31 00:25:25 -06:00
|
|
|
import androidx.navigation.fragment.findNavController
|
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager
|
2023-11-19 19:24:45 -06:00
|
|
|
import coil.load
|
2024-01-07 23:51:18 -06:00
|
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
2023-07-31 00:25:25 -06:00
|
|
|
import com.isolaatti.BuildConfig
|
|
|
|
|
import com.isolaatti.R
|
2023-11-25 22:10:35 -06:00
|
|
|
import com.isolaatti.audio.audios_list.ui.AudiosFragment
|
2023-12-11 23:10:57 -06:00
|
|
|
import com.isolaatti.audio.common.domain.Audio
|
2024-01-31 01:06:45 -06:00
|
|
|
import com.isolaatti.audio.common.domain.Playable
|
2023-12-11 23:10:57 -06:00
|
|
|
import com.isolaatti.audio.player.AudioPlayerConnector
|
2023-11-19 19:24:45 -06:00
|
|
|
import com.isolaatti.common.CoilImageLoader.imageLoader
|
2023-08-27 23:03:40 -06:00
|
|
|
import com.isolaatti.common.Dialogs
|
2023-09-09 16:09:22 -06:00
|
|
|
import com.isolaatti.common.ErrorMessageViewModel
|
2023-09-12 22:31:52 -06:00
|
|
|
import com.isolaatti.common.Ownable
|
|
|
|
|
import com.isolaatti.common.options_bottom_sheet.domain.OptionClicked
|
|
|
|
|
import com.isolaatti.common.options_bottom_sheet.domain.Options
|
|
|
|
|
import com.isolaatti.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel
|
|
|
|
|
import com.isolaatti.common.options_bottom_sheet.ui.BottomSheetPostOptionsFragment
|
2023-11-25 22:10:35 -06:00
|
|
|
import com.isolaatti.databinding.FragmentDiscussionsBinding
|
|
|
|
|
import com.isolaatti.followers.domain.FollowingState
|
2024-01-06 00:32:20 -06:00
|
|
|
import com.isolaatti.images.image_chooser.ui.ImageChooserContract
|
2023-11-20 22:53:14 -06:00
|
|
|
import com.isolaatti.images.image_list.ui.ImagesFragment
|
2023-11-25 22:10:35 -06:00
|
|
|
import com.isolaatti.posting.comments.ui.BottomSheetPostComments
|
2023-08-27 20:00:43 -06:00
|
|
|
import com.isolaatti.posting.posts.domain.entity.Post
|
2023-08-27 23:03:40 -06:00
|
|
|
import com.isolaatti.posting.posts.presentation.CreatePostContract
|
|
|
|
|
import com.isolaatti.posting.posts.presentation.EditPostContract
|
2023-08-06 22:11:28 -06:00
|
|
|
import com.isolaatti.posting.posts.presentation.PostListingRecyclerViewAdapterWiring
|
2023-07-31 00:25:25 -06:00
|
|
|
import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter
|
2023-08-06 22:11:28 -06:00
|
|
|
import com.isolaatti.posting.posts.presentation.UpdateEvent
|
2024-04-21 14:17:41 -06:00
|
|
|
import com.isolaatti.posting.posts.ui.PostInfoActivity
|
2023-11-25 22:10:35 -06:00
|
|
|
import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
|
2023-09-12 22:31:52 -06:00
|
|
|
import com.isolaatti.profile.domain.entity.UserProfile
|
2024-01-07 23:51:18 -06:00
|
|
|
import com.isolaatti.profile.presentation.EditProfileContract
|
2023-07-31 00:25:25 -06:00
|
|
|
import com.isolaatti.profile.presentation.ProfileViewModel
|
2024-04-20 11:45:12 -06:00
|
|
|
import com.isolaatti.reports.data.ContentType
|
2024-04-14 02:20:35 -06:00
|
|
|
import com.isolaatti.reports.ui.NewReportBottomSheetDialogFragment
|
2023-07-31 00:25:25 -06:00
|
|
|
import com.isolaatti.utils.UrlGen
|
|
|
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
|
|
|
import io.noties.markwon.AbstractMarkwonPlugin
|
|
|
|
|
import io.noties.markwon.Markwon
|
|
|
|
|
import io.noties.markwon.MarkwonConfiguration
|
2023-11-19 19:24:45 -06:00
|
|
|
import io.noties.markwon.image.coil.CoilImagesPlugin
|
2023-07-31 00:25:25 -06:00
|
|
|
import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute
|
|
|
|
|
import io.noties.markwon.linkify.LinkifyPlugin
|
2023-09-10 13:17:50 -06:00
|
|
|
import kotlinx.coroutines.launch
|
2023-02-11 23:41:23 -06:00
|
|
|
|
2023-07-31 00:25:25 -06:00
|
|
|
@AndroidEntryPoint
|
2023-08-06 23:22:53 -06:00
|
|
|
class ProfileMainFragment : Fragment() {
|
2023-02-11 23:41:23 -06:00
|
|
|
lateinit var viewBinding: FragmentDiscussionsBinding
|
2023-07-31 00:25:25 -06:00
|
|
|
private val viewModel: ProfileViewModel by viewModels()
|
2023-08-06 22:11:28 -06:00
|
|
|
val optionsViewModel: BottomSheetPostOptionsViewModel by activityViewModels()
|
2023-09-09 16:09:22 -06:00
|
|
|
val errorViewModel: ErrorMessageViewModel by activityViewModels()
|
2023-07-31 00:25:25 -06:00
|
|
|
private var userId: Int? = null
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
lateinit var postsAdapter: PostsRecyclerViewAdapter
|
|
|
|
|
|
2023-12-11 23:10:57 -06:00
|
|
|
private var audioDescriptionAudio: Audio? = null
|
|
|
|
|
|
|
|
|
|
private lateinit var audioPlayerConnector: AudioPlayerConnector
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
// collapsing bar
|
2023-07-31 00:25:25 -06:00
|
|
|
private var title = ""
|
2023-08-06 22:11:28 -06:00
|
|
|
private var scrollRange = -1
|
|
|
|
|
private var isShow = false
|
|
|
|
|
|
2023-08-27 23:03:40 -06:00
|
|
|
private val createDiscussion = registerForActivityResult(CreatePostContract()) {
|
2023-12-26 22:02:35 -06:00
|
|
|
if(it == null)
|
|
|
|
|
return@registerForActivityResult
|
|
|
|
|
|
|
|
|
|
Toast.makeText(requireContext(), R.string.posted_successfully, Toast.LENGTH_SHORT).show()
|
2023-11-25 22:39:16 -06:00
|
|
|
|
2023-12-26 22:02:35 -06:00
|
|
|
viewModel.onPostAddedAtTheBeginning(it)
|
2023-08-27 23:03:40 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-07 01:17:16 -06:00
|
|
|
private val chooseImageLauncher = registerForActivityResult(ImageChooserContract()) { image ->
|
2024-01-06 00:32:20 -06:00
|
|
|
// here change profile picture
|
2024-01-07 01:17:16 -06:00
|
|
|
if(image != null) {
|
|
|
|
|
viewModel.setProfileImage(image)
|
|
|
|
|
}
|
2024-01-06 00:32:20 -06:00
|
|
|
}
|
|
|
|
|
|
2023-08-27 23:03:40 -06:00
|
|
|
private val editDiscussion = registerForActivityResult(EditPostContract()) {
|
|
|
|
|
if(it != null) {
|
|
|
|
|
viewModel.onPostUpdate(it)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-13 20:35:14 -06:00
|
|
|
private val editProfile = registerForActivityResult(EditProfileContract()) { updatedProfile ->
|
|
|
|
|
if(updatedProfile != null) {
|
|
|
|
|
viewModel.setProfile(updatedProfile)
|
|
|
|
|
}
|
2024-01-07 23:51:18 -06:00
|
|
|
}
|
|
|
|
|
|
2024-03-03 20:25:49 -06:00
|
|
|
|
2023-12-20 23:06:01 -06:00
|
|
|
private val audioPlayerConnectorListener = object: AudioPlayerConnector.Listener {
|
2024-01-31 01:06:45 -06:00
|
|
|
override fun onPlaying(isPlaying: Boolean, audio: Playable) {
|
2024-03-03 20:25:49 -06:00
|
|
|
Log.d(LOG_TAG, "onPlaying() isPlaying: $isPlaying: audio $audio")
|
|
|
|
|
if(audio == audioDescriptionAudio) {
|
|
|
|
|
viewBinding.playButton.icon =
|
|
|
|
|
AppCompatResources.getDrawable(
|
|
|
|
|
requireContext(),
|
|
|
|
|
if(isPlaying) R.drawable.baseline_pause_circle_24 else R.drawable.baseline_play_circle_24
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
if(audio is Audio)
|
|
|
|
|
postsAdapter.setIsPlaying(isPlaying, audio)
|
2023-12-20 23:06:01 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 01:06:45 -06:00
|
|
|
override fun isLoading(isLoading: Boolean, audio: Playable) {
|
2024-03-03 20:25:49 -06:00
|
|
|
if(audio == audioDescriptionAudio) {
|
|
|
|
|
viewBinding.playButton.isEnabled = !isLoading
|
|
|
|
|
viewBinding.audioProgress.isIndeterminate = isLoading
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(audio is Audio)
|
|
|
|
|
postsAdapter.setIsLoading(isLoading, audio)
|
|
|
|
|
|
2023-12-20 23:06:01 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 01:06:45 -06:00
|
|
|
override fun progressChanged(second: Int, audio: Playable) {
|
2024-03-03 20:25:49 -06:00
|
|
|
if(audio == audioDescriptionAudio) {
|
|
|
|
|
viewBinding.audioProgress.setProgress(second, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(audio is Audio)
|
|
|
|
|
postsAdapter.setProgress(second, audio)
|
2023-12-20 23:06:01 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 01:06:45 -06:00
|
|
|
override fun durationChanged(duration: Int, audio: Playable) {
|
2024-03-03 20:25:49 -06:00
|
|
|
if(audio == audioDescriptionAudio) {
|
|
|
|
|
viewBinding.audioProgress.max = duration
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(audio is Audio)
|
|
|
|
|
postsAdapter.setDuration(duration, audio)
|
2023-12-20 23:06:01 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 01:06:45 -06:00
|
|
|
override fun onEnded(audio: Playable) {
|
2024-03-03 20:25:49 -06:00
|
|
|
if(audio == audioDescriptionAudio) {
|
|
|
|
|
viewBinding.audioProgress.progress = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(audio is Audio)
|
|
|
|
|
postsAdapter.setEnded(audio)
|
2024-01-31 01:06:45 -06:00
|
|
|
}
|
|
|
|
|
|
2023-12-20 23:06:01 -06:00
|
|
|
}
|
|
|
|
|
|
2023-09-12 22:31:52 -06:00
|
|
|
private val profileObserver = Observer<UserProfile> { profile ->
|
2024-01-07 01:17:16 -06:00
|
|
|
viewBinding.profileImageView.load(UrlGen.userProfileImage(profile.userId, invalidateCache = true), imageLoader)
|
2023-07-31 00:25:25 -06:00
|
|
|
|
|
|
|
|
title = profile.name
|
|
|
|
|
viewBinding.textViewUsername.text = profile.name
|
|
|
|
|
viewBinding.textViewDescription.text = profile.descriptionText
|
2023-08-27 23:21:01 -06:00
|
|
|
if(profile.descriptionText.isNullOrBlank()) {
|
|
|
|
|
viewBinding.descriptionCard.visibility = View.GONE
|
|
|
|
|
}
|
2023-08-12 00:59:02 -06:00
|
|
|
|
|
|
|
|
viewBinding.goToFollowersBtn.text = getString(
|
|
|
|
|
R.string.go_to_followers_btn_text,
|
|
|
|
|
profile.numberOfFollowers.toString(),
|
|
|
|
|
profile.numberOfFollowing.toString()
|
|
|
|
|
)
|
2023-08-27 23:21:01 -06:00
|
|
|
|
|
|
|
|
|
2023-09-12 22:31:52 -06:00
|
|
|
viewBinding.profileImageView.setOnClickListener {
|
|
|
|
|
optionsViewModel.setOptions(Options.PROFILE_PHOTO_OPTIONS, CALLER_ID, profile)
|
|
|
|
|
val fragment = BottomSheetPostOptionsFragment()
|
|
|
|
|
fragment.show(parentFragmentManager, BottomSheetPostOptionsFragment.TAG)
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 23:10:57 -06:00
|
|
|
audioDescriptionAudio = profile.descriptionAudio
|
2023-12-20 23:06:01 -06:00
|
|
|
viewBinding.playButtonContainer.visibility = if(profile.descriptionAudio != null) View.VISIBLE else View.GONE
|
2023-12-11 23:10:57 -06:00
|
|
|
|
2023-08-27 23:21:01 -06:00
|
|
|
setupUiForUserType(profile.isUserItself)
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
|
|
|
|
|
2023-08-27 20:00:43 -06:00
|
|
|
private val postsObserver: Observer<Pair<List<Post>?, UpdateEvent>?> = Observer {
|
2023-08-06 23:22:53 -06:00
|
|
|
if(it?.first != null) {
|
2023-08-06 22:11:28 -06:00
|
|
|
postsAdapter.updateList(it.first!!, it.second)
|
2023-08-15 00:02:29 -06:00
|
|
|
postsAdapter.newContentRequestFinished()
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-10 23:32:47 -06:00
|
|
|
private val followingStateObserver: Observer<FollowingState> = Observer {
|
|
|
|
|
when(it) {
|
|
|
|
|
FollowingState.FollowingThisUser -> {
|
|
|
|
|
viewBinding.textViewFollowingState.setText(R.string.following_user)
|
|
|
|
|
viewBinding.followButton.setText(R.string.unfollow)
|
2023-08-12 00:59:02 -06:00
|
|
|
viewBinding.followButton.isChecked = true
|
2023-08-10 23:32:47 -06:00
|
|
|
}
|
|
|
|
|
FollowingState.MutuallyFollowing -> {
|
|
|
|
|
viewBinding.textViewFollowingState.setText(R.string.mutually_following)
|
|
|
|
|
viewBinding.followButton.setText(R.string.unfollow)
|
2023-08-12 00:59:02 -06:00
|
|
|
viewBinding.followButton.isChecked = true
|
2023-08-10 23:32:47 -06:00
|
|
|
}
|
|
|
|
|
FollowingState.ThisUserIsFollowingMe -> {
|
|
|
|
|
viewBinding.textViewFollowingState.setText(R.string.following_you)
|
|
|
|
|
viewBinding.followButton.setText(R.string.follow)
|
2023-08-12 00:59:02 -06:00
|
|
|
viewBinding.followButton.isChecked = false
|
2023-08-10 23:32:47 -06:00
|
|
|
}
|
|
|
|
|
FollowingState.NotMutuallyFollowing -> {
|
|
|
|
|
viewBinding.textViewFollowingState.text = ""
|
|
|
|
|
viewBinding.followButton.setText(R.string.follow)
|
2023-08-12 00:59:02 -06:00
|
|
|
viewBinding.followButton.isChecked = false
|
2023-08-10 23:32:47 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-27 23:03:40 -06:00
|
|
|
private val optionsObserver: Observer<OptionClicked?> = Observer { optionClicked ->
|
2023-09-12 22:31:52 -06:00
|
|
|
if(optionClicked?.callerId == CALLER_ID) {
|
|
|
|
|
Log.d("ProfileMainFragment", optionClicked.toString())
|
|
|
|
|
|
|
|
|
|
when(optionClicked.optionsId) {
|
|
|
|
|
Options.PROFILE_PHOTO_OPTIONS -> {
|
|
|
|
|
val profile = optionClicked.payload as? UserProfile
|
|
|
|
|
when(optionClicked.optionId) {
|
2024-01-06 00:32:20 -06:00
|
|
|
Options.Option.OPTION_PROFILE_PHOTO_CHANGE_PHOTO -> {
|
|
|
|
|
chooseImageLauncher.launch(ImageChooserContract.Requester.UserPost)
|
|
|
|
|
}
|
2024-01-07 23:51:18 -06:00
|
|
|
Options.Option.OPTION_PROFILE_PHOTO_REMOVE_PHOTO -> {
|
|
|
|
|
showRemoveProfileImageDialog()
|
|
|
|
|
}
|
2023-09-12 22:31:52 -06:00
|
|
|
Options.Option.OPTION_PROFILE_PHOTO_VIEW_PHOTO -> {
|
|
|
|
|
val profilePictureUrl = profile?.profilePictureUrl
|
|
|
|
|
if(profilePictureUrl != null) {
|
2024-01-07 23:51:18 -06:00
|
|
|
// TODO show image
|
2023-09-12 22:31:52 -06:00
|
|
|
}
|
2023-08-27 23:03:40 -06:00
|
|
|
}
|
2023-09-12 22:31:52 -06:00
|
|
|
}
|
2023-08-27 23:03:40 -06:00
|
|
|
optionsViewModel.handle()
|
|
|
|
|
}
|
2023-09-12 22:31:52 -06:00
|
|
|
Options.POST_OPTIONS -> {
|
|
|
|
|
// post id should come as payload
|
|
|
|
|
val post = optionClicked.payload as? Post ?: return@Observer
|
|
|
|
|
when(optionClicked.optionId) {
|
|
|
|
|
Options.Option.OPTION_DELETE -> {
|
|
|
|
|
Dialogs.buildDeletePostDialog(requireContext()) { delete ->
|
|
|
|
|
optionsViewModel.handle()
|
|
|
|
|
if(delete) {
|
|
|
|
|
viewModel.deletePost(post.id)
|
|
|
|
|
}
|
|
|
|
|
}.show()
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
Options.Option.OPTION_EDIT -> {
|
|
|
|
|
optionsViewModel.handle()
|
|
|
|
|
editDiscussion.launch(post.id)
|
|
|
|
|
}
|
|
|
|
|
Options.Option.OPTION_REPORT -> {
|
|
|
|
|
optionsViewModel.handle()
|
2024-04-20 11:45:12 -06:00
|
|
|
NewReportBottomSheetDialogFragment.newInstance(ContentType.Post, post.id.toString()).show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
2023-09-12 22:31:52 -06:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-27 23:03:40 -06:00
|
|
|
}
|
|
|
|
|
}
|
2023-09-12 22:31:52 -06:00
|
|
|
|
|
|
|
|
|
2023-08-27 23:03:40 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-07 23:51:18 -06:00
|
|
|
private fun showRemoveProfileImageDialog() {
|
|
|
|
|
MaterialAlertDialogBuilder(requireContext())
|
|
|
|
|
.setMessage(R.string.remove_image_message_confirmation)
|
|
|
|
|
.setTitle(R.string.remove_photo)
|
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
|
|
|
|
.setPositiveButton(R.string.yes_continue) { _, _ ->
|
|
|
|
|
// remove image here
|
|
|
|
|
}
|
|
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
private lateinit var postListingRecyclerViewAdapterWiring: PostListingRecyclerViewAdapterWiring
|
2023-02-11 23:41:23 -06:00
|
|
|
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
private fun setupCollapsingBar() {
|
|
|
|
|
|
2023-07-31 00:25:25 -06:00
|
|
|
viewBinding.topAppBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
|
|
|
|
|
if (scrollRange == -1) scrollRange = appBarLayout.totalScrollRange
|
|
|
|
|
if (scrollRange + verticalOffset == 0) {
|
2023-09-12 22:31:52 -06:00
|
|
|
viewBinding.collapsingToolbarLayout.title = viewModel.profile.value?.name
|
2023-07-31 00:25:25 -06:00
|
|
|
isShow = true
|
|
|
|
|
} else if (isShow) {
|
|
|
|
|
viewBinding.collapsingToolbarLayout.title = " "
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun bind() {
|
|
|
|
|
|
2023-08-15 00:02:29 -06:00
|
|
|
if(userId == null) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-31 00:25:25 -06:00
|
|
|
|
|
|
|
|
viewBinding.topAppBar.setNavigationOnClickListener {
|
2023-08-19 17:31:50 -06:00
|
|
|
requireActivity().finish()
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-07 23:51:18 -06:00
|
|
|
viewBinding.topAppBar.setOnMenuItemClickListener {
|
|
|
|
|
when(it.itemId) {
|
|
|
|
|
R.id.edit_profile -> {
|
2024-01-13 20:35:14 -06:00
|
|
|
viewModel.profile.value?.let { profile -> editProfile.launch(profile) }
|
|
|
|
|
|
2024-01-07 23:51:18 -06:00
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
R.id.user_link_menu_item -> {
|
2024-01-13 23:12:31 -06:00
|
|
|
viewModel.profile.value?.let { profile ->
|
|
|
|
|
findNavController().navigate(ProfileMainFragmentDirections.actionMainFragmentToQrCodeFragment(profile))
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-07 23:51:18 -06:00
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
R.id.report_profile_menu_item -> {
|
2024-04-20 11:45:12 -06:00
|
|
|
NewReportBottomSheetDialogFragment.newInstance(ContentType.Profile, viewModel.profileId.toString()).show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
2024-01-07 23:51:18 -06:00
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
R.id.block_profile_menu_item -> {
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
else -> false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 00:32:20 -06:00
|
|
|
viewBinding.audiosButton.setOnClickListener {
|
|
|
|
|
findNavController().navigate(ProfileMainFragmentDirections.actionDiscussionsFragmentToAudiosFragment(AudiosFragment.SOURCE_PROFILE, userId.toString()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
viewBinding.imagesButton.setOnClickListener {
|
|
|
|
|
findNavController().navigate(
|
|
|
|
|
ProfileMainFragmentDirections.actionDiscussionsFragmentToImagesFragment(ImagesFragment.SOURCE_PROFILE, userId.toString())
|
|
|
|
|
)
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-06 00:32:20 -06:00
|
|
|
viewBinding.createPostButton.setOnClickListener {
|
2023-11-25 23:18:37 -06:00
|
|
|
createDiscussion.launch(Unit)
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-12 00:59:02 -06:00
|
|
|
viewBinding.goToFollowersBtn.setOnClickListener {
|
2023-08-15 00:02:29 -06:00
|
|
|
findNavController().navigate(ProfileMainFragmentDirections.actionDiscussionsFragmentToMainFollowersFragment(userId!!))
|
2023-08-12 00:59:02 -06:00
|
|
|
}
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
viewBinding.feedRecyclerView.adapter = postsAdapter
|
|
|
|
|
viewBinding.feedRecyclerView.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
2023-08-06 23:22:53 -06:00
|
|
|
|
|
|
|
|
viewBinding.swipeToRefresh.setOnRefreshListener {
|
2024-04-06 19:55:25 -06:00
|
|
|
viewModel.getFeed(true, null)
|
2023-08-06 23:22:53 -06:00
|
|
|
}
|
2023-12-11 23:10:57 -06:00
|
|
|
viewBinding.playButton.setOnClickListener {
|
|
|
|
|
audioDescriptionAudio?.let { audio ->
|
2023-12-20 23:06:01 -06:00
|
|
|
audioPlayerConnector.playPauseAudio(audio)
|
2023-12-11 23:10:57 -06:00
|
|
|
}
|
|
|
|
|
}
|
2024-01-07 23:01:26 -06:00
|
|
|
|
|
|
|
|
viewBinding.followButton.setOnClickListener {
|
|
|
|
|
it.isEnabled = false
|
|
|
|
|
viewModel.followUser()
|
|
|
|
|
}
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun setObservers() {
|
2023-07-31 00:25:25 -06:00
|
|
|
viewModel.profile.observe(viewLifecycleOwner, profileObserver)
|
|
|
|
|
viewModel.posts.observe(viewLifecycleOwner, postsObserver)
|
2023-08-10 23:32:47 -06:00
|
|
|
viewModel.followingState.observe(viewLifecycleOwner, followingStateObserver)
|
2023-08-27 23:03:40 -06:00
|
|
|
optionsViewModel.optionClicked.observe(viewLifecycleOwner, optionsObserver)
|
2023-08-06 23:22:53 -06:00
|
|
|
viewModel.loadingPosts.observe(viewLifecycleOwner) {
|
2023-08-15 00:02:29 -06:00
|
|
|
viewBinding.loadingIndicator.visibility = if(it) View.VISIBLE else View.GONE
|
2023-08-15 23:11:15 -06:00
|
|
|
if(!it) {
|
|
|
|
|
viewBinding.swipeToRefresh.isRefreshing = false
|
|
|
|
|
}
|
2023-08-06 23:22:53 -06:00
|
|
|
}
|
2023-09-09 16:09:22 -06:00
|
|
|
viewModel.errorLoading.observe(viewLifecycleOwner) {
|
|
|
|
|
errorViewModel.error.postValue(it)
|
|
|
|
|
}
|
2024-01-07 23:01:26 -06:00
|
|
|
viewModel.followingLoading.observe(viewLifecycleOwner) {
|
|
|
|
|
viewBinding.followButton.isEnabled = !it
|
|
|
|
|
}
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun getData() {
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
userId?.let { profileId ->
|
|
|
|
|
viewModel.profileId = profileId
|
|
|
|
|
viewModel.getProfile()
|
2024-04-06 19:55:25 -06:00
|
|
|
viewModel.getFeed(true, null)
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
private fun setupPostsAdapter() {
|
2023-07-31 00:25:25 -06:00
|
|
|
val markwon = Markwon.builder(requireContext())
|
|
|
|
|
.usePlugin(object: AbstractMarkwonPlugin() {
|
|
|
|
|
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
|
|
|
|
builder
|
|
|
|
|
.imageDestinationProcessor(
|
|
|
|
|
ImageDestinationProcessorRelativeToAbsolute
|
2023-08-06 22:11:28 -06:00
|
|
|
.create(BuildConfig.backend))
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
|
|
|
|
})
|
2023-11-19 19:24:45 -06:00
|
|
|
.usePlugin(CoilImagesPlugin.create(requireContext(), imageLoader))
|
2023-07-31 00:25:25 -06:00
|
|
|
.usePlugin(LinkifyPlugin.create())
|
|
|
|
|
.build()
|
|
|
|
|
|
2023-08-27 20:00:43 -06:00
|
|
|
postsAdapter = PostsRecyclerViewAdapter(markwon,postListingRecyclerViewAdapterWiring )
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-27 23:21:01 -06:00
|
|
|
private fun setupUiForUserType(isOwnProfile: Boolean) {
|
|
|
|
|
if(isOwnProfile) {
|
|
|
|
|
viewBinding.followButton.visibility = View.GONE
|
2024-01-07 23:51:18 -06:00
|
|
|
viewBinding.topAppBar.menu?.run {
|
|
|
|
|
removeItem(R.id.block_profile_menu_item)
|
|
|
|
|
removeItem(R.id.report_profile_menu_item)
|
|
|
|
|
}
|
2023-08-27 23:21:01 -06:00
|
|
|
} else {
|
2024-01-06 00:32:20 -06:00
|
|
|
viewBinding.createPostButton.visibility = View.GONE
|
2024-01-07 23:51:18 -06:00
|
|
|
viewBinding.topAppBar.menu.removeItem(R.id.edit_profile)
|
2023-08-27 23:21:01 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
|
super.onCreate(savedInstanceState)
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
userId = (requireActivity()).intent.extras?.getInt(ProfileActivity.EXTRA_USER_ID)
|
2023-11-25 22:39:16 -06:00
|
|
|
getData()
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
override fun onAttach(context: Context) {
|
|
|
|
|
super.onAttach(context)
|
2023-12-11 23:10:57 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
postListingRecyclerViewAdapterWiring = object: PostListingRecyclerViewAdapterWiring(viewModel) {
|
|
|
|
|
override fun onComment(postId: Long) {
|
|
|
|
|
val modalBottomSheet = BottomSheetPostComments.getInstance(postId)
|
|
|
|
|
modalBottomSheet.show(requireActivity().supportFragmentManager, BottomSheetPostComments.TAG)
|
|
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
override fun onOpenPost(postId: Long) {
|
|
|
|
|
PostViewerActivity.startActivity(requireContext(), postId)
|
|
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-27 20:00:43 -06:00
|
|
|
override fun onOptions(post: Ownable) {
|
2023-09-12 22:31:52 -06:00
|
|
|
optionsViewModel.setOptions(Options.POST_OPTIONS, CALLER_ID, post)
|
2023-08-06 22:11:28 -06:00
|
|
|
val modalBottomSheet = BottomSheetPostOptionsFragment()
|
|
|
|
|
modalBottomSheet.show(requireActivity().supportFragmentManager, BottomSheetPostOptionsFragment.TAG)
|
|
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
override fun onProfileClick(userId: Int) {
|
|
|
|
|
//ProfileActivity.startActivity(requireContext(), userId)
|
|
|
|
|
}
|
2023-08-15 00:02:29 -06:00
|
|
|
|
2024-03-03 20:25:49 -06:00
|
|
|
override fun onPlay(audio: Audio) {
|
|
|
|
|
audioPlayerConnector.playPauseAudio(audio)
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-15 00:02:29 -06:00
|
|
|
override fun onLoadMore() {
|
2024-04-06 19:55:25 -06:00
|
|
|
viewModel.getFeed(false, null)
|
2023-08-15 00:02:29 -06:00
|
|
|
}
|
2024-04-21 14:17:41 -06:00
|
|
|
|
|
|
|
|
override fun onMoreInfo(postId: Long) {
|
|
|
|
|
PostInfoActivity.startActivity(requireContext(), postId)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onShare(postId: Long) {
|
|
|
|
|
val intent = Intent.createChooser(Intent().apply {
|
|
|
|
|
action = Intent.ACTION_SEND
|
|
|
|
|
putExtra(Intent.EXTRA_TEXT, "${BuildConfig.backend}/pub/${postId}")
|
|
|
|
|
type = "text/plain"
|
|
|
|
|
}, getString(R.string.share_post))
|
|
|
|
|
startActivity(intent)
|
|
|
|
|
}
|
2023-08-06 22:11:28 -06:00
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
override fun onCreateView(
|
|
|
|
|
inflater: LayoutInflater,
|
|
|
|
|
container: ViewGroup?,
|
|
|
|
|
savedInstanceState: Bundle?
|
|
|
|
|
): View {
|
|
|
|
|
viewBinding = FragmentDiscussionsBinding.inflate(inflater)
|
|
|
|
|
|
|
|
|
|
return viewBinding.root
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
|
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
2023-09-12 22:31:52 -06:00
|
|
|
|
2023-08-06 22:11:28 -06:00
|
|
|
setupPostsAdapter()
|
|
|
|
|
bind()
|
|
|
|
|
setObservers()
|
2023-09-12 22:31:52 -06:00
|
|
|
setupCollapsingBar()
|
2023-09-10 13:17:50 -06:00
|
|
|
|
2023-12-11 23:10:57 -06:00
|
|
|
audioPlayerConnector = AudioPlayerConnector(requireContext())
|
|
|
|
|
|
2023-12-20 23:06:01 -06:00
|
|
|
audioPlayerConnector.addListener(audioPlayerConnectorListener)
|
|
|
|
|
|
2023-12-11 23:10:57 -06:00
|
|
|
viewLifecycleOwner.lifecycle.addObserver(audioPlayerConnector)
|
2023-09-10 13:17:50 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
viewLifecycleOwner.lifecycleScope.launch {
|
|
|
|
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
|
|
|
errorViewModel.retry.collect {
|
|
|
|
|
viewModel.retry()
|
|
|
|
|
errorViewModel.handleRetry()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-31 00:25:25 -06:00
|
|
|
}
|
2023-09-12 22:31:52 -06:00
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
const val CALLER_ID = 30
|
2024-03-03 20:25:49 -06:00
|
|
|
const val LOG_TAG = "ProfileMainFragment"
|
2023-09-12 22:31:52 -06:00
|
|
|
}
|
2023-02-11 23:41:23 -06:00
|
|
|
}
|