chat theme change event
mark messages as important refactoring
This commit is contained in:
@@ -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
-1
@@ -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
-1
@@ -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
|
||||
+16
-1
@@ -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
-1
@@ -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
-1
@@ -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
-1
@@ -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
-1
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -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(
|
||||
+2
-2
@@ -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)
|
||||
|
||||
}
|
||||
+2
-2
@@ -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
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.meloda.fast.database.dao.UsersDao
|
||||
VkUser::class,
|
||||
VkGroup::class
|
||||
],
|
||||
version = 15,
|
||||
version = 16,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
@@ -2,10 +2,10 @@ package com.meloda.fast.di
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.meloda.fast.api.datasource.AuthDataSource
|
||||
import com.meloda.fast.api.datasource.ConversationsDataSource
|
||||
import com.meloda.fast.api.datasource.MessagesDataSource
|
||||
import com.meloda.fast.api.datasource.UsersDataSource
|
||||
import com.meloda.fast.api.network.datasource.AuthDataSource
|
||||
import com.meloda.fast.api.network.datasource.ConversationsDataSource
|
||||
import com.meloda.fast.api.network.datasource.MessagesDataSource
|
||||
import com.meloda.fast.api.network.datasource.UsersDataSource
|
||||
import com.meloda.fast.api.network.AuthInterceptor
|
||||
import com.meloda.fast.api.network.ResultCallFactory
|
||||
import com.meloda.fast.api.network.repo.AuthRepo
|
||||
|
||||
+30
-21
@@ -9,7 +9,6 @@ import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import coil.load
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.api.UserConfig
|
||||
import com.meloda.fast.api.model.VkConversation
|
||||
@@ -27,34 +26,38 @@ class ConversationsFragment :
|
||||
BaseViewModelFragment<ConversationsViewModel>(R.layout.fragment_conversations) {
|
||||
|
||||
companion object {
|
||||
val TAG: String = ConversationsFragment::class.java.name
|
||||
const val TAG = "ConversationsFragment"
|
||||
}
|
||||
|
||||
override val viewModel: ConversationsViewModel by viewModels()
|
||||
private val binding: FragmentConversationsBinding by viewBinding()
|
||||
|
||||
private lateinit var adapter: ConversationsAdapter
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewModel.loadProfileUser()
|
||||
|
||||
prepareViews()
|
||||
|
||||
adapter = ConversationsAdapter(requireContext(), mutableListOf()).also {
|
||||
private val adapter: ConversationsAdapter by lazy {
|
||||
ConversationsAdapter(
|
||||
requireContext(),
|
||||
mutableListOf(),
|
||||
hashMapOf(),
|
||||
hashMapOf()
|
||||
).also {
|
||||
it.itemClickListener = this::onItemClick
|
||||
it.itemLongClickListener = this::onItemLongClick
|
||||
}
|
||||
}
|
||||
|
||||
private var isPaused = false
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
isPaused = true
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
prepareViews()
|
||||
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
viewModel.loadConversations()
|
||||
|
||||
binding.createChat.setOnClickListener {
|
||||
Snackbar.make(it, "Test Snackbar with action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action") {}.show()
|
||||
|
||||
}
|
||||
binding.createChat.setOnClickListener {}
|
||||
|
||||
UserConfig.vkUser.observe(viewLifecycleOwner) {
|
||||
it?.let { user -> binding.avatar.load(user.photo200) { crossfade(100) } }
|
||||
@@ -68,10 +71,16 @@ class ConversationsFragment :
|
||||
|
||||
val alpha = 1 - abs(verticalOffset * 0.01).toFloat()
|
||||
|
||||
// println("offset: $verticalOffset; alpha: $alpha")
|
||||
|
||||
binding.avatarContainer.alpha = alpha
|
||||
})
|
||||
|
||||
if (isPaused) {
|
||||
isPaused = false
|
||||
return
|
||||
}
|
||||
|
||||
viewModel.loadProfileUser()
|
||||
viewModel.loadConversations()
|
||||
}
|
||||
|
||||
override fun onEvent(event: VKEvent) {
|
||||
|
||||
@@ -3,13 +3,13 @@ package com.meloda.fast.screens.conversations
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.meloda.fast.api.UserConfig
|
||||
import com.meloda.fast.api.VKConstants
|
||||
import com.meloda.fast.api.datasource.ConversationsDataSource
|
||||
import com.meloda.fast.api.datasource.UsersDataSource
|
||||
import com.meloda.fast.api.network.datasource.ConversationsDataSource
|
||||
import com.meloda.fast.api.network.datasource.UsersDataSource
|
||||
import com.meloda.fast.api.model.VkConversation
|
||||
import com.meloda.fast.api.model.VkGroup
|
||||
import com.meloda.fast.api.model.VkUser
|
||||
import com.meloda.fast.api.network.request.ConversationsGetRequest
|
||||
import com.meloda.fast.api.network.request.UsersGetRequest
|
||||
import com.meloda.fast.api.model.request.ConversationsGetRequest
|
||||
import com.meloda.fast.api.model.request.UsersGetRequest
|
||||
import com.meloda.fast.base.viewmodel.BaseViewModel
|
||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||
|
||||
@@ -6,8 +6,8 @@ import com.meloda.fast.api.UserConfig
|
||||
import com.meloda.fast.api.VKConstants
|
||||
import com.meloda.fast.api.VKException
|
||||
import com.meloda.fast.api.VkUtils
|
||||
import com.meloda.fast.api.datasource.AuthDataSource
|
||||
import com.meloda.fast.api.network.request.RequestAuthDirect
|
||||
import com.meloda.fast.api.network.datasource.AuthDataSource
|
||||
import com.meloda.fast.api.model.request.RequestAuthDirect
|
||||
import com.meloda.fast.base.viewmodel.BaseViewModel
|
||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||
|
||||
@@ -3,19 +3,22 @@ package com.meloda.fast.screens.messages
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.appcompat.widget.LinearLayoutCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import coil.load
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.api.VkUtils
|
||||
import com.meloda.fast.api.model.VkConversation
|
||||
import com.meloda.fast.api.model.VkGroup
|
||||
import com.meloda.fast.api.model.VkMessage
|
||||
import com.meloda.fast.api.model.VkUser
|
||||
import com.meloda.fast.api.model.attachments.VkPhoto
|
||||
import com.meloda.fast.base.adapter.BaseAdapter
|
||||
import com.meloda.fast.base.adapter.BaseHolder
|
||||
import com.meloda.fast.common.AppGlobal
|
||||
import com.meloda.fast.databinding.ItemMessageInBinding
|
||||
import com.meloda.fast.databinding.ItemMessageOutBinding
|
||||
import com.meloda.fast.databinding.ItemMessageServiceBinding
|
||||
import com.meloda.fast.databinding.*
|
||||
import com.meloda.fast.util.AndroidUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -37,6 +40,15 @@ class MessagesHistoryAdapter constructor(
|
||||
if (viewType == -1) {
|
||||
getItem(position).let {
|
||||
if (it.action != null) viewType = SERVICE
|
||||
|
||||
val attachments = it.attachments ?: return@let
|
||||
if (attachments.isEmpty()) return@let
|
||||
if (VkUtils.isAttachmentsHaveOneType(attachments) &&
|
||||
attachments[0] is VkPhoto
|
||||
) {
|
||||
return if (it.isOut) ATTACHMENT_PHOTOS_OUT else ATTACHMENT_PHOTOS_IN
|
||||
}
|
||||
|
||||
if (it.isOut) viewType = OUTGOING
|
||||
if (!it.isOut) viewType = INCOMING
|
||||
}
|
||||
@@ -52,9 +64,21 @@ class MessagesHistoryAdapter constructor(
|
||||
return when (viewType) {
|
||||
HEADER -> Header(createEmptyView(60))
|
||||
FOOTER -> Footer(createEmptyView(36))
|
||||
SERVICE -> ServiceMessage(ItemMessageServiceBinding.inflate(inflater, parent, false))
|
||||
OUTGOING -> OutgoingMessage(ItemMessageOutBinding.inflate(inflater, parent, false))
|
||||
INCOMING -> IncomingMessage(ItemMessageInBinding.inflate(inflater, parent, false))
|
||||
SERVICE -> ServiceMessage(
|
||||
ItemMessageServiceBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
ATTACHMENT_PHOTOS_IN -> AttachmentPhotosIncoming(
|
||||
ItemMessageAttachmentPhotoInBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
ATTACHMENT_PHOTOS_OUT -> AttachmentPhotosOutgoing(
|
||||
ItemMessageAttachmentPhotoOutBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
OUTGOING -> OutgoingMessage(
|
||||
ItemMessageOutBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
INCOMING -> IncomingMessage(
|
||||
ItemMessageInBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
else -> Holder()
|
||||
}
|
||||
}
|
||||
@@ -83,12 +107,87 @@ class MessagesHistoryAdapter constructor(
|
||||
|
||||
inner class Footer(v: View) : Holder(v)
|
||||
|
||||
inner class AttachmentPhotosIncoming(
|
||||
private val binding: ItemMessageAttachmentPhotoInBinding
|
||||
) : Holder(binding.root) {
|
||||
|
||||
init {
|
||||
binding.photo.shapeAppearanceModel = binding.photo.shapeAppearanceModel.withCornerSize {
|
||||
AndroidUtils.px(12)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(position: Int) {
|
||||
val message = getItem(position)
|
||||
|
||||
val photo = message.attachments?.get(0) as? VkPhoto ?: return
|
||||
|
||||
val size = photo.sizeOfType('m') ?: return
|
||||
|
||||
binding.photo.layoutParams = FrameLayout.LayoutParams(
|
||||
AndroidUtils.px(size.width).roundToInt(),
|
||||
AndroidUtils.px(size.height).roundToInt()
|
||||
)
|
||||
|
||||
binding.photo.load(size.url)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class AttachmentPhotosOutgoing(
|
||||
private val binding: ItemMessageAttachmentPhotoOutBinding
|
||||
) : Holder(binding.root) {
|
||||
|
||||
init {
|
||||
binding.photo.shapeAppearanceModel = binding.photo.shapeAppearanceModel.withCornerSize {
|
||||
AndroidUtils.px(12)
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(position: Int) {
|
||||
val message = getItem(position)
|
||||
|
||||
val photo = message.attachments?.get(0) as? VkPhoto ?: return
|
||||
|
||||
val size = photo.sizeOfType('m') ?: return
|
||||
|
||||
binding.photo.layoutParams = LinearLayoutCompat.LayoutParams(
|
||||
AndroidUtils.px(size.width).roundToInt(),
|
||||
AndroidUtils.px(size.height).roundToInt()
|
||||
)
|
||||
|
||||
binding.photo.load(size.url)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class ServiceMessage(
|
||||
private val binding: ItemMessageServiceBinding
|
||||
) : Holder(binding.root) {
|
||||
|
||||
override fun bind(position: Int) {
|
||||
private val youPrefix = context.getString(R.string.you_message_prefix)
|
||||
|
||||
override fun bind(position: Int) {
|
||||
val message = getItem(position)
|
||||
|
||||
val messageUser =
|
||||
if (message.isUser()) profiles[message.fromId]
|
||||
else null
|
||||
|
||||
val messageGroup =
|
||||
if (message.isGroup()) groups[message.fromId]
|
||||
else null
|
||||
|
||||
message.action ?: return
|
||||
|
||||
binding.message.text = VkUtils.getActionMessageText(
|
||||
message = message,
|
||||
youPrefix = youPrefix,
|
||||
profiles = profiles,
|
||||
groups = groups,
|
||||
messageUser = messageUser,
|
||||
messageGroup = messageGroup
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,11 +275,14 @@ class MessagesHistoryAdapter constructor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val INCOMING = 1001
|
||||
private const val OUTGOING = 1002
|
||||
private const val SERVICE = 1003
|
||||
private const val SERVICE = 1
|
||||
private const val HEADER = 0
|
||||
private const val FOOTER = 2
|
||||
private const val INCOMING = 3
|
||||
private const val OUTGOING = 4
|
||||
|
||||
private const val ATTACHMENT_PHOTOS_IN = 101
|
||||
private const val ATTACHMENT_PHOTOS_OUT = 1011
|
||||
|
||||
private val COMPARATOR = object : DiffUtil.ItemCallback<VkMessage>() {
|
||||
override fun areItemsTheSame(
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.load
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.api.UserConfig
|
||||
import com.meloda.fast.api.model.VkConversation
|
||||
@@ -57,7 +58,10 @@ class MessagesHistoryFragment :
|
||||
}
|
||||
|
||||
private val adapter: MessagesHistoryAdapter by lazy {
|
||||
MessagesHistoryAdapter(requireContext(), mutableListOf(), conversation)
|
||||
MessagesHistoryAdapter(requireContext(), mutableListOf(), conversation).also {
|
||||
it.itemClickListener = this::onItemClick
|
||||
it.itemLongClickListener = this::onItemLongClick
|
||||
}
|
||||
}
|
||||
|
||||
private var timestampTimer: Timer? = null
|
||||
@@ -183,6 +187,7 @@ class MessagesHistoryFragment :
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun performAction() {
|
||||
if (action.value == Action.RECORD) {
|
||||
|
||||
@@ -203,7 +208,7 @@ class MessagesHistoryFragment :
|
||||
)
|
||||
|
||||
adapter.add(message)
|
||||
adapter.notifyItemRangeInserted(adapter.lastPosition - 1, 1)
|
||||
adapter.notifyDataSetChanged()
|
||||
binding.recyclerView.smoothScrollToPosition(adapter.lastPosition)
|
||||
binding.message.clear()
|
||||
|
||||
@@ -217,6 +222,7 @@ class MessagesHistoryFragment :
|
||||
|
||||
override fun onEvent(event: VKEvent) {
|
||||
when (event) {
|
||||
is MessagesMarkAsImportant -> markMessagesAsImportant(event)
|
||||
is MessagesLoaded -> refreshMessages(event)
|
||||
is StartProgressEvent -> onProgressStarted()
|
||||
is StopProgressEvent -> onProgressStopped()
|
||||
@@ -264,6 +270,19 @@ class MessagesHistoryFragment :
|
||||
}
|
||||
}
|
||||
|
||||
private fun markMessagesAsImportant(event: MessagesMarkAsImportant) {
|
||||
var changed = false
|
||||
for (i in adapter.values.indices) {
|
||||
val message = adapter.values[i]
|
||||
if (event.messagesIds.contains(message.id)) {
|
||||
if (!changed) changed = true
|
||||
adapter.values[i] = message.copy(important = event.important)
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun refreshMessages(event: MessagesLoaded) {
|
||||
adapter.profiles += event.profiles
|
||||
adapter.groups += event.groups
|
||||
@@ -282,4 +301,30 @@ class MessagesHistoryFragment :
|
||||
else binding.recyclerView.scrollToPosition(adapter.lastPosition)
|
||||
}
|
||||
|
||||
private fun onItemClick(position: Int) {
|
||||
val message = adapter.values[position]
|
||||
|
||||
val important = if (message.important) "Unmark as important" else "Mark as important"
|
||||
|
||||
val params = arrayOf(important)
|
||||
|
||||
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||
.setItems(params) { _, which ->
|
||||
if (which == 0) {
|
||||
viewModel.markAsImportant(
|
||||
messagesIds = listOf(message.id),
|
||||
important = !message.important
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
|
||||
}
|
||||
|
||||
private fun onItemLongClick(position: Int): Boolean {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.meloda.fast.screens.messages
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.meloda.fast.api.datasource.MessagesDataSource
|
||||
import com.meloda.fast.api.model.VkConversation
|
||||
import com.meloda.fast.api.model.VkGroup
|
||||
import com.meloda.fast.api.model.VkMessage
|
||||
import com.meloda.fast.api.model.VkUser
|
||||
import com.meloda.fast.api.network.request.MessagesGetHistoryRequest
|
||||
import com.meloda.fast.api.network.request.MessagesSendRequest
|
||||
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.datasource.MessagesDataSource
|
||||
import com.meloda.fast.base.viewmodel.BaseViewModel
|
||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||
@@ -109,6 +110,33 @@ class MessagesHistoryViewModel @Inject constructor(
|
||||
})
|
||||
}
|
||||
|
||||
fun markAsImportant(
|
||||
messagesIds: List<Int>,
|
||||
important: Boolean
|
||||
) = viewModelScope.launch {
|
||||
makeJob({
|
||||
dataSource.markAsImportant(
|
||||
MessagesMarkAsImportantRequest(
|
||||
messagesIds = messagesIds,
|
||||
important = important
|
||||
)
|
||||
)
|
||||
},
|
||||
onAnswer = {
|
||||
val response = it.response ?: return@makeJob
|
||||
sendEvent(
|
||||
MessagesMarkAsImportant(
|
||||
messagesIds = response,
|
||||
important = important
|
||||
)
|
||||
)
|
||||
},
|
||||
onError = {
|
||||
val throwable = it
|
||||
val i = 0
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class MessagesLoaded(
|
||||
@@ -117,4 +145,9 @@ data class MessagesLoaded(
|
||||
val messages: List<VkMessage>,
|
||||
val profiles: HashMap<Int, VkUser>,
|
||||
val groups: HashMap<Int, VkGroup>
|
||||
) : VKEvent()
|
||||
|
||||
data class MessagesMarkAsImportant(
|
||||
val messagesIds: List<Int>,
|
||||
val important: Boolean
|
||||
) : VKEvent()
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</layout>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:padding="12dp">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
</layout>
|
||||
@@ -3,15 +3,19 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="2.5dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Service" />
|
||||
android:textColor="?textColorService"
|
||||
tools:text="Service" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/nav_graph"
|
||||
app:startDestination="@id/conversationsFragment">
|
||||
|
||||
<include app:graph="@navigation/messages" />
|
||||
|
||||
</navigation>
|
||||
@@ -10,6 +10,10 @@
|
||||
@android:color/transparent
|
||||
</item>
|
||||
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
|
||||
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryVariant">@color/colorPrimaryVariant</item>
|
||||
<item name="colorOnPrimary">@color/colorOnPrimary</item>
|
||||
@@ -18,9 +22,18 @@
|
||||
<item name="colorSecondaryVariant">@color/colorSecondaryVariant</item>
|
||||
<item name="colorOnSecondary">@color/colorOnSecondary</item>
|
||||
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
<item name="colorSecondary2">@color/colorSecondary2</item>
|
||||
<item name="colorSecondary2Variant">@color/colorSecondary2Variant</item>
|
||||
<item name="colorOnSecondary2">@color/colorOnSecondary2</item>
|
||||
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
|
||||
<item name="colorSecondary3">@color/colorSecondary3</item>
|
||||
<item name="colorSecondary3Variant">@color/colorSecondary3Variant</item>
|
||||
<item name="colorOnSecondary3">@color/colorOnSecondary3</item>
|
||||
|
||||
<item name="textColorPrimary">@color/textColorPrimary</item>
|
||||
<item name="textColorSecondary">@color/textColorSecondary</item>
|
||||
<item name="textColorSecondaryVariant">@color/textColorSecondaryVariant</item>
|
||||
<item name="textColorService">@color/textColorService</item>
|
||||
|
||||
<item name="dialogCornerRadius">12dp</item>
|
||||
</style>
|
||||
|
||||
@@ -25,5 +25,6 @@
|
||||
<color name="n2_10">@android:color/system_neutral2_10</color>
|
||||
<color name="n2_100">@android:color/system_neutral2_100</color>
|
||||
<color name="n2_500">@android:color/system_neutral2_500</color>
|
||||
<color name="n2_600">@android:color/system_neutral2_600</color>
|
||||
|
||||
</resources>
|
||||
@@ -1,9 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<attr name="textColorPrimary" format="color"/>
|
||||
<attr name="textColorSecondary" format="color"/>
|
||||
<attr name="textColorSecondaryVariant" format="color"/>
|
||||
<attr name="textColorPrimary" format="color" />
|
||||
<attr name="textColorSecondary" format="color" />
|
||||
<attr name="textColorSecondaryVariant" format="color" />
|
||||
<attr name="textColorService" format="color" />
|
||||
|
||||
<attr name="colorSecondary2" format="color" />
|
||||
<attr name="colorSecondary2Variant" format="color" />
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<color name="textColorPrimary">@color/n1_900</color>
|
||||
<color name="textColorSecondary">@color/n1_900</color>
|
||||
<color name="textColorSecondaryVariant">@color/n2_500</color>
|
||||
<color name="textColorService">@color/n2_600</color>
|
||||
|
||||
<color name="colorSurface">@color/a1_0</color>
|
||||
|
||||
@@ -50,5 +51,6 @@
|
||||
<color name="n2_10">#FDFBFE</color>
|
||||
<color name="n2_100">#E0E2EB</color>
|
||||
<color name="n2_500">#74767D</color>
|
||||
<color name="n2_600">#5C5E65</color>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<item name="textColorPrimary">@color/textColorPrimary</item>
|
||||
<item name="textColorSecondary">@color/textColorSecondary</item>
|
||||
<item name="textColorSecondaryVariant">@color/textColorSecondaryVariant</item>
|
||||
<item name="textColorService">@color/textColorService</item>
|
||||
|
||||
<item name="colorSurface">@color/colorSurface</item>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user