Merge branch 'fix_comments' into 'master'

Fix comments: open comments in activity.

See merge request pixeldroid/PixelDroid!311
This commit is contained in:
Matthieu 2021-03-14 16:45:28 +00:00
commit 681fdc5582
7 changed files with 255 additions and 283 deletions

View File

@ -1,26 +1,36 @@
package com.h.pixeldroid.posts package com.h.pixeldroid.posts
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
import android.widget.LinearLayout
import android.widget.Toast
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.h.pixeldroid.R import com.h.pixeldroid.R
import com.h.pixeldroid.databinding.ActivityPostBinding import com.h.pixeldroid.databinding.ActivityPostBinding
import com.h.pixeldroid.utils.api.objects.Status import com.h.pixeldroid.databinding.CommentBinding
import com.h.pixeldroid.utils.api.objects.Status.Companion.DISCOVER_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.DOMAIN_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_TAG
import com.h.pixeldroid.utils.BaseActivity import com.h.pixeldroid.utils.BaseActivity
import com.h.pixeldroid.utils.api.PixelfedAPI
import com.h.pixeldroid.utils.api.objects.Mention
import com.h.pixeldroid.utils.api.objects.Status
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_COMMENT_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG
import com.h.pixeldroid.utils.displayDimensionsInPx
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
class PostActivity : BaseActivity() { class PostActivity : BaseActivity() {
private lateinit var postFragment : PostFragment
lateinit var domain : String lateinit var domain : String
private lateinit var accessToken : String private lateinit var accessToken : String
private lateinit var binding: ActivityPostBinding private lateinit var binding: ActivityPostBinding
private lateinit var status: Status
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityPostBinding.inflate(layoutInflater) binding = ActivityPostBinding.inflate(layoutInflater)
@ -28,18 +38,41 @@ class PostActivity : BaseActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
val status = intent.getSerializableExtra(POST_TAG) as Status? status = intent.getSerializableExtra(POST_TAG) as Status
val viewComments: Boolean = (intent.getSerializableExtra(VIEW_COMMENTS_TAG) ?: false) as Boolean
val postComment: Boolean = (intent.getSerializableExtra(POST_COMMENT_TAG) ?: false) as Boolean
val user = db.userDao().getActiveUser() val user = db.userDao().getActiveUser()
domain = user?.instance_uri.orEmpty() domain = user?.instance_uri.orEmpty()
accessToken = user?.accessToken.orEmpty() accessToken = user?.accessToken.orEmpty()
postFragment = PostFragment()
val arguments = Bundle()
arguments.putString(DOMAIN_TAG, domain)
initializeFragment(arguments, status) supportActionBar?.title = getString(R.string.post_title).format(status.account?.getDisplayName())
val holder = StatusViewHolder(binding.postFragmentSingle)
holder.bind(status, apiHolder.api!!, db, lifecycleScope, displayDimensionsInPx(), isActivity = true)
val credential = "Bearer $accessToken"
activateCommenter(credential)
if(viewComments || postComment){
//Scroll already down as much as possible (since comments are not loaded yet)
binding.scrollview.requestChildFocus(binding.editComment, binding.editComment)
//Open keyboard if we want to post a comment
if(postComment && binding.editComment.requestFocus()) {
window.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE)
binding.editComment.requestFocus()
}
// also retrieve comments if we're not posting the comment
if(!postComment) retrieveComments(apiHolder.api!!, credential)
}
binding.postFragmentSingle.viewComments.setOnClickListener {
retrieveComments(apiHolder.api!!, credential)
}
} }
override fun onSupportNavigateUp(): Boolean { override fun onSupportNavigateUp(): Boolean {
@ -47,13 +80,109 @@ class PostActivity : BaseActivity() {
return true return true
} }
private fun initializeFragment(arguments: Bundle, status: Status?){ private fun activateCommenter(credential: String) {
supportActionBar?.title = getString(R.string.post_title).format(status!!.account?.getDisplayName()) //Activate commenter
arguments.putSerializable(POST_TAG, status) binding.submitComment.setOnClickListener {
postFragment.arguments = arguments val textIn = binding.editComment.text
supportFragmentManager.isStateSaved //Open text input
supportFragmentManager.beginTransaction() if(textIn.isNullOrEmpty()) {
.add(R.id.postFragmentSingle, postFragment).commit() Toast.makeText(
binding.postFragmentSingle.visibility = View.VISIBLE binding.root.context,
binding.root.context.getString(R.string.empty_comment),
Toast.LENGTH_SHORT
).show()
} else {
//Post the comment
lifecycleScope.launchWhenCreated {
apiHolder.api?.let { it1 -> postComment(it1, credential) }
}
}
}
} }
private fun addComment(context: Context, commentContainer: LinearLayout,
commentUsername: String, commentContent: String, mentions: List<Mention>,
credential: String) {
val itemBinding = CommentBinding.inflate(
LayoutInflater.from(context), commentContainer, true
)
itemBinding.user.text = commentUsername
itemBinding.commentText.text = parseHTMLText(
commentContent,
mentions,
apiHolder.api!!,
context,
credential,
lifecycleScope
)
}
private fun retrieveComments(api: PixelfedAPI, credential: String) {
lifecycleScope.launchWhenCreated {
status.id.let {
try {
val statuses = api.statusComments(it, credential).descendants
binding.commentContainer.removeAllViews()
//Create the new views for each comment
for (status in statuses) {
addComment(binding.root.context, binding.commentContainer, status.account!!.username!!,
status.content!!, status.mentions.orEmpty(), credential
)
}
binding.commentContainer.visibility = View.VISIBLE
//Focus the comments
binding.scrollview.requestChildFocus(binding.commentContainer, binding.commentContainer)
} catch (exception: IOException) {
Log.e("COMMENT FETCH ERROR", exception.toString())
} catch (exception: HttpException) {
Log.e("COMMENT ERROR", "${exception.code()} with body ${exception.response()?.errorBody()}")
}
}
}
}
private suspend fun postComment(
api: PixelfedAPI,
credential: String,
) {
val textIn = binding.editComment.text
val nonNullText = textIn.toString()
status.id.let {
try {
val response = api.postStatus(credential, nonNullText, it)
binding.commentIn.visibility = View.GONE
//Add the comment to the comment section
addComment(
binding.root.context, binding.commentContainer, response.account!!.username!!,
response.content!!, response.mentions.orEmpty(), credential
)
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.comment_posted).format(textIn),
Toast.LENGTH_SHORT
).show()
} catch (exception: IOException) {
Log.e("COMMENT ERROR", exception.toString())
Toast.makeText(
binding.root.context, binding.root.context.getString(R.string.comment_error),
Toast.LENGTH_SHORT
).show()
} catch (exception: HttpException) {
Toast.makeText(
binding.root.context, binding.root.context.getString(R.string.comment_error),
Toast.LENGTH_SHORT
).show()
Log.e("ERROR_CODE", exception.code().toString())
}
}
}
} }

View File

@ -1,52 +0,0 @@
package com.h.pixeldroid.posts
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import com.h.pixeldroid.databinding.PostFragmentBinding
import com.h.pixeldroid.utils.api.objects.Status
import com.h.pixeldroid.utils.api.objects.Status.Companion.DOMAIN_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_TAG
import com.h.pixeldroid.utils.BaseFragment
import com.h.pixeldroid.utils.bindingLifecycleAware
import com.h.pixeldroid.utils.displayDimensionsInPx
class PostFragment : BaseFragment() {
private lateinit var statusDomain: String
private var currentStatus: Status? = null
var binding: PostFragmentBinding by bindingLifecycleAware()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
currentStatus = arguments?.getSerializable(POST_TAG) as Status?
statusDomain = arguments?.getString(DOMAIN_TAG)!!
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = PostFragmentBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
val holder = StatusViewHolder(binding)
holder.bind(currentStatus, api, db, lifecycleScope, requireContext().displayDimensionsInPx())
}
}

View File

@ -19,13 +19,15 @@ import com.bumptech.glide.RequestBuilder
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.h.pixeldroid.R import com.h.pixeldroid.R
import com.h.pixeldroid.databinding.AlbumImageViewBinding import com.h.pixeldroid.databinding.AlbumImageViewBinding
import com.h.pixeldroid.databinding.CommentBinding
import com.h.pixeldroid.databinding.PostFragmentBinding import com.h.pixeldroid.databinding.PostFragmentBinding
import com.h.pixeldroid.utils.BlurHashDecoder import com.h.pixeldroid.utils.BlurHashDecoder
import com.h.pixeldroid.utils.ImageConverter import com.h.pixeldroid.utils.ImageConverter
import com.h.pixeldroid.utils.api.PixelfedAPI import com.h.pixeldroid.utils.api.PixelfedAPI
import com.h.pixeldroid.utils.api.objects.Attachment import com.h.pixeldroid.utils.api.objects.Attachment
import com.h.pixeldroid.utils.api.objects.Status import com.h.pixeldroid.utils.api.objects.Status
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_COMMENT_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_TAG
import com.h.pixeldroid.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG
import com.h.pixeldroid.utils.db.AppDatabase import com.h.pixeldroid.utils.db.AppDatabase
import com.karumi.dexter.Dexter import com.karumi.dexter.Dexter
import com.karumi.dexter.listener.PermissionDeniedResponse import com.karumi.dexter.listener.PermissionDeniedResponse
@ -44,7 +46,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
private var status: Status? = null private var status: Status? = null
fun bind(status: Status?, pixelfedAPI: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope, displayDimensionsInPx: Pair<Int, Int>) { fun bind(status: Status?, pixelfedAPI: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope, displayDimensionsInPx: Pair<Int, Int>, isActivity: Boolean = false) {
this.itemView.visibility = View.VISIBLE this.itemView.visibility = View.VISIBLE
this.status = status this.status = status
@ -67,14 +69,13 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
} }
//Setup the post layout //Setup the post layout
val picRequest = Glide.with(itemView) val picRequest = Glide.with(itemView).asDrawable().fitCenter()
.asDrawable().fitCenter()
val user = db.userDao().getActiveUser()!! val user = db.userDao().getActiveUser()!!
setupPost(picRequest, user.instance_uri, false) setupPost(picRequest, user.instance_uri, isActivity)
activateButtons(pixelfedAPI, db, lifecycleScope) activateButtons(pixelfedAPI, db, lifecycleScope, isActivity)
} }
@ -130,10 +131,6 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
binding.postPager.visibility = View.GONE binding.postPager.visibility = View.GONE
binding.postIndicator.visibility = View.GONE binding.postIndicator.visibility = View.GONE
} }
//Set comment initial visibility
binding.commentIn.visibility = View.GONE
binding.commentContainer.visibility = View.GONE
} }
private fun setupPostPics( private fun setupPostPics(
@ -200,8 +197,13 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
} }
} }
} }
//region buttons
private fun activateButtons(api: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope){ private fun activateButtons(
api: PixelfedAPI,
db: AppDatabase,
lifecycleScope: LifecycleCoroutineScope,
isActivity: Boolean
){
val user = db.userDao().getActiveUser()!! val user = db.userDao().getActiveUser()!!
val credential = "Bearer ${user.accessToken}" val credential = "Bearer ${user.accessToken}"
@ -217,9 +219,23 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
api, credential, status?.reblogged ?: false, api, credential, status?.reblogged ?: false,
lifecycleScope lifecycleScope
) )
activateCommenter(api, credential, lifecycleScope)
showComments(api, credential, lifecycleScope) if(isActivity){
binding.commenter.visibility = View.INVISIBLE
}
else {
binding.commenter.setOnClickListener {
lifecycleScope.launchWhenCreated {
//Open status in activity
val intent = Intent(it.context, PostActivity::class.java)
intent.putExtra(POST_TAG, status)
intent.putExtra(POST_COMMENT_TAG, true)
it.context.startActivity(intent)
}
}
}
showComments(lifecycleScope, isActivity)
activateMoreButton(api, db, lifecycleScope) activateMoreButton(api, db, lifecycleScope)
} }
@ -514,13 +530,13 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
} }
} }
} }
//endregion
private fun showComments( private fun showComments(
api: PixelfedAPI, lifecycleScope: LifecycleCoroutineScope,
credential: String, isActivity: Boolean
lifecycleScope: LifecycleCoroutineScope
) { ) {
//Show all comments of a post //Show number of comments on the post
if (status?.replies_count == 0) { if (status?.replies_count == 0) {
binding.viewComments.text = binding.root.context.getString(R.string.NoCommentsToShow) binding.viewComments.text = binding.root.context.getString(R.string.NoCommentsToShow)
} else { } else {
@ -529,143 +545,22 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
status?.replies_count ?: 0, status?.replies_count ?: 0,
status?.replies_count ?: 0 status?.replies_count ?: 0
) )
setOnClickListener { if(!isActivity) {
visibility = View.GONE setOnClickListener {
lifecycleScope.launchWhenCreated {
lifecycleScope.launchWhenCreated { //Open status in activity
//Retrieve the comments val intent = Intent(context, PostActivity::class.java)
retrieveComments(api, credential) intent.putExtra(POST_TAG, status)
intent.putExtra(VIEW_COMMENTS_TAG, true)
context.startActivity(intent)
}
} }
} }
} }
} }
} }
private fun activateCommenter(
api: PixelfedAPI,
credential: String,
lifecycleScope: LifecycleCoroutineScope
) {
//Toggle comment button
toggleCommentInput()
//Activate commenterpostPicture
binding.submitComment.setOnClickListener {
val textIn = binding.editComment.text
//Open text input
if(textIn.isNullOrEmpty()) {
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.empty_comment),
Toast.LENGTH_SHORT
).show()
} else {
//Post the comment
lifecycleScope.launchWhenCreated {
postComment(api, credential)
}
}
}
}
private fun toggleCommentInput() {
//Toggle comment button
binding.commenter.setOnClickListener {
when(binding.commentIn.visibility) {
View.VISIBLE -> {
binding.commentIn.visibility = View.GONE
ImageConverter.setImageFromDrawable(
binding.root,
binding.commenter,
R.drawable.ic_comment_empty
)
}
View.GONE -> {
binding.commentIn.visibility = View.VISIBLE
ImageConverter.setImageFromDrawable(
binding.root,
binding.commenter,
R.drawable.ic_comment_blue
)
}
}
}
}
fun addComment(context: android.content.Context, commentContainer: LinearLayout, commentUsername: String, commentContent: String) {
val itemBinding = CommentBinding.inflate(
LayoutInflater.from(context), commentContainer, false
)
itemBinding.user.text = commentUsername
itemBinding.commentText.text = commentContent
}
private suspend fun retrieveComments(
api: PixelfedAPI,
credential: String,
) {
status?.id?.let {
try {
val statuses = api.statusComments(it, credential).descendants
binding.commentContainer.removeAllViews()
//Create the new views for each comment
for (status in statuses) {
addComment(binding.root.context, binding.commentContainer, status.account!!.username!!,
status.content!!
)
}
binding.commentContainer.visibility = View.VISIBLE
} catch (exception: IOException) {
Log.e("COMMENT FETCH ERROR", exception.toString())
} catch (exception: HttpException) {
Log.e("COMMENT ERROR", "${exception.code()} with body ${exception.response()?.errorBody()}")
}
}
}
private suspend fun postComment(
api: PixelfedAPI,
credential: String,
) {
val textIn = binding.editComment.text
val nonNullText = textIn.toString()
status?.id?.let {
try {
val response = api.postStatus(credential, nonNullText, it)
binding.commentIn.visibility = View.GONE
//Add the comment to the comment section
addComment(
binding.root.context, binding.commentContainer, response.account!!.username!!,
response.content!!
)
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.comment_posted).format(textIn),
Toast.LENGTH_SHORT
).show()
} catch (exception: IOException) {
Log.e("COMMENT ERROR", exception.toString())
Toast.makeText(
binding.root.context, binding.root.context.getString(R.string.comment_error),
Toast.LENGTH_SHORT
).show()
} catch (exception: HttpException) {
Toast.makeText(
binding.root.context, binding.root.context.getString(R.string.comment_error),
Toast.LENGTH_SHORT
).show()
Log.e("ERROR_CODE", exception.code().toString())
}
}
}
companion object { companion object {

View File

@ -64,8 +64,8 @@ open class Status(
{ {
companion object { companion object {
const val POST_TAG = "postTag" const val POST_TAG = "postTag"
const val DOMAIN_TAG = "domainTag" const val VIEW_COMMENTS_TAG = "view_comments_tag"
const val DISCOVER_TAG = "discoverTag" const val POST_COMMENT_TAG = "post_comment_tag"
} }
fun getPostUrl() : String? = media_attachments?.firstOrNull()?.url fun getPostUrl() : String? = media_attachments?.firstOrNull()?.url

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_comment_empty"
android:state_pressed="false" />
<item
android:drawable="@drawable/ic_comment_blue"
android:state_pressed="true"/>
</selector>

View File

@ -1,26 +1,59 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".posts.PostActivity"> tools:context=".posts.PostActivity"
android:id="@+id/scrollview">
<ScrollView <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/postFragmentSingle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:context=".posts.PostFragment"
tools:visibility="visible"/>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> <include layout="@layout/post_fragment"
android:id="@+id/postFragmentSingle"/>
<LinearLayout
android:id="@+id/commentIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/postFragmentSingle"
tools:layout_editor_absoluteX="10dp">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3">
<EditText
android:id="@+id/editComment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="@string/comment"
android:inputType="text"
android:importantForAutofill="no" />
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/submitComment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_weight="1"
android:contentDescription="@string/submit_comment"
android:src="@drawable/ic_send_blue" />
</LinearLayout>
<LinearLayout
android:id="@+id/commentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@+id/commentIn">
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@ -6,8 +6,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
xmlns:sparkbutton="http://schemas.android.com/apk/res-auto" xmlns:sparkbutton="http://schemas.android.com/apk/res-auto">
tools:context=".posts.PostFragment">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -119,7 +118,7 @@
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:padding="4dp" android:padding="4dp"
android:src="@drawable/ic_comment_empty" android:src="@drawable/selector_commenter"
app:layout_constraintBottom_toBottomOf="@+id/liker" app:layout_constraintBottom_toBottomOf="@+id/liker"
app:layout_constraintEnd_toStartOf="@id/reblogger" app:layout_constraintEnd_toStartOf="@id/reblogger"
app:layout_constraintStart_toEndOf="@id/liker" app:layout_constraintStart_toEndOf="@id/liker"
@ -227,49 +226,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/commentIn"
tools:text="3 comments" />
<LinearLayout
android:id="@+id/commentIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/postDate" app:layout_constraintTop_toBottomOf="@+id/postDate"
tools:layout_editor_absoluteX="10dp"> tools:text="3 comments" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3">
<EditText
android:id="@+id/editComment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="@string/comment"
android:inputType="text"
android:importantForAutofill="no" />
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/submitComment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_weight="1"
android:contentDescription="@string/submit_comment"
android:src="@drawable/ic_send_blue" />
</LinearLayout>
<LinearLayout
android:id="@+id/commentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@+id/viewComments">
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>