Skip to content

Commit fc7923d

Browse files
Merge pull request #6026 from nextcloud/fix/6025/chatDarkMode
Fix chat dark mode
2 parents 0f98a2b + f9f3508 commit fc7923d

11 files changed

Lines changed: 235 additions & 158 deletions

File tree

app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -557,20 +557,22 @@ class ChatActivity :
557557

558558
private fun setPinnedMessageContent() {
559559
binding.pinnedMessageComposeView.setContent {
560-
val uiState by chatViewModel.uiState.collectAsStateWithLifecycle()
561-
val pinnedMessage = uiState.pinnedMessage
562-
binding.pinnedMessageContainer.visibility = if (pinnedMessage != null) View.VISIBLE else View.GONE
563-
if (pinnedMessage != null) {
564-
PinnedMessageView(
565-
message = pinnedMessage,
566-
viewThemeUtils = viewThemeUtils,
567-
currentConversation = uiState.conversation,
568-
scrollToMessageWithIdWithOffset = { messageId ->
569-
scrollToMessageById(messageId.toLong())
570-
},
571-
hidePinnedMessage = ::hidePinnedMessage,
572-
unPinMessage = ::unPinMessage
573-
)
560+
MaterialTheme(colorScheme = viewThemeUtils.getColorScheme(this@ChatActivity)) {
561+
val uiState by chatViewModel.uiState.collectAsStateWithLifecycle()
562+
val pinnedMessage = uiState.pinnedMessage
563+
binding.pinnedMessageContainer.visibility = if (pinnedMessage != null) View.VISIBLE else View.GONE
564+
if (pinnedMessage != null) {
565+
PinnedMessageView(
566+
message = pinnedMessage,
567+
viewThemeUtils = viewThemeUtils,
568+
currentConversation = uiState.conversation,
569+
scrollToMessageWithIdWithOffset = { messageId ->
570+
scrollToMessageById(messageId.toLong())
571+
},
572+
hidePinnedMessage = ::hidePinnedMessage,
573+
unPinMessage = ::unPinMessage
574+
)
575+
}
574576
}
575577
}
576578
}
@@ -591,41 +593,43 @@ class ChatActivity :
591593

592594
private fun setChatListContent() {
593595
binding.messagesListViewCompose.setContent {
594-
val uiState by chatViewModel.uiState.collectAsStateWithLifecycle()
595-
currentConversation = uiState.conversation
596+
MaterialTheme(colorScheme = viewThemeUtils.getColorScheme(this@ChatActivity)) {
597+
val uiState by chatViewModel.uiState.collectAsStateWithLifecycle()
598+
currentConversation = uiState.conversation
596599

597-
binding.messagesListViewCompose.visibility = View.VISIBLE
600+
binding.messagesListViewCompose.visibility = View.VISIBLE
598601

599-
val listState = rememberLazyListState()
600-
SideEffect { chatListState = listState }
602+
val listState = rememberLazyListState()
603+
SideEffect { chatListState = listState }
601604

602-
CompositionLocalProvider(
603-
LocalViewThemeUtils provides viewThemeUtils,
604-
LocalMessageUtils provides messageUtils,
605-
LocalOpenGraphFetcher provides { url -> chatViewModel.fetchOpenGraph(url) }
606-
) {
607-
val isOneToOneConversation = uiState.isOneToOneConversation
608-
Log.d(TAG, "isOneToOneConversation=" + isOneToOneConversation)
609-
610-
ChatView(
611-
chatItems = uiState.items,
612-
isOneToOneConversation = isOneToOneConversation,
613-
conversationThreadId = conversationThreadId,
614-
onLoadMore = { loadMoreMessagesCompose() },
615-
advanceLocalLastReadMessageIfNeeded = { advanceLocalLastReadMessageIfNeeded(it) },
616-
updateRemoteLastReadMessageIfNeeded = { updateRemoteLastReadMessageIfNeeded() },
617-
onLongClick = { openMessageActionsDialog(it) },
618-
onFileClick = { downloadAndOpenFile(it) },
619-
onPollClick = { pollId, pollName -> openPollDialog(pollId, pollName) },
620-
onVoicePlayPauseClick = { onVoicePlayPauseClickCompose(it) },
621-
onVoiceSeek = { _, progress -> chatViewModel.seekToMediaPlayer(progress) },
622-
onVoiceSpeedClick = { onVoiceSpeedClickCompose(it) },
623-
onReactionClick = { messageId, emoji -> handleReactionClick(messageId, emoji) },
624-
onReactionLongClick = { messageId -> openReactionsDialog(messageId) },
625-
onOpenThreadClick = { messageId -> openThread(messageId.toLong()) },
626-
onLoadQuotedMessageClick = { messageId -> onLoadQuotedMessage(messageId) },
627-
listState = listState
628-
)
605+
CompositionLocalProvider(
606+
LocalViewThemeUtils provides viewThemeUtils,
607+
LocalMessageUtils provides messageUtils,
608+
LocalOpenGraphFetcher provides { url -> chatViewModel.fetchOpenGraph(url) }
609+
) {
610+
val isOneToOneConversation = uiState.isOneToOneConversation
611+
Log.d(TAG, "isOneToOneConversation=" + isOneToOneConversation)
612+
613+
ChatView(
614+
chatItems = uiState.items,
615+
isOneToOneConversation = isOneToOneConversation,
616+
conversationThreadId = conversationThreadId,
617+
onLoadMore = { loadMoreMessagesCompose() },
618+
advanceLocalLastReadMessageIfNeeded = { advanceLocalLastReadMessageIfNeeded(it) },
619+
updateRemoteLastReadMessageIfNeeded = { updateRemoteLastReadMessageIfNeeded() },
620+
onLongClick = { openMessageActionsDialog(it) },
621+
onFileClick = { downloadAndOpenFile(it) },
622+
onPollClick = { pollId, pollName -> openPollDialog(pollId, pollName) },
623+
onVoicePlayPauseClick = { onVoicePlayPauseClickCompose(it) },
624+
onVoiceSeek = { _, progress -> chatViewModel.seekToMediaPlayer(progress) },
625+
onVoiceSpeedClick = { onVoiceSpeedClickCompose(it) },
626+
onReactionClick = { messageId, emoji -> handleReactionClick(messageId, emoji) },
627+
onReactionLongClick = { messageId -> openReactionsDialog(messageId) },
628+
onOpenThreadClick = { messageId -> openThread(messageId.toLong()) },
629+
onLoadQuotedMessageClick = { messageId -> onLoadQuotedMessage(messageId) },
630+
listState = listState
631+
)
632+
}
629633
}
630634
}
631635
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Nextcloud Talk - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: GPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.talk.ui.chat
9+
10+
import android.content.res.Configuration
11+
import androidx.compose.foundation.isSystemInDarkTheme
12+
import androidx.compose.material3.MaterialTheme
13+
import androidx.compose.material3.darkColorScheme
14+
import androidx.compose.material3.lightColorScheme
15+
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.CompositionLocalProvider
17+
import androidx.compose.runtime.remember
18+
import androidx.compose.ui.platform.LocalContext
19+
import androidx.compose.ui.tooling.preview.Preview
20+
import com.nextcloud.talk.chat.ui.model.ChatMessageUi
21+
import com.nextcloud.talk.chat.ui.model.MessageReactionUi
22+
import com.nextcloud.talk.chat.ui.model.MessageStatusIcon
23+
import com.nextcloud.talk.chat.ui.model.MessageTypeContent
24+
import com.nextcloud.talk.ui.theme.LocalViewThemeUtils
25+
import com.nextcloud.talk.utils.preview.ComposePreviewUtils
26+
import java.time.LocalDate
27+
28+
internal val previewReactions = listOf(
29+
MessageReactionUi(emoji = "👍", amount = 1, isSelfReaction = true),
30+
MessageReactionUi(emoji = "❤️", amount = 1, isSelfReaction = false)
31+
)
32+
33+
@Preview(showBackground = true, name = "Light")
34+
@Preview(
35+
showBackground = true,
36+
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL,
37+
name = "Dark"
38+
)
39+
@Preview(showBackground = true, locale = "ar", name = "RTL Arabic")
40+
internal annotation class ChatMessagePreviews
41+
42+
@Composable
43+
internal fun PreviewContainer(content: @Composable () -> Unit) {
44+
val context = LocalContext.current
45+
val previewUtils = remember { ComposePreviewUtils.getInstance(context) }
46+
val colorScheme = if (isSystemInDarkTheme()) darkColorScheme() else lightColorScheme()
47+
48+
CompositionLocalProvider(
49+
LocalViewThemeUtils provides previewUtils.viewThemeUtils
50+
) {
51+
MaterialTheme(colorScheme = colorScheme) {
52+
content()
53+
}
54+
}
55+
}
56+
57+
internal fun createBaseMessage(content: MessageTypeContent?): ChatMessageUi =
58+
ChatMessageUi(
59+
id = 1,
60+
message = "Sample message text",
61+
plainMessage = "Sample message text",
62+
renderMarkdown = false,
63+
actorDisplayName = "John Doe",
64+
isThread = false,
65+
threadTitle = "",
66+
threadReplies = 0,
67+
incoming = true,
68+
isDeleted = false,
69+
avatarUrl = null,
70+
statusIcon = MessageStatusIcon.SENT,
71+
timestamp = System.currentTimeMillis() / 1000,
72+
date = LocalDate.now(),
73+
content = content,
74+
reactions = previewReactions
75+
)
76+
77+
internal fun createBaseMessageWithoutCaption(content: MessageTypeContent?): ChatMessageUi =
78+
ChatMessageUi(
79+
id = 1,
80+
message = "",
81+
plainMessage = "",
82+
renderMarkdown = false,
83+
actorDisplayName = "John Doe",
84+
isThread = false,
85+
threadTitle = "",
86+
threadReplies = 0,
87+
incoming = true,
88+
isDeleted = false,
89+
avatarUrl = null,
90+
statusIcon = MessageStatusIcon.SENT,
91+
timestamp = System.currentTimeMillis() / 1000,
92+
date = LocalDate.now(),
93+
content = content,
94+
reactions = previewReactions
95+
)
96+
97+
internal fun createLongBaseMessage(content: MessageTypeContent?): ChatMessageUi =
98+
ChatMessageUi(
99+
id = 1,
100+
message = "Sample message text that is very very very very very long",
101+
plainMessage = "Sample message text that is very very very very very long",
102+
renderMarkdown = false,
103+
actorDisplayName = "John Doe",
104+
isThread = false,
105+
threadTitle = "",
106+
threadReplies = 0,
107+
incoming = true,
108+
isDeleted = false,
109+
avatarUrl = null,
110+
statusIcon = MessageStatusIcon.SENT,
111+
timestamp = System.currentTimeMillis() / 1000,
112+
date = LocalDate.now(),
113+
content = content,
114+
reactions = previewReactions
115+
)

app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ fun EnrichedText(message: ChatMessageUi, modifier: Modifier) {
768768
modifier = modifier,
769769
textStyle = TextStyle(
770770
fontSize = regularTextSize,
771+
color = colorScheme.onSurface,
771772
lineHeight = regularTextSize * LINE_SPACING
772773
)
773774
)

0 commit comments

Comments
 (0)