mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3210 Chats | Enhancement | Add search field to chat reaction picker (#2497)
This commit is contained in:
parent
f55144794a
commit
8b1e379785
4 changed files with 68 additions and 27 deletions
|
@ -16,9 +16,17 @@ import com.anytypeio.anytype.emojifier.data.EmojiProvider
|
|||
import com.anytypeio.anytype.emojifier.suggest.EmojiSuggester
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
@ -42,9 +50,36 @@ class SelectChatReactionViewModel @Inject constructor(
|
|||
|
||||
private val recentlyUsed = MutableStateFlow<List<String>>(emptyList())
|
||||
|
||||
val views = combine(default, recentlyUsed) { default, recentlyUsed ->
|
||||
buildList<ReactionPickerView> {
|
||||
if (recentlyUsed.isNotEmpty()) {
|
||||
private val rawQuery = MutableStateFlow("")
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
private val debouncedQuery = rawQuery
|
||||
.debounce(DEBOUNCE_DURATION)
|
||||
.distinctUntilChanged()
|
||||
.onStart { emit(rawQuery.value) }
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private val queries = debouncedQuery.flatMapLatest { query ->
|
||||
flow {
|
||||
val emojis = if (query.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
suggester.search(query).map { result ->
|
||||
ReactionPickerView.Emoji(
|
||||
unicode = result.emoji,
|
||||
page = -1,
|
||||
index = -1,
|
||||
emojified = Emojifier.safeUri(result.emoji)
|
||||
)
|
||||
}
|
||||
}
|
||||
emit(query to emojis)
|
||||
}
|
||||
}.flowOn(dispatchers.io)
|
||||
|
||||
val views = combine(default, recentlyUsed, queries) { default, recentlyUsed, (query, results) ->
|
||||
buildList {
|
||||
if (query.isEmpty() && recentlyUsed.isNotEmpty()) {
|
||||
add(ReactionPickerView.RecentUsedSection)
|
||||
addAll(
|
||||
recentlyUsed.map { unicode ->
|
||||
|
@ -57,11 +92,16 @@ class SelectChatReactionViewModel @Inject constructor(
|
|||
}
|
||||
)
|
||||
}
|
||||
addAll(default)
|
||||
if (query.isEmpty()) {
|
||||
addAll(default)
|
||||
} else {
|
||||
addAll(results)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
viewModelScope.launch {
|
||||
observeRecentlyUsedChatReactions
|
||||
.flow()
|
||||
|
@ -126,6 +166,10 @@ class SelectChatReactionViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun onQueryChanged(input: String) {
|
||||
rawQuery.value = input
|
||||
}
|
||||
|
||||
class Factory @Inject constructor(
|
||||
private val params: Params,
|
||||
private val emojiProvider: EmojiProvider,
|
||||
|
@ -165,5 +209,6 @@ class SelectChatReactionViewModel @Inject constructor(
|
|||
|
||||
companion object {
|
||||
const val MAX_RECENTLY_USED_COUNT = 20
|
||||
const val DEBOUNCE_DURATION = 300L
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ package com.anytypeio.anytype.feature_chats.ui
|
|||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
|
@ -25,6 +27,7 @@ import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
|||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Medium
|
||||
import com.anytypeio.anytype.core_ui.widgets.SearchField
|
||||
import com.anytypeio.anytype.emojifier.data.Emoji
|
||||
import com.anytypeio.anytype.feature_chats.R
|
||||
import com.anytypeio.anytype.feature_chats.presentation.SelectChatReactionViewModel.ReactionPickerView
|
||||
|
@ -35,9 +38,10 @@ import com.bumptech.glide.integration.compose.GlideImage
|
|||
@Composable
|
||||
fun SelectChatReactionScreen(
|
||||
views: List<ReactionPickerView> = emptyList(),
|
||||
onEmojiClicked: (String) -> Unit
|
||||
onEmojiClicked: (String) -> Unit,
|
||||
onQueryChanged: (String) -> Unit
|
||||
) {
|
||||
Box(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(rememberNestedScrollInteropConnection())
|
||||
|
@ -45,14 +49,21 @@ fun SelectChatReactionScreen(
|
|||
Dragger(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.align(Alignment.TopCenter)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
SearchField(
|
||||
onQueryChanged = onQueryChanged,
|
||||
onFocused = {
|
||||
// Do nothing
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(6),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(
|
||||
top = 16.dp,
|
||||
start = 16.dp,
|
||||
end = 16.dp
|
||||
),
|
||||
|
@ -149,6 +160,7 @@ fun PickerPreview() {
|
|||
)
|
||||
)
|
||||
},
|
||||
onEmojiClicked = {}
|
||||
onEmojiClicked = {},
|
||||
onQueryChanged = {}
|
||||
)
|
||||
}
|
|
@ -114,7 +114,6 @@ fun ChatScreenWrapper(
|
|||
onViewChatReaction: (Id, String) -> Unit
|
||||
) {
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false)
|
||||
var showReactionSheet by remember { mutableStateOf(false) }
|
||||
var showSendRateLimitWarning by remember { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
Box(
|
||||
|
@ -262,21 +261,6 @@ fun ChatScreenWrapper(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (showReactionSheet) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = {
|
||||
showReactionSheet = false
|
||||
},
|
||||
sheetState = sheetState,
|
||||
containerColor = colorResource(id = R.color.background_secondary),
|
||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||
dragHandle = null
|
||||
) {
|
||||
SelectChatReactionScreen(
|
||||
onEmojiClicked = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showSendRateLimitWarning) {
|
||||
ModalBottomSheet(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue