Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/main/kotlin/chatserver/MessageResult.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package chatserver

import chatserver.ReadChatRepository.ReadResult
import chatserver.messages.SupabaseMessageRepository.*

data class MessageResult(
override val isOk: Boolean,
override val item: List<String>,
override val item: List<Message>,
override val error: Exception?,
) :
ReadResult<List<String>> {
ReadResult<List<Message>> {
companion object {
fun ok(item: List<String>): MessageResult = MessageResult(true, item, null)
fun ok(item: List<Message>): MessageResult = MessageResult(true, item, null)

fun fail(e: Exception? = null): MessageResult = MessageResult(false, emptyList(), e)
}
Expand Down
66 changes: 66 additions & 0 deletions src/main/kotlin/chatserver/messages/SupabaseMessageRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package chatserver.messages

import chatserver.MessageResult
import chatserver.ReadChatRepository
import chatserver.SubscribeChatRepository
import chatserver.WriteChatRepository
import io.github.jan.supabase.SupabaseClient
import io.github.jan.supabase.annotations.SupabaseExperimental
import io.github.jan.supabase.auth.auth
import io.github.jan.supabase.postgrest.from
import io.github.jan.supabase.realtime.selectAsFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.util.UUID

class SupabaseMessageRepository(
private val client: SupabaseClient,
private val scope: CoroutineScope,
) : ReadChatRepository<MessageResult>, WriteChatRepository<String>, SubscribeChatRepository {
private val messages: MutableStateFlow<MessageResult> = MutableStateFlow(MessageResult.ok(emptyList()))

override fun latest(): MessageResult = messages.value

override fun observe(): Flow<MessageResult> = messages.asStateFlow()

@OptIn(SupabaseExperimental::class)
override fun subscribe() {
client.from("messages")
.selectAsFlow(Message::id)
.map { MessageResult.ok(it) }
.onEach { messages.value = it }
.catch { println(it) }
.launchIn(scope)
}

override fun write(item: String) {
scope.launch {
client.from("messages").insert(item.toChatMessage())
}
}

private fun String.toChatMessage() =
Message(
id = UUID.randomUUID().toString(),
profileId = client.auth.currentUserOrNull()?.id.orEmpty(),
content = this,
createdAt = Clock.System.now().toString(),
)

override fun unsubscribe() {
scope.cancel()
}

@Serializable
data class Message(
@SerialName("id") val id: String,
@SerialName("profile_id") val profileId: String,
@SerialName("content") val content: String,
@SerialName("created_at") val createdAt: String,
)
}
Loading