fixed participants after leave_conversation event
This commit is contained in:
parent
f29e2f47c7
commit
09b033fb06
|
@ -13,6 +13,7 @@ import org.mariotaku.twidere.model.message.conversation.DefaultConversationExtra
|
|||
import org.mariotaku.twidere.model.message.conversation.TwitterOfficialConversationExtras
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper
|
||||
import org.mariotaku.twidere.util.UserColorNameManager
|
||||
import java.util.*
|
||||
|
||||
fun ParcelableMessageConversation.applyFrom(message: ParcelableMessage, details: AccountDetails) {
|
||||
account_key = details.key
|
||||
|
@ -34,46 +35,6 @@ fun ParcelableMessageConversation.applyFrom(message: ParcelableMessage, details:
|
|||
val ParcelableMessageConversation.timestamp: Long
|
||||
get() = if (message_timestamp > 0) message_timestamp else local_timestamp
|
||||
|
||||
fun ParcelableMessageConversation.getTitle(context: Context, manager: UserColorNameManager,
|
||||
nameFirst: Boolean): Pair<String, String?> {
|
||||
if (conversation_type == ConversationType.ONE_TO_ONE) {
|
||||
val user = this.user ?: return Pair(context.getString(R.string.title_direct_messages), null)
|
||||
return Pair(user.name, "@${user.screen_name}")
|
||||
}
|
||||
if (conversation_name != null) {
|
||||
return Pair(conversation_name, null)
|
||||
}
|
||||
return Pair(participants.joinToString(separator = ", ") { manager.getDisplayName(it, nameFirst) }, null)
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.getSubtitle(context: Context): String? {
|
||||
if (conversation_type == ConversationType.ONE_TO_ONE) {
|
||||
val user = this.user ?: return null
|
||||
return "@${user.screen_name}"
|
||||
}
|
||||
val resources = context.resources
|
||||
return resources.getQuantityString(R.plurals.N_message_participants, participants.size,
|
||||
participants.size)
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.getSummaryText(context: Context, manager: UserColorNameManager,
|
||||
nameFirst: Boolean): CharSequence? {
|
||||
return getSummaryText(context, manager, nameFirst, message_type, message_extras, sender_key,
|
||||
text_unescaped, this)
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.displayAvatarTo(mediaLoader: MediaLoaderWrapper, view: ImageView) {
|
||||
if (conversation_type == ConversationType.ONE_TO_ONE) {
|
||||
val user = this.user
|
||||
if (user != null) {
|
||||
mediaLoader.displayProfileImage(view, user)
|
||||
} else {
|
||||
mediaLoader.displayProfileImage(view, null)
|
||||
}
|
||||
} else {
|
||||
mediaLoader.displayGroupConversationAvatar(view, conversation_avatar)
|
||||
}
|
||||
}
|
||||
|
||||
val ParcelableMessageConversation.user: ParcelableUser?
|
||||
get() {
|
||||
|
@ -121,4 +82,66 @@ var ParcelableMessageConversation.notificationDisabled: Boolean
|
|||
extras.notificationsDisabled = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.getTitle(context: Context, manager: UserColorNameManager,
|
||||
nameFirst: Boolean): Pair<String, String?> {
|
||||
if (conversation_type == ConversationType.ONE_TO_ONE) {
|
||||
val user = this.user ?: return Pair(context.getString(R.string.title_direct_messages), null)
|
||||
return Pair(user.name, "@${user.screen_name}")
|
||||
}
|
||||
if (conversation_name != null) {
|
||||
return Pair(conversation_name, null)
|
||||
}
|
||||
return Pair(participants.joinToString(separator = ", ") { manager.getDisplayName(it, nameFirst) }, null)
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.getSubtitle(context: Context): String? {
|
||||
if (conversation_type == ConversationType.ONE_TO_ONE) {
|
||||
val user = this.user ?: return null
|
||||
return "@${user.screen_name}"
|
||||
}
|
||||
val resources = context.resources
|
||||
return resources.getQuantityString(R.plurals.N_message_participants, participants.size,
|
||||
participants.size)
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.getSummaryText(context: Context, manager: UserColorNameManager,
|
||||
nameFirst: Boolean): CharSequence? {
|
||||
return getSummaryText(context, manager, nameFirst, message_type, message_extras, sender_key,
|
||||
text_unescaped, this)
|
||||
}
|
||||
|
||||
fun ParcelableMessageConversation.displayAvatarTo(mediaLoader: MediaLoaderWrapper, view: ImageView) {
|
||||
if (conversation_type == ConversationType.ONE_TO_ONE) {
|
||||
val user = this.user
|
||||
if (user != null) {
|
||||
mediaLoader.displayProfileImage(view, user)
|
||||
} else {
|
||||
mediaLoader.displayProfileImage(view, null)
|
||||
}
|
||||
} else {
|
||||
mediaLoader.displayGroupConversationAvatar(view, conversation_avatar)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun ParcelableMessageConversation.addParticipants(users: Collection<ParcelableUser>) {
|
||||
val participants = this.participants
|
||||
if (participants == null) {
|
||||
this.participants = arrayOf(user)
|
||||
} else {
|
||||
val addingUsers = ArrayList<ParcelableUser>()
|
||||
users.forEach { user ->
|
||||
val index = participants.indexOfFirst { it.key == user.key }
|
||||
if (index >= 0) {
|
||||
participants[index] = user
|
||||
} else {
|
||||
addingUsers += user
|
||||
}
|
||||
}
|
||||
this.participants += addingUsers
|
||||
}
|
||||
this.participant_keys = this.participants.map(ParcelableUser::key).toTypedArray()
|
||||
this.participants.sortBy(ParcelableUser::screen_name)
|
||||
}
|
||||
|
|
|
@ -242,7 +242,7 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment,
|
|||
private fun performAddParticipant(user: ParcelableUser) {
|
||||
ProgressDialogFragment.show(childFragmentManager, "add_participant_progress")
|
||||
val weakThis = WeakReference(this)
|
||||
val task = AddParticipantsTask(context, accountKey, conversationId, arrayOf(user.key.id))
|
||||
val task = AddParticipantsTask(context, accountKey, conversationId, listOf(user))
|
||||
task.callback = callback@ { succeed ->
|
||||
val f = weakThis.get() ?: return@callback
|
||||
f.dismissAlertDialogThen("add_participant_progress") {}
|
||||
|
|
|
@ -24,12 +24,15 @@ import android.content.Context
|
|||
import org.mariotaku.microblog.library.MicroBlog
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.extension.model.addParticipants
|
||||
import org.mariotaku.twidere.extension.model.isOfficial
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.model.AccountDetails
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.util.AccountUtils
|
||||
import org.mariotaku.twidere.task.ExceptionHandlingAbstractTask
|
||||
import org.mariotaku.twidere.util.DataStoreUtils
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/2/25.
|
||||
|
@ -39,14 +42,21 @@ class AddParticipantsTask(
|
|||
context: Context,
|
||||
val accountKey: UserKey,
|
||||
val conversationId: String,
|
||||
val participantIds: Array<String>
|
||||
val participants: Collection<ParcelableUser>
|
||||
) : ExceptionHandlingAbstractTask<Unit?, Boolean, MicroBlogException, ((Boolean) -> Unit)?>(context) {
|
||||
override fun onExecute(params: Unit?): Boolean {
|
||||
val account = AccountUtils.getAccountDetails(AccountManager.get(context), accountKey, true) ?:
|
||||
throw MicroBlogException("No account")
|
||||
val conversation = DataStoreUtils.findMessageConversation(context, accountKey, conversationId)
|
||||
if (conversation != null && conversation.is_temp) {
|
||||
val addData = GetMessagesTask.DatabaseUpdateData(listOf(conversation), emptyList())
|
||||
conversation.addParticipants(participants)
|
||||
GetMessagesTask.storeMessages(context, addData, account, showNotification = false)
|
||||
return true
|
||||
}
|
||||
val microBlog = account.newMicroBlogInstance(context, cls = MicroBlog::class.java)
|
||||
val addData = requestAddParticipants(microBlog, account)
|
||||
GetMessagesTask.storeMessages(context, addData, account)
|
||||
GetMessagesTask.storeMessages(context, addData, account, showNotification = false)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -59,7 +69,8 @@ class AddParticipantsTask(
|
|||
when (account.type) {
|
||||
AccountType.TWITTER -> {
|
||||
if (account.isOfficial(context)) {
|
||||
val response = microBlog.addParticipants(conversationId, participantIds);
|
||||
val ids = participants.map { it.key.id }.toTypedArray()
|
||||
val response = microBlog.addParticipants(conversationId, ids)
|
||||
return GetMessagesTask.createDatabaseUpdateData(context, account, response)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,12 @@ import org.mariotaku.ktextension.useCursor
|
|||
import org.mariotaku.microblog.library.MicroBlog
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.twitter.model.DMResponse
|
||||
import org.mariotaku.microblog.library.twitter.model.DirectMessage
|
||||
import org.mariotaku.microblog.library.twitter.model.Paging
|
||||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.twidere.TwidereConstants.QUERY_PARAM_SHOW_NOTIFICATION
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.extension.model.applyFrom
|
||||
import org.mariotaku.twidere.extension.model.isOfficial
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.extension.model.timestamp
|
||||
import org.mariotaku.twidere.extension.model.*
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
|
||||
import org.mariotaku.twidere.model.event.GetMessagesTaskEvent
|
||||
|
@ -46,7 +43,6 @@ import org.mariotaku.twidere.model.util.AccountUtils
|
|||
import org.mariotaku.twidere.model.util.AccountUtils.getAccountDetails
|
||||
import org.mariotaku.twidere.model.util.ParcelableMessageUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
||||
import org.mariotaku.twidere.model.util.UserKeyUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
|
||||
import org.mariotaku.twidere.task.BaseAbstractTask
|
||||
|
@ -163,30 +159,15 @@ class GetMessagesTask(
|
|||
conversations.addLocalConversations(context, accountKey, conversationIds)
|
||||
|
||||
received.forEachIndexed { i, dm ->
|
||||
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, false,
|
||||
1.0 - (i.toDouble() / received.size))
|
||||
insertMessages.add(message)
|
||||
val conversation = conversations.addConversation(message.conversation_id, details,
|
||||
message, setOf(dm.sender, dm.recipient)) ?: return@forEachIndexed
|
||||
conversation.conversation_extras_type = ParcelableMessageConversation.ExtrasType.DEFAULT
|
||||
if (conversation.conversation_extras == null) {
|
||||
conversation.conversation_extras = DefaultConversationExtras()
|
||||
}
|
||||
addConversationMessage(insertMessages, conversations, details, dm, i, received.size, false)
|
||||
}
|
||||
sent.forEachIndexed { i, dm ->
|
||||
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, true,
|
||||
1.0 - (i.toDouble() / sent.size))
|
||||
insertMessages.add(message)
|
||||
val conversation = conversations.addConversation(message.conversation_id, details,
|
||||
message, setOf(dm.sender, dm.recipient)) ?: return@forEachIndexed
|
||||
conversation.conversation_extras_type = ParcelableMessageConversation.ExtrasType.DEFAULT
|
||||
if (conversation.conversation_extras == null) {
|
||||
conversation.conversation_extras = DefaultConversationExtras()
|
||||
}
|
||||
addConversationMessage(insertMessages, conversations, details, dm, i, sent.size, true)
|
||||
}
|
||||
return DatabaseUpdateData(conversations.values, insertMessages)
|
||||
}
|
||||
|
||||
|
||||
private fun getTwitterOfficialConversation(microBlog: MicroBlog, details: AccountDetails,
|
||||
conversationId: String, param: RefreshMessagesTaskParam, index: Int): DatabaseUpdateData {
|
||||
val maxId = param.maxIds?.get(index) ?: return DatabaseUpdateData(emptyList(), emptyList())
|
||||
|
@ -235,8 +216,10 @@ class GetMessagesTask(
|
|||
// Sender is our self, treat as outgoing message
|
||||
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, dm.senderId == accountKey.id,
|
||||
1.0 - (i.toDouble() / result.size))
|
||||
val sender = ParcelableUserUtils.fromUser(dm.sender, accountKey)
|
||||
val recipient = ParcelableUserUtils.fromUser(dm.recipient, accountKey)
|
||||
val mc = conversations.addConversation(message.conversation_id, details, message,
|
||||
setOf(dm.sender, dm.recipient))
|
||||
setOf(sender, recipient))
|
||||
mc?.request_cursor = "page:$page"
|
||||
}
|
||||
return DatabaseUpdateData(conversations.values, emptyList())
|
||||
|
@ -365,7 +348,7 @@ class GetMessagesTask(
|
|||
|
||||
val conversations = hashMapOf<String, ParcelableMessageConversation>()
|
||||
|
||||
conversations.addLocalConversations(context, account.key, respConversations.keys)
|
||||
conversations.addLocalConversations(context, accountKey, respConversations.keys)
|
||||
val messages = ArrayList<ParcelableMessage>()
|
||||
val messageDeletionsMap = HashMap<String, ArrayList<String>>()
|
||||
val conversationDeletions = ArrayList<String>()
|
||||
|
@ -383,23 +366,27 @@ class GetMessagesTask(
|
|||
return@mapNotNullTo null
|
||||
}
|
||||
else -> {
|
||||
return@mapNotNullTo ParcelableMessageUtils.fromEntry(account.key, entry, respUsers)
|
||||
return@mapNotNullTo ParcelableMessageUtils.fromEntry(accountKey, entry, respUsers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val messagesMap = messages.groupBy(ParcelableMessage::conversation_id)
|
||||
|
||||
conversations.addLocalConversations(context, accountKey, messagesMap.keys)
|
||||
|
||||
for ((k, v) in respConversations) {
|
||||
val recentMessage = messagesMap[k]?.maxBy(ParcelableMessage::message_timestamp)
|
||||
val participants = respUsers.filterKeys { userId ->
|
||||
v.participants.any { it.userId == userId }
|
||||
}.values
|
||||
}.values.map { ParcelableUserUtils.fromUser(it, accountKey) }
|
||||
val conversationType = when (v.type?.toUpperCase(Locale.US)) {
|
||||
DMResponse.Conversation.Type.ONE_TO_ONE -> ConversationType.ONE_TO_ONE
|
||||
DMResponse.Conversation.Type.GROUP_DM -> ConversationType.GROUP
|
||||
else -> ConversationType.ONE_TO_ONE
|
||||
}
|
||||
val conversation = conversations.addConversation(k, account, recentMessage, participants,
|
||||
conversationType) ?: continue
|
||||
false, conversationType) ?: continue
|
||||
if (conversation.id in conversationDeletions) continue
|
||||
conversation.conversation_name = v.name
|
||||
conversation.conversation_avatar = v.avatarImageHttps
|
||||
|
@ -482,9 +469,10 @@ class GetMessagesTask(
|
|||
@SuppressLint("Recycle")
|
||||
internal fun MutableMap<String, ParcelableMessageConversation>.addLocalConversations(context: Context,
|
||||
accountKey: UserKey, conversationIds: Set<String>) {
|
||||
val where = Expression.and(Expression.inArgs(Conversations.CONVERSATION_ID, conversationIds.size),
|
||||
val newIds = conversationIds.filterNot { it in this.keys }
|
||||
val where = Expression.and(Expression.inArgs(Conversations.CONVERSATION_ID, newIds.size),
|
||||
Expression.equalsArgs(Conversations.ACCOUNT_KEY)).sql
|
||||
val whereArgs = conversationIds.toTypedArray() + accountKey.toString()
|
||||
val whereArgs = newIds.toTypedArray() + accountKey.toString()
|
||||
return context.contentResolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS,
|
||||
where, whereArgs, null).useCursor { cur ->
|
||||
val indices = ParcelableMessageConversationCursorIndices(cur)
|
||||
|
@ -507,26 +495,6 @@ class GetMessagesTask(
|
|||
}
|
||||
|
||||
|
||||
private fun ParcelableMessageConversation.addParticipant(
|
||||
accountKey: UserKey,
|
||||
user: User
|
||||
) {
|
||||
val userKey = UserKeyUtils.fromUser(user)
|
||||
val participants = this.participants
|
||||
if (participants == null) {
|
||||
this.participants = arrayOf(ParcelableUserUtils.fromUser(user, accountKey))
|
||||
} else {
|
||||
val index = participants.indexOfFirst { it.key == userKey }
|
||||
if (index >= 0) {
|
||||
participants[index] = ParcelableUserUtils.fromUser(user, accountKey)
|
||||
} else {
|
||||
this.participants = participants + ParcelableUserUtils.fromUser(user, accountKey)
|
||||
}
|
||||
}
|
||||
this.participant_keys = this.participants.map(ParcelableUser::key).toTypedArray()
|
||||
this.participants.sortBy(ParcelableUser::screen_name)
|
||||
}
|
||||
|
||||
private fun Map<String, List<ParcelableMessage>>.findLastReadTimestamp(conversationId: String, lastReadEventId: String?): Long {
|
||||
val longEventId = lastReadEventId.toLong(-1)
|
||||
return this[conversationId]?.filter { message ->
|
||||
|
@ -536,11 +504,12 @@ class GetMessagesTask(
|
|||
}?.maxBy(ParcelableMessage::message_timestamp)?.message_timestamp ?: -1
|
||||
}
|
||||
|
||||
internal fun MutableMap<String, ParcelableMessageConversation>.addConversation(
|
||||
fun MutableMap<String, ParcelableMessageConversation>.addConversation(
|
||||
conversationId: String,
|
||||
details: AccountDetails,
|
||||
message: ParcelableMessage?,
|
||||
users: Collection<User>,
|
||||
users: Collection<ParcelableUser>,
|
||||
addUsers: Boolean = false,
|
||||
conversationType: String = ConversationType.ONE_TO_ONE
|
||||
): ParcelableMessageConversation? {
|
||||
val conversation = this[conversationId] ?: run {
|
||||
|
@ -555,12 +524,31 @@ class GetMessagesTask(
|
|||
if (message != null && message.timestamp > conversation.timestamp) {
|
||||
conversation.applyFrom(message, details)
|
||||
}
|
||||
users.forEach { user ->
|
||||
conversation.addParticipant(details.key, user)
|
||||
if (addUsers) {
|
||||
conversation.addParticipants(users)
|
||||
} else {
|
||||
conversation.participants = users.toTypedArray()
|
||||
conversation.participant_keys = users.map(ParcelableUser::key).toTypedArray()
|
||||
}
|
||||
return conversation
|
||||
}
|
||||
|
||||
internal fun addConversationMessage(messages: MutableCollection<ParcelableMessage>,
|
||||
conversations: MutableMap<String, ParcelableMessageConversation>,
|
||||
details: AccountDetails, dm: DirectMessage, index: Int, size: Int, outgoing: Boolean) {
|
||||
val accountKey = details.key
|
||||
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, outgoing,
|
||||
1.0 - (index.toDouble() / size))
|
||||
messages.add(message)
|
||||
val sender = ParcelableUserUtils.fromUser(dm.sender, accountKey)
|
||||
val recipient = ParcelableUserUtils.fromUser(dm.recipient, accountKey)
|
||||
val conversation = conversations.addConversation(message.conversation_id, details,
|
||||
message, setOf(sender, recipient)) ?: return
|
||||
conversation.conversation_extras_type = ParcelableMessageConversation.ExtrasType.DEFAULT
|
||||
if (conversation.conversation_extras == null) {
|
||||
conversation.conversation_extras = DefaultConversationExtras()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.mariotaku.twidere.model.ParcelableMessageConversation
|
|||
import org.mariotaku.twidere.model.ParcelableNewMessage
|
||||
import org.mariotaku.twidere.model.event.SendMessageTaskEvent
|
||||
import org.mariotaku.twidere.model.util.ParcelableMessageUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
|
||||
import org.mariotaku.twidere.task.ExceptionHandlingAbstractTask
|
||||
import org.mariotaku.twidere.task.twitter.UpdateStatusTask
|
||||
|
@ -142,7 +143,9 @@ class SendMessageTask(
|
|||
val conversations = hashMapOf<String, ParcelableMessageConversation>()
|
||||
conversations.addLocalConversations(context, accountKey, conversationIds)
|
||||
val message = ParcelableMessageUtils.fromMessage(accountKey, dm, true)
|
||||
conversations.addConversation(message.conversation_id, details, message, setOf(dm.sender, dm.recipient))
|
||||
val sender = ParcelableUserUtils.fromUser(dm.sender, accountKey)
|
||||
val recipient = ParcelableUserUtils.fromUser(dm.recipient, accountKey)
|
||||
conversations.addConversation(message.conversation_id, details, message, setOf(sender, recipient), true)
|
||||
return GetMessagesTask.DatabaseUpdateData(conversations.values, listOf(message))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue