a lot of changes

This commit is contained in:
Avently
2025-01-10 00:14:35 +07:00
parent 51b339baec
commit 3c79b21d94
5 changed files with 173 additions and 106 deletions
@@ -347,7 +347,9 @@ fun ChatView(
setGroupMembers(chatRh, groupInfo, chatModel)
if (!isActive) return@launch
ModalManager.end.closeModals()
if (!groupReports.value.reportsView) {
ModalManager.end.closeModals()
}
ModalManager.end.showModalCloseable(true) { close ->
remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem ->
GroupMemberInfoView(chatRh, groupInfo, mem, stats, code, chatModel, close, close)
@@ -744,7 +746,7 @@ fun ChatLayout(
sheetShape = RoundedCornerShape(topStart = 18.dp, topEnd = 18.dp)
) {
val composeViewHeight = remember { mutableStateOf(0.dp) }
Box(Modifier.fillMaxSize().chatViewBackgroundModifier(MaterialTheme.colors, MaterialTheme.wallpaper, LocalAppBarHandler.current?.backgroundGraphicsLayerSize, LocalAppBarHandler.current?.backgroundGraphicsLayer)) {
Box(Modifier.fillMaxSize().chatViewBackgroundModifier(MaterialTheme.colors, MaterialTheme.wallpaper, LocalAppBarHandler.current?.backgroundGraphicsLayerSize, LocalAppBarHandler.current?.backgroundGraphicsLayer, !groupReports.value.reportsView)) {
val remoteHostId = remember { remoteHostId }.value
val chatInfo = remember { chatInfo }.value
val oneHandUI = remember { appPrefs.oneHandUI.state }
@@ -766,7 +768,42 @@ fun ChatLayout(
}
}
}
if (!groupReports.value.reportsView) {
if (groupReports.value.reportsView) {
Column(
Modifier
.layoutId(CHAT_COMPOSE_LAYOUT_ID)
.align(Alignment.BottomCenter)
.navigationBarsPadding()
.imePadding()
) {
AnimatedVisibility(selectedChatItems.value != null) {
if (chatInfo != null) {
SelectedItemsBottomToolbar(
reversedChatItems = reversedChatItems,
selectedChatItems = selectedChatItems,
chatInfo = chatInfo,
deleteItems = { _ ->
val itemIds = selectedChatItems.value
val questionText = generalGetString(MR.strings.delete_messages_cannot_be_undone_warning)
if (itemIds != null) {
deleteMessagesAlertDialog(itemIds.sorted(), questionText = questionText, forAll = false, deleteMessages = { ids, _ ->
deleteMessages(remoteHostId, chatInfo, ids, false, moderate = false) {
selectedChatItems.value = null
}
})
}
},
moderateItems = {},
forwardItems = {}
)
}
}
if (oneHandUI.value) {
// That's placeholder to take some space for bottom app bar in oneHandUI
Box(Modifier.height(AppBarHeight * fontSizeSqrtMultiplier))
}
}
} else {
Box(
Modifier
.layoutId(CHAT_COMPOSE_LAYOUT_ID)
@@ -777,49 +814,46 @@ fun ChatLayout(
) {
composeView()
}
} else {
// That's placeholder to take some space for bottom app bar in oneHandUI
Box(
Modifier
.layoutId(CHAT_COMPOSE_LAYOUT_ID)
.align(Alignment.BottomCenter)
.height(if (oneHandUI.value) AppBarHeight * fontSizeSqrtMultiplier else 0.dp)
)
}
}
if (oneHandUI.value && chatBottomBar.value) {
if (groupReports.value.showBar) {
GroupReportsToolbar(groupReports, withStatusBar = true, showGroupReports)
} else {
StatusBarBackground()
}
if (groupReports.value.showBar) {
ReportedCountToolbar(groupReports, withStatusBar = true, showGroupReports)
} else {
StatusBarBackground()
}
} else {
NavigationBarBackground(true, oneHandUI.value, noAlpha = true)
}
Column(if (oneHandUI.value && chatBottomBar.value) Modifier.align(Alignment.BottomStart).imePadding() else Modifier) {
if (!groupReports.value.reportsView) {
if (groupReports.value.reportsView) {
if (oneHandUI.value) {
StatusBarBackground()
}
Column(if (oneHandUI.value) Modifier.align(Alignment.BottomStart).imePadding() else Modifier) {
Box {
if (selectedChatItems.value == null) {
GroupReportsAppBar(groupReports, { ModalManager.end.closeModal() }, showArchived = { showHide ->
showArchivedReports.value = showHide
}, onSearchValueChanged)
} else {
SelectedItemsTopToolbar(selectedChatItems, !oneHandUI.value)
}
}
}
} else {
Column(if (oneHandUI.value && chatBottomBar.value) Modifier.align(Alignment.BottomStart).imePadding() else Modifier) {
Box {
if (selectedChatItems.value == null) {
if (chatInfo != null) {
ChatInfoToolbar(chatInfo, groupReports, back, info, startCall, endCall, addMembers, openGroupLink, changeNtfsState, onSearchValueChanged, showSearch)
}
} else {
SelectedItemsTopToolbar(selectedChatItems)
SelectedItemsTopToolbar(selectedChatItems, !oneHandUI.value || !chatBottomBar.value)
}
}
}
if (groupReports.value.showBar && (!oneHandUI.value || !chatBottomBar.value)) {
GroupReportsToolbar(groupReports, withStatusBar = false, showGroupReports)
}
}
if (groupReports.value.reportsView) {
if (oneHandUI.value) {
StatusBarBackground()
}
Box(Modifier.align(if (oneHandUI.value) Alignment.BottomStart else Alignment.TopStart)) {
GroupReportsAppBar(groupReports, { ModalManager.end.closeModal() }, showArchived = { showHide ->
showArchivedReports.value = showHide
}, onSearchValueChanged)
if (groupReports.value.showBar && (!oneHandUI.value || !chatBottomBar.value)) {
ReportedCountToolbar(groupReports, withStatusBar = false, showGroupReports)
}
}
}
}
@@ -1047,7 +1081,7 @@ fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Colo
}
@Composable
private fun GroupReportsToolbar(
private fun ReportedCountToolbar(
groupReports: State<GroupReports>,
withStatusBar: Boolean,
showGroupReports: () -> Unit
@@ -1139,7 +1173,7 @@ fun BoxScope.ChatItemsList(
val maxHeightForList = rememberUpdatedState(
with(LocalDensity.current) { LocalWindowHeight().roundToPx() - topPaddingToContentPx.value - (AppBarHeight * fontSizeSqrtMultiplier * 2).roundToPx() }
)
val listState = rememberUpdatedState(rememberSaveable(chatInfo.id, searchValueIsEmpty.value, saver = LazyListState.Saver) {
val listState = rememberUpdatedState(rememberSaveable(chatInfo.id, searchValueIsEmpty.value, groupReports.value.showArchived, saver = LazyListState.Saver) {
val index = mergedItems.value.items.indexOfLast { it.hasUnread() }
val reportsState = reportsListState
if (reportsState != null) {
@@ -1187,7 +1221,13 @@ fun BoxScope.ChatItemsList(
}
val scrollToQuotedItemFromItem: (Long) -> Unit = remember { findQuotedItemFromItem(remoteHostIdUpdated, chatInfoUpdated, scope, scrollToItem, groupReports.value.contentTag) }
if (!groupReports.value.reportsView) {
LaunchedEffect(Unit) { snapshotFlow { scrollToItemId.value }.filterNotNull().collect { scrollToItem(it); scrollToItemId.value = null } }
LaunchedEffect(Unit) { snapshotFlow { scrollToItemId.value }.filterNotNull().collect {
if (appPlatform.isAndroid) {
ModalManager.end.closeModals()
}
scrollToItem(it)
scrollToItemId.value = null }
}
}
LoadLastItems(loadingMoreItems, remoteHostId, chatInfo, groupReports)
SmallScrollOnNewMessage(listState, reversedChatItems)
@@ -2347,7 +2387,8 @@ fun Modifier.chatViewBackgroundModifier(
colors: Colors,
wallpaper: AppWallpaper,
backgroundGraphicsLayerSize: MutableState<IntSize>?,
backgroundGraphicsLayer: GraphicsLayer?
backgroundGraphicsLayer: GraphicsLayer?,
drawWallpaper: Boolean
): Modifier {
val wallpaperImage = wallpaper.type.image
val wallpaperType = wallpaper.type
@@ -2355,7 +2396,7 @@ fun Modifier.chatViewBackgroundModifier(
val tintColor = wallpaper.tint ?: wallpaperType.defaultTintColor(CurrentColors.value.base)
return this
.then(if (wallpaperImage != null)
.then(if (wallpaperImage != null && drawWallpaper)
Modifier.drawWithCache { chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor, backgroundGraphicsLayerSize, backgroundGraphicsLayer) }
else
Modifier.drawWithCache { onDrawBehind { copyBackgroundToAppBar(backgroundGraphicsLayerSize, backgroundGraphicsLayer) { drawRect(backgroundColor) } } }
@@ -21,11 +21,10 @@ import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
@Composable
fun BoxScope.SelectedItemsTopToolbar(selectedChatItems: MutableState<Set<Long>?>) {
fun BoxScope.SelectedItemsTopToolbar(selectedChatItems: MutableState<Set<Long>?>, onTop: Boolean) {
val onBackClicked = { selectedChatItems.value = null }
BackHandler(onBack = onBackClicked)
val count = selectedChatItems.value?.size ?: 0
val oneHandUI = remember { appPrefs.oneHandUI.state }
DefaultAppBar(
navigationButton = { NavigationButtonClose(onButtonClicked = onBackClicked) },
title = {
@@ -41,7 +40,7 @@ fun BoxScope.SelectedItemsTopToolbar(selectedChatItems: MutableState<Set<Long>?>
)
},
onTitleClick = null,
onTop = !oneHandUI.value,
onTop = onTop,
onSearchValueChanged = {},
)
}
@@ -1,13 +1,18 @@
package chat.simplex.common.views.chat.group
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.*
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.platform.*
import chat.simplex.common.views.chat.ChatView
import chat.simplex.common.views.chat.apiLoadMessages
import chat.simplex.common.views.chat.*
import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.chatlist.*
import chat.simplex.common.views.helpers.*
@@ -15,7 +20,6 @@ import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
val LocalContentTag: ProvidableCompositionLocal<MsgContentTag?> = staticCompositionLocalOf { null }
@@ -69,29 +73,40 @@ fun GroupReportsAppBar(
IconButton({ showMenu.value = true }) {
Icon(MoreVertFilled, stringResource(MR.strings.icon_descr_more_button), tint = MaterialTheme.colors.primary)
}
val onClosedAction = remember { mutableStateOf({}) }
DefaultDropdownMenu(
showMenu,
onClosed = onClosedAction
) {
ItemAction(stringResource(MR.strings.search_verb), painterResource(MR.images.ic_search), onClick = {
showMenu.value = false
showSearch.value = true
})
ItemAction(
if (groupReports.value.showArchived) stringResource(MR.strings.group_reports_show_active) else stringResource(MR.strings.group_reports_show_archived),
painterResource(if (groupReports.value.showArchived) MR.images.ic_flag else MR.images.ic_inventory_2),
onClick = {
onClosedAction.value = {
showArchived(!groupReports.value.showArchived)
onClosedAction.value = {}
}
showMenu.value = false
}
)
}
}
)
Box(Modifier.fillMaxWidth().wrapContentSize(Alignment.TopEnd)) {
val density = LocalDensity.current
val width = remember { mutableStateOf(250.dp) }
val height = remember { mutableStateOf(0.dp) }
val onClosedAction = remember { mutableStateOf({}) }
DefaultDropdownMenu(
showMenu,
modifier = Modifier.onSizeChanged { with(density) {
width.value = it.width.toDp().coerceAtLeast(250.dp)
if (oneHandUI.value && (appPlatform.isDesktop || (platform.androidApiLevel ?: 0) >= 30)) height.value = it.height.toDp()
} },
offset = DpOffset(-width.value, if (oneHandUI.value) -height.value else AppBarHeight),
onClosed = onClosedAction
) {
ItemAction(stringResource(MR.strings.search_verb), painterResource(MR.images.ic_search), onClick = {
showMenu.value = false
showSearch.value = true
})
ItemAction(
if (groupReports.value.showArchived) stringResource(MR.strings.group_reports_show_active) else stringResource(MR.strings.group_reports_show_archived),
painterResource(if (groupReports.value.showArchived) MR.images.ic_flag else MR.images.ic_inventory_2),
onClick = {
onClosedAction.value = {
showArchived(!groupReports.value.showArchived)
onClosedAction.value = {}
}
showMenu.value = false
}
)
}
}
ItemsReload(groupReports)
}
@@ -128,17 +128,6 @@ fun FramedItemView(
Modifier
.background(if (sent) sentColor else receivedColor)
.fillMaxWidth()
.combinedClickable(
onLongClick = { showMenu.value = true },
onClick = {
if (qi.itemId != null) {
scrollToItem(qi.itemId)
} else {
scrollToQuotedItemFromItem(ci.id)
}
}
)
.onRightClick { showMenu.value = true }
) {
when (qi.content) {
is MsgContent.MCImage -> {
@@ -216,39 +205,61 @@ fun FramedItemView(
.padding(start = if (tailRendered) msgTailWidthDp else 0.dp, end = if (sent && tailRendered) msgTailWidthDp else 0.dp)
) {
PriorityLayout(Modifier, CHAT_IMAGE_LAYOUT_ID) {
if (ci.isReport) {
if (ci.meta.itemDeleted == null) {
FramedItemHeader(
stringResource(if (ci.chatDir.sent) MR.strings.report_item_visibility_submitter else MR.strings.report_item_visibility_moderators),
true,
painterResource(MR.images.ic_flag),
iconColor = Color.Red
)
} else {
FramedItemHeader(stringResource(MR.strings.report_item_archived), true, painterResource(MR.images.ic_flag))
@Composable
fun Header() {
if (ci.isReport) {
if (ci.meta.itemDeleted == null) {
FramedItemHeader(
stringResource(if (ci.chatDir.sent) MR.strings.report_item_visibility_submitter else MR.strings.report_item_visibility_moderators),
true,
painterResource(MR.images.ic_flag),
iconColor = Color.Red
)
} else {
FramedItemHeader(stringResource(MR.strings.report_item_archived), true, painterResource(MR.images.ic_flag))
}
} else if (ci.meta.itemDeleted != null) {
when (ci.meta.itemDeleted) {
is CIDeleted.Moderated -> {
FramedItemHeader(String.format(stringResource(MR.strings.moderated_item_description), ci.meta.itemDeleted.byGroupMember.chatViewName), true, painterResource(MR.images.ic_flag))
}
is CIDeleted.Blocked -> {
FramedItemHeader(stringResource(MR.strings.blocked_item_description), true, painterResource(MR.images.ic_back_hand))
}
is CIDeleted.BlockedByAdmin -> {
FramedItemHeader(stringResource(MR.strings.blocked_by_admin_item_description), true, painterResource(MR.images.ic_back_hand))
}
is CIDeleted.Deleted -> {
FramedItemHeader(stringResource(MR.strings.marked_deleted_description), true, painterResource(MR.images.ic_delete))
}
}
} else if (ci.meta.isLive) {
FramedItemHeader(stringResource(MR.strings.live), false)
}
} else if (ci.meta.itemDeleted != null) {
when (ci.meta.itemDeleted) {
is CIDeleted.Moderated -> {
FramedItemHeader(String.format(stringResource(MR.strings.moderated_item_description), ci.meta.itemDeleted.byGroupMember.chatViewName), true, painterResource(MR.images.ic_flag))
}
is CIDeleted.Blocked -> {
FramedItemHeader(stringResource(MR.strings.blocked_item_description), true, painterResource(MR.images.ic_back_hand))
}
is CIDeleted.BlockedByAdmin -> {
FramedItemHeader(stringResource(MR.strings.blocked_by_admin_item_description), true, painterResource(MR.images.ic_back_hand))
}
is CIDeleted.Deleted -> {
FramedItemHeader(stringResource(MR.strings.marked_deleted_description), true, painterResource(MR.images.ic_delete))
}
}
} else if (ci.meta.isLive) {
FramedItemHeader(stringResource(MR.strings.live), false)
}
if (ci.quotedItem != null) {
ciQuoteView(ci.quotedItem)
} else if (ci.meta.itemForwarded != null) {
FramedItemHeader(ci.meta.itemForwarded.text(chatInfo.chatType), true, painterResource(MR.images.ic_forward), pad = true)
Column(
Modifier
.combinedClickable(
onLongClick = { showMenu.value = true },
onClick = {
if (ci.quotedItem.itemId != null) {
scrollToItem(ci.quotedItem.itemId)
} else {
scrollToQuotedItemFromItem(ci.id)
}
}
)
.onRightClick { showMenu.value = true }
) {
Header()
ciQuoteView(ci.quotedItem)
}
} else {
Header()
if (ci.meta.itemForwarded != null) {
FramedItemHeader(ci.meta.itemForwarded.text(chatInfo.chatType), true, painterResource(MR.images.ic_forward), pad = true)
}
}
if (ci.file == null && ci.formattedText == null && !ci.meta.isLive && isShortEmoji(ci.content.text)) {
Box(Modifier.padding(vertical = 6.dp, horizontal = 12.dp)) {
@@ -35,7 +35,8 @@ fun DefaultAppBar(
// If I just disable clickable modifier when don't need it, it will stop passing clicks to search. Replacing the whole modifier
val modifier = if (!showSearch) {
Modifier.clickable(enabled = onTitleClick != null, onClick = onTitleClick ?: { })
} else Modifier.imePadding()
} else if (!onTop) Modifier.imePadding()
else Modifier
val themeBackgroundMix = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.97f)
val prefAlpha = remember { appPrefs.inAppBarsAlpha.state }