Skip to content

Commit 9018cd5

Browse files
authored
Merge pull request #248 from RocketChat/fix/add-a-reaction-on-a-message-not-working
[FIX] Add a reaction on a message not working
2 parents 9af4a70 + 7054669 commit 9018cd5

File tree

24 files changed

+374
-55
lines changed

24 files changed

+374
-55
lines changed

common/src/main/kotlin/chat/rocket/common/model/BaseUser.kt

+28-1
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,31 @@ fun userStatusOf(status: String): UserStatus {
3939
"offline" -> UserStatus.Offline()
4040
else -> UserStatus.Unknown(status)
4141
}
42-
}
42+
}
43+
44+
@FallbackSealedClass(name = "Unknown", fieldName = "rawAvatar")
45+
sealed class UserAvatar {
46+
@Json(name = "upload")
47+
class Upload : chat.rocket.common.model.UserAvatar()
48+
@Json(name = "url")
49+
class Url : chat.rocket.common.model.UserAvatar()
50+
class Cleared : chat.rocket.common.model.UserAvatar()
51+
class Unknown(val rawAvatar: String) : UserAvatar()
52+
53+
override fun toString(): String {
54+
return when (this) {
55+
is Upload -> "upload"
56+
is Url -> "url"
57+
else -> "cleared"
58+
}
59+
}
60+
}
61+
62+
fun userAvatarOf(avatar: String): UserAvatar {
63+
return when(avatar) {
64+
"upload" -> UserAvatar.Upload()
65+
"url" -> UserAvatar.Url()
66+
"cleared" -> UserAvatar.Cleared()
67+
else -> UserAvatar.Unknown(avatar)
68+
}
69+
}

compat/src/main/kotlin/chat/rocket/core/compat/Server.kt

+4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import chat.rocket.core.RocketChatClient
55
import chat.rocket.core.compat.internal.callback
66
import chat.rocket.core.internal.rest.serverInfo
77
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.ExperimentalCoroutinesApi
9+
import kotlinx.coroutines.InternalCoroutinesApi
810

911
/**
1012
* Returns the current logged server information.
1113
* Must be used with a coroutine context (async, launch, etc)
1214
*/
15+
@ExperimentalCoroutinesApi
16+
@InternalCoroutinesApi
1317
fun RocketChatClient.serverInfo(future: Callback<ServerInfo>): Call = callback(Dispatchers.IO, future) { serverInfo() }

compat/src/main/kotlin/chat/rocket/core/compat/User.kt

+4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import chat.rocket.core.compat.internal.callback
55
import chat.rocket.core.internal.rest.me
66
import chat.rocket.core.model.Myself
77
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.ExperimentalCoroutinesApi
9+
import kotlinx.coroutines.InternalCoroutinesApi
810

911
/**
1012
* Returns the current logged user information, useful to check if the Token from TokenProvider
1113
* is still valid. Must be used with a coroutine context (async, launch, etc)
1214
*/
15+
@ExperimentalCoroutinesApi
16+
@InternalCoroutinesApi
1317
fun RocketChatClient.me(future: Callback<Myself>): Call = callback(Dispatchers.IO, future) { me() }

compat/src/main/kotlin/chat/rocket/core/compat/internal/Callback.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import chat.rocket.core.compat.Callback
66
import kotlinx.coroutines.AbstractCoroutine
77
import kotlinx.coroutines.CoroutineScope
88
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.ExperimentalCoroutinesApi
910
import kotlinx.coroutines.GlobalScope
1011
import kotlinx.coroutines.InternalCoroutinesApi
1112
import kotlinx.coroutines.Job
1213
import kotlinx.coroutines.newCoroutineContext
1314
import kotlin.coroutines.CoroutineContext
1415
import kotlin.coroutines.startCoroutine
1516

