This commit is contained in:
Халимов Рустам
2026-04-14 13:46:17 +03:00
parent 2d0bc0d75c
commit 8ce4bc714f
13 changed files with 560 additions and 10 deletions
@@ -18,7 +18,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import chats.presentation.components.EmojiPicker
import chats.presentation.components.MediaPicker
import chats.presentation.components.MessageBubble
import core.presentation.components.AppAvatar
import core.presentation.components.AppMediaLightbox
@@ -246,7 +246,30 @@ fun ChatDetailScreen(
}
if (isEmojiPickerVisible) {
EmojiPicker(onEmojiSelected = { textInput += it })
LaunchedEffect(Unit) {
viewModel.loadTrendingGifs()
}
MediaPicker(
trendingGifs = state.trendingGifs,
searchedGifs = state.searchedGifs,
recentGifs = state.recentGifs,
gifCategories = state.gifCategories,
isGifsLoading = state.isGifsLoading,
error = state.error,
onEmojiSelected = { textInput += it },
onGifSelected = { url ->
viewModel.sendGif(url)
isEmojiPickerVisible = false
},
onGifSearch = { query ->
viewModel.searchGifs(query)
}
)
LaunchedEffect(Unit) {
viewModel.loadTrendingGifs()
viewModel.loadGifCategories()
}
}
}
}
@@ -17,6 +17,8 @@ import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject
import chats.data.remote.api.KlipyGifDto
data class ChatDetailState(
val messages: List<Message> = emptyList(),
val chatName: String? = null,
@@ -26,7 +28,12 @@ data class ChatDetailState(
val typingUser: String? = null,
val error: String? = null,
val canCall: Boolean = true,
val maxFileSize: Long = 100 * 1024 * 1024
val maxFileSize: Long = 100 * 1024 * 1024,
val trendingGifs: List<KlipyGifDto> = emptyList(),
val searchedGifs: List<KlipyGifDto> = emptyList(),
val recentGifs: List<KlipyGifDto> = emptyList(),
val gifCategories: List<chats.data.remote.api.GifCategoryDto> = emptyList(),
val isGifsLoading: Boolean = false
)
@HiltViewModel
@@ -182,5 +189,78 @@ class ChatDetailViewModel @Inject constructor(
}
}
}
fun loadTrendingGifs() {
if (_state.value.trendingGifs.isNotEmpty()) return
viewModelScope.launch {
_state.update { it.copy(isGifsLoading = true) }
try {
val gifs = repository.getTrendingGifs(0)
_state.update { it.copy(trendingGifs = gifs, isGifsLoading = false) }
} catch (e: Exception) {
_state.update { it.copy(isGifsLoading = false, error = "GIF load error: ${e.message}") }
}
}
}
fun loadGifCategories() {
if (_state.value.gifCategories.isNotEmpty()) return
viewModelScope.launch {
try {
val categories = repository.getGifCategories()
_state.update { it.copy(gifCategories = categories) }
} catch (e: Exception) {
// Ignore failure
}
}
}
private var searchJob: Job? = null
fun searchGifs(query: String) {
searchJob?.cancel()
if (query.isBlank()) {
_state.update { it.copy(searchedGifs = emptyList()) }
return
}
searchJob = viewModelScope.launch {
delay(500)
_state.update { it.copy(isGifsLoading = true) }
try {
val gifs = repository.searchGifs(query, 0)
_state.update { it.copy(searchedGifs = gifs, isGifsLoading = false) }
} catch (e: Exception) {
_state.update { it.copy(isGifsLoading = false) }
}
}
}
fun sendGif(url: String) {
val chatId = currentChatId ?: return
viewModelScope.launch {
try {
repository.sendMessage(chatId, url)
// Add to recent
val allGifs = _state.value.trendingGifs + _state.value.searchedGifs + _state.value.recentGifs
val selectedGif = allGifs.find { gif ->
val gifUrl = gif.files?.get("hd")?.get("gif")?.url
?: gif.files?.get("sd")?.get("gif")?.url
?: gif.file?.get("hd")?.get("gif")?.url
?: gif.file?.get("sd")?.get("gif")?.url
?: gif.media_formats?.get("gif")?.url
?: gif.images?.original?.url
gifUrl == url
}
selectedGif?.let { gif ->
val newList = (listOf(gif) + _state.value.recentGifs).distinctBy { it.id }.take(20)
_state.update { it.copy(recentGifs = newList) }
}
} catch (e: Exception) {
_state.update { it.copy(error = e.localizedMessage) }
}
}
}
}