chat theme change event

mark messages as important
refactoring
This commit is contained in:
2021-09-14 23:33:10 +03:00
parent 088c6c8712
commit a3a282c32c
55 changed files with 722 additions and 111 deletions
@@ -1,7 +1,10 @@
package com.meloda.fast.api
import android.content.Context
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.SpannableString
import android.text.style.StyleSpan
import androidx.core.content.ContextCompat
import com.meloda.fast.R
import com.meloda.fast.api.model.VkGroup
@@ -51,9 +54,7 @@ object VkUtils {
when (baseAttachment.getPreparedType()) {
BaseVkAttachmentItem.AttachmentType.PHOTO -> {
val photo = baseAttachment.photo ?: continue
attachments += VkPhoto(
link = photo.sizes[0].url
)
attachments += photo.asVkPhoto()
}
BaseVkAttachmentItem.AttachmentType.VIDEO -> {
val video = baseAttachment.video ?: continue
@@ -206,8 +207,6 @@ object VkUtils {
val actionUser = profiles?.get(memberId)
val actionGroup = groups?.get(memberId)
// val actionUser = profiles?.find { it.id == memberId }
// val actionGroup = groups?.find { it.id == memberId }
if (isUser && actionUser == null) return null
if (isGroup && actionGroup == null) return null
@@ -233,8 +232,6 @@ object VkUtils {
val actionUser = profiles?.get(memberId)
val actionGroup = groups?.get(memberId)
// val actionUser = profiles?.find { it.id == memberId }
// val actionGroup = groups?.find { it.id == memberId }
if (isUser && actionUser == null) return null
if (isGroup && actionGroup == null) return null
@@ -302,11 +299,257 @@ object VkUtils {
"$prefix took a screenshot"
}
VkMessage.Action.CHAT_STYLE_UPDATE -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
"$prefix changed chat theme"
}
null -> null
else -> "[${message.action}]"
}
}
fun getActionMessageText(
message: VkMessage,
youPrefix: String,
profiles: HashMap<Int, VkUser>? = null,
groups: HashMap<Int, VkGroup>? = null,
messageUser: VkUser? = null,
messageGroup: VkGroup? = null
): SpannableString? {
return when (message.getPreparedAction()) {
VkMessage.Action.CHAT_CREATE -> {
val text = message.actionText ?: return null
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix created «$text»"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
it.setSpan(
StyleSpan(Typeface.BOLD),
spanText.indexOf(text, startIndex = prefix.length),
text.length, 0
)
}
}
VkMessage.Action.CHAT_TITLE_UPDATE -> {
val text = message.actionText ?: return null
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix renamed chat to «$text»"
val startIndex = spanText.indexOf(text)
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
it.setSpan(
StyleSpan(Typeface.BOLD), startIndex, startIndex + text.length, 0
)
}
}
VkMessage.Action.CHAT_PHOTO_UPDATE -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix updated the chat photo"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
VkMessage.Action.CHAT_PHOTO_REMOVE -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix deleted the chat photo"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
VkMessage.Action.CHAT_KICK_USER -> {
val memberId = message.actionMemberId ?: return null
val isUser = memberId > 0
val isGroup = memberId < 0
val actionUser = profiles?.get(memberId)
val actionGroup = groups?.get(memberId)
if (isUser && actionUser == null) return null
if (isGroup && actionGroup == null) return null
if (memberId == message.fromId) {
val prefix = if (memberId == UserConfig.userId) youPrefix
else actionUser.toString()
val spanText = "$prefix left the chat"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
} else {
val prefix =
if (message.fromId == UserConfig.userId) youPrefix
else messageUser?.toString() ?: messageGroup?.toString() ?: "..."
val postfix =
if (memberId == UserConfig.userId) youPrefix.lowercase()
else actionUser.toString()
val spanText = "$prefix kicked $postfix"
val startIndex = spanText.indexOf(postfix)
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
it.setSpan(
StyleSpan(Typeface.BOLD), startIndex, startIndex + postfix.length, 0
)
}
}
}
VkMessage.Action.CHAT_INVITE_USER -> {
val memberId = message.actionMemberId ?: 0
val isUser = memberId > 0
val isGroup = memberId < 0
val actionUser = profiles?.get(memberId)
val actionGroup = groups?.get(memberId)
if (isUser && actionUser == null) return null
if (isGroup && actionGroup == null) return null
if (memberId == message.fromId) {
val prefix = if (memberId == UserConfig.userId) youPrefix
else actionUser.toString()
val spanText = "$prefix returned the chat"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
} else {
val prefix = if (message.fromId == UserConfig.userId) youPrefix
else messageUser?.toString() ?: messageGroup?.toString() ?: "..."
val postfix =
if (memberId == UserConfig.userId) youPrefix.lowercase()
else actionUser.toString()
val spanText = "$prefix invited $postfix"
val startIndex = spanText.indexOf(postfix)
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
it.setSpan(
StyleSpan(Typeface.BOLD), startIndex, startIndex + postfix.length, 0
)
}
}
}
VkMessage.Action.CHAT_INVITE_USER_BY_LINK -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix joined the chat via link"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
VkMessage.Action.CHAT_INVITE_USER_BY_CALL_LINK -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix joined the call via link"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
VkMessage.Action.CHAT_PIN_MESSAGE -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val actionMessage = message.actionMessage ?: return null
val spanText = "$prefix pinned message «$actionMessage»"
val startIndex = spanText.indexOf(actionMessage)
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
it.setSpan(
StyleSpan(Typeface.BOLD), startIndex, startIndex + actionMessage.length, 0
)
}
}
VkMessage.Action.CHAT_UNPIN_MESSAGE -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix unpinned message"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
VkMessage.Action.CHAT_SCREENSHOT -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isGroup() -> messageGroup?.name
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix took a screenshot"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
VkMessage.Action.CHAT_STYLE_UPDATE -> {
val prefix = when {
message.fromId == UserConfig.userId -> youPrefix
message.isUser() -> messageUser?.toString()
else -> return null
} ?: return null
val spanText = "$prefix changed chat theme"
SpannableString(spanText).also {
it.setSpan(StyleSpan(Typeface.BOLD), 0, prefix.length, 0)
}
}
null -> null
else -> SpannableString("[${message.action}]")
}
}
fun getForwardsConversationText(context: Context, message: VkMessage): String? {
if (message.forwards.isNullOrEmpty()) return null
@@ -1,18 +0,0 @@
package com.meloda.fast.api.datasource
import com.meloda.fast.api.network.repo.MessagesRepo
import com.meloda.fast.api.network.request.MessagesGetHistoryRequest
import com.meloda.fast.api.network.request.MessagesSendRequest
import com.meloda.fast.database.dao.MessagesDao
import javax.inject.Inject
class MessagesDataSource @Inject constructor(
private val repo: MessagesRepo,
private val dao: MessagesDao
) {
suspend fun getHistory(params: MessagesGetHistoryRequest) = repo.getHistory(params.map)
suspend fun send(params: MessagesSendRequest) = repo.send(params.map)
}
@@ -24,7 +24,8 @@ data class VkMessage(
val actionText: String? = null,
val actionConversationMessageId: Int? = null,
val actionMessage: String? = null,
val geoType: String? = null
val geoType: String? = null,
val important: Boolean = false
) : Parcelable {
@IgnoredOnParcel
@@ -61,7 +62,8 @@ data class VkMessage(
actionText = actionText,
actionConversationMessageId = actionConversationMessageId,
actionMessage = actionMessage,
geoType = geoType
geoType = geoType,
important = important
)
enum class Action(val value: String) {
@@ -78,7 +80,8 @@ data class VkMessage(
// TODO: 9/11/2021 catch this shit
CHAT_INVITE_USER_BY_CALL("chat_invite_user_by_call"),
CHAT_INVITE_USER_BY_CALL_LINK("chat_invite_user_by_call_join_link");
CHAT_INVITE_USER_BY_CALL_LINK("chat_invite_user_by_call_join_link"),
CHAT_STYLE_UPDATE("conversation_style_update");
companion object {
fun parse(value: String) = values().first { it.value == value }
@@ -1,3 +1,5 @@
package com.meloda.fast.api.model.attachments
abstract class VkAttachment
import android.os.Parcelable
abstract class VkAttachment : Parcelable
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkAudio(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkCall(
val initiatorId: Int
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkFile(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkGift(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkGraffiti(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkGroupCall(
val initiatorId: Int
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkLink(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkMiniApp(
val link: String
) : VkAttachment()
@@ -1,5 +1,28 @@
package com.meloda.fast.api.model.attachments
import com.meloda.fast.api.model.base.attachments.Size
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkPhoto(
val link: String
) : VkAttachment()
val albumId: Int,
val date: Int,
val id: Int,
val ownerId: Int,
val hasTags: Boolean,
val accessKey: String?,
val sizes: List<Size>,
val text: String,
val userId: Int?
) : VkAttachment() {
fun sizeOfType(type: Char): Size? {
for (size in sizes) {
if (size.type == type.toString())
return size
}
return null
}
}
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkPoll(
val id: Int
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkSticker(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkVideo(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkVoiceMessage(
val link: String
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkWall(
val id: Int
) : VkAttachment()
@@ -1,5 +1,8 @@
package com.meloda.fast.api.model.attachments
import kotlinx.parcelize.Parcelize
@Parcelize
data class VkWallReply(
val id: Int
) : VkAttachment()
@@ -46,7 +46,8 @@ data class BaseVkMessage(
actionText = action?.text,
actionConversationMessageId = action?.conversationMessageId,
actionMessage = action?.message,
geoType = geo?.type
geoType = geo?.type,
important = important
).also {
it.attachments = VkUtils.parseAttachments(attachments)
it.forwards = VkUtils.parseForwards(fwdMessages)
@@ -2,6 +2,7 @@ package com.meloda.fast.api.model.base.attachments
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import com.meloda.fast.api.model.attachments.VkPhoto
import kotlinx.parcelize.Parcelize
@Parcelize
@@ -15,12 +16,26 @@ data class BaseVkPhoto(
@SerializedName("has_tags")
val hasTags: Boolean,
@SerializedName("access_key")
val accessKey: String,
val accessKey: String?,
val sizes: List<Size>,
val text: String,
@SerializedName("user_id")
val userId: Int?
) : BaseVkAttachment()
) : BaseVkAttachment() {
fun asVkPhoto() = VkPhoto(
albumId = albumId,
date = date,
id = id,
ownerId = ownerId,
hasTags = hasTags,
accessKey = accessKey,
sizes = sizes,
text = text,
userId = userId
)
}
@Parcelize
data class Size(
@@ -1,4 +1,4 @@
package com.meloda.fast.api.network.request
package com.meloda.fast.api.model.request
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
@@ -1,4 +1,4 @@
package com.meloda.fast.api.network.request
package com.meloda.fast.api.model.request
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@@ -1,6 +1,7 @@
package com.meloda.fast.api.network.request
package com.meloda.fast.api.model.request
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
@@ -54,5 +55,19 @@ data class MessagesSendRequest(
disableMentions?.let { this["disable_mentions"] = (if (it) 1 else 0).toString() }
dontParseLinks?.let { this["dont_parse_links"] = (if (it) 1 else 0).toString() }
}
}
@Parcelize
data class MessagesMarkAsImportantRequest(
@SerializedName("message_ids")
val messagesIds: List<Int>,
val important: Boolean
) : Parcelable {
val map
get() = mutableMapOf(
"message_ids" to messagesIds.joinToString { it.toString() },
"important" to (if (important) 1 else 0).toString()
)
}
@@ -1,4 +1,4 @@
package com.meloda.fast.api.network.request
package com.meloda.fast.api.model.request
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@@ -1,4 +1,4 @@
package com.meloda.fast.api.network.response
package com.meloda.fast.api.model.response
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
@@ -1,4 +1,4 @@
package com.meloda.fast.api.network.response
package com.meloda.fast.api.model.response
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
@@ -1,4 +1,4 @@
package com.meloda.fast.api.network.response
package com.meloda.fast.api.model.response
import android.os.Parcelable
import com.meloda.fast.api.model.base.BaseVkConversation
@@ -0,0 +1,2 @@
package com.meloda.fast.api.model.response
@@ -21,6 +21,7 @@ object VKUrls {
object Messages {
const val GetHistory = "$API/messages.getHistory"
const val Send = "$API/messages.send"
const val MarkAsImportant = "$API/messages.markAsImportant"
}
@@ -1,7 +1,7 @@
package com.meloda.fast.api.datasource
package com.meloda.fast.api.network.datasource
import com.meloda.fast.api.network.repo.AuthRepo
import com.meloda.fast.api.network.request.RequestAuthDirect
import com.meloda.fast.api.model.request.RequestAuthDirect
import javax.inject.Inject
class AuthDataSource @Inject constructor(
@@ -1,8 +1,8 @@
package com.meloda.fast.api.datasource
package com.meloda.fast.api.network.datasource
import com.meloda.fast.api.model.VkConversation
import com.meloda.fast.api.network.repo.ConversationsRepo
import com.meloda.fast.api.network.request.ConversationsGetRequest
import com.meloda.fast.api.model.request.ConversationsGetRequest
import com.meloda.fast.database.dao.ConversationsDao
import javax.inject.Inject
@@ -0,0 +1,24 @@
package com.meloda.fast.api.network.datasource
import com.meloda.fast.api.model.request.MessagesGetHistoryRequest
import com.meloda.fast.api.model.request.MessagesMarkAsImportantRequest
import com.meloda.fast.api.model.request.MessagesSendRequest
import com.meloda.fast.api.network.repo.MessagesRepo
import com.meloda.fast.database.dao.MessagesDao
import javax.inject.Inject
class MessagesDataSource @Inject constructor(
private val repo: MessagesRepo,
private val dao: MessagesDao
) {
suspend fun getHistory(params: MessagesGetHistoryRequest) =
repo.getHistory(params.map)
suspend fun send(params: MessagesSendRequest) =
repo.send(params.map)
suspend fun markAsImportant(params: MessagesMarkAsImportantRequest) =
repo.markAsImportant(params.map)
}
@@ -1,8 +1,8 @@
package com.meloda.fast.api.datasource
package com.meloda.fast.api.network.datasource
import com.meloda.fast.api.model.VkUser
import com.meloda.fast.api.network.repo.UsersRepo
import com.meloda.fast.api.network.request.UsersGetRequest
import com.meloda.fast.api.model.request.UsersGetRequest
import com.meloda.fast.database.dao.UsersDao
import javax.inject.Inject
@@ -1,9 +1,9 @@
package com.meloda.fast.api.network.repo
import com.meloda.fast.api.network.VKUrls
import com.meloda.fast.api.network.response.ResponseAuthDirect
import com.meloda.fast.api.model.response.ResponseAuthDirect
import com.meloda.fast.api.network.Answer
import com.meloda.fast.api.network.response.ResponseSendSms
import com.meloda.fast.api.model.response.ResponseSendSms
import retrofit2.http.*
interface AuthRepo {
@@ -3,7 +3,7 @@ package com.meloda.fast.api.network.repo
import com.meloda.fast.api.base.ApiResponse
import com.meloda.fast.api.network.Answer
import com.meloda.fast.api.network.VKUrls
import com.meloda.fast.api.network.response.ConversationsGetResponse
import com.meloda.fast.api.model.response.ConversationsGetResponse
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
@@ -1,9 +1,9 @@
package com.meloda.fast.api.network.repo
import com.meloda.fast.api.base.ApiResponse
import com.meloda.fast.api.model.response.MessagesGetHistoryResponse
import com.meloda.fast.api.network.Answer
import com.meloda.fast.api.network.VKUrls
import com.meloda.fast.api.network.response.MessagesGetHistoryResponse
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
@@ -18,4 +18,8 @@ interface MessagesRepo {
@POST(VKUrls.Messages.Send)
suspend fun send(@FieldMap params: Map<String, String>): Answer<ApiResponse<Int>>
@FormUrlEncoded
@POST(VKUrls.Messages.MarkAsImportant)
suspend fun markAsImportant(@FieldMap params: Map<String, String>): Answer<ApiResponse<List<Int>>>
}
@@ -1,5 +0,0 @@
package com.meloda.fast.api.network.response
import android.os.Parcelable
import kotlinx.parcelize.Parcelize