ui: knocking UI improvements (texts, icons, layout, chat view shortcut split toolbar, set admission on creating group) (#5879)

This commit is contained in:
spaced4ndy
2025-05-08 13:44:55 +00:00
committed by GitHub
parent f5926e8b84
commit 2a9df3e10b
11 changed files with 221 additions and 140 deletions
@@ -342,7 +342,7 @@ fun ChatView(
}
}
},
showReportsOrSupportChats = {
showReports = {
val info = activeChatInfo.value ?: return@ChatLayout
if (ModalManager.end.hasModalsOpen()) {
ModalManager.end.closeModals()
@@ -350,9 +350,18 @@ fun ChatView(
}
hideKeyboard(view)
scope.launch {
if (reportsCount > 0) {
showGroupReportsView(staleChatId, scrollToItemId, info)
} else if (info is ChatInfo.Group && info.groupInfo.membership.memberRole >= GroupMemberRole.Moderator) {
showGroupReportsView(staleChatId, scrollToItemId, info)
}
},
showSupportChats = {
val info = activeChatInfo.value ?: return@ChatLayout
if (ModalManager.end.hasModalsOpen()) {
ModalManager.end.closeModals()
return@ChatLayout
}
hideKeyboard(view)
scope.launch {
if (info is ChatInfo.Group && info.groupInfo.membership.memberRole >= GroupMemberRole.Moderator) {
ModalManager.end.showCustomModal { close ->
MemberSupportView(
chatRh,
@@ -733,7 +742,8 @@ fun ChatLayout(
selectedChatItems: MutableState<Set<Long>?>,
back: () -> Unit,
info: () -> Unit,
showReportsOrSupportChats: () -> Unit,
showReports: () -> Unit,
showSupportChats: () -> Unit,
showMemberInfo: (GroupInfo, GroupMember) -> Unit,
loadMessages: suspend (ChatId, ChatPagination, visibleItemIndexesNonReversed: () -> IntRange) -> Unit,
deleteMessage: (Long, CIDeleteMode) -> Unit,
@@ -887,7 +897,7 @@ fun ChatLayout(
val supportChatsUnreadCount = supportChatsUnreadCount(chatInfo?.id)
if (oneHandUI.value && chatBottomBar.value) {
if (chatsCtx.secondaryContextFilter == null && (reportsCount > 0 || supportChatsUnreadCount > 0)) {
SupportChatsCountToolbar(reportsCount, supportChatsUnreadCount, withStatusBar = true, showReportsOrSupportChats)
SupportChatsCountToolbar(reportsCount, supportChatsUnreadCount, withStatusBar = true, showReports, showSupportChats)
} else {
StatusBarBackground()
}
@@ -944,7 +954,7 @@ fun ChatLayout(
}
}
if ((reportsCount > 0 || supportChatsUnreadCount > 0) && (!oneHandUI.value || !chatBottomBar.value)) {
SupportChatsCountToolbar(reportsCount, supportChatsUnreadCount, withStatusBar = false, showReportsOrSupportChats)
SupportChatsCountToolbar(reportsCount, supportChatsUnreadCount, withStatusBar = false, showReports, showSupportChats)
}
}
}
@@ -1180,37 +1190,64 @@ private fun SupportChatsCountToolbar(
reportsCount: Int,
supportChatsUnreadCount: Int,
withStatusBar: Boolean,
showReportsOrSupportChats: () -> Unit
showReports: () -> Unit,
showSupportChats: () -> Unit
) {
Box {
val statusBarPadding = if (withStatusBar) WindowInsets.statusBars.asPaddingValues().calculateTopPadding() else 0.dp
Row(
Modifier
.fillMaxWidth()
.height(AppBarHeight * fontSizeSqrtMultiplier + statusBarPadding)
.background(MaterialTheme.colors.background)
.clickable(onClick = showReportsOrSupportChats)
.padding(top = statusBarPadding),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
) {
val iconColor = if (reportsCount == 0) MaterialTheme.colors.primary else MaterialTheme.colors.error
Icon(painterResource(MR.images.ic_flag), null, Modifier.size(22.dp), tint = iconColor)
Spacer(Modifier.width(4.dp))
Text(
if (supportChatsUnreadCount == 0) {
if (reportsCount == 1) {
stringResource(MR.strings.group_reports_active_one)
} else {
stringResource(MR.strings.group_reports_active).format(reportsCount)
}
} else if (reportsCount == 0) {
stringResource(MR.strings.group_new_support_messages).format(supportChatsUnreadCount)
} else {
String.format(generalGetString(MR.strings.group_reports_active_new_support_messages), reportsCount, supportChatsUnreadCount)
},
style = MaterialTheme.typography.button
)
if (reportsCount > 0) {
Row(
Modifier
.fillMaxWidth()
.weight(1F)
.height(AppBarHeight * fontSizeSqrtMultiplier + statusBarPadding)
.background(MaterialTheme.colors.background)
.clickable(onClick = showReports)
.padding(top = statusBarPadding),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Icon(painterResource(MR.images.ic_flag), null, Modifier.size(22.dp), tint = MaterialTheme.colors.error)
Spacer(Modifier.width(4.dp))
Text(
if (reportsCount == 1) {
stringResource(MR.strings.group_reports_active_one)
} else {
stringResource(MR.strings.group_reports_active).format(reportsCount)
},
style = MaterialTheme.typography.button
)
}
}
if (supportChatsUnreadCount > 0) {
Row(
Modifier
.fillMaxWidth()
.weight(1F)
.height(AppBarHeight * fontSizeSqrtMultiplier + statusBarPadding)
.background(MaterialTheme.colors.background)
.clickable(onClick = showSupportChats)
.padding(top = statusBarPadding),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Icon(painterResource(MR.images.ic_flag), null, Modifier.size(22.dp), tint = MaterialTheme.colors.primary)
Spacer(Modifier.width(4.dp))
Text(
if (appPlatform.isAndroid)
stringResource(MR.strings.group_new_support_messages_short).format(supportChatsUnreadCount)
else
stringResource(MR.strings.group_new_support_messages).format(supportChatsUnreadCount),
style = MaterialTheme.typography.button
)
}
}
}
Divider(Modifier.align(Alignment.BottomStart))
}
@@ -3027,7 +3064,8 @@ fun PreviewChatLayout() {
selectedChatItems = remember { mutableStateOf(setOf()) },
back = {},
info = {},
showReportsOrSupportChats = {},
showReports = {},
showSupportChats = {},
showMemberInfo = { _, _ -> },
loadMessages = { _, _, _ -> },
deleteMessage = { _, _ -> },
@@ -3105,7 +3143,8 @@ fun PreviewGroupChatLayout() {
selectedChatItems = remember { mutableStateOf(setOf()) },
back = {},
info = {},
showReportsOrSupportChats = {},
showReports = {},
showSupportChats = {},
showMemberInfo = { _, _ -> },
loadMessages = { _, _, _ -> },
deleteMessage = { _, _ -> },
@@ -55,6 +55,16 @@ fun AddGroupMembersView(rhId: Long?, groupInfo: GroupInfo, creatingGroup: Boolea
GroupPreferencesView(chatModel, rhId, groupInfo.id, close)
}
},
openMemberAdmission = {
ModalManager.end.showCustomModal { close ->
MemberAdmissionView(
chat.simplex.common.platform.chatModel,
rhId,
groupInfo.id,
close
)
}
},
inviteMembers = {
allowModifyMembers = false
withLongRunningApi(slow = 120_000) {
@@ -110,6 +120,7 @@ fun AddGroupMembersLayout(
allowModifyMembers: Boolean,
searchText: MutableState<TextFieldValue>,
openPreferences: () -> Unit,
openMemberAdmission: () -> Unit,
inviteMembers: () -> Unit,
clearSelection: () -> Unit,
addContact: (Long) -> Unit,
@@ -165,6 +176,9 @@ fun AddGroupMembersLayout(
} else {
SectionView {
if (creatingGroup) {
SectionItemView(openMemberAdmission) {
Text(stringResource(MR.strings.set_member_admission))
}
SectionItemView(openPreferences) {
Text(stringResource(MR.strings.set_group_preferences))
}
@@ -376,6 +390,7 @@ fun PreviewAddGroupMembersLayout() {
allowModifyMembers = true,
searchText = remember { mutableStateOf(TextFieldValue("")) },
openPreferences = {},
openMemberAdmission = {},
inviteMembers = {},
clearSelection = {},
addContact = {},
@@ -463,22 +463,30 @@ fun ModalData.GroupChatInfoLayout(
var anyTopSectionRowShow = false
SectionView {
if (groupInfo.membership.supportChat != null) {
if (groupInfo.canAddMembers && groupInfo.businessChat == null) {
anyTopSectionRowShow = true
UserSupportChatButton(groupInfo, scrollToItemId)
if (groupLink == null) {
CreateGroupLinkButton(manageGroupLink)
} else {
GroupLinkButton(manageGroupLink)
}
}
if (groupInfo.businessChat == null && groupInfo.membership.memberRole >= GroupMemberRole.Moderator) {
anyTopSectionRowShow = true
MemberSupportButton(openMemberSupport)
MemberSupportButton(chat, openMemberSupport)
}
if (groupInfo.canModerate) {
anyTopSectionRowShow = true
GroupReportsButton {
GroupReportsButton(chat) {
scope.launch {
showGroupReportsView(chatModel.chatId, scrollToItemId, chat.chatInfo)
}
}
}
if (groupInfo.membership.supportChat != null) {
anyTopSectionRowShow = true
UserSupportChatButton(groupInfo, scrollToItemId)
}
}
if (anyTopSectionRowShow) {
SectionDividerSpaced(maxBottomPadding = false)
@@ -520,13 +528,6 @@ fun ModalData.GroupChatInfoLayout(
SectionView(title = String.format(generalGetString(MR.strings.group_info_section_title_num_members), activeSortedMembers.count() + 1)) {
if (groupInfo.canAddMembers) {
if (groupInfo.businessChat == null) {
if (groupLink == null) {
CreateGroupLinkButton(manageGroupLink)
} else {
GroupLinkButton(manageGroupLink)
}
}
val onAddMembersClick = if (chat.chatInfo.incognito) ::cantInviteIncognitoAlert else addMembers
val tint = if (chat.chatInfo.incognito) MaterialTheme.colors.secondary else MaterialTheme.colors.primary
val addMembersTitleId = when (groupInfo.businessChat?.chatType) {
@@ -738,11 +739,12 @@ private fun GroupChatInfoHeader(cInfo: ChatInfo, groupInfo: GroupInfo) {
}
@Composable
private fun MemberSupportButton(onClick: () -> Unit) {
private fun MemberSupportButton(chat: Chat, onClick: () -> Unit) {
SettingsActionItem(
painterResource(MR.images.ic_flag),
painterResource(if (chat.chatStats.supportChatsUnreadCount > 0) MR.images.ic_flag_filled else MR.images.ic_flag),
stringResource(MR.strings.member_support),
click = onClick
click = onClick,
iconColor = (if (chat.chatStats.supportChatsUnreadCount > 0) MaterialTheme.colors.primary else MaterialTheme.colors.secondary)
)
}
@@ -756,11 +758,12 @@ private fun GroupPreferencesButton(titleId: StringResource, onClick: () -> Unit)
}
@Composable
private fun GroupReportsButton(onClick: () -> Unit) {
private fun GroupReportsButton(chat: Chat, onClick: () -> Unit) {
SettingsActionItem(
painterResource(MR.images.ic_flag),
painterResource(if (chat.chatStats.reportsCount > 0) MR.images.ic_flag_filled else MR.images.ic_flag),
stringResource(MR.strings.group_reports_member_reports),
click = onClick
click = onClick,
iconColor = (if (chat.chatStats.reportsCount > 0) Color.Red else MaterialTheme.colors.secondary)
)
}
@@ -466,7 +466,7 @@
<string name="group_reports_active">%d reports</string>
<string name="group_reports_member_reports">Member reports</string>
<string name="group_new_support_messages">%d new support messages</string>
<string name="group_reports_active_new_support_messages">%1$d reports, %2$d new support messages</string>
<string name="group_new_support_messages_short">%d messages</string>
<!-- ShareListView.kt -->
<string name="share_message">Share message…</string>
@@ -512,7 +512,7 @@
<string name="report_compose_reason_header_illegal">Report content: only group moderators will see it.</string>
<string name="report_compose_reason_header_other">Report other: only group moderators will see it.</string>
<string name="report_sent_alert_title">Report sent to moderators</string>
<string name="report_sent_alert_msg_view_in_support_chat">You can view your reports in Support Chat.</string>
<string name="report_sent_alert_msg_view_in_support_chat">You can view your reports in Chat with admins.</string>
<!-- Images - chat.simplex.app.views.chat.item.CIImageView.kt -->
<string name="image_descr">Image</string>
@@ -1767,7 +1767,7 @@
<string name="button_remove_member_question">Remove member?</string>
<string name="button_remove_members_question">Remove members?</string>
<string name="button_remove_member">Remove member</string>
<string name="button_support_chat">Support chat</string>
<string name="button_support_chat">Chat with admins</string>
<string name="button_send_direct_message">Send direct message</string>
<string name="member_will_be_removed_from_group_cannot_be_undone">Member will be removed from group - this cannot be undone!</string>
<string name="members_will_be_removed_from_group_cannot_be_undone">Members will be removed from group - this cannot be undone!</string>
@@ -2044,6 +2044,7 @@
<string name="contact_preferences">Contact preferences</string>
<string name="group_preferences">Group preferences</string>
<string name="set_group_preferences">Set group preferences</string>
<string name="set_member_admission">Set member admission</string>
<string name="your_preferences">Your preferences</string>
<string name="timed_messages">Disappearing messages</string>
<string name="direct_messages">Direct messages</string>
@@ -2163,17 +2164,17 @@
<!-- MemberAdmission.kt -->
<string name="member_admission">Member admission</string>
<string name="admission_stage_review">Review</string>
<string name="admission_stage_review_descr">Review new members before admitting to group.</string>
<string name="admission_stage_review">Review members</string>
<string name="admission_stage_review_descr">Review members before admitting ("knocking").</string>
<string name="member_criteria_off">off</string>
<string name="member_criteria_all">all</string>
<!-- MemberSupportView.kt -->
<string name="member_support">Member support</string>
<string name="no_support_chats">No support chats</string>
<string name="member_support">Chats with members</string>
<string name="no_support_chats">No chats with members</string>
<!-- MemberSupportChatView.kt -->
<string name="support_chat">Support</string>
<string name="support_chat">Chat with admins</string>
<string name="remove_pending_member_button">Remove</string>
<string name="accept_pending_member_button">Accept</string>
<string name="accept_pending_member_alert_title">Accept member</string>