AIRA-android/app/src/main/java/sushi/hardcore/aira/adapters/ChatAdapter.kt

139 lines
5.2 KiB
Kotlin
Raw Normal View History

2021-01-26 19:45:18 +01:00
package sushi.hardcore.aira.adapters
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
2021-05-05 20:54:25 +02:00
import androidx.core.view.marginEnd
import androidx.core.view.updatePadding
2021-01-26 19:45:18 +01:00
import androidx.recyclerview.widget.RecyclerView
import sushi.hardcore.aira.ChatItem
import sushi.hardcore.aira.R
class ChatAdapter(
private val context: Context,
private val onSavingFile: (filename: String, rawUuid: ByteArray) -> Unit
): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
const val BUBBLE_MARGIN = 70
}
private val inflater: LayoutInflater = LayoutInflater.from(context)
private val chatItems = mutableListOf<ChatItem>()
fun newMessage(chatItem: ChatItem) {
chatItems.add(chatItem)
notifyItemInserted(chatItems.size-1)
}
fun newLoadedMessage(chatItem: ChatItem) {
chatItems.add(0, chatItem)
notifyItemInserted(0)
}
fun clear() {
chatItems.clear()
notifyDataSetChanged()
}
internal open class BubbleViewHolder(private val context: Context, itemView: View): RecyclerView.ViewHolder(itemView) {
fun handleItemView(position: Int) {
2021-05-05 20:54:25 +02:00
itemView.updatePadding(top = if (position == 0) {
50
} else {
itemView.paddingBottom
})
2021-01-26 19:45:18 +01:00
}
fun setBubbleColor(bubble: View, outgoing: Boolean) {
if (outgoing) {
bubble.background.clearColorFilter()
} else {
bubble.background.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(context, R.color.incomingBubbleBackground), PorterDuff.Mode.SRC)
}
}
}
internal class MessageViewHolder(context: Context, itemView: View): BubbleViewHolder(context, itemView) {
fun bind(chatItem: ChatItem, position: Int) {
itemView.findViewById<TextView>(R.id.text_message).apply {
text = chatItem.data.sliceArray(1 until chatItem.data.size).decodeToString()
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
if (chatItem.outgoing) {
gravity = Gravity.END
marginStart = BUBBLE_MARGIN
} else {
gravity = Gravity.START
marginEnd = BUBBLE_MARGIN
}
}
setBubbleColor(this, chatItem.outgoing)
}
handleItemView(position)
}
}
internal class FileViewHolder(context: Context, itemView: View): BubbleViewHolder(context, itemView) {
fun bind(chatItem: ChatItem, position: Int, onSavingFile: (filename: String, rawUuid: ByteArray) -> Unit) {
val filename = chatItem.data.sliceArray(17 until chatItem.data.size).decodeToString()
itemView.findViewById<TextView>(R.id.text_filename).text = filename
itemView.findViewById<ImageButton>(R.id.button_save).setOnClickListener {
onSavingFile(filename, chatItem.data.sliceArray(1 until 17))
}
itemView.findViewById<LinearLayout>(R.id.bubble_content).apply {
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
if (chatItem.outgoing) {
gravity = Gravity.END
marginStart = BUBBLE_MARGIN
} else {
gravity = Gravity.START
marginEnd = BUBBLE_MARGIN
}
}
setBubbleColor(this, chatItem.outgoing)
}
handleItemView(position)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
ChatItem.MESSAGE -> {
val view = inflater.inflate(R.layout.adapter_chat_message, parent, false)
MessageViewHolder(context, view)
}
ChatItem.FILE -> {
val view = inflater.inflate(R.layout.adapter_chat_file, parent, false)
FileViewHolder(context, view)
}
else -> throw RuntimeException("Invalid chat item type")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val chatItem = chatItems[position]
when (chatItem.itemType) {
ChatItem.MESSAGE -> {
(holder as MessageViewHolder).bind(chatItem, position)
}
ChatItem.FILE -> {
(holder as FileViewHolder).bind(chatItem, position, onSavingFile)
}
}
}
override fun getItemCount(): Int {
return chatItems.size
}
override fun getItemViewType(position: Int): Int {
return chatItems[position].itemType
}
}