17+
@ExperimentalCoroutinesApi
18+
@InternalCoroutinesApi
1619
@JvmOverloads
1720
fun <T> callback(
1821
context: CoroutineContext = Dispatchers.Default,
@@ -26,7 +29,7 @@ fun <T> callback(
2629
return Call(job)
2730
}
2831

29-
@UseExperimental(InternalCoroutinesApi::class)
32+
@InternalCoroutinesApi
3033
private class CallbackCoroutine<in T>(
3134
parentContext: CoroutineContext,
3235
private val callback: Callback<T>

core/src/main/kotlin/chat/rocket/core/RocketChatClient.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import chat.rocket.common.util.NoOpLogger
1111
import chat.rocket.common.util.PlatformLogger
1212
import chat.rocket.common.util.RealLogger
1313
import chat.rocket.common.util.ifNull
14-
import chat.rocket.core.internal.RestResult
15-
import chat.rocket.core.internal.RestMultiResult
16-
import chat.rocket.core.internal.SettingsAdapter
1714
import chat.rocket.core.internal.AttachmentAdapterFactory
18-
import chat.rocket.core.internal.RoomListAdapterFactory
1915
import chat.rocket.core.internal.CoreJsonAdapterFactory
2016
import chat.rocket.core.internal.MessageListAdapterFactory
2117
import chat.rocket.core.internal.ReactionsAdapter
18+
import chat.rocket.core.internal.RestMultiResult
19+
import chat.rocket.core.internal.RestResult
20+
import chat.rocket.core.internal.RoomListAdapterFactory
21+
import chat.rocket.core.internal.SettingsAdapter
2222
import chat.rocket.core.internal.model.Subscription
2323
import chat.rocket.core.internal.realtime.socket.Socket
2424
import chat.rocket.core.internal.realtime.socket.model.State
@@ -55,13 +55,13 @@ class RocketChatClient private constructor(
5555
.add(AttachmentAdapterFactory(logger))
5656
.add(RoomListAdapterFactory(logger))
5757
.add(MessageListAdapterFactory(logger))
58+
.add(ReactionsAdapter())
5859
.add(MetaJsonAdapter.ADAPTER_FACTORY)
5960
.add(java.lang.Long::class.java, ISO8601Date::class.java, TimestampAdapter(CalendarISO8601Converter()))
6061
.add(Long::class.java, ISO8601Date::class.java, TimestampAdapter(CalendarISO8601Converter()))
6162
// XXX - MAKE SURE TO KEEP CommonJsonAdapterFactory and CoreJsonAdapterFactory as the latest Adapters...
6263
.add(CommonJsonAdapterFactory.INSTANCE)
6364
.add(CoreJsonAdapterFactory.INSTANCE)
64-
.add(ReactionsAdapter())
6565
.build()
6666

6767
internal lateinit var restUrl: HttpUrl

core/src/main/kotlin/chat/rocket/core/internal/ReactionsAdapter.kt

+7-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ class ReactionsAdapter : JsonAdapter<Reactions>() {
5757
reader.endObject()
5858
reactions.set(shortname, usernameList, nameList)
5959
}
60-
reader.endObject()
61-
reader.endObject()
60+
61+
if (reader.peek() == JsonReader.Token.END_OBJECT) {
62+
reader.endObject()
63+
}
64+
if (reader.peek() == JsonReader.Token.END_OBJECT) {
65+
reader.endObject()
66+
}
6267
return reactions
6368
}
6469

core/src/main/kotlin/chat/rocket/core/internal/model/Subscription.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ import se.ansman.kotshi.JsonSerializable
1212
@JsonSerializable
1313
data class Subscription(
1414
@Json(name = "rid") val roomId: String,
15+
@Json(name = "prid") val parentId: String?, // Not empty if it is a discussion
1516
@Json(name = "_id") override val id: String,
1617
@Json(name = "t") override val type: RoomType,
1718
@Json(name = "u") override val user: SimpleUser?,
18-
val name: String?,
19-
@Json(name = "fname") override val fullName: String?,
19+
val name: String?, // Name of the subscription
20+
@Json(name = "fname") override val fullName: String?, // Full name of the user, in the case of using the full user name setting (UI_Use_Real_Name)
2021
@Json(name = "ro") override val readonly: Boolean? = false,
2122
@Json(name = "ts") @ISO8601Date val timestamp: Long?,
2223
@Json(name = "ls") @ISO8601Date val lastSeen: Long?,

core/src/main/kotlin/chat/rocket/core/internal/realtime/socket/Login.kt

+3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import chat.rocket.core.internal.realtime.socket.model.State
66
import chat.rocket.core.internal.model.TypedResponse
77
import chat.rocket.core.internal.realtime.message.loginMethod
88
import com.squareup.moshi.Types
9+
import kotlinx.coroutines.ObsoleteCoroutinesApi
910

11+
@ObsoleteCoroutinesApi
1012
fun Socket.login(token: Token?) {
1113
token?.let { authToken ->
1214
socket?.let {
@@ -16,6 +18,7 @@ fun Socket.login(token: Token?) {
1618
}
1719
}
1820

21+
@ObsoleteCoroutinesApi
1922
internal fun Socket.processLoginResult(text: String) {
2023
val type = Types.newParameterizedType(TypedResponse::class.java, SocketToken::class.java)
2124
val adapter = moshi.adapter<TypedResponse<SocketToken>>(type)

core/src/main/kotlin/chat/rocket/core/internal/realtime/socket/Socket.kt

+37-12
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ import chat.rocket.core.model.Room
1717
import com.squareup.moshi.JsonAdapter
1818
import kotlinx.coroutines.CoroutineScope
1919
import kotlinx.coroutines.Dispatchers
20+
import kotlinx.coroutines.ExperimentalCoroutinesApi
2021
import kotlinx.coroutines.Job
22+
import kotlinx.coroutines.ObsoleteCoroutinesApi
2123
import kotlinx.coroutines.channels.Channel
2224
import kotlinx.coroutines.channels.SendChannel
25+
import kotlinx.coroutines.coroutineScope
2326
import kotlinx.coroutines.delay
2427
import kotlinx.coroutines.isActive
2528
import kotlinx.coroutines.launch
@@ -35,6 +38,7 @@ import kotlin.coroutines.CoroutineContext
3538

3639
const val PING_INTERVAL = 15000L
3740

41+
@ObsoleteCoroutinesApi
3842
class Socket(
3943
internal val client: RocketChatClient,
4044
internal val roomsChannel: SendChannel<StreamMessage<Room>>,
@@ -71,6 +75,7 @@ class Socket(
7175

7276
internal val subscriptionsMap = HashMap<String, (Boolean, String) -> Unit>()
7377

78+
@ObsoleteCoroutinesApi
7479
private val connectionContext = newSingleThreadContext("connection-context")
7580
private val reconnectionStrategy = ReconnectionStrategy()
7681
private var reconnectJob: Job? = null
@@ -84,6 +89,7 @@ class Socket(
8489
socketMessageAdapter = moshi.adapter(SocketMessage::class.java)
8590
}
8691

92+
@ObsoleteCoroutinesApi
8793
internal fun connect(resetCounter: Boolean = false) {
8894
selfDisconnect = false
8995
// reset id counter
@@ -101,6 +107,7 @@ class Socket(
101107
socket = httpClient.newWebSocket(request, this)
102108
}
103109

110+
@ObsoleteCoroutinesApi
104111
internal fun disconnect() {
105112
when (currentState) {
106113
State.Disconnected() -> return
@@ -116,6 +123,7 @@ class Socket(
116123
}
117124
}
118125

126+
@ObsoleteCoroutinesApi
119127
private fun startReconnection() {
120128
// Ignore self disconnection
121129
if (selfDisconnect) {
@@ -142,10 +150,11 @@ class Socket(
142150
}
143151
}
144152

153+
@ObsoleteCoroutinesApi
145154
private suspend fun delayReconnection(reconnectInterval: Int) {
146155
val seconds = reconnectInterval / 1000
147156
withContext(connectionContext) {
148-
for (second in 0..(seconds - 1)) {
157+
for (second in 0 until seconds) {
149158
if (!coroutineContext.isActive) {
150159
logger.debug { "Reconnect job inactive, ignoring" }
151160
return@withContext
@@ -158,6 +167,7 @@ class Socket(
158167
}
159168
}
160169

170+
@ExperimentalCoroutinesApi
161171
private fun processIncomingMessage(text: String) {
162172
messagesProcessed++
163173
logger.debug {
@@ -175,7 +185,7 @@ class Socket(
175185
return
176186
}
177187

178-
reschedulePing(message.type)
188+
reschedulePing()
179189

180190
when (currentState) {
181191
is State.Connecting -> {
@@ -193,6 +203,7 @@ class Socket(
193203
}
194204
}
195205

206+
@ObsoleteCoroutinesApi
196207
private fun processConnectionMessage(message: SocketMessage) {
197208
when (message.type) {
198209
MessageType.CONNECTED -> {
@@ -205,6 +216,8 @@ class Socket(
205216
}
206217
}
207218

219+
@ObsoleteCoroutinesApi
220+
@ExperimentalCoroutinesApi
208221
private fun processAuthenticationResponse(message: SocketMessage, text: String) {
209222
when (message.type) {
210223
MessageType.ADDED, MessageType.UPDATED -> {
@@ -224,6 +237,7 @@ class Socket(
224237
}
225238
}
226239

240+
@ExperimentalCoroutinesApi
227241
private fun processMessage(message: SocketMessage, text: String) {
228242
when (message.type) {
229243
MessageType.PING -> {
@@ -245,7 +259,7 @@ class Socket(
245259
socket?.send(message)
246260
}
247261

248-
private fun reschedulePing(type: MessageType) {
262+
private fun reschedulePing() {
249263
logger.debug { "Rescheduling ping in $PING_INTERVAL milliseconds" }
250264

251265
timeoutJob?.cancel()
@@ -266,20 +280,23 @@ class Socket(
266280
private suspend fun schedulePingTimeout() {
267281
val timeout = (PING_INTERVAL * 1.5).toLong()
268282
logger.debug { "Scheduling ping timeout in $timeout milliseconds" }
269-
timeoutJob = launch(parentJob) {
270-
delay(timeout)
271-
if (!isActive) return@launch
272-
when (currentState) {
273-
is State.Disconnected,
274-
is State.Disconnecting -> logger.warn { "Pong not received, but already disconnected" }
275-
else -> {
276-
logger.warn { "Pong not received" }
277-
socket?.cancel()
283+
timeoutJob = coroutineScope {
284+
launch(parentJob) {
285+
delay(timeout)
286+
if (!isActive) return@launch
287+
when (currentState) {
288+
is State.Disconnected,
289+
is State.Disconnecting -> logger.warn { "Pong not received, but already disconnected" }
290+
else -> {
291+
logger.warn { "Pong not received" }
292+
socket?.cancel()
293+
}
278294
}
279295
}
280296
}
281297
}
282298

299+
@ObsoleteCoroutinesApi
283300
internal fun setState(newState: State) {
284301
if (newState != currentState) {
285302
logger.debug { "Setting state to: $newState - oldState: $currentState, channels: ${statusChannelList.size}" }
@@ -288,6 +305,7 @@ class Socket(
288305
}
289306
}
290307

308+
@ObsoleteCoroutinesApi
291309
private fun sendState(state: State) {
292310
launch(connectionContext) {
293311
for (channel in statusChannelList) {
@@ -306,6 +324,7 @@ class Socket(
306324
parentJob.cancel()
307325
}
308326

327+
@ExperimentalCoroutinesApi
309328
override fun onOpen(webSocket: WebSocket, response: Response?) {
310329
readJob = launch {
311330
for (message in processingChannel!!) {
@@ -316,6 +335,7 @@ class Socket(
316335
send(CONNECT_MESSAGE)
317336
}
318337

338+
@ObsoleteCoroutinesApi
319339
override fun onFailure(webSocket: WebSocket, throwable: Throwable?, response: Response?) {
320340
logger.warn { "Socket.onFailure(). THROWABLE MESSAGE: ${throwable?.message} - RESPONSE MESSAGE: ${response?.message()}" }
321341
throwable?.printStackTrace()
@@ -324,18 +344,21 @@ class Socket(
324344
startReconnection()
325345
}
326346

347+
@ObsoleteCoroutinesApi
327348
override fun onClosing(webSocket: WebSocket, code: Int, reason: String?) {
328349
logger.warn { "Socket.onClosing() called. Received CODE = $code - Received REASON = $reason" }
329350
setState(State.Disconnecting())
330351
startReconnection()
331352
}
353+
@ObsoleteCoroutinesApi
332354
override fun onClosed(webSocket: WebSocket, code: Int, reason: String?) {
333355
logger.warn { "Socket.onClosed() called. Received CODE = $code - Received REASON = $reason" }
334356
setState(State.Disconnected())
335357
close()
336358
startReconnection()
337359
}
338360

361+
@ExperimentalCoroutinesApi
339362
override fun onMessage(webSocket: WebSocket, text: String?) {
340363
logger.warn { "Socket.onMessage(). Received TEXT = $text for processing channel = $processingChannel" }
341364
text?.let {
@@ -357,6 +380,8 @@ class Socket(
357380
}
358381
}
359382

383+
@ObsoleteCoroutinesApi
360384
fun RocketChatClient.connect(resetCounter: Boolean = false) = socket.connect(resetCounter)
361385

386+
@ObsoleteCoroutinesApi
362387
fun RocketChatClient.disconnect() = socket.disconnect()

0 commit comments

Comments
 (0)