Ability to disable notifications per chat (#964)

* Ability to disable notifications per chat

* All Buttons in AlertDialog replaced with TextButtons

* update icon

* update strings

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
Stanislav Dmitrenko
2022-08-22 23:16:01 +03:00
committed by GitHub
parent a06499d710
commit 04592f52de
11 changed files with 183 additions and 22 deletions

View File

@@ -325,6 +325,7 @@ interface SomeChat {
val apiId: Long val apiId: Long
val ready: Boolean val ready: Boolean
val sendMsgEnabled: Boolean val sendMsgEnabled: Boolean
val ntfsEnabled: Boolean
val createdAt: Instant val createdAt: Instant
val updatedAt: Instant val updatedAt: Instant
} }
@@ -383,6 +384,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = contact.apiId override val apiId get() = contact.apiId
override val ready get() = contact.ready override val ready get() = contact.ready
override val sendMsgEnabled get() = contact.sendMsgEnabled override val sendMsgEnabled get() = contact.sendMsgEnabled
override val ntfsEnabled get() = contact.chatSettings.enableNtfs
override val createdAt get() = contact.createdAt override val createdAt get() = contact.createdAt
override val updatedAt get() = contact.updatedAt override val updatedAt get() = contact.updatedAt
override val displayName get() = contact.displayName override val displayName get() = contact.displayName
@@ -402,6 +404,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = groupInfo.apiId override val apiId get() = groupInfo.apiId
override val ready get() = groupInfo.ready override val ready get() = groupInfo.ready
override val sendMsgEnabled get() = groupInfo.sendMsgEnabled override val sendMsgEnabled get() = groupInfo.sendMsgEnabled
override val ntfsEnabled get() = groupInfo.chatSettings.enableNtfs
override val createdAt get() = groupInfo.createdAt override val createdAt get() = groupInfo.createdAt
override val updatedAt get() = groupInfo.updatedAt override val updatedAt get() = groupInfo.updatedAt
override val displayName get() = groupInfo.displayName override val displayName get() = groupInfo.displayName
@@ -421,6 +424,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = contactRequest.apiId override val apiId get() = contactRequest.apiId
override val ready get() = contactRequest.ready override val ready get() = contactRequest.ready
override val sendMsgEnabled get() = contactRequest.sendMsgEnabled override val sendMsgEnabled get() = contactRequest.sendMsgEnabled
override val ntfsEnabled get() = false
override val createdAt get() = contactRequest.createdAt override val createdAt get() = contactRequest.createdAt
override val updatedAt get() = contactRequest.updatedAt override val updatedAt get() = contactRequest.updatedAt
override val displayName get() = contactRequest.displayName override val displayName get() = contactRequest.displayName
@@ -440,6 +444,7 @@ sealed class ChatInfo: SomeChat, NamedChat {
override val apiId get() = contactConnection.apiId override val apiId get() = contactConnection.apiId
override val ready get() = contactConnection.ready override val ready get() = contactConnection.ready
override val sendMsgEnabled get() = contactConnection.sendMsgEnabled override val sendMsgEnabled get() = contactConnection.sendMsgEnabled
override val ntfsEnabled get() = false
override val createdAt get() = contactConnection.createdAt override val createdAt get() = contactConnection.createdAt
override val updatedAt get() = contactConnection.updatedAt override val updatedAt get() = contactConnection.updatedAt
override val displayName get() = contactConnection.displayName override val displayName get() = contactConnection.displayName
@@ -454,13 +459,13 @@ sealed class ChatInfo: SomeChat, NamedChat {
} }
@Serializable @Serializable
class Contact( data class Contact(
val contactId: Long, val contactId: Long,
override val localDisplayName: String, override val localDisplayName: String,
val profile: Profile, val profile: Profile,
val activeConn: Connection, val activeConn: Connection,
val viaGroup: Long? = null, val viaGroup: Long? = null,
// val chatSettings: ChatSettings, val chatSettings: ChatSettings,
override val createdAt: Instant, override val createdAt: Instant,
override val updatedAt: Instant override val updatedAt: Instant
): SomeChat, NamedChat { ): SomeChat, NamedChat {
@@ -469,6 +474,7 @@ class Contact(
override val apiId get() = contactId override val apiId get() = contactId
override val ready get() = activeConn.connStatus == ConnStatus.Ready override val ready get() = activeConn.connStatus == ConnStatus.Ready
override val sendMsgEnabled get() = true override val sendMsgEnabled get() = true
override val ntfsEnabled get() = chatSettings.enableNtfs
override val displayName get() = profile.displayName override val displayName get() = profile.displayName
override val fullName get() = profile.fullName override val fullName get() = profile.fullName
override val image get() = profile.image override val image get() = profile.image
@@ -482,6 +488,7 @@ class Contact(
localDisplayName = "alice", localDisplayName = "alice",
profile = Profile.sampleData, profile = Profile.sampleData,
activeConn = Connection.sampleData, activeConn = Connection.sampleData,
chatSettings = ChatSettings(true),
createdAt = Clock.System.now(), createdAt = Clock.System.now(),
updatedAt = Clock.System.now() updatedAt = Clock.System.now()
) )
@@ -536,12 +543,12 @@ class Group (
) )
@Serializable @Serializable
class GroupInfo ( data class GroupInfo (
val groupId: Long, val groupId: Long,
override val localDisplayName: String, override val localDisplayName: String,
val groupProfile: GroupProfile, val groupProfile: GroupProfile,
val membership: GroupMember, val membership: GroupMember,
// val chatSettings: ChatSettings, val chatSettings: ChatSettings,
override val createdAt: Instant, override val createdAt: Instant,
override val updatedAt: Instant override val updatedAt: Instant
): SomeChat, NamedChat { ): SomeChat, NamedChat {
@@ -550,6 +557,7 @@ class GroupInfo (
override val apiId get() = groupId override val apiId get() = groupId
override val ready get() = true override val ready get() = true
override val sendMsgEnabled get() = membership.memberActive override val sendMsgEnabled get() = membership.memberActive
override val ntfsEnabled get() = chatSettings.enableNtfs
override val displayName get() = groupProfile.displayName override val displayName get() = groupProfile.displayName
override val fullName get() = groupProfile.fullName override val fullName get() = groupProfile.fullName
override val image get() = groupProfile.image override val image get() = groupProfile.image
@@ -569,6 +577,7 @@ class GroupInfo (
localDisplayName = "team", localDisplayName = "team",
groupProfile = GroupProfile.sampleData, groupProfile = GroupProfile.sampleData,
membership = GroupMember.sampleData, membership = GroupMember.sampleData,
chatSettings = ChatSettings(true),
createdAt = Clock.System.now(), createdAt = Clock.System.now(),
updatedAt = Clock.System.now() updatedAt = Clock.System.now()
) )
@@ -770,6 +779,7 @@ class UserContactRequest (
override val apiId get() = contactRequestId override val apiId get() = contactRequestId
override val ready get() = true override val ready get() = true
override val sendMsgEnabled get() = false override val sendMsgEnabled get() = false
override val ntfsEnabled get() = false
override val displayName get() = profile.displayName override val displayName get() = profile.displayName
override val fullName get() = profile.fullName override val fullName get() = profile.fullName
override val image get() = profile.image override val image get() = profile.image
@@ -799,6 +809,7 @@ class PendingContactConnection(
override val apiId get() = pccConnId override val apiId get() = pccConnId
override val ready get() = false override val ready get() = false
override val sendMsgEnabled get() = false override val sendMsgEnabled get() = false
override val ntfsEnabled get() = false
override val localDisplayName get() = String.format(generalGetString(R.string.connection_local_display_name), pccConnId) override val localDisplayName get() = String.format(generalGetString(R.string.connection_local_display_name), pccConnId)
override val displayName: String get() { override val displayName: String get() {
val initiated = pccConnStatus.initiated val initiated = pccConnStatus.initiated

View File

@@ -64,6 +64,8 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
} }
fun notifyMessageReceived(cInfo: ChatInfo, cItem: ChatItem) { fun notifyMessageReceived(cInfo: ChatInfo, cItem: ChatItem) {
if (!cInfo.ntfsEnabled) return
notifyMessageReceived(chatId = cInfo.id, displayName = cInfo.displayName, msgText = hideSecrets(cItem)) notifyMessageReceived(chatId = cInfo.id, displayName = cInfo.displayName, msgText = hideSecrets(cItem))
} }

View File

@@ -388,6 +388,17 @@ open class ChatController(private val ctrl: ChatCtrl, val ntfManager: NtfManager
} }
} }
suspend fun apiSetSettings(type: ChatType,id: Long, settings: ChatSettings): Boolean {
val r = sendCmd(CC.APISetChatSettings(type, id, settings))
return when (r) {
is CR.CmdOk -> true
else -> {
Log.e(TAG, "apiSetSettings bad response: ${r.responseType} ${r.details}")
false
}
}
}
suspend fun apiContactInfo(contactId: Long): ConnectionStats? { suspend fun apiContactInfo(contactId: Long): ConnectionStats? {
val r = sendCmd(CC.APIContactInfo(contactId)) val r = sendCmd(CC.APIContactInfo(contactId))
if (r is CR.ContactInfo) return r.connectionStats if (r is CR.ContactInfo) return r.connectionStats
@@ -942,7 +953,7 @@ open class ChatController(private val ctrl: ChatCtrl, val ntfManager: NtfManager
} }
}, },
confirmButton = { confirmButton = {
Button(onClick = AlertManager.shared::hideAlert) { Text(stringResource(R.string.ok)) } TextButton(onClick = AlertManager.shared::hideAlert) { Text(stringResource(R.string.ok)) }
} }
) )
} }
@@ -973,7 +984,7 @@ open class ChatController(private val ctrl: ChatCtrl, val ntfManager: NtfManager
} }
}, },
confirmButton = { confirmButton = {
Button(onClick = ignoreOptimization) { Text(stringResource(R.string.ok)) } TextButton(onClick = ignoreOptimization) { Text(stringResource(R.string.ok)) }
} }
) )
} }
@@ -999,7 +1010,7 @@ open class ChatController(private val ctrl: ChatCtrl, val ntfManager: NtfManager
} }
}, },
confirmButton = { confirmButton = {
Button(onClick = AlertManager.shared::hideAlert) { Text(stringResource(R.string.ok)) } TextButton(onClick = AlertManager.shared::hideAlert) { Text(stringResource(R.string.ok)) }
} }
) )
} }

View File

@@ -43,11 +43,43 @@ fun ChatInfoView(chatModel: ChatModel, connStats: ConnectionStats?, close: () ->
connStats, connStats,
developerTools, developerTools,
deleteContact = { deleteContactDialog(chat.chatInfo, chatModel, close) }, deleteContact = { deleteContactDialog(chat.chatInfo, chatModel, close) },
clearChat = { clearChatDialog(chat.chatInfo, chatModel, close) } clearChat = { clearChatDialog(chat.chatInfo, chatModel, close) },
changeNtfsState = { enabled ->
changeNtfsState(enabled, chat, chatModel)
},
) )
} }
} }
fun changeNtfsState(enabled: Boolean, chat: Chat, chatModel: ChatModel) {
val newChatInfo = when(chat.chatInfo) {
is ChatInfo.Direct -> with (chat.chatInfo) {
ChatInfo.Direct(contact.copy(chatSettings = contact.chatSettings.copy(enableNtfs = enabled)))
}
is ChatInfo.Group -> with(chat.chatInfo) {
ChatInfo.Group(groupInfo.copy(chatSettings = groupInfo.chatSettings.copy(enableNtfs = enabled)))
}
else -> null
}
withApi {
val res = when (newChatInfo) {
is ChatInfo.Direct -> with(newChatInfo) {
chatModel.controller.apiSetSettings(chatType, apiId, contact.chatSettings)
}
is ChatInfo.Group -> with(newChatInfo) {
chatModel.controller.apiSetSettings(chatType, apiId, groupInfo.chatSettings)
}
else -> false
}
if (res && newChatInfo != null) {
chatModel.updateChatInfo(newChatInfo)
if (!enabled) {
chatModel.controller.ntfManager.cancelNotificationsForChat(chat.id)
}
}
}
}
fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) { fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) {
AlertManager.shared.showAlertMsg( AlertManager.shared.showAlertMsg(
title = generalGetString(R.string.delete_contact_question), title = generalGetString(R.string.delete_contact_question),
@@ -91,7 +123,8 @@ fun ChatInfoLayout(
connStats: ConnectionStats?, connStats: ConnectionStats?,
developerTools: Boolean, developerTools: Boolean,
deleteContact: () -> Unit, deleteContact: () -> Unit,
clearChat: () -> Unit clearChat: () -> Unit,
changeNtfsState: (Boolean) -> Unit,
) { ) {
Column( Column(
Modifier Modifier
@@ -126,6 +159,17 @@ fun ChatInfoLayout(
SectionSpacer() SectionSpacer()
} }
var ntfsEnabled by remember { mutableStateOf(chat.chatInfo.ntfsEnabled) }
SectionView(title = stringResource(R.string.settings_section_title_settings)) {
SectionItemView {
NtfsSwitch(ntfsEnabled) {
ntfsEnabled = !ntfsEnabled
changeNtfsState(ntfsEnabled)
}
}
}
SectionSpacer()
SectionView { SectionView {
SectionItemView { SectionItemView {
ClearChatButton(clearChat) ClearChatButton(clearChat)
@@ -236,6 +280,38 @@ fun SimplexServers(text: String, servers: List<String>) {
} }
} }
@Composable
fun NtfsSwitch(
ntfsEnabled: Boolean,
toggleNtfs: (Boolean) -> Unit
) {
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(
Icons.Outlined.Notifications,
stringResource(R.string.notifications),
tint = HighOrLowlight
)
Text(stringResource(R.string.notifications))
}
Switch(
checked = ntfsEnabled,
onCheckedChange = toggleNtfs,
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.colors.primary,
uncheckedThumbColor = HighOrLowlight
),
)
}
}
@Composable @Composable
fun ClearChatButton(clearChat: () -> Unit) { fun ClearChatButton(clearChat: () -> Unit) {
Row( Row(
@@ -282,6 +358,7 @@ fun PreviewChatInfoLayout() {
chatItems = arrayListOf(), chatItems = arrayListOf(),
serverInfo = Chat.ServerInfo(Chat.NetworkStatus.Error("agent BROKER TIMEOUT")) serverInfo = Chat.ServerInfo(Chat.NetworkStatus.Error("agent BROKER TIMEOUT"))
), ),
changeNtfsState = {},
developerTools = false, developerTools = false,
connStats = null, connStats = null,
deleteContact = {}, clearChat = {} deleteContact = {}, clearChat = {}

View File

@@ -11,7 +11,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.* import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -72,7 +72,10 @@ fun GroupChatInfoView(chatModel: ChatModel, close: () -> Unit) {
}, },
deleteGroup = { deleteGroupDialog(chat.chatInfo, chatModel, close) }, deleteGroup = { deleteGroupDialog(chat.chatInfo, chatModel, close) },
clearChat = { clearChatDialog(chat.chatInfo, chatModel, close) }, clearChat = { clearChatDialog(chat.chatInfo, chatModel, close) },
leaveGroup = { leaveGroupDialog(groupInfo, chatModel, close) } leaveGroup = { leaveGroupDialog(groupInfo, chatModel, close) },
changeNtfsState = { enabled ->
changeNtfsState(enabled, chat, chatModel)
},
) )
} }
} }
@@ -122,6 +125,7 @@ fun GroupChatInfoLayout(
deleteGroup: () -> Unit, deleteGroup: () -> Unit,
clearChat: () -> Unit, clearChat: () -> Unit,
leaveGroup: () -> Unit, leaveGroup: () -> Unit,
changeNtfsState: (Boolean) -> Unit,
) { ) {
Column( Column(
Modifier Modifier
@@ -154,6 +158,17 @@ fun GroupChatInfoLayout(
} }
SectionSpacer() SectionSpacer()
var ntfsEnabled by remember { mutableStateOf(chat.chatInfo.ntfsEnabled) }
SectionView(title = stringResource(R.string.settings_section_title_settings)) {
SectionItemView {
NtfsSwitch(ntfsEnabled) {
ntfsEnabled = !ntfsEnabled
changeNtfsState(ntfsEnabled)
}
}
}
SectionSpacer()
SectionView { SectionView {
if (groupInfo.canEdit) { if (groupInfo.canEdit) {
SectionItemView { SectionItemView {
@@ -322,7 +337,8 @@ fun PreviewGroupChatInfoLayout() {
groupInfo = GroupInfo.sampleData, groupInfo = GroupInfo.sampleData,
members = listOf(GroupMember.sampleData, GroupMember.sampleData, GroupMember.sampleData), members = listOf(GroupMember.sampleData, GroupMember.sampleData, GroupMember.sampleData),
developerTools = false, developerTools = false,
addMembers = {}, showMemberInfo = {}, editGroupProfile = {}, deleteGroup = {}, clearChat = {}, leaveGroup = {} addMembers = {}, showMemberInfo = {}, editGroupProfile = {}, deleteGroup = {}, clearChat = {}, leaveGroup = {},
changeNtfsState = {},
) )
} }
} }

View File

@@ -184,13 +184,13 @@ fun deleteMessageAlertDialog(chatItem: ChatItem, deleteMessage: (Long, CIDeleteM
.padding(horizontal = 8.dp, vertical = 2.dp), .padding(horizontal = 8.dp, vertical = 2.dp),
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
) { ) {
Button(onClick = { TextButton(onClick = {
deleteMessage(chatItem.id, CIDeleteMode.cidmInternal) deleteMessage(chatItem.id, CIDeleteMode.cidmInternal)
AlertManager.shared.hideAlert() AlertManager.shared.hideAlert()
}) { Text(stringResource(R.string.for_me_only)) } }) { Text(stringResource(R.string.for_me_only)) }
if (chatItem.meta.editable) { if (chatItem.meta.editable) {
Spacer(Modifier.padding(horizontal = 4.dp)) Spacer(Modifier.padding(horizontal = 4.dp))
Button(onClick = { TextButton(onClick = {
deleteMessage(chatItem.id, CIDeleteMode.cidmBroadcast) deleteMessage(chatItem.id, CIDeleteMode.cidmBroadcast)
AlertManager.shared.hideAlert() AlertManager.shared.hideAlert()
}) { Text(stringResource(R.string.for_everybody)) } }) { Text(stringResource(R.string.for_everybody)) }

View File

@@ -119,6 +119,7 @@ fun ContactMenuItems(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Bo
if (showMarkRead) { if (showMarkRead) {
MarkReadChatAction(chat, chatModel, showMenu) MarkReadChatAction(chat, chatModel, showMenu)
} }
ToggleNotificationsChatAction(chat, chatModel, chat.chatInfo.ntfsEnabled, showMenu)
ClearChatAction(chat, chatModel, showMenu) ClearChatAction(chat, chatModel, showMenu)
DeleteContactAction(chat, chatModel, showMenu) DeleteContactAction(chat, chatModel, showMenu)
} }
@@ -136,6 +137,7 @@ fun GroupMenuItems(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, showM
if (showMarkRead) { if (showMarkRead) {
MarkReadChatAction(chat, chatModel, showMenu) MarkReadChatAction(chat, chatModel, showMenu)
} }
ToggleNotificationsChatAction(chat, chatModel, chat.chatInfo.ntfsEnabled, showMenu)
ClearChatAction(chat, chatModel, showMenu) ClearChatAction(chat, chatModel, showMenu)
if (groupInfo.membership.memberCurrent) { if (groupInfo.membership.memberCurrent) {
LeaveGroupAction(groupInfo, chatModel, showMenu) LeaveGroupAction(groupInfo, chatModel, showMenu)
@@ -160,6 +162,18 @@ fun MarkReadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<
) )
} }
@Composable
fun ToggleNotificationsChatAction(chat: Chat, chatModel: ChatModel, ntfsEnabled: Boolean, showMenu: MutableState<Boolean>) {
ItemAction(
if (ntfsEnabled) stringResource(R.string.mute_chat) else stringResource(R.string.unmute_chat),
if (ntfsEnabled) Icons.Outlined.NotificationsOff else Icons.Outlined.Notifications,
onClick = {
changeNtfsState(!ntfsEnabled, chat, chatModel)
showMenu.value = false
}
)
}
@Composable @Composable
fun ClearChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Boolean>) { fun ClearChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<Boolean>) {
ItemAction( ItemAction(
@@ -318,14 +332,14 @@ fun contactConnectionAlertDialog(connection: PendingContactConnection, chatModel
.padding(horizontal = 8.dp, vertical = 2.dp), .padding(horizontal = 8.dp, vertical = 2.dp),
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
) { ) {
Button(onClick = { TextButton(onClick = {
AlertManager.shared.hideAlert() AlertManager.shared.hideAlert()
deleteContactConnectionAlert(connection, chatModel) deleteContactConnectionAlert(connection, chatModel)
}) { }) {
Text(stringResource(R.string.delete_verb)) Text(stringResource(R.string.delete_verb))
} }
Spacer(Modifier.padding(horizontal = 4.dp)) Spacer(Modifier.padding(horizontal = 4.dp))
Button(onClick = { AlertManager.shared.hideAlert() }) { TextButton(onClick = { AlertManager.shared.hideAlert() }) {
Text(stringResource(R.string.ok)) Text(stringResource(R.string.ok))
} }
} }

View File

@@ -8,7 +8,8 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Cancel import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.outlined.ErrorOutline import androidx.compose.material.icons.filled.NotificationsOff
import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -23,8 +24,7 @@ import chat.simplex.app.R
import chat.simplex.app.model.* import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.* import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.chat.item.MarkdownText import chat.simplex.app.views.chat.item.MarkdownText
import chat.simplex.app.views.helpers.ChatInfoImage import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.helpers.badgeLayout
@Composable @Composable
fun ChatPreviewView(chat: Chat, stopped: Boolean) { fun ChatPreviewView(chat: Chat, stopped: Boolean) {
@@ -134,6 +134,7 @@ fun ChatPreviewView(chat: Chat, stopped: Boolean) {
modifier = Modifier.padding(bottom = 5.dp) modifier = Modifier.padding(bottom = 5.dp)
) )
val n = chat.chatStats.unreadCount val n = chat.chatStats.unreadCount
val showNtfsIcon = !chat.chatInfo.ntfsEnabled && (chat.chatInfo is ChatInfo.Direct || chat.chatInfo is ChatInfo.Group)
if (n > 0) { if (n > 0) {
Box( Box(
Modifier.padding(top = 24.dp), Modifier.padding(top = 24.dp),
@@ -144,12 +145,27 @@ fun ChatPreviewView(chat: Chat, stopped: Boolean) {
color = MaterialTheme.colors.onPrimary, color = MaterialTheme.colors.onPrimary,
fontSize = 11.sp, fontSize = 11.sp,
modifier = Modifier modifier = Modifier
.background(if (stopped) HighOrLowlight else MaterialTheme.colors.primary, shape = CircleShape) .background(if (stopped || showNtfsIcon) HighOrLowlight else MaterialTheme.colors.primary, shape = CircleShape)
.badgeLayout() .badgeLayout()
.padding(horizontal = 3.dp) .padding(horizontal = 3.dp)
.padding(vertical = 1.dp) .padding(vertical = 1.dp)
) )
} }
} else if (showNtfsIcon) {
Box(
Modifier.padding(top = 24.dp),
contentAlignment = Alignment.Center
) {
Icon(
Icons.Filled.NotificationsOff,
contentDescription = generalGetString(R.string.notifications),
tint = HighOrLowlight,
modifier = Modifier
.padding(horizontal = 3.dp)
.padding(vertical = 1.dp)
.size(17.dp)
)
}
} }
if (cInfo is ChatInfo.Direct) { if (cInfo is ChatInfo.Direct) {
Box( Box(

View File

@@ -53,13 +53,13 @@ class AlertManager {
title = { Text(title) }, title = { Text(title) },
text = alertText, text = alertText,
confirmButton = { confirmButton = {
Button(onClick = { TextButton(onClick = {
onConfirm?.invoke() onConfirm?.invoke()
hideAlert() hideAlert()
}) { Text(confirmText) } }) { Text(confirmText) }
}, },
dismissButton = { dismissButton = {
Button(onClick = { TextButton(onClick = {
onDismiss?.invoke() onDismiss?.invoke()
hideAlert() hideAlert()
}) { Text(dismissText) } }) { Text(dismissText) }

View File

@@ -141,6 +141,9 @@
<string name="file_not_found">Файл не найден</string> <string name="file_not_found">Файл не найден</string>
<string name="error_saving_file">Ошибка сохранения файла</string> <string name="error_saving_file">Ошибка сохранения файла</string>
<!-- Chat Info Settings - ChatInfoView.kt -->
<string name="notifications">Уведомления</string>
<!-- Chat Info Actions - ChatInfoView.kt --> <!-- Chat Info Actions - ChatInfoView.kt -->
<string name="delete_contact_question">Удалить контакт?</string> <string name="delete_contact_question">Удалить контакт?</string>
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">Контакт и все сообщения будут удалены - это действие нельзя отменить!</string> <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Контакт и все сообщения будут удалены - это действие нельзя отменить!</string>
@@ -205,6 +208,10 @@
<string name="clear_chat_button">Очистить чат</string> <string name="clear_chat_button">Очистить чат</string>
<string name="mark_read">Прочитано</string> <string name="mark_read">Прочитано</string>
<!-- Actions - ChatListNavLinkView.kt -->
<string name="mute_chat">Без звука</string>
<string name="unmute_chat">Уведомлять</string>
<!-- Pending contact connection alert dialogues --> <!-- Pending contact connection alert dialogues -->
<string name="you_invited_your_contact">Вы пригласили ваш контакт</string> <string name="you_invited_your_contact">Вы пригласили ваш контакт</string>
<string name="you_accepted_connection">Вы приняли приглашение соединиться</string> <string name="you_accepted_connection">Вы приняли приглашение соединиться</string>

View File

@@ -141,6 +141,9 @@
<string name="file_not_found">File not found</string> <string name="file_not_found">File not found</string>
<string name="error_saving_file">Error saving file</string> <string name="error_saving_file">Error saving file</string>
<!-- Chat Info Settings - ChatInfoView.kt -->
<string name="notifications">Notifications</string>
<!-- Chat Info Actions - ChatInfoView.kt --> <!-- Chat Info Actions - ChatInfoView.kt -->
<string name="delete_contact_question">Delete contact?</string> <string name="delete_contact_question">Delete contact?</string>
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">Contact and all messages will be deleted - this cannot be undone!</string> <string name="delete_contact_all_messages_deleted_cannot_undo_warning">Contact and all messages will be deleted - this cannot be undone!</string>
@@ -205,6 +208,10 @@
<string name="clear_chat_button">Clear chat</string> <string name="clear_chat_button">Clear chat</string>
<string name="mark_read">Mark read</string> <string name="mark_read">Mark read</string>
<!-- Actions - ChatListNavLinkView.kt -->
<string name="mute_chat">Mute</string>
<string name="unmute_chat">Unmute</string>
<!-- Pending contact connection alert dialogues --> <!-- Pending contact connection alert dialogues -->
<string name="you_invited_your_contact">You invited your contact</string> <string name="you_invited_your_contact">You invited your contact</string>
<string name="you_accepted_connection">You accepted connection</string> <string name="you_accepted_connection">You accepted connection</string>