Skip to content

Commit

Permalink
Support member milestone messages
Browse files Browse the repository at this point in the history
Pending actual test in live stream, but this is based on data from an archive stream.
  • Loading branch information
arkon committed May 18, 2024
1 parent 84b0133 commit 4a491c0
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 96 deletions.
16 changes: 16 additions & 0 deletions app/src/main/assets/ChatInjector.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ const messageReceiveCallback = async (response) => {
return;
}

const headerRuns = [];
if (messageItem.headerPrimaryText && messageItem.headerPrimaryText.runs) {
messageItem.headerPrimaryText.runs.forEach((run) => {
if (run.text) {
headerRuns.push({
type: 'text',
text: decodeURIComponent(escape(unescape(encodeURIComponent(
run.text
))))
});
}
});
}

let isAuthorModerator = false;
let isAuthorVerified = false;
let isAuthorOwner = false;
Expand Down Expand Up @@ -134,6 +148,7 @@ const messageReceiveCallback = async (response) => {

const timestampUsec = parseInt(messageItem.timestampUsec, 10);
const authorThumbnails = messageItem.authorPhoto.thumbnails;
// Corresponds with "YTChatMessage" data class in Models.kt
const item = {
author: {
name: messageItem.authorName.simpleText,
Expand All @@ -146,6 +161,7 @@ const messageReceiveCallback = async (response) => {
membershipBadge: authorMembership,
},
messages: runs,
headerRuns: headerRuns,
timestamp: timestampUsec,
delay: isReplay
? getUsec(messageItem.timestampText.simpleText, timestampUsec)
Expand Down
39 changes: 28 additions & 11 deletions app/src/main/kotlin/com/livetl/android/data/chat/Models.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.livetl.android.data.chat

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.util.fastFilter
import androidx.compose.ui.util.fastMap
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -42,22 +43,25 @@ sealed class ChatMessage {
val textColor = Color.White
}

data class MemberMilestone(
override val author: MessageAuthor,
override val content: List<ChatMessageContent>,
override val timestamp: Long,
val milestone: String,
) : ChatMessage() {
val backgroundColor = Color(0xFF0E9D58)
val textColor = Color.White
}

fun getTextContent(): String = content
.joinToString("") { it.toString() }
.trim()

fun withContent(newContent: List<ChatMessageContent>): ChatMessage = when (this) {
is RegularChat -> {
copy(content = newContent)
}

is SuperChat -> {
copy(content = newContent)
}

is NewMember -> {
this
}
is RegularChat -> copy(content = newContent)
is SuperChat -> copy(content = newContent)
is MemberMilestone -> copy(content = newContent)
is NewMember -> this
}
}

Expand Down Expand Up @@ -107,6 +111,7 @@ data class YTChatMessages(val messages: List<YTChatMessage>, val isReplay: Boole
data class YTChatMessage(
val author: YTChatAuthor,
val messages: List<YTChatMessageData>,
val headerRuns: List<YTChatMessageData>,
val timestamp: Long,
val delay: Long? = null,
val superchat: YTSuperChat? = null,
Expand All @@ -129,6 +134,18 @@ data class YTChatMessage(
)
}

headerRuns.isNotEmpty() -> {
ChatMessage.MemberMilestone(
author = author.toMessageAuthor(),
content = messages.fastMap { it.toChatMessageContent() },
timestamp = timestamp,
milestone = headerRuns
.fastMap { it.toChatMessageContent() }
.filterIsInstance<ChatMessageContent.Text>()
.joinToString { it.text },
)
}

else -> {
ChatMessage.RegularChat(
author = author.toMessageAuthor(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.livetl.android.ui.screen.player.composable.chat

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
Expand All @@ -20,13 +19,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.livetl.android.R
import com.livetl.android.data.chat.ChatMessage
import com.livetl.android.data.chat.ChatMessageContent
import com.livetl.android.data.chat.MessageAuthor
import com.livetl.android.ui.common.LoadingIndicator
import com.livetl.android.ui.screen.player.PlayerViewModel
import kotlinx.collections.immutable.ImmutableList
Expand Down Expand Up @@ -119,83 +115,3 @@ fun Chat(
null -> {}
}
}

@Preview
@Composable
private fun RegularChatPreviews() {
val author = MessageAuthor(
id = "1",
name = "Name",
)

Column {
Message(
message = ChatMessage.RegularChat(
author = author,
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)

Message(
message = ChatMessage.RegularChat(
author = author.copy(isModerator = true),
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)

Message(
message = ChatMessage.RegularChat(
author = author.copy(isVerified = true),
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)

Message(
message = ChatMessage.RegularChat(
author = author.copy(isOwner = true),
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)
}
}

@Preview
@Composable
private fun SuperChatPreview() {
Message(
message = ChatMessage.SuperChat(
author = MessageAuthor(
id = "2",
name = "Pekora Shachou",
),
content = listOf(ChatMessageContent.Text("HA↑HA↓HA↑HA↓ PE↗KO↘PE↗KO↘ 😂")),
timestamp = 1615001105,
amount = "$100.00",
level = ChatMessage.SuperChat.Level.RED,
),
emojiCache = EmojiCache(),
)
}

@Preview
@Composable
private fun NewMemberPreview() {
Message(
message = ChatMessage.NewMember(
author = MessageAuthor(
id = "3",
name = "Ina Ina Ina",
),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.livetl.android.ui.screen.player.composable.chat

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidth
Expand All @@ -26,6 +27,7 @@ import androidx.compose.ui.text.PlaceholderVerticalAlign
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
Expand All @@ -43,6 +45,7 @@ fun Message(message: ChatMessage, emojiCache: EmojiCache, modifier: Modifier = M
is ChatMessage.RegularChat -> LocalContentColor.current
is ChatMessage.SuperChat -> message.level.textColor
is ChatMessage.NewMember -> message.textColor
is ChatMessage.MemberMilestone -> message.textColor
}

val text = buildAnnotatedString {
Expand Down Expand Up @@ -75,6 +78,18 @@ fun Message(message: ChatMessage, emojiCache: EmojiCache, modifier: Modifier = M
)
}

if (message is ChatMessage.MemberMilestone) {
append(
AnnotatedString(
text = "${message.milestone} ",
spanStyle = SpanStyle(
color = textColor,
fontWeight = FontWeight.Bold,
)
)
)
}

// Actual chat message contents
if (message is ChatMessage.NewMember) {
append(stringResource(R.string.new_member))
Expand All @@ -99,10 +114,15 @@ fun Message(message: ChatMessage, emojiCache: EmojiCache, modifier: Modifier = M
.clip(ChatShape)
.background(color = message.backgroundColor)
.chatPadding()
is ChatMessage.MemberMilestone ->
modifier
.clip(ChatShape)
.background(color = message.backgroundColor)
.chatPadding()
},
text = text,
style = MaterialTheme.typography.bodyMedium.copy(
color = LocalContentColor.current,
color = textColor,
fontSize = MaterialTheme.typography.bodyMedium.fontSize * fontScale,
),
inlineContent = message.author.getPhotoInlineContent() +
Expand Down Expand Up @@ -183,3 +203,102 @@ private val parsedContentTypes = setOf(
SymbolAnnotationType.LINK.name,
SymbolAnnotationType.EMOJI.name,
)


@Preview
@Composable
private fun RegularChatPreviews() {
val author = MessageAuthor(
id = "1",
name = "Name",
)

Column {
Message(
message = ChatMessage.RegularChat(
author = author,
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)

Message(
message = ChatMessage.RegularChat(
author = author.copy(isModerator = true),
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)

Message(
message = ChatMessage.RegularChat(
author = author.copy(isVerified = true),
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)

Message(
message = ChatMessage.RegularChat(
author = author.copy(isOwner = true),
content = listOf(ChatMessageContent.Text("Hello world")),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)
}
}

@Preview
@Composable
private fun SuperChatPreview() {
Message(
message = ChatMessage.SuperChat(
author = MessageAuthor(
id = "2",
name = "Pekora Shachou",
),
content = listOf(ChatMessageContent.Text("HA↑HA↓HA↑HA↓ PE↗KO↘PE↗KO↘ 😂")),
timestamp = 1615001105,
amount = "$100.00",
level = ChatMessage.SuperChat.Level.RED,
),
emojiCache = EmojiCache(),
)
}

@Preview
@Composable
private fun NewMemberPreview() {
Message(
message = ChatMessage.NewMember(
author = MessageAuthor(
id = "3",
name = "Ina Ina Ina",
),
timestamp = 1615001105,
),
emojiCache = EmojiCache(),
)
}


@Preview
@Composable
private fun MemberMilestonePreview() {
Message(
message = ChatMessage.MemberMilestone(
author = MessageAuthor(
id = "4",
name = "Rose",
),
content = listOf(ChatMessageContent.Text("It's been 84 years...")),
timestamp = 1615001105,
milestone = "Member for 84 years",
),
emojiCache = EmojiCache(),
)
}

0 comments on commit 4a491c0

Please sign in to comment.