Twidere-App-Android-Twitter.../twidere/src/main/kotlin/org/mariotaku/twidere/adapter/MessagesConversationAdapter.kt

221 lines
9.0 KiB
Kotlin
Raw Normal View History

2017-02-10 07:17:48 +01:00
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.adapter
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
2017-02-14 07:30:07 +01:00
import android.view.View
2017-02-10 07:17:48 +01:00
import android.view.ViewGroup
2017-03-01 15:12:25 +01:00
import com.bumptech.glide.RequestManager
import org.apache.commons.lang3.time.DateUtils
import org.mariotaku.kpreferences.get
2017-04-28 15:44:45 +02:00
import org.mariotaku.library.objectcursor.ObjectCursor
2017-02-10 07:17:48 +01:00
import org.mariotaku.twidere.adapter.iface.IItemCountsAdapter
2017-02-14 17:26:48 +01:00
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
import org.mariotaku.twidere.annotation.PreviewStyle
import org.mariotaku.twidere.constant.linkHighlightOptionKey
import org.mariotaku.twidere.constant.mediaPreviewStyleKey
2017-02-12 15:26:09 +01:00
import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.extension.model.timestamp
2017-02-12 15:26:09 +01:00
import org.mariotaku.twidere.model.*
2017-02-10 07:17:48 +01:00
import org.mariotaku.twidere.model.ParcelableMessage.MessageType
2017-04-28 15:44:45 +02:00
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
import org.mariotaku.twidere.util.DirectMessageOnLinkClickHandler
import org.mariotaku.twidere.util.TwidereLinkify
2017-02-14 07:30:07 +01:00
import org.mariotaku.twidere.view.CardMediaContainer.OnMediaClickListener
2017-02-14 17:26:48 +01:00
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder
2017-02-10 07:17:48 +01:00
import org.mariotaku.twidere.view.holder.message.AbsMessageViewHolder
import org.mariotaku.twidere.view.holder.message.MessageViewHolder
2017-02-12 15:26:09 +01:00
import org.mariotaku.twidere.view.holder.message.NoticeSummaryEventViewHolder
2017-02-10 07:17:48 +01:00
import org.mariotaku.twidere.view.holder.message.StickerMessageViewHolder
import java.util.*
2017-02-10 07:17:48 +01:00
2017-03-01 15:12:25 +01:00
class MessagesConversationAdapter(
context: Context,
2017-03-02 07:59:19 +01:00
requestManager: RequestManager
) : LoadMoreSupportAdapter<RecyclerView.ViewHolder>(context, requestManager),
2017-02-10 07:17:48 +01:00
IItemCountsAdapter {
2017-02-14 17:26:48 +01:00
override val itemCounts: ItemCounts = ItemCounts(2)
@PreviewStyle
val mediaPreviewStyle: Int = preferences[mediaPreviewStyleKey]
val linkHighlightingStyle: Int = preferences[linkHighlightOptionKey]
2017-02-12 15:26:09 +01:00
val nameFirst: Boolean = preferences[nameFirstKey]
val linkify: TwidereLinkify = TwidereLinkify(DirectMessageOnLinkClickHandler(context, null, preferences))
2017-02-14 07:30:07 +01:00
val mediaClickListener: OnMediaClickListener = object : OnMediaClickListener {
override fun onMediaClick(view: View, current: ParcelableMedia, accountKey: UserKey?, id: Long) {
listener?.onMediaClick(id.toInt(), current, accountKey)
2017-02-14 07:30:07 +01:00
}
}
2017-02-14 17:26:48 +01:00
val messageRange: IntRange
get() {
return itemCounts.getItemStartPosition(ITEM_START_MESSAGE) until itemCounts[ITEM_START_MESSAGE]
}
2017-02-10 07:17:48 +01:00
var messages: List<ParcelableMessage>? = null
2017-02-12 15:26:09 +01:00
private set
var conversation: ParcelableMessageConversation? = null
private set
2017-02-14 07:30:07 +01:00
var listener: Listener? = null
2017-02-14 17:26:48 +01:00
var displaySenderProfile: Boolean = false
2017-02-10 07:17:48 +01:00
override var loadMoreIndicatorPosition: Long
get() = super.loadMoreIndicatorPosition
set(value) {
super.loadMoreIndicatorPosition = value
updateItemCounts()
}
2017-04-28 15:44:45 +02:00
private val calendars = Pair(Calendar.getInstance(), Calendar.getInstance())
private val reuseMessage = ParcelableMessage()
2017-02-10 07:17:48 +01:00
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
when (viewType) {
ITEM_TYPE_TEXT_MESSAGE -> {
val view = inflater.inflate(MessageViewHolder.layoutResource, parent, false)
val holder = MessageViewHolder(view, this)
holder.setup()
return holder
2017-02-10 07:17:48 +01:00
}
ITEM_TYPE_STICKER_MESSAGE -> {
val view = inflater.inflate(StickerMessageViewHolder.layoutResource, parent, false)
val holder = StickerMessageViewHolder(view, this)
holder.setup()
return holder
2017-02-10 07:17:48 +01:00
}
ITEM_TYPE_NOTICE_MESSAGE -> {
2017-02-12 15:26:09 +01:00
val view = inflater.inflate(NoticeSummaryEventViewHolder.layoutResource, parent, false)
val holder = NoticeSummaryEventViewHolder(view, this)
holder.setup()
return holder
2017-02-12 03:39:47 +01:00
}
2017-02-14 17:26:48 +01:00
ITEM_LOAD_OLDER_INDICATOR -> {
val view = inflater.inflate(LoadIndicatorViewHolder.layoutResource, parent, false)
val holder = LoadIndicatorViewHolder(view)
return holder
}
2017-02-10 07:17:48 +01:00
}
throw UnsupportedOperationException()
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder.itemViewType) {
ITEM_TYPE_TEXT_MESSAGE, ITEM_TYPE_STICKER_MESSAGE, ITEM_TYPE_NOTICE_MESSAGE -> {
2017-04-28 15:44:45 +02:00
val message = getMessage(position, true)
// Display date for oldest item
var showDate = true
// ... or if current message is > 1 day newer than previous one
if (position < itemCounts.getItemStartPosition(ITEM_START_MESSAGE)
+ itemCounts[ITEM_START_MESSAGE] - 1) {
2017-04-28 15:44:45 +02:00
calendars.first.timeInMillis = getMessageTimestamp(position + 1)
calendars.second.timeInMillis = message.timestamp
showDate = !DateUtils.isSameDay(calendars.first, calendars.second)
}
(holder as AbsMessageViewHolder).display(message, showDate)
2017-02-10 07:17:48 +01:00
}
}
}
override fun getItemCount(): Int {
return itemCounts.itemCount
}
override fun getItemViewType(position: Int): Int {
when (itemCounts.getItemCountIndex(position)) {
ITEM_START_MESSAGE -> {
2017-04-28 15:44:45 +02:00
when (getMessage(position, reuse = true).message_type) {
2017-02-10 07:17:48 +01:00
MessageType.STICKER -> {
return ITEM_TYPE_STICKER_MESSAGE
}
MessageType.CONVERSATION_CREATE, MessageType.JOIN_CONVERSATION,
MessageType.PARTICIPANTS_LEAVE, MessageType.PARTICIPANTS_JOIN,
2017-02-13 15:08:28 +01:00
MessageType.CONVERSATION_NAME_UPDATE, MessageType.CONVERSATION_AVATAR_UPDATE -> {
return ITEM_TYPE_NOTICE_MESSAGE
2017-02-12 15:26:09 +01:00
}
2017-02-10 07:17:48 +01:00
else -> return ITEM_TYPE_TEXT_MESSAGE
}
}
2017-02-14 17:26:48 +01:00
ITEM_START_LOAD_OLDER -> return ITEM_LOAD_OLDER_INDICATOR
2017-02-10 07:17:48 +01:00
}
throw UnsupportedOperationException()
}
2017-04-28 15:44:45 +02:00
fun getMessage(position: Int, reuse: Boolean = false): ParcelableMessage {
val messages = this.messages!!
val dataPosition = position - itemCounts.getItemStartPosition(ITEM_START_MESSAGE)
if (reuse && messages is ObjectCursor) {
return messages.setInto(dataPosition, reuseMessage)
}
return messages[dataPosition]
}
private fun getMessageTimestamp(position: Int): Long {
val messages = this.messages!!
if (messages is ObjectCursor) {
val cursor = messages.cursor
val indices = messages.indices
val timestamp = cursor.getLong(indices[Messages.MESSAGE_TIMESTAMP])
if (timestamp > 0) return timestamp
return cursor.getLong(indices[Messages.LOCAL_TIMESTAMP])
}
return getMessage(position, false).timestamp
2017-02-12 15:26:09 +01:00
}
fun findUser(key: UserKey): ParcelableUser? {
return conversation?.participants?.firstOrNull { it.key == key }
}
fun setData(conversation: ParcelableMessageConversation?, messages: List<ParcelableMessage>?) {
this.conversation = conversation
this.messages = messages
updateItemCounts()
2017-02-12 15:26:09 +01:00
notifyDataSetChanged()
}
private fun updateItemCounts() {
itemCounts[ITEM_START_MESSAGE] = messages?.size ?: 0
itemCounts[ITEM_START_LOAD_OLDER] = if (loadMoreIndicatorPosition and ILoadMoreSupportAdapter.START != 0L) 1 else 0
}
2017-02-14 07:30:07 +01:00
interface Listener {
2017-02-16 07:50:25 +01:00
2017-02-14 07:30:07 +01:00
fun onMediaClick(position: Int, media: ParcelableMedia, accountKey: UserKey?)
2017-02-16 07:50:25 +01:00
fun onMessageLongClick(position: Int, holder: RecyclerView.ViewHolder): Boolean
2017-02-14 07:30:07 +01:00
}
2017-02-10 07:17:48 +01:00
companion object {
private const val ITEM_START_MESSAGE = 0
2017-02-14 17:26:48 +01:00
private const val ITEM_START_LOAD_OLDER = 1
2017-02-14 17:26:48 +01:00
private const val ITEM_TYPE_TEXT_MESSAGE = 1
private const val ITEM_TYPE_STICKER_MESSAGE = 2
private const val ITEM_TYPE_NOTICE_MESSAGE = 3
private const val ITEM_LOAD_OLDER_INDICATOR = 4
2017-02-10 07:17:48 +01:00
}
2017-02-12 15:26:09 +01:00
}