refactor: split message transport actions
This commit is contained in:
-204
@@ -1,12 +1,6 @@
|
|||||||
package dev.meloda.fast.messageshistory
|
package dev.meloda.fast.messageshistory
|
||||||
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.TextRange
|
import androidx.compose.ui.text.TextRange
|
||||||
@@ -15,21 +9,12 @@ import androidx.compose.ui.text.font.FontStyle
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.core.graphics.drawable.toBitmapOrNull
|
|
||||||
import coil.imageLoader
|
|
||||||
import coil.request.ImageRequest
|
|
||||||
import com.conena.nanokt.collections.indexOfFirstOrNull
|
|
||||||
import dev.meloda.fast.common.extensions.listenValue
|
import dev.meloda.fast.common.extensions.listenValue
|
||||||
import dev.meloda.fast.common.extensions.orDots
|
|
||||||
import dev.meloda.fast.common.extensions.removeIfCompat
|
import dev.meloda.fast.common.extensions.removeIfCompat
|
||||||
import dev.meloda.fast.common.extensions.setValue
|
import dev.meloda.fast.common.extensions.setValue
|
||||||
import dev.meloda.fast.common.provider.ResourceProvider
|
import dev.meloda.fast.common.provider.ResourceProvider
|
||||||
import dev.meloda.fast.data.State
|
|
||||||
import dev.meloda.fast.data.UserConfig
|
import dev.meloda.fast.data.UserConfig
|
||||||
import dev.meloda.fast.data.VkMemoryCache
|
import dev.meloda.fast.data.VkMemoryCache
|
||||||
import dev.meloda.fast.data.VkUtils
|
|
||||||
import dev.meloda.fast.data.processState
|
|
||||||
import dev.meloda.fast.domain.MessagesUseCase
|
import dev.meloda.fast.domain.MessagesUseCase
|
||||||
import dev.meloda.fast.domain.util.extractReplySummary
|
import dev.meloda.fast.domain.util.extractReplySummary
|
||||||
import dev.meloda.fast.domain.util.extractReplyTitle
|
import dev.meloda.fast.domain.util.extractReplyTitle
|
||||||
@@ -37,32 +22,22 @@ import dev.meloda.fast.domain.util.extractTitle
|
|||||||
import dev.meloda.fast.messageshistory.model.ActionMode
|
import dev.meloda.fast.messageshistory.model.ActionMode
|
||||||
import dev.meloda.fast.messageshistory.model.MessageDialog
|
import dev.meloda.fast.messageshistory.model.MessageDialog
|
||||||
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
|
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
|
||||||
import dev.meloda.fast.model.BaseError
|
|
||||||
import dev.meloda.fast.model.api.domain.FormatDataType
|
import dev.meloda.fast.model.api.domain.FormatDataType
|
||||||
import dev.meloda.fast.model.api.domain.VkMessage
|
import dev.meloda.fast.model.api.domain.VkMessage
|
||||||
import dev.meloda.fast.model.api.domain.VkPhotoDomain
|
|
||||||
import dev.meloda.fast.ui.R
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.add
|
import kotlinx.serialization.json.add
|
||||||
import kotlinx.serialization.json.buildJsonArray
|
import kotlinx.serialization.json.buildJsonArray
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
import kotlinx.serialization.json.put
|
import kotlinx.serialization.json.put
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
internal class MessagesHistoryMessageActions(
|
internal class MessagesHistoryMessageActions(
|
||||||
private val applicationContext: Context,
|
|
||||||
private val viewModelScope: CoroutineScope,
|
private val viewModelScope: CoroutineScope,
|
||||||
private val messagesUseCase: MessagesUseCase,
|
private val messagesUseCase: MessagesUseCase,
|
||||||
private val resourceProvider: ResourceProvider,
|
private val resourceProvider: ResourceProvider,
|
||||||
private val screenState: MutableStateFlow<MessagesHistoryScreenState>,
|
private val screenState: MutableStateFlow<MessagesHistoryScreenState>,
|
||||||
private val messages: MutableStateFlow<List<VkMessage>>,
|
private val messages: MutableStateFlow<List<VkMessage>>,
|
||||||
private val baseError: MutableStateFlow<BaseError?>,
|
|
||||||
private val showKeyboard: MutableStateFlow<Boolean>,
|
private val showKeyboard: MutableStateFlow<Boolean>,
|
||||||
private val dialog: MutableStateFlow<MessageDialog?>,
|
private val dialog: MutableStateFlow<MessageDialog?>,
|
||||||
private val syncUiMessages: () -> Unit,
|
private val syncUiMessages: () -> Unit,
|
||||||
@@ -285,180 +260,6 @@ internal class MessagesHistoryMessageActions(
|
|||||||
Log.d("MessagesHistoryViewModelImpl", "editMessage: $newMessage")
|
Log.d("MessagesHistoryViewModelImpl", "editMessage: $newMessage")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun markAsImportant(messageIds: List<Long>, important: Boolean) {
|
|
||||||
messagesUseCase.markAsImportant(
|
|
||||||
peerId = screenState.value.convoId,
|
|
||||||
messageIds = messageIds,
|
|
||||||
important = important
|
|
||||||
).listenValue(viewModelScope) { state ->
|
|
||||||
state.processState(
|
|
||||||
error = ::handleError,
|
|
||||||
success = {
|
|
||||||
val newMessages = messages.value
|
|
||||||
.toMutableList()
|
|
||||||
.map { message ->
|
|
||||||
if (message.id in messageIds) {
|
|
||||||
message.copy(isImportant = important)
|
|
||||||
} else {
|
|
||||||
message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
messages.setValue { newMessages }
|
|
||||||
syncUiMessages()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteMessage(
|
|
||||||
messageIds: List<Long>,
|
|
||||||
spam: Boolean = false,
|
|
||||||
deleteForAll: Boolean = false,
|
|
||||||
onSuccess: () -> Unit = {}
|
|
||||||
) {
|
|
||||||
messagesUseCase.delete(
|
|
||||||
peerId = screenState.value.convoId,
|
|
||||||
messageIds = messageIds,
|
|
||||||
spam = spam,
|
|
||||||
deleteForAll = deleteForAll
|
|
||||||
).listenValue(viewModelScope) { state ->
|
|
||||||
state.processState(
|
|
||||||
error = ::handleError,
|
|
||||||
success = {
|
|
||||||
onSuccess()
|
|
||||||
val newMessages = messages.value.toMutableList()
|
|
||||||
val messagesToDelete = newMessages.filter { it.id in messageIds }
|
|
||||||
newMessages.removeAll(messagesToDelete)
|
|
||||||
messages.setValue { newMessages }
|
|
||||||
syncUiMessages()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pinMessage(messageId: Long) {
|
|
||||||
messagesUseCase.pin(
|
|
||||||
peerId = screenState.value.convoId,
|
|
||||||
messageId = messageId,
|
|
||||||
cmId = null
|
|
||||||
).listenValue(viewModelScope) { state ->
|
|
||||||
state.processState(
|
|
||||||
error = ::handleError,
|
|
||||||
success = { pinnedMessage ->
|
|
||||||
onPinnedMessageChanged(pinnedMessage)
|
|
||||||
|
|
||||||
val newMessages = messages.value.toMutableList()
|
|
||||||
val index = newMessages.indexOfFirstOrNull { it.id == messageId }
|
|
||||||
if (index != null) {
|
|
||||||
newMessages[index] = pinnedMessage
|
|
||||||
messages.setValue { newMessages }
|
|
||||||
syncUiMessages()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unpinMessage(messageId: Long) {
|
|
||||||
messagesUseCase.unpin(screenState.value.convoId)
|
|
||||||
.listenValue(viewModelScope) { state ->
|
|
||||||
state.processState(
|
|
||||||
error = ::handleError,
|
|
||||||
success = {
|
|
||||||
val newMessages = messages.value.toMutableList()
|
|
||||||
val index = newMessages.indexOfFirstOrNull { it.id == messageId }
|
|
||||||
if (index != null) {
|
|
||||||
newMessages[index] = newMessages[index].copy(isPinned = false)
|
|
||||||
messages.setValue { newMessages }
|
|
||||||
syncUiMessages()
|
|
||||||
}
|
|
||||||
|
|
||||||
onPinnedMessageChanged(null)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun readMessage(message: VkMessage) {
|
|
||||||
messagesUseCase.markAsRead(
|
|
||||||
peerId = screenState.value.convoId,
|
|
||||||
startMessageId = message.id
|
|
||||||
).listenValue(viewModelScope) { state ->
|
|
||||||
state.processState(
|
|
||||||
error = ::handleError,
|
|
||||||
success = {
|
|
||||||
val oldConvo = screenState.value.convo
|
|
||||||
val newConvo = oldConvo.copy(
|
|
||||||
inRead = if (!message.isOut) message.id else oldConvo.inRead,
|
|
||||||
outRead = if (message.isOut) message.id else oldConvo.outRead
|
|
||||||
)
|
|
||||||
|
|
||||||
screenState.setValue { old ->
|
|
||||||
old.copy(convo = newConvo)
|
|
||||||
}
|
|
||||||
|
|
||||||
syncUiMessages()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyMessage(message: VkMessage) {
|
|
||||||
val clipboardManager =
|
|
||||||
applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
|
|
||||||
val messageToCopy = message.text.orEmpty().trim()
|
|
||||||
if (messageToCopy.isEmpty()) {
|
|
||||||
val photo = with(message.attachments.orEmpty()) {
|
|
||||||
if (size == 1 && all { it is VkPhotoDomain }) {
|
|
||||||
first() as? VkPhotoDomain
|
|
||||||
} else null
|
|
||||||
} ?: return
|
|
||||||
|
|
||||||
val photoMaxSize = photo.getMaxSize() ?: return
|
|
||||||
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
val drawable = applicationContext.imageLoader.execute(
|
|
||||||
ImageRequest.Builder(applicationContext)
|
|
||||||
.data(photoMaxSize.url)
|
|
||||||
.build()
|
|
||||||
).drawable ?: return@launch
|
|
||||||
|
|
||||||
val imagesDir = File(applicationContext.cacheDir, "images")
|
|
||||||
if (!imagesDir.exists()) imagesDir.mkdirs()
|
|
||||||
val imageFile = File(imagesDir, "shared_image_id${photo.id}.png")
|
|
||||||
FileOutputStream(imageFile).use {
|
|
||||||
drawable.toBitmapOrNull()?.compress(Bitmap.CompressFormat.PNG, 100, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val uri = FileProvider.getUriForFile(
|
|
||||||
applicationContext,
|
|
||||||
"${applicationContext.packageName}.provider",
|
|
||||||
imageFile
|
|
||||||
)
|
|
||||||
|
|
||||||
val clip = ClipData.newUri(applicationContext.contentResolver, "Image", uri)
|
|
||||||
clipboardManager.setPrimaryClip(clip)
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext,
|
|
||||||
"Image copied to clipboard",
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
clipboardManager.setPrimaryClip(ClipData.newPlainText("Message", messageToCopy))
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S) {
|
|
||||||
Toast.makeText(applicationContext, R.string.copied_to_clipboard, Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateFormatting(type: FormatDataType) {
|
private fun updateFormatting(type: FormatDataType) {
|
||||||
val selectionRange = screenState.value.message.selection
|
val selectionRange = screenState.value.message.selection
|
||||||
val newItems = formatData.items.toMutableList()
|
val newItems = formatData.items.toMutableList()
|
||||||
@@ -512,9 +313,4 @@ internal class MessagesHistoryMessageActions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleError(error: State.Error) {
|
|
||||||
VkUtils.parseError(error)?.let { newBaseError ->
|
|
||||||
baseError.setValue { newBaseError }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+222
@@ -0,0 +1,222 @@
|
|||||||
|
package dev.meloda.fast.messageshistory
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.os.Build
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
|
import androidx.core.graphics.drawable.toBitmapOrNull
|
||||||
|
import coil.imageLoader
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import com.conena.nanokt.collections.indexOfFirstOrNull
|
||||||
|
import dev.meloda.fast.common.extensions.listenValue
|
||||||
|
import dev.meloda.fast.common.extensions.setValue
|
||||||
|
import dev.meloda.fast.data.State
|
||||||
|
import dev.meloda.fast.data.VkUtils
|
||||||
|
import dev.meloda.fast.data.processState
|
||||||
|
import dev.meloda.fast.domain.MessagesUseCase
|
||||||
|
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
|
||||||
|
import dev.meloda.fast.model.BaseError
|
||||||
|
import dev.meloda.fast.model.api.domain.VkMessage
|
||||||
|
import dev.meloda.fast.model.api.domain.VkPhotoDomain
|
||||||
|
import dev.meloda.fast.ui.R
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
|
||||||
|
internal class MessagesHistoryMessageTransportActions(
|
||||||
|
private val applicationContext: Context,
|
||||||
|
private val viewModelScope: CoroutineScope,
|
||||||
|
private val messagesUseCase: MessagesUseCase,
|
||||||
|
private val screenState: MutableStateFlow<MessagesHistoryScreenState>,
|
||||||
|
private val messages: MutableStateFlow<List<VkMessage>>,
|
||||||
|
private val baseError: MutableStateFlow<BaseError?>,
|
||||||
|
private val syncUiMessages: () -> Unit,
|
||||||
|
private val onPinnedMessageChanged: (VkMessage?) -> Unit
|
||||||
|
) {
|
||||||
|
fun markAsImportant(messageIds: List<Long>, important: Boolean) {
|
||||||
|
messagesUseCase.markAsImportant(
|
||||||
|
peerId = screenState.value.convoId,
|
||||||
|
messageIds = messageIds,
|
||||||
|
important = important
|
||||||
|
).listenValue(viewModelScope) { state ->
|
||||||
|
state.processState(
|
||||||
|
error = ::handleError,
|
||||||
|
success = {
|
||||||
|
val newMessages = messages.value
|
||||||
|
.toMutableList()
|
||||||
|
.map { message ->
|
||||||
|
if (message.id in messageIds) {
|
||||||
|
message.copy(isImportant = important)
|
||||||
|
} else {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
messages.setValue { newMessages }
|
||||||
|
syncUiMessages()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteMessage(
|
||||||
|
messageIds: List<Long>,
|
||||||
|
spam: Boolean = false,
|
||||||
|
deleteForAll: Boolean = false,
|
||||||
|
onSuccess: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
messagesUseCase.delete(
|
||||||
|
peerId = screenState.value.convoId,
|
||||||
|
messageIds = messageIds,
|
||||||
|
spam = spam,
|
||||||
|
deleteForAll = deleteForAll
|
||||||
|
).listenValue(viewModelScope) { state ->
|
||||||
|
state.processState(
|
||||||
|
error = ::handleError,
|
||||||
|
success = {
|
||||||
|
onSuccess()
|
||||||
|
val newMessages = messages.value.toMutableList()
|
||||||
|
val messagesToDelete = newMessages.filter { it.id in messageIds }
|
||||||
|
newMessages.removeAll(messagesToDelete)
|
||||||
|
messages.setValue { newMessages }
|
||||||
|
syncUiMessages()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pinMessage(messageId: Long) {
|
||||||
|
messagesUseCase.pin(
|
||||||
|
peerId = screenState.value.convoId,
|
||||||
|
messageId = messageId,
|
||||||
|
cmId = null
|
||||||
|
).listenValue(viewModelScope) { state ->
|
||||||
|
state.processState(
|
||||||
|
error = ::handleError,
|
||||||
|
success = { pinnedMessage ->
|
||||||
|
onPinnedMessageChanged(pinnedMessage)
|
||||||
|
|
||||||
|
val newMessages = messages.value.toMutableList()
|
||||||
|
val index = newMessages.indexOfFirstOrNull { it.id == messageId }
|
||||||
|
if (index != null) {
|
||||||
|
newMessages[index] = pinnedMessage
|
||||||
|
messages.setValue { newMessages }
|
||||||
|
syncUiMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unpinMessage(messageId: Long) {
|
||||||
|
messagesUseCase.unpin(screenState.value.convoId)
|
||||||
|
.listenValue(viewModelScope) { state ->
|
||||||
|
state.processState(
|
||||||
|
error = ::handleError,
|
||||||
|
success = {
|
||||||
|
val newMessages = messages.value.toMutableList()
|
||||||
|
val index = newMessages.indexOfFirstOrNull { it.id == messageId }
|
||||||
|
if (index != null) {
|
||||||
|
newMessages[index] = newMessages[index].copy(isPinned = false)
|
||||||
|
messages.setValue { newMessages }
|
||||||
|
syncUiMessages()
|
||||||
|
}
|
||||||
|
|
||||||
|
onPinnedMessageChanged(null)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readMessage(message: VkMessage) {
|
||||||
|
messagesUseCase.markAsRead(
|
||||||
|
peerId = screenState.value.convoId,
|
||||||
|
startMessageId = message.id
|
||||||
|
).listenValue(viewModelScope) { state ->
|
||||||
|
state.processState(
|
||||||
|
error = ::handleError,
|
||||||
|
success = {
|
||||||
|
val oldConvo = screenState.value.convo
|
||||||
|
val newConvo = oldConvo.copy(
|
||||||
|
inRead = if (!message.isOut) message.id else oldConvo.inRead,
|
||||||
|
outRead = if (message.isOut) message.id else oldConvo.outRead
|
||||||
|
)
|
||||||
|
|
||||||
|
screenState.setValue { old ->
|
||||||
|
old.copy(convo = newConvo)
|
||||||
|
}
|
||||||
|
|
||||||
|
syncUiMessages()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyMessage(message: VkMessage) {
|
||||||
|
val clipboardManager =
|
||||||
|
applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
|
||||||
|
val messageToCopy = message.text.orEmpty().trim()
|
||||||
|
if (messageToCopy.isEmpty()) {
|
||||||
|
val photo = with(message.attachments.orEmpty()) {
|
||||||
|
if (size == 1 && all { it is VkPhotoDomain }) {
|
||||||
|
first() as? VkPhotoDomain
|
||||||
|
} else null
|
||||||
|
} ?: return
|
||||||
|
|
||||||
|
val photoMaxSize = photo.getMaxSize() ?: return
|
||||||
|
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val drawable = applicationContext.imageLoader.execute(
|
||||||
|
ImageRequest.Builder(applicationContext)
|
||||||
|
.data(photoMaxSize.url)
|
||||||
|
.build()
|
||||||
|
).drawable ?: return@launch
|
||||||
|
|
||||||
|
val imagesDir = File(applicationContext.cacheDir, "images")
|
||||||
|
if (!imagesDir.exists()) imagesDir.mkdirs()
|
||||||
|
val imageFile = File(imagesDir, "shared_image_id${photo.id}.png")
|
||||||
|
FileOutputStream(imageFile).use {
|
||||||
|
drawable.toBitmapOrNull()?.compress(Bitmap.CompressFormat.PNG, 100, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val uri = FileProvider.getUriForFile(
|
||||||
|
applicationContext,
|
||||||
|
"${applicationContext.packageName}.provider",
|
||||||
|
imageFile
|
||||||
|
)
|
||||||
|
|
||||||
|
val clip = ClipData.newUri(applicationContext.contentResolver, "Image", uri)
|
||||||
|
clipboardManager.setPrimaryClip(clip)
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
"Image copied to clipboard",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
clipboardManager.setPrimaryClip(ClipData.newPlainText("Message", messageToCopy))
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S) {
|
||||||
|
Toast.makeText(applicationContext, R.string.copied_to_clipboard, Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleError(error: State.Error) {
|
||||||
|
VkUtils.parseError(error)?.let { newBaseError ->
|
||||||
|
baseError.setValue { newBaseError }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-10
@@ -66,19 +66,28 @@ class MessagesHistoryViewModelImpl(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val messageActions = MessagesHistoryMessageActions(
|
private val messageActions = MessagesHistoryMessageActions(
|
||||||
applicationContext = applicationContext,
|
|
||||||
viewModelScope = viewModelScope,
|
viewModelScope = viewModelScope,
|
||||||
messagesUseCase = messagesUseCase,
|
messagesUseCase = messagesUseCase,
|
||||||
resourceProvider = resourceProvider,
|
resourceProvider = resourceProvider,
|
||||||
screenState = screenState,
|
screenState = screenState,
|
||||||
messages = messages,
|
messages = messages,
|
||||||
baseError = baseError,
|
|
||||||
showKeyboard = showKeyboard,
|
showKeyboard = showKeyboard,
|
||||||
dialog = dialog,
|
dialog = dialog,
|
||||||
syncUiMessages = ::syncUiMessages,
|
syncUiMessages = ::syncUiMessages,
|
||||||
onPinnedMessageChanged = pinnedMessageHandler::update
|
onPinnedMessageChanged = pinnedMessageHandler::update
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val messageTransportActions = MessagesHistoryMessageTransportActions(
|
||||||
|
applicationContext = applicationContext,
|
||||||
|
viewModelScope = viewModelScope,
|
||||||
|
messagesUseCase = messagesUseCase,
|
||||||
|
screenState = screenState,
|
||||||
|
messages = messages,
|
||||||
|
baseError = baseError,
|
||||||
|
syncUiMessages = ::syncUiMessages,
|
||||||
|
onPinnedMessageChanged = pinnedMessageHandler::update
|
||||||
|
)
|
||||||
|
|
||||||
private val loaders = MessagesHistoryLoaders(
|
private val loaders = MessagesHistoryLoaders(
|
||||||
convoUseCase = convoUseCase,
|
convoUseCase = convoUseCase,
|
||||||
messagesUseCase = messagesUseCase,
|
messagesUseCase = messagesUseCase,
|
||||||
@@ -151,7 +160,7 @@ class MessagesHistoryViewModelImpl(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
messageActions.deleteMessage(
|
messageTransportActions.deleteMessage(
|
||||||
messageIds = listOf(dialog.message.id),
|
messageIds = listOf(dialog.message.id),
|
||||||
deleteForAll = deleteForEveryone
|
deleteForAll = deleteForEveryone
|
||||||
)
|
)
|
||||||
@@ -166,7 +175,7 @@ class MessagesHistoryViewModelImpl(
|
|||||||
.filter { it.id > 0 }
|
.filter { it.id > 0 }
|
||||||
.map(VkMessage::id)
|
.map(VkMessage::id)
|
||||||
|
|
||||||
messageActions.deleteMessage(
|
messageTransportActions.deleteMessage(
|
||||||
messageIds = messageIdsToDelete,
|
messageIds = messageIdsToDelete,
|
||||||
deleteForAll = deleteForEveryone,
|
deleteForAll = deleteForEveryone,
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
@@ -180,15 +189,15 @@ class MessagesHistoryViewModelImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is MessageDialog.MessagePin -> {
|
is MessageDialog.MessagePin -> {
|
||||||
messageActions.pinMessage(dialog.messageId)
|
messageTransportActions.pinMessage(dialog.messageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
is MessageDialog.MessageUnpin -> {
|
is MessageDialog.MessageUnpin -> {
|
||||||
messageActions.unpinMessage(dialog.messageId)
|
messageTransportActions.unpinMessage(dialog.messageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
is MessageDialog.MessageMarkImportance -> {
|
is MessageDialog.MessageMarkImportance -> {
|
||||||
messageActions.markAsImportant(
|
messageTransportActions.markAsImportant(
|
||||||
messageIds = listOf(dialog.message.id),
|
messageIds = listOf(dialog.message.id),
|
||||||
important = dialog.isImportant
|
important = dialog.isImportant
|
||||||
)
|
)
|
||||||
@@ -196,7 +205,7 @@ class MessagesHistoryViewModelImpl(
|
|||||||
|
|
||||||
is MessageDialog.MessageSpam -> {
|
is MessageDialog.MessageSpam -> {
|
||||||
if (dialog.isSpam) {
|
if (dialog.isSpam) {
|
||||||
messageActions.deleteMessage(
|
messageTransportActions.deleteMessage(
|
||||||
messageIds = listOf(dialog.message.id),
|
messageIds = listOf(dialog.message.id),
|
||||||
spam = true
|
spam = true
|
||||||
)
|
)
|
||||||
@@ -247,11 +256,11 @@ class MessagesHistoryViewModelImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
MessageOption.Read -> {
|
MessageOption.Read -> {
|
||||||
messageActions.readMessage(dialog.message)
|
messageTransportActions.readMessage(dialog.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageOption.Copy -> {
|
MessageOption.Copy -> {
|
||||||
messageActions.copyMessage(dialog.message)
|
messageTransportActions.copyMessage(dialog.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageOption.MarkAsImportant,
|
MessageOption.MarkAsImportant,
|
||||||
|
|||||||
Reference in New Issue
Block a user