WIP visor de discusiones
This commit is contained in:
parent
003ab3ea5d
commit
5cf9fcb426
@ -31,7 +31,7 @@
|
||||
android:parentActivityName=".MainActivity"/>
|
||||
<activity android:name=".settings.ui.SettingsActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".posting.posts.ui.CreatePostActivity" android:theme="@style/Theme.Isolaatti" android:windowSoftInputMode="adjustResize"/>
|
||||
<activity android:name=".posting.PostViewerActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".posting.posts.viewer.ui.PostViewerActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".drafts.ui.DraftsActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".about.AboutActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".picture_viewer.ui.PictureViewerActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
|
||||
@ -25,7 +25,7 @@ import com.isolaatti.databinding.FragmentFeedBinding
|
||||
import com.isolaatti.drafts.ui.DraftsActivity
|
||||
import com.isolaatti.home.presentation.FeedViewModel
|
||||
import com.isolaatti.picture_viewer.ui.PictureViewerActivity
|
||||
import com.isolaatti.posting.PostViewerActivity
|
||||
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
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
package com.isolaatti.posting
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.isolaatti.common.IsolaattiBaseActivity
|
||||
import com.isolaatti.databinding.ActivityCreatePostBinding
|
||||
import com.isolaatti.databinding.ActivityPostViewerBinding
|
||||
|
||||
class PostViewerActivity : IsolaattiBaseActivity() {
|
||||
companion object {
|
||||
const val POST_ID = "postId"
|
||||
fun startActivity(context: Context, postId: Long) {
|
||||
context.startActivity(Intent(context, PostViewerActivity::class.java).apply {
|
||||
putExtra(POST_ID, postId)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private lateinit var binding: ActivityPostViewerBinding
|
||||
|
||||
private var postId: Long? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityPostViewerBinding.inflate(layoutInflater)
|
||||
|
||||
setContentView(binding.root)
|
||||
}
|
||||
}
|
||||
@ -5,24 +5,36 @@ import com.isolaatti.posting.likes.data.remote.LikeDto
|
||||
import com.isolaatti.posting.likes.data.remote.LikesApi
|
||||
import com.isolaatti.posting.likes.domain.repository.LikesRepository
|
||||
import com.isolaatti.utils.LongIdentificationWrapper
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import retrofit2.Response
|
||||
import retrofit2.awaitResponse
|
||||
|
||||
class LikesRepositoryImpl(private val likesApi: LikesApi) : LikesRepository {
|
||||
override fun likePost(postId: Long): Flow<LikeDto> = flow {
|
||||
val response = likesApi.likePost(LongIdentificationWrapper(postId)).awaitResponse()
|
||||
Log.d("likes_repo", response.toString())
|
||||
if(response.isSuccessful) {
|
||||
response.body()?.let { emit(it) }
|
||||
override fun likePost(postId: Long): Flow<Resource<LikeDto>> = flow {
|
||||
try {
|
||||
val response = likesApi.likePost(LongIdentificationWrapper(postId)).awaitResponse()
|
||||
if(response.isSuccessful) {
|
||||
response.body()?.let { emit(Resource.Success(it)) }
|
||||
} else {
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||
}
|
||||
} catch(_: Exception) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||
}
|
||||
}
|
||||
|
||||
override fun unLikePost(postId: Long): Flow<LikeDto> = flow {
|
||||
val response = likesApi.unLikePost(LongIdentificationWrapper(postId)).awaitResponse()
|
||||
Log.d("likes_repo", response.toString())
|
||||
if(response.isSuccessful) {
|
||||
response.body()?.let { emit(it) }
|
||||
override fun unLikePost(postId: Long): Flow<Resource<LikeDto>> = flow {
|
||||
try {
|
||||
val response = likesApi.unLikePost(LongIdentificationWrapper(postId)).awaitResponse()
|
||||
if(response.isSuccessful) {
|
||||
response.body()?.let { emit(Resource.Success(it)) }
|
||||
} else {
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||
}
|
||||
} catch(_: Exception) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
package com.isolaatti.posting.likes.domain.repository
|
||||
|
||||
import com.isolaatti.posting.likes.data.remote.LikeDto
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LikesRepository {
|
||||
fun likePost(postId: Long): Flow<LikeDto>
|
||||
fun unLikePost(postId: Long): Flow<LikeDto>
|
||||
fun likePost(postId: Long): Flow<Resource<LikeDto>>
|
||||
fun unLikePost(postId: Long): Flow<Resource<LikeDto>>
|
||||
}
|
||||
@ -94,13 +94,16 @@ class PostsRepositoryImpl @Inject constructor(private val feedsApi: FeedsApi, pr
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadPost(postId: Long): Flow<Resource<FeedDto.PostDto>> = flow {
|
||||
override fun loadPost(postId: Long): Flow<Resource<Post>> = flow {
|
||||
emit(Resource.Loading())
|
||||
try {
|
||||
val result = postApi.getPost(postId).execute()
|
||||
if(result.isSuccessful) {
|
||||
emit(Resource.Success(result.body()))
|
||||
return@flow
|
||||
val dto = result.body()
|
||||
if(dto != null) {
|
||||
emit(Resource.Success(Post.fromPostDto(dto)))
|
||||
return@flow
|
||||
}
|
||||
}
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(result.code())))
|
||||
} catch(_: Exception) {
|
||||
|
||||
@ -18,5 +18,5 @@ interface PostsRepository {
|
||||
fun makePost(createPostDto: CreatePostDto): Flow<Resource<FeedDto.PostDto>>
|
||||
fun editPost(editPostDto: EditPostDto): Flow<Resource<FeedDto.PostDto>>
|
||||
fun deletePost(postId: Long): Flow<Resource<PostDeletedDto>>
|
||||
fun loadPost(postId: Long): Flow<Resource<FeedDto.PostDto>>
|
||||
fun loadPost(postId: Long): Flow<Resource<Post>>
|
||||
}
|
||||
@ -36,5 +36,22 @@ data class Post(
|
||||
)
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
fun fromPostDto(postDto: FeedDto.PostDto): Post {
|
||||
return Post(
|
||||
id = postDto.post.id,
|
||||
userId = postDto.post.userId,
|
||||
textContent = postDto.post.textContent,
|
||||
privacy = postDto.post.privacy,
|
||||
date = postDto.post.date,
|
||||
audioId = postDto.post.audioId,
|
||||
squadId = postDto.post.squadId,
|
||||
numberOfComments = postDto.numberOfComments,
|
||||
numberOfLikes = postDto.numberOfLikes,
|
||||
userName = postDto.userName,
|
||||
squadName = postDto.squadName,
|
||||
liked = postDto.liked
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
package com.isolaatti.posting.posts.domain.use_case
|
||||
|
||||
import com.isolaatti.posting.posts.data.remote.FeedDto
|
||||
import com.isolaatti.posting.posts.domain.PostsRepository
|
||||
import com.isolaatti.posting.posts.domain.entity.Post
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoadSinglePost @Inject constructor(private val postsRepository: PostsRepository) {
|
||||
operator fun invoke(postId: Long): Flow<Resource<FeedDto.PostDto>> {
|
||||
operator fun invoke(postId: Long): Flow<Resource<Post>> {
|
||||
return postsRepository.loadPost(postId)
|
||||
}
|
||||
}
|
||||
@ -72,7 +72,7 @@ class CreatePostViewModel @Inject constructor(private val makePost: MakePost, pr
|
||||
loadPost(postId).onEach { postRes ->
|
||||
if(postRes is Resource.Success) {
|
||||
postRes.data?.let {
|
||||
postToEdit.postValue(EditPostDto(PRIVACY_ISOLAATTI, content = it.post.textContent, postId = it.post.id))
|
||||
postToEdit.postValue(EditPostDto(PRIVACY_ISOLAATTI, content = it.textContent, postId = it.id))
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
|
||||
@ -43,36 +43,54 @@ abstract class PostListingViewModelBase : ViewModel() {
|
||||
|
||||
fun likePost(postId: Long) {
|
||||
viewModelScope.launch {
|
||||
likesRepository.likePost(postId).onEach {likeDto ->
|
||||
val likedPost = posts.value?.first?.find { post -> post.id == likeDto.postId }
|
||||
val index = posts.value?.first?.indexOf(likedPost)
|
||||
if(index != null){
|
||||
val temp = posts.value?.first?.toMutableList()
|
||||
Log.d("***", temp.toString())
|
||||
temp?.set(index, likedPost!!.apply {
|
||||
liked = true
|
||||
numberOfLikes = likeDto.likesCount
|
||||
likesRepository.likePost(postId).onEach {like ->
|
||||
|
||||
})
|
||||
when(like) {
|
||||
is Resource.Error -> {}
|
||||
is Resource.Loading -> {}
|
||||
is Resource.Success -> {
|
||||
val likedPost = posts.value?.first?.find { post -> post.id == like.data?.postId }
|
||||
val index = posts.value?.first?.indexOf(likedPost)
|
||||
if(index != null){
|
||||
val temp = posts.value?.first?.toMutableList()
|
||||
Log.d("***", temp.toString())
|
||||
temp?.set(index, likedPost!!.apply {
|
||||
liked = true
|
||||
numberOfLikes = like.data?.likesCount ?: 0
|
||||
|
||||
})
|
||||
}
|
||||
posts.postValue(posts.value?.copy(second = UpdateEvent(UpdateEvent.UpdateType.POST_LIKED, index)))
|
||||
}
|
||||
}
|
||||
posts.postValue(posts.value?.copy(second = UpdateEvent(UpdateEvent.UpdateType.POST_LIKED, index)))
|
||||
|
||||
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun unLikePost(postId: Long) {
|
||||
viewModelScope.launch {
|
||||
likesRepository.unLikePost(postId).onEach {likeDto ->
|
||||
val likedPost = posts.value?.first?.find { post -> post.id == likeDto.postId }
|
||||
val index = posts.value?.first?.indexOf(likedPost)
|
||||
if(index != null){
|
||||
val temp = posts.value?.first?.toMutableList()
|
||||
temp?.set(index, likedPost!!.apply {
|
||||
liked = false
|
||||
numberOfLikes = likeDto.likesCount
|
||||
})
|
||||
likesRepository.unLikePost(postId).onEach {like ->
|
||||
|
||||
when(like) {
|
||||
is Resource.Error -> TODO()
|
||||
is Resource.Loading -> TODO()
|
||||
is Resource.Success -> {
|
||||
val likedPost = posts.value?.first?.find { post -> post.id == like.data?.postId }
|
||||
val index = posts.value?.first?.indexOf(likedPost)
|
||||
if(index != null){
|
||||
val temp = posts.value?.first?.toMutableList()
|
||||
temp?.set(index, likedPost!!.apply {
|
||||
liked = false
|
||||
numberOfLikes = like.data?.likesCount ?: 0
|
||||
})
|
||||
}
|
||||
posts.postValue(posts.value?.copy(second = UpdateEvent(UpdateEvent.UpdateType.POST_LIKED, index)))
|
||||
}
|
||||
}
|
||||
posts.postValue(posts.value?.copy(second = UpdateEvent(UpdateEvent.UpdateType.POST_LIKED, index)))
|
||||
|
||||
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
package com.isolaatti.posting.posts.viewer.presentation
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.isolaatti.posting.comments.domain.use_case.GetComments
|
||||
import com.isolaatti.posting.likes.domain.repository.LikesRepository
|
||||
import com.isolaatti.posting.posts.domain.entity.Post
|
||||
import com.isolaatti.posting.posts.domain.use_case.LoadSinglePost
|
||||
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 PostViewerViewModel @Inject constructor(private val loadSinglePost: LoadSinglePost, private val likesRepository: LikesRepository) : ViewModel() {
|
||||
val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData()
|
||||
val post: MutableLiveData<Post> = MutableLiveData()
|
||||
var postId: Long = 0
|
||||
|
||||
private val toRetry: MutableList<Runnable> = mutableListOf()
|
||||
|
||||
val postLiked: MutableLiveData<Boolean> = MutableLiveData()
|
||||
|
||||
|
||||
// runs the lists of "Runnable" one by one and clears list. After this is executed,
|
||||
// caller should report as handled
|
||||
fun retry() {
|
||||
toRetry.forEach {
|
||||
it.run()
|
||||
}
|
||||
|
||||
toRetry.clear()
|
||||
}
|
||||
|
||||
fun getPost() {
|
||||
viewModelScope.launch {
|
||||
loadSinglePost(postId).onEach {
|
||||
when(it) {
|
||||
is Resource.Error -> {
|
||||
error.postValue(it.errorType)
|
||||
toRetry.add {
|
||||
getPost()
|
||||
}
|
||||
}
|
||||
is Resource.Loading -> {}
|
||||
is Resource.Success -> {
|
||||
if(it.data != null) {
|
||||
post.postValue(it.data)
|
||||
postLiked.postValue(it.data.liked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLikesCount(likesCount: Int) {
|
||||
val updatedPost = post.value?.copy(numberOfLikes = likesCount)
|
||||
if(updatedPost != null) {
|
||||
post.postValue(updatedPost)
|
||||
}
|
||||
}
|
||||
|
||||
fun likeDislikePost() {
|
||||
viewModelScope.launch {
|
||||
if(postLiked.value == true) {
|
||||
likesRepository.unLikePost(postId).onEach {
|
||||
when(it) {
|
||||
is Resource.Error -> TODO()
|
||||
is Resource.Loading -> TODO()
|
||||
is Resource.Success -> {
|
||||
updateLikesCount(it.data?.likesCount ?: 0)
|
||||
postLiked.postValue(false)
|
||||
}
|
||||
}
|
||||
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
} else {
|
||||
likesRepository.likePost(postId).onEach {
|
||||
when(it) {
|
||||
is Resource.Error -> TODO()
|
||||
is Resource.Loading -> TODO()
|
||||
is Resource.Success -> {
|
||||
updateLikesCount(it.data?.likesCount ?: 0)
|
||||
postLiked.postValue(true)
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
package com.isolaatti.posting.posts.viewer.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.content.ContentProviderCompat.requireContext
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.isolaatti.BuildConfig
|
||||
import com.isolaatti.R
|
||||
import com.isolaatti.common.ErrorMessageViewModel
|
||||
import com.isolaatti.common.IsolaattiBaseActivity
|
||||
import com.isolaatti.databinding.ActivityPostViewerBinding
|
||||
import com.isolaatti.posting.comments.ui.BottomSheetPostComments
|
||||
import com.isolaatti.posting.posts.viewer.presentation.PostViewerViewModel
|
||||
import com.isolaatti.profile.ui.ProfileActivity
|
||||
import com.isolaatti.utils.PicassoImagesPluginDef
|
||||
import com.isolaatti.utils.UrlGen
|
||||
import com.squareup.picasso.Picasso
|
||||
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
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class PostViewerActivity : IsolaattiBaseActivity() {
|
||||
companion object {
|
||||
const val POST_ID = "postId"
|
||||
fun startActivity(context: Context, postId: Long) {
|
||||
context.startActivity(Intent(context, PostViewerActivity::class.java).apply {
|
||||
putExtra(POST_ID, postId)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private lateinit var binding: ActivityPostViewerBinding
|
||||
private val viewModel: PostViewerViewModel by viewModels()
|
||||
private var postId: Long = 0
|
||||
private lateinit var markwon: Markwon
|
||||
|
||||
private fun openComments() {
|
||||
val modalBottomSheet = BottomSheetPostComments.getInstance(postId)
|
||||
modalBottomSheet.show(supportFragmentManager, BottomSheetPostComments.TAG)
|
||||
}
|
||||
|
||||
private fun setObservers() {
|
||||
viewModel.error.observe(this) {
|
||||
errorViewModel.error.postValue(it)
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
errorViewModel.retry.collect {
|
||||
viewModel.retry()
|
||||
errorViewModel.handleRetry()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.post.observe(this) {
|
||||
markwon.setMarkdown(binding.markwonContainer, it.textContent)
|
||||
binding.author.text = it.userName
|
||||
Picasso.get().load(UrlGen.userProfileImage(it.userId)).into(binding.profileImageView)
|
||||
binding.commentsInfo.text = getString(R.string.comments_info, it.numberOfComments)
|
||||
binding.likesInfo.text = getString(R.string.likes_info, it.numberOfLikes)
|
||||
binding.author.setOnClickListener {_ ->
|
||||
ProfileActivity.startActivity(this@PostViewerActivity, it.userId)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
viewModel.postLiked.observe(this) {
|
||||
val color = if(it) R.color.purple_lighter else R.color.on_surface
|
||||
val menuItem = binding.toolbar.menu.findItem(R.id.like)
|
||||
|
||||
menuItem.isEnabled = true
|
||||
menuItem.icon?.setTint(ResourcesCompat.getColor(resources, color, null))
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setListeners() {
|
||||
binding.toolbar.setOnMenuItemClickListener {
|
||||
when(it.itemId) {
|
||||
R.id.like -> {
|
||||
viewModel.likeDislikePost()
|
||||
true
|
||||
}
|
||||
R.id.comments -> {
|
||||
openComments()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
binding.commentsInfo.setOnClickListener {
|
||||
openComments()
|
||||
}
|
||||
}
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
postId = intent.getLongExtra(POST_ID, 0)
|
||||
|
||||
binding = ActivityPostViewerBinding.inflate(layoutInflater)
|
||||
markwon = Markwon.builder(this)
|
||||
.usePlugin(object: AbstractMarkwonPlugin() {
|
||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||
builder
|
||||
.imageDestinationProcessor(
|
||||
ImageDestinationProcessorRelativeToAbsolute
|
||||
.create(BuildConfig.backend))
|
||||
}
|
||||
})
|
||||
.usePlugin(PicassoImagesPluginDef.picassoImagePlugin)
|
||||
.usePlugin(LinkifyPlugin.create())
|
||||
.build()
|
||||
|
||||
setContentView(binding.root)
|
||||
if(postId!! > 0) {
|
||||
viewModel.postId = postId
|
||||
setObservers()
|
||||
setListeners()
|
||||
viewModel.getPost()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ import com.isolaatti.common.ErrorMessageViewModel
|
||||
import com.isolaatti.databinding.FragmentDiscussionsBinding
|
||||
import com.isolaatti.followers.domain.FollowingState
|
||||
import com.isolaatti.home.FeedFragment
|
||||
import com.isolaatti.posting.PostViewerActivity
|
||||
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
|
||||
|
||||
@ -4,6 +4,6 @@
|
||||
android:viewportWidth="640"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="@color/on_surface"
|
||||
android:pathData="M208,352c114.9,0 208,-78.8 208,-176S322.9,0 208,0S0,78.8 0,176c0,38.6 14.7,74.3 39.6,103.4c-3.5,9.4 -8.7,17.7 -14.2,24.7c-4.8,6.2 -9.7,11 -13.3,14.3c-1.8,1.6 -3.3,2.9 -4.3,3.7c-0.5,0.4 -0.9,0.7 -1.1,0.8l-0.2,0.2 0,0 0,0C1,327.2 -1.4,334.4 0.8,340.9S9.1,352 16,352c21.8,0 43.8,-5.6 62.1,-12.5c9.2,-3.5 17.8,-7.4 25.3,-11.4C134.1,343.3 169.8,352 208,352zM448,176c0,112.3 -99.1,196.9 -216.5,207C255.8,457.4 336.4,512 432,512c38.2,0 73.9,-8.7 104.7,-23.9c7.5,4 16,7.9 25.2,11.4c18.3,6.9 40.3,12.5 62.1,12.5c6.9,0 13.1,-4.5 15.2,-11.1c2.1,-6.6 -0.2,-13.8 -5.8,-17.9l0,0 0,0 -0.2,-0.2c-0.2,-0.2 -0.6,-0.4 -1.1,-0.8c-1,-0.8 -2.5,-2 -4.3,-3.7c-3.6,-3.3 -8.5,-8.1 -13.3,-14.3c-5.5,-7 -10.7,-15.4 -14.2,-24.7c24.9,-29 39.6,-64.7 39.6,-103.4c0,-92.8 -84.9,-168.9 -192.6,-175.5c0.4,5.1 0.6,10.3 0.6,15.5z"/>
|
||||
</vector>
|
||||
|
||||
@ -4,6 +4,6 @@
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillColor="@color/on_surface"
|
||||
android:pathData="M336,16L336,80c0,8.8 -7.2,16 -16,16s-16,-7.2 -16,-16L304,16c0,-8.8 7.2,-16 16,-16s16,7.2 16,16zM237.3,23.1l32,48c4.9,7.4 2.9,17.3 -4.4,22.2s-17.3,2.9 -22.2,-4.4l-32,-48c-4.9,-7.4 -2.9,-17.3 4.4,-22.2s17.3,-2.9 22.2,4.4zM135,119c9.4,-9.4 24.6,-9.4 33.9,0L292.7,242.7c10.1,10.1 27.3,2.9 27.3,-11.3L320,192c0,-17.7 14.3,-32 32,-32s32,14.3 32,32L384,345.6c0,57.1 -30,110 -78.9,139.4c-64,38.4 -145.8,28.3 -198.5,-24.4L7,361c-9.4,-9.4 -9.4,-24.6 0,-33.9s24.6,-9.4 33.9,0l53,53c6.1,6.1 16,6.1 22.1,0s6.1,-16 0,-22.1L23,265c-9.4,-9.4 -9.4,-24.6 0,-33.9s24.6,-9.4 33.9,0l93,93c6.1,6.1 16,6.1 22.1,0s6.1,-16 0,-22.1L55,185c-9.4,-9.4 -9.4,-24.6 0,-33.9s24.6,-9.4 33.9,0l117,117c6.1,6.1 16,6.1 22.1,0s6.1,-16 0,-22.1l-93,-93c-9.4,-9.4 -9.4,-24.6 0,-33.9zM433.1,484.9c-24.2,14.5 -50.9,22.1 -77.7,23.1c48.1,-39.6 76.6,-99 76.6,-162.4l0,-98.1c8.2,-0.1 16,-6.4 16,-16L448,192c0,-17.7 14.3,-32 32,-32s32,14.3 32,32L512,345.6c0,57.1 -30,110 -78.9,139.4zM424.9,18.7c7.4,4.9 9.3,14.8 4.4,22.2l-32,48c-4.9,7.4 -14.8,9.3 -22.2,4.4s-9.3,-14.8 -4.4,-22.2l32,-48c4.9,-7.4 14.8,-9.3 22.2,-4.4z"/>
|
||||
</vector>
|
||||
|
||||
@ -1,21 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Theme.Isolaatti"
|
||||
app:navigationIcon="@drawable/baseline_arrow_back_24"
|
||||
app:navigationIconTint="@color/on_surface"
|
||||
/>
|
||||
app:title="@string/discussion"
|
||||
app:menu="@menu/post_viewer_menu"/>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/profile_image_view"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||
tools:srcCompat="@tools:sample/avatars"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/author"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="username"
|
||||
android:textAlignment="center"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
style="@style/Widget.Material3.Button.TextButton"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_horizontal">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/comments_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_marginEnd="4dp"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/likes_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Material3.Button.TextButton"/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/markwon_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
20
app/src/main/res/menu/post_viewer_menu.xml
Normal file
20
app/src/main/res/menu/post_viewer_menu.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/comments"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:title="@string/comments"
|
||||
android:icon="@drawable/comments_solid"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/like"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:title="@string/clap"
|
||||
android:icon="@drawable/hands_clapping_solid"
|
||||
android:enabled="false"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
||||
@ -80,4 +80,8 @@
|
||||
<string name="retry">Retry</string>
|
||||
<string name="not_found">The resource you are trying to load could not be found</string>
|
||||
<string name="unknown_error">An unkwnow error occurred</string>
|
||||
<string name="clap">Clap</string>
|
||||
<string name="comments">Comments</string>
|
||||
<string name="likes_info">Claps: %d</string>
|
||||
<string name="comments_info">Comments: %d</string>
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user