WIP
This commit is contained in:
parent
a763926c18
commit
0a8946167f
@ -1,4 +1,4 @@
|
||||
package com.isolaatti.posting.common.domain
|
||||
package com.isolaatti.common
|
||||
|
||||
interface OnUserInteractedCallback {
|
||||
fun onOptions(postId: Ownable)
|
||||
@ -1,4 +1,4 @@
|
||||
package com.isolaatti.posting.common.domain
|
||||
package com.isolaatti.common
|
||||
|
||||
interface OnUserInteractedWithPostCallback : OnUserInteractedCallback {
|
||||
fun onLiked(postId: Long)
|
||||
5
app/src/main/java/com/isolaatti/common/Ownable.kt
Normal file
5
app/src/main/java/com/isolaatti/common/Ownable.kt
Normal file
@ -0,0 +1,5 @@
|
||||
package com.isolaatti.common
|
||||
|
||||
interface Ownable {
|
||||
val userId: Int
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.isolaatti.common.options_bottom_sheet.domain
|
||||
|
||||
/**
|
||||
* @param optionsId Identify what dialog it is
|
||||
* @param optionId Identify action
|
||||
* @param callerId Identify who started dialog
|
||||
* @param payload Data to identify on what item perform action
|
||||
*/
|
||||
data class OptionClicked(val optionsId: Int, val optionId: Int, val callerId: Int, val payload: Any? = null)
|
||||
@ -1,4 +1,4 @@
|
||||
package com.isolaatti.posting.common.options_bottom_sheet.domain
|
||||
package com.isolaatti.common.options_bottom_sheet.domain
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
@ -6,6 +6,7 @@ import com.isolaatti.R
|
||||
|
||||
data class Options(
|
||||
@StringRes val title: Int,
|
||||
val id: Int,
|
||||
val items: List<Option>
|
||||
) {
|
||||
data class Option(
|
||||
@ -19,14 +20,18 @@ data class Options(
|
||||
const val OPTION_REPORT = 3
|
||||
const val OPTION_SAVE = 4
|
||||
const val OPTION_SNAPSHOT = 5
|
||||
const val OPTION_PROFILE_PHOTO_VIEW_PHOTO = 6
|
||||
const val OPTION_PROFILE_PHOTO_CHANGE_PHOTO = 7
|
||||
const val OPTION_PROFILE_PHOTO_REMOVE_PHOTO = 8
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val POST_OPTIONS = 1
|
||||
const val COMMENT_OPTIONS = 2
|
||||
const val PROFILE_PHOTO_OPTIONS = 3
|
||||
|
||||
val noOptions = Options(0, listOf())
|
||||
val noOptions = Options(0, 0, listOf())
|
||||
|
||||
fun getPostsOptions(userOwned: Boolean, savable: Boolean, snapshotAble: Boolean): Options {
|
||||
val list = mutableListOf(
|
||||
@ -36,7 +41,8 @@ data class Options(
|
||||
if(userOwned) {
|
||||
list.addAll(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.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -48,7 +54,7 @@ data class Options(
|
||||
list.add(Option(R.string.save_snapshot, R.drawable.baseline_download_24, Option.OPTION_SNAPSHOT))
|
||||
}
|
||||
|
||||
return Options(R.string.post_options_title, list)
|
||||
return Options(R.string.post_options_title, POST_OPTIONS, list)
|
||||
}
|
||||
|
||||
fun getCommentOptions(userOwned: Boolean, savable: Boolean, snapshotAble: Boolean): Options {
|
||||
@ -59,7 +65,8 @@ data class Options(
|
||||
if(userOwned) {
|
||||
list.addAll(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.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -71,7 +78,20 @@ data class Options(
|
||||
list.add(Option(R.string.save_snapshot, R.drawable.baseline_download_24, Option.OPTION_SNAPSHOT))
|
||||
}
|
||||
|
||||
return Options(R.string.comment_options, list)
|
||||
return Options(R.string.comment_options, COMMENT_OPTIONS, list)
|
||||
}
|
||||
|
||||
fun getProfilePhotoOptions(userOwned: Boolean): Options {
|
||||
val list = mutableListOf(Option(R.string.view_photo, R.drawable.baseline_image_24, Option.OPTION_PROFILE_PHOTO_VIEW_PHOTO))
|
||||
|
||||
if(userOwned) {
|
||||
list.addAll(listOf(
|
||||
Option(R.string.change_profile_photo, R.drawable.baseline_edit_24, Option.OPTION_PROFILE_PHOTO_CHANGE_PHOTO),
|
||||
Option(R.string.remove_photo, R.drawable.baseline_remove_circle_24, Option.OPTION_PROFILE_PHOTO_REMOVE_PHOTO)
|
||||
))
|
||||
}
|
||||
|
||||
return Options(R.string.profile_photo,PROFILE_PHOTO_OPTIONS, list)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,15 @@
|
||||
package com.isolaatti.posting.common.options_bottom_sheet.presentation
|
||||
package com.isolaatti.common.options_bottom_sheet.presentation
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
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.domain.Options.Companion.COMMENT_OPTIONS
|
||||
import com.isolaatti.posting.common.options_bottom_sheet.domain.Options.Companion.POST_OPTIONS
|
||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||
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.domain.Options.Companion.COMMENT_OPTIONS
|
||||
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.POST_OPTIONS
|
||||
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.PROFILE_PHOTO_OPTIONS
|
||||
import com.isolaatti.settings.domain.UserIdSetting
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -39,7 +39,8 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett
|
||||
when(options) {
|
||||
POST_OPTIONS -> {
|
||||
userIdSetting.getUserId()?.let { userId ->
|
||||
_options.postValue(Options.getPostsOptions(
|
||||
_options.postValue(
|
||||
Options.getPostsOptions(
|
||||
userOwned = userId == payload?.userId,
|
||||
savable = false,
|
||||
snapshotAble = false)
|
||||
@ -50,7 +51,8 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett
|
||||
}
|
||||
COMMENT_OPTIONS -> {
|
||||
userIdSetting.getUserId()?.let { userId ->
|
||||
_options.postValue(Options.getCommentOptions(
|
||||
_options.postValue(
|
||||
Options.getCommentOptions(
|
||||
userOwned = userId == payload?.userId,
|
||||
savable = false,
|
||||
snapshotAble = false)
|
||||
@ -59,13 +61,20 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett
|
||||
_payload = payload
|
||||
}
|
||||
}
|
||||
PROFILE_PHOTO_OPTIONS -> {
|
||||
userIdSetting.getUserId()?.let { userId ->
|
||||
_options.postValue(Options.getProfilePhotoOptions(userOwned = userId == payload?.userId,))
|
||||
_callerId = callerId
|
||||
_payload = payload
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun optionClicked(optionId: Int) {
|
||||
_optionClicked.postValue(OptionClicked(optionId, _callerId, _payload))
|
||||
fun optionClicked(optionsId: Int, optionId: Int) {
|
||||
_optionClicked.postValue(OptionClicked(optionsId, optionId, _callerId, _payload))
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.isolaatti.posting.common.options_bottom_sheet.presentation
|
||||
package com.isolaatti.common.options_bottom_sheet.presentation
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
@ -6,14 +6,14 @@ import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.isolaatti.databinding.OptionItemBinding
|
||||
import com.isolaatti.posting.common.options_bottom_sheet.domain.Options
|
||||
import com.isolaatti.common.options_bottom_sheet.domain.Options
|
||||
|
||||
class OptionsRecyclerAdapter(val options: List<Options.Option>, private val optionCallback: OptionsCallback) : RecyclerView.Adapter<OptionsRecyclerAdapter.OptionViewHolder>() {
|
||||
class OptionsRecyclerAdapter(val optionsId: Int, val options: List<Options.Option>, private val optionCallback: OptionsCallback) : RecyclerView.Adapter<OptionsRecyclerAdapter.OptionViewHolder>() {
|
||||
|
||||
inner class OptionViewHolder(val viewBinding: OptionItemBinding) : RecyclerView.ViewHolder(viewBinding.root)
|
||||
|
||||
fun interface OptionsCallback {
|
||||
fun optionClicked(optionId: Int)
|
||||
fun optionClicked(optionsId:Int, optionId: Int)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder {
|
||||
@ -34,7 +34,7 @@ class OptionsRecyclerAdapter(val options: List<Options.Option>, private val opti
|
||||
text = context.getText(options[position].stringRes)
|
||||
icon = AppCompatResources.getDrawable(context, options[position].icon)
|
||||
setOnClickListener {
|
||||
optionCallback.optionClicked(options[position].optionId)
|
||||
optionCallback.optionClicked(optionsId, options[position].optionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package com.isolaatti.posting.common.options_bottom_sheet.ui
|
||||
package com.isolaatti.common.options_bottom_sheet.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
@ -15,9 +15,9 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.isolaatti.R
|
||||
import com.isolaatti.databinding.BottomSheetPostOptionsBinding
|
||||
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.presentation.OptionsRecyclerAdapter
|
||||
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.presentation.OptionsRecyclerAdapter
|
||||
|
||||
class BottomSheetPostOptionsFragment : BottomSheetDialogFragment(), OptionsRecyclerAdapter.OptionsCallback {
|
||||
private lateinit var viewBinding: BottomSheetPostOptionsBinding
|
||||
@ -56,7 +56,7 @@ class BottomSheetPostOptionsFragment : BottomSheetDialogFragment(), OptionsRecyc
|
||||
|
||||
private fun renderOptions(options: Options) {
|
||||
viewBinding.title.text = requireContext().getText(options.title)
|
||||
viewBinding.recyclerOptions.adapter = OptionsRecyclerAdapter(options.items, this)
|
||||
viewBinding.recyclerOptions.adapter = OptionsRecyclerAdapter(options.id, options.items, this)
|
||||
viewBinding.recyclerOptions.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ class BottomSheetPostOptionsFragment : BottomSheetDialogFragment(), OptionsRecyc
|
||||
|
||||
}
|
||||
|
||||
override fun optionClicked(optionId: Int) {
|
||||
viewModel.optionClicked(optionId)
|
||||
override fun optionClicked(optionsId:Int, optionId: Int) {
|
||||
viewModel.optionClicked(optionsId, optionId)
|
||||
}
|
||||
}
|
||||
@ -27,12 +27,12 @@ import com.isolaatti.home.presentation.FeedViewModel
|
||||
import com.isolaatti.images.picture_viewer.ui.PictureViewerActivity
|
||||
import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
|
||||
import com.isolaatti.posting.comments.ui.BottomSheetPostComments
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedWithPostCallback
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
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.common.OnUserInteractedWithPostCallback
|
||||
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
|
||||
import com.isolaatti.posting.posts.domain.entity.Post
|
||||
import com.isolaatti.posting.posts.presentation.CreatePostContract
|
||||
import com.isolaatti.posting.posts.presentation.EditPostContract
|
||||
@ -194,14 +194,14 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
|
||||
val textViewName: TextView? = header?.findViewById(R.id.textViewName)
|
||||
val textViewEmail: TextView? = header?.findViewById(R.id.textViewEmail)
|
||||
|
||||
Picasso.get().load(UrlGen.userProfileImage(it.id)).into(image)
|
||||
Picasso.get().load(UrlGen.userProfileImage(it.userId)).into(image)
|
||||
image?.setOnClickListener {_ ->
|
||||
PictureViewerActivity.startActivityWithUrls(requireContext(), arrayOf(UrlGen.userProfileImageFullQuality(it.id)))
|
||||
PictureViewerActivity.startActivityWithUrls(requireContext(), arrayOf(UrlGen.userProfileImageFullQuality(it.userId)))
|
||||
}
|
||||
|
||||
textViewName?.text = it.name
|
||||
textViewEmail?.text = it.email
|
||||
currentUserId = it.id
|
||||
currentUserId = it.userId
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import com.isolaatti.posting.posts.domain.PostsRepository
|
||||
import com.isolaatti.posting.posts.presentation.PostListingViewModelBase
|
||||
import com.isolaatti.posting.posts.presentation.UpdateEvent
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.domain.entity.UserProfile
|
||||
import com.isolaatti.profile.domain.use_case.GetProfile
|
||||
import com.isolaatti.utils.Resource
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@ -75,8 +76,8 @@ class FeedViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
// User profile
|
||||
private val _userProfile: MutableLiveData<UserProfileDto> = MutableLiveData()
|
||||
val userProfile: LiveData<UserProfileDto> get() = _userProfile
|
||||
private val _userProfile: MutableLiveData<UserProfile> = MutableLiveData()
|
||||
val userProfile: LiveData<UserProfile> get() = _userProfile
|
||||
|
||||
fun getProfile() {
|
||||
viewModelScope.launch {
|
||||
|
||||
@ -2,8 +2,7 @@ package com.isolaatti.posting.comments.domain.model
|
||||
|
||||
import com.isolaatti.posting.comments.data.remote.CommentDto
|
||||
import com.isolaatti.posting.comments.data.remote.FeedCommentsDto
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||
import com.isolaatti.common.Ownable
|
||||
|
||||
data class Comment(
|
||||
val id: Long,
|
||||
|
||||
@ -5,10 +5,8 @@ import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.isolaatti.databinding.CommentLayoutBinding
|
||||
import com.isolaatti.posting.comments.data.remote.CommentDto
|
||||
import com.isolaatti.posting.comments.domain.model.Comment
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedCallback
|
||||
import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter
|
||||
import com.isolaatti.common.OnUserInteractedCallback
|
||||
import com.isolaatti.utils.UrlGen
|
||||
import com.squareup.picasso.Picasso
|
||||
import io.noties.markwon.Markwon
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
package com.isolaatti.posting.comments.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.doOnLayout
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
@ -15,9 +13,7 @@ import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HALF_EXPANDED
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.isolaatti.R
|
||||
@ -28,12 +24,12 @@ import com.isolaatti.posting.comments.domain.model.Comment
|
||||
import com.isolaatti.posting.comments.presentation.CommentsRecyclerViewAdapter
|
||||
import com.isolaatti.posting.comments.presentation.CommentsViewModel
|
||||
import com.isolaatti.posting.comments.presentation.UpdateEvent
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedCallback
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
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.common.OnUserInteractedCallback
|
||||
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
|
||||
import com.isolaatti.profile.ui.ProfileActivity
|
||||
import com.isolaatti.utils.PicassoImagesPluginDef
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
@ -42,7 +38,6 @@ import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.MarkwonConfiguration
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute
|
||||
import io.noties.markwon.linkify.LinkifyPlugin
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
package com.isolaatti.posting.common.domain
|
||||
|
||||
interface Ownable {
|
||||
val userId: Int
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package com.isolaatti.posting.common.options_bottom_sheet.domain
|
||||
|
||||
/**
|
||||
* @param optionId Identify action
|
||||
* @param callerId Identify who started dialog
|
||||
* @param payload Data to identify on what item perform action
|
||||
*/
|
||||
data class OptionClicked(val optionId: Int, val callerId: Int, val payload: Any? = null)
|
||||
@ -1,6 +1,6 @@
|
||||
package com.isolaatti.posting.posts.domain.entity
|
||||
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
import com.isolaatti.common.Ownable
|
||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||
|
||||
data class Post(
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
package com.isolaatti.posting.posts.presentation
|
||||
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedWithPostCallback
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
import com.isolaatti.common.OnUserInteractedWithPostCallback
|
||||
import com.isolaatti.common.Ownable
|
||||
|
||||
abstract class PostListingRecyclerViewAdapterWiring(private val postsViewModelBase: PostListingViewModelBase) : OnUserInteractedWithPostCallback {
|
||||
abstract class PostListingRecyclerViewAdapterWiring(private val postsViewModelBase: PostListingViewModelBase) :
|
||||
OnUserInteractedWithPostCallback {
|
||||
|
||||
override fun onLiked(postId: Long) {
|
||||
postsViewModelBase.likePost(postId)
|
||||
|
||||
@ -12,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.isolaatti.R
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedWithPostCallback
|
||||
import com.isolaatti.common.OnUserInteractedWithPostCallback
|
||||
import com.isolaatti.posting.posts.domain.entity.Post
|
||||
import com.isolaatti.utils.UrlGen.userProfileImage
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
@ -102,6 +102,11 @@ class PostViewerActivity : IsolaattiBaseActivity() {
|
||||
binding.commentsInfo.setOnClickListener {
|
||||
openComments()
|
||||
}
|
||||
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
}
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@ -3,7 +3,7 @@ package com.isolaatti.profile.data.remote
|
||||
data class UserProfileDto(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val email: String,
|
||||
val email: String?,
|
||||
val numberOfFollowers: Int,
|
||||
val numberOfFollowing: Int,
|
||||
val numberOfLikes: Int,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
package com.isolaatti.profile.data.repository
|
||||
|
||||
import android.util.Log
|
||||
import com.isolaatti.profile.data.remote.ProfileApi
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.domain.ProfileRepository
|
||||
import com.isolaatti.profile.domain.entity.UserProfile
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
@ -10,15 +11,20 @@ import retrofit2.awaitResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
class ProfileRepositoryImpl @Inject constructor(private val profileApi: ProfileApi) : ProfileRepository {
|
||||
override fun getProfile(userId: Int): Flow<Resource<UserProfileDto>> = flow {
|
||||
override fun getProfile(userId: Int): Flow<Resource<UserProfile>> = flow {
|
||||
try {
|
||||
val result = profileApi.userProfile(userId).awaitResponse()
|
||||
if(result.isSuccessful) {
|
||||
emit(Resource.Success(result.body()))
|
||||
return@flow
|
||||
val dto = result.body()
|
||||
if(dto != null) {
|
||||
emit(Resource.Success(UserProfile.fromDto(dto)))
|
||||
}
|
||||
} else {
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(result.code())))
|
||||
} catch(_: Exception) {
|
||||
}
|
||||
|
||||
} catch(e: Exception) {
|
||||
Log.e("ProfileRepositoryImpl", e.message.toString())
|
||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
package com.isolaatti.profile.domain
|
||||
|
||||
import com.isolaatti.profile.data.remote.ProfileApi
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.domain.entity.UserProfile
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ProfileRepository {
|
||||
fun getProfile(userId: Int): Flow<Resource<UserProfileDto>>
|
||||
fun getProfile(userId: Int): Flow<Resource<UserProfile>>
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.isolaatti.profile.domain.entity
|
||||
|
||||
import com.isolaatti.common.Ownable
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.utils.UrlGen
|
||||
|
||||
data class UserProfile(
|
||||
override val userId: Int,
|
||||
val name: String,
|
||||
val email: String?,
|
||||
val numberOfFollowers: Int,
|
||||
val numberOfFollowing: Int,
|
||||
val numberOfLikes: Int,
|
||||
val numberOfPosts: Int,
|
||||
val isUserItself: Boolean,
|
||||
val followingThisUser: Boolean,
|
||||
val thisUserIsFollowingMe: Boolean,
|
||||
val profileImageId: String?,
|
||||
val descriptionText: String?,
|
||||
val descriptionAudioId: String?
|
||||
) : Ownable {
|
||||
|
||||
val profileAvatarPictureUrl: String get() = UrlGen.userProfileImage(userId)
|
||||
val profilePictureUrl: String get() = UrlGen.userProfileImageFullQuality(userId)
|
||||
companion object {
|
||||
fun fromDto(userProfileDto: UserProfileDto): UserProfile {
|
||||
return UserProfile(
|
||||
userId = userProfileDto.id,
|
||||
name = userProfileDto.name,
|
||||
email = userProfileDto.email,
|
||||
numberOfFollowers = userProfileDto.numberOfFollowers,
|
||||
numberOfFollowing = userProfileDto.numberOfFollowing,
|
||||
numberOfLikes = userProfileDto.numberOfLikes,
|
||||
numberOfPosts = userProfileDto.numberOfPosts,
|
||||
isUserItself = userProfileDto.isUserItself,
|
||||
followingThisUser = userProfileDto.followingThisUser,
|
||||
thisUserIsFollowingMe = userProfileDto.thisUserIsFollowingMe,
|
||||
profileImageId = userProfileDto.profileImageId,
|
||||
descriptionText = userProfileDto.descriptionText,
|
||||
descriptionAudioId = userProfileDto.descriptionAudioId
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,11 @@ package com.isolaatti.profile.domain.use_case
|
||||
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.domain.ProfileRepository
|
||||
import com.isolaatti.profile.domain.entity.UserProfile
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetProfile @Inject constructor(private val profileRepository: ProfileRepository) {
|
||||
operator fun invoke(userId: Int): Flow<Resource<UserProfileDto>> = profileRepository.getProfile(userId)
|
||||
operator fun invoke(userId: Int): Flow<Resource<UserProfile>> = profileRepository.getProfile(userId)
|
||||
}
|
||||
@ -11,6 +11,7 @@ import com.isolaatti.posting.posts.presentation.PostListingViewModelBase
|
||||
import com.isolaatti.posting.posts.presentation.UpdateEvent
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.domain.ProfileRepository
|
||||
import com.isolaatti.profile.domain.entity.UserProfile
|
||||
import com.isolaatti.profile.domain.use_case.GetProfile
|
||||
import com.isolaatti.profile.domain.use_case.GetProfilePosts
|
||||
import com.isolaatti.utils.Resource
|
||||
@ -28,8 +29,8 @@ import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ProfileViewModel @Inject constructor(private val getProfileUseCase: GetProfile, private val getProfilePostsUseCase: GetProfilePosts) : PostListingViewModelBase() {
|
||||
private val _profile = MutableLiveData<UserProfileDto>()
|
||||
val profile: LiveData<UserProfileDto> get() = _profile
|
||||
private val _profile = MutableLiveData<UserProfile>()
|
||||
val profile: LiveData<UserProfile> get() = _profile
|
||||
|
||||
var profileId: Int = 0
|
||||
|
||||
|
||||
@ -3,44 +3,9 @@ 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
|
||||
import androidx.core.content.ContentProviderCompat.requireContext
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
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.BuildConfig
|
||||
import com.isolaatti.R
|
||||
import com.isolaatti.common.IsolaattiBaseActivity
|
||||
import com.isolaatti.databinding.ActivityProfileBinding
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedCallback
|
||||
import com.isolaatti.posting.common.domain.OnUserInteractedWithPostCallback
|
||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||
import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.presentation.ProfileViewModel
|
||||
import com.isolaatti.utils.PicassoImagesPluginDef
|
||||
import com.isolaatti.utils.UrlGen
|
||||
import com.squareup.picasso.Picasso
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.noties.markwon.AbstractMarkwonPlugin
|
||||
import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.MarkwonConfiguration
|
||||
import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute
|
||||
import io.noties.markwon.linkify.LinkifyPlugin
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ProfileActivity : IsolaattiBaseActivity() {
|
||||
|
||||
@ -2,6 +2,7 @@ package com.isolaatti.profile.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -24,11 +25,12 @@ import com.isolaatti.followers.domain.FollowingState
|
||||
import com.isolaatti.home.FeedFragment
|
||||
import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
|
||||
import com.isolaatti.posting.comments.ui.BottomSheetPostComments
|
||||
import com.isolaatti.posting.common.domain.Ownable
|
||||
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.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
|
||||
import com.isolaatti.images.picture_viewer.ui.PictureViewerActivity
|
||||
import com.isolaatti.posting.posts.domain.entity.Post
|
||||
import com.isolaatti.posting.posts.presentation.CreatePostContract
|
||||
import com.isolaatti.posting.posts.presentation.EditPostContract
|
||||
@ -36,6 +38,7 @@ import com.isolaatti.posting.posts.presentation.PostListingRecyclerViewAdapterWi
|
||||
import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter
|
||||
import com.isolaatti.posting.posts.presentation.UpdateEvent
|
||||
import com.isolaatti.profile.data.remote.UserProfileDto
|
||||
import com.isolaatti.profile.domain.entity.UserProfile
|
||||
import com.isolaatti.profile.presentation.ProfileViewModel
|
||||
import com.isolaatti.utils.PicassoImagesPluginDef
|
||||
import com.isolaatti.utils.UrlGen
|
||||
@ -75,9 +78,9 @@ class ProfileMainFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private val profileObserver = Observer<UserProfileDto> { profile ->
|
||||
private val profileObserver = Observer<UserProfile> { profile ->
|
||||
Picasso.get()
|
||||
.load(UrlGen.userProfileImage(profile.id))
|
||||
.load(UrlGen.userProfileImage(profile.userId))
|
||||
.into(viewBinding.profileImageView)
|
||||
|
||||
title = profile.name
|
||||
@ -94,6 +97,12 @@ class ProfileMainFragment : Fragment() {
|
||||
)
|
||||
|
||||
|
||||
viewBinding.profileImageView.setOnClickListener {
|
||||
optionsViewModel.setOptions(Options.PROFILE_PHOTO_OPTIONS, CALLER_ID, profile)
|
||||
val fragment = BottomSheetPostOptionsFragment()
|
||||
fragment.show(parentFragmentManager, BottomSheetPostOptionsFragment.TAG)
|
||||
}
|
||||
|
||||
setupUiForUserType(profile.isUserItself)
|
||||
}
|
||||
|
||||
@ -131,7 +140,25 @@ class ProfileMainFragment : Fragment() {
|
||||
}
|
||||
|
||||
private val optionsObserver: Observer<OptionClicked?> = Observer { optionClicked ->
|
||||
if(optionClicked?.callerId == FeedFragment.CALLER_ID) {
|
||||
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) {
|
||||
Options.Option.OPTION_PROFILE_PHOTO_CHANGE_PHOTO -> {}
|
||||
Options.Option.OPTION_PROFILE_PHOTO_REMOVE_PHOTO -> {}
|
||||
Options.Option.OPTION_PROFILE_PHOTO_VIEW_PHOTO -> {
|
||||
val profilePictureUrl = profile?.profilePictureUrl
|
||||
if(profilePictureUrl != null) {
|
||||
PictureViewerActivity.startActivityWithUrls(requireContext(), arrayOf(profilePictureUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
optionsViewModel.handle()
|
||||
}
|
||||
Options.POST_OPTIONS -> {
|
||||
// post id should come as payload
|
||||
val post = optionClicked.payload as? Post ?: return@Observer
|
||||
when(optionClicked.optionId) {
|
||||
@ -155,6 +182,10 @@ class ProfileMainFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var postListingRecyclerViewAdapterWiring: PostListingRecyclerViewAdapterWiring
|
||||
|
||||
|
||||
@ -163,7 +194,7 @@ class ProfileMainFragment : Fragment() {
|
||||
viewBinding.topAppBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
|
||||
if (scrollRange == -1) scrollRange = appBarLayout.totalScrollRange
|
||||
if (scrollRange + verticalOffset == 0) {
|
||||
viewBinding.collapsingToolbarLayout.title = title
|
||||
viewBinding.collapsingToolbarLayout.title = viewModel.profile.value?.name
|
||||
isShow = true
|
||||
} else if (isShow) {
|
||||
viewBinding.collapsingToolbarLayout.title = " "
|
||||
@ -278,7 +309,7 @@ class ProfileMainFragment : Fragment() {
|
||||
}
|
||||
|
||||
override fun onOptions(post: Ownable) {
|
||||
optionsViewModel.setOptions(Options.POST_OPTIONS, FeedFragment.CALLER_ID, post)
|
||||
optionsViewModel.setOptions(Options.POST_OPTIONS, CALLER_ID, post)
|
||||
val modalBottomSheet = BottomSheetPostOptionsFragment()
|
||||
modalBottomSheet.show(requireActivity().supportFragmentManager, BottomSheetPostOptionsFragment.TAG)
|
||||
}
|
||||
@ -305,11 +336,12 @@ class ProfileMainFragment : Fragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupCollapsingBar()
|
||||
|
||||
setupPostsAdapter()
|
||||
bind()
|
||||
setObservers()
|
||||
getData()
|
||||
setupCollapsingBar()
|
||||
|
||||
|
||||
|
||||
@ -322,4 +354,8 @@ class ProfileMainFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CALLER_ID = 30
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/drawable/baseline_remove_circle_24.xml
Normal file
5
app/src/main/res/drawable/baseline_remove_circle_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13L7,13v-2h10v2z"/>
|
||||
</vector>
|
||||
@ -84,4 +84,8 @@
|
||||
<string name="comments">Comments</string>
|
||||
<string name="likes_info">Claps: %d</string>
|
||||
<string name="comments_info">Comments: %d</string>
|
||||
<string name="view_photo">View photo</string>
|
||||
<string name="change_profile_photo">Change profile photo</string>
|
||||
<string name="profile_photo">Profile photo</string>
|
||||
<string name="remove_photo">Remove photo</string>
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user