Skip to content

Commit

Permalink
name paint fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
crackededed committed Dec 15, 2024
1 parent 67338ed commit 4867387
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 9 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ android {
minSdk = 21
targetSdk = 35
versionCode = 121
versionName = "2.40.1"
versionName = "2.40.2"
}

buildTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ interface MiscApi {
@GET("https://7tv.io/v3/users/twitch/{channelId}")
suspend fun getStvEmotes(@Path("channelId") channelId: String): StvChannelResponse

@GET("https://7tv.io/v3/users/twitch/{userId}")
suspend fun getStvUser(@Path("userId") userId: String): ResponseBody

@POST("https://7tv.io/v3/users/{userId}/presences")
suspend fun sendStvPresence(@Path("userId") userId: String, @Body body: RequestBody)

@GET("https://api.betterttv.net/3/cached/emotes/global")
suspend fun getGlobalBttvEmotes(): List<BttvResponse>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
import okhttp3.Credentials
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.Response
import java.net.InetSocketAddress
import java.net.Proxy
Expand Down Expand Up @@ -275,6 +279,23 @@ class PlayerRepository @Inject constructor(
}
}

suspend fun getStvUser(userId: String): String? = withContext(Dispatchers.IO) {
JSONObject(misc.getStvUser(userId).string()).optJSONObject("user")?.optString("id")
}

suspend fun sendStvPresence(stvUserId: String, channelId: String, sessionId: String?, self: Boolean) = withContext(Dispatchers.IO) {
val json = buildJsonObject {
put("kind", 1)
put("passive", self)
put("session_id", if (self) sessionId else "undefined")
putJsonObject("data") {
put("platform", "TWITCH")
put("id", channelId)
}
}.toString().toRequestBody()
misc.sendStvPresence(stvUserId, json)
}

suspend fun loadGlobalBttvEmotes(): List<Emote> = withContext(Dispatchers.IO) {
parseBttvEmotes(misc.getGlobalBttvEmotes())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ class ChatFragment : BaseNetworkFragment(), LifecycleListener, MessageClickedDia
val useChatWebSocket = requireContext().prefs().getBoolean(C.CHAT_USE_WEBSOCKET, false)
val useSSL = requireContext().prefs().getBoolean(C.CHAT_USE_SSL, true)
val usePubSub = requireContext().prefs().getBoolean(C.CHAT_PUBSUB_ENABLED, true)
val showNamePaints = requireContext().prefs().getBoolean(C.CHAT_SHOW_PAINTS, false)
val showNamePaints = requireContext().prefs().getBoolean(C.CHAT_SHOW_PAINTS, true)
val emoteQuality = requireContext().prefs().getString(C.CHAT_IMAGE_QUALITY, "4") ?: "4"
val animateGifs = requireContext().prefs().getBoolean(C.ANIMATED_EMOTES, true)
val showUserNotice = requireContext().prefs().getBoolean(C.CHAT_SHOW_USERNOTICE, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ class ChatViewModel @Inject constructor(
private var eventSub: EventSubWebSocket? = null
private var pubSub: PubSubWebSocket? = null
private var stvEventApi: STVEventApiWebSocket? = null
private var stvUserId: String? = null
private var stvLastPresenceUpdate: Long? = null
private val allEmotes = mutableListOf<Emote>()
private var usedRaidId: String? = null

Expand Down Expand Up @@ -588,6 +590,15 @@ class ChatViewModel @Inject constructor(
}
if (showNamePaints && !channelId.isNullOrBlank()) {
stvEventApi = STVEventApiWebSocket(channelId, okHttpClient, viewModelScope, this).apply { connect() }
if (isLoggedIn && !account.id.isNullOrBlank()) {
viewModelScope.launch {
try {
stvUserId = playerRepository.getStvUser(account.id).takeIf { !it.isNullOrBlank() }
} catch (e: Exception) {

}
}
}
}
}

Expand All @@ -605,6 +616,9 @@ class ChatViewModel @Inject constructor(
private fun onChatMessage(message: ChatMessage) {
onMessage(message)
addChatter(message.userName)
if (isLoggedIn && !account.id.isNullOrBlank() && message.userId == account.id) {
onUpdatePresence(null, false)
}
}

override fun onConnect() {
Expand Down Expand Up @@ -934,9 +948,28 @@ class ChatViewModel @Inject constructor(
}

override fun onUserUpdate(userId: String, paintId: String) {
paintUsers.entries.find { it.key == userId }?.let { paintUsers.remove(it.key) }
paintUsers.put(userId, paintId)
newPaintUser.value = Pair(userId, paintId)
val item = paintUsers.entries.find { it.key == userId }
if (item == null || item.value != paintId) {
item?.let { paintUsers.remove(it.key) }
paintUsers.put(userId, paintId)
newPaintUser.value = Pair(userId, paintId)
}
}

override fun onUpdatePresence(sessionId: String?, self: Boolean) {
stvUserId?.let { stvUserId ->
if (stvUserId.isNotBlank() && !channelId.isNullOrBlank() && (self && !sessionId.isNullOrBlank() || !self) &&
stvLastPresenceUpdate?.let { (System.currentTimeMillis() - it) > 10000 } != false) {
stvLastPresenceUpdate = System.currentTimeMillis()
viewModelScope.launch {
try {
playerRepository.sendStvPresence(stvUserId, channelId, sessionId, self)
} catch (e: Exception) {

}
}
}
}
}

fun addEmotes(list: List<Emote>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class ChatView : ConstraintLayout {
isLightTheme = context.isLightTheme,
nameDisplay = context.prefs().getString(C.UI_NAME_DISPLAY, "0"),
useBoldNames = context.prefs().getBoolean(C.CHAT_BOLDNAMES, false),
showNamePaints = context.prefs().getBoolean(C.CHAT_SHOW_PAINTS, false),
showNamePaints = context.prefs().getBoolean(C.CHAT_SHOW_PAINTS, true),
namePaintsList = namePaints,
paintUsersMap = paintUsers,
showSystemMessageEmotes = context.prefs().getBoolean(C.CHAT_SYSTEM_MESSAGE_EMOTES, true),
Expand Down Expand Up @@ -438,14 +438,23 @@ class ChatView : ConstraintLayout {
paintUsers.entries.find { it.key == pair.first }?.let { paintUsers.remove(it.key) }
paintUsers.put(pair.first, pair.second)
}
adapter.messages?.toList()?.let { messages ->
messages.filter { it.userId == pair.first }.forEach { message ->
messages.indexOf(message).takeIf { it != -1 }?.let {
adapter.notifyItemChanged(it)
}
}
}
messageDialog?.adapter?.paintUsers?.let { paintUsers ->
paintUsers.entries.find { it.key == pair.first }?.let { paintUsers.remove(it.key) }
paintUsers.put(pair.first, pair.second)
}
messageDialog?.updatePaint(pair.first)
replyDialog?.adapter?.paintUsers?.let { paintUsers ->
paintUsers.entries.find { it.key == pair.first }?.let { paintUsers.remove(it.key) }
paintUsers.put(pair.first, pair.second)
}
replyDialog?.updatePaint(pair.first)
}

fun setUsername(username: String?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,18 @@ class MessageClickedDialog : BottomSheetDialogFragment(), IntegrityDialog.Callba
}
}

fun updatePaint(userId: String) {
adapter?.let { adapter ->
adapter.messages?.toList()?.let { messages ->
messages.filter { it.userId == userId }.forEach { message ->
messages.indexOf(message).takeIf { it != -1 }?.let {
adapter.notifyItemChanged(it)
}
}
}
}
}

fun scrollToLastPosition() {
if (!isChatTouched && !shouldShowButton()) {
adapter?.messages?.let { binding.recyclerView.scrollToPosition(it.lastIndex) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ class ReplyClickedDialog : BottomSheetDialogFragment() {
}
}

fun updatePaint(userId: String) {
adapter?.let { adapter ->
adapter.messages?.toList()?.let { messages ->
messages.filter { it.userId == userId }.forEach { message ->
messages.indexOf(message).takeIf { it != -1 }?.let {
adapter.notifyItemChanged(it)
}
}
}
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import com.github.andreyasadchy.xtra.model.chat.NamePaint
interface STVEventApiListener {
fun onPaintUpdate(paint: NamePaint)
fun onUserUpdate(userId: String, paintId: String)
fun onUpdatePresence(sessionId: String?, self: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ class STVEventApiWebSocket(
}
}
}
OPCODE_HELLO -> {
val data = json.optJSONObject("d")
val sessionId = data?.optString("session_id")
if (sessionId != null) {
listener.onUpdatePresence(sessionId, true)
}
}
OPCODE_RECONNECT -> reconnect()
}
} catch (e: Exception) {
Expand All @@ -189,6 +196,7 @@ class STVEventApiWebSocket(

companion object {
private const val OPCODE_DISPATCH = 0
private const val OPCODE_HELLO = 1
private const val OPCODE_RECONNECT = 4
private const val OPCODE_SUBSCRIBE = 35
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@
app:singleLineTitle="false" />

<SwitchPreferenceCompat
android:defaultValue="false"
android:defaultValue="true"
android:key="chat_show_paints"
android:title="@string/show_name_paints"
app:iconSpaceReserved="false"
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ ksp = "2.1.0-1.0.29"
lifecycle = "2.8.7"
material = "1.12.0"
media3 = "1.5.0"
navigation = "2.8.4"
navigation = "2.8.5"
okhttp = "5.0.0-alpha.14"
okio = "3.9.1"
paging = "3.3.4"
paging = "3.3.5"
preference = "1.2.1"
recyclerview = "1.3.2"
retrofit = "2.11.0"
Expand Down

0 comments on commit 4867387

Please sign in to comment.