Skip to content

Commit

Permalink
Add JS wrappers for all Chat APIs (#110)
Browse files Browse the repository at this point in the history
Contains all JS APIs that match the Chat TypeScript types definition file, including MessageDraft V1 for Chat JS only.
  • Loading branch information
wkal-pubnub authored Nov 21, 2024
1 parent e48d4a2 commit a2fe6fa
Show file tree
Hide file tree
Showing 67 changed files with 5,522 additions and 286 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ jobs:
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install JDK
uses: actions/setup-java@v4
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '21'
- name: Checkout actions
uses: actions/checkout@v4
with:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/run-validations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ jobs:
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install JDK
uses: actions/setup-java@v4
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '21'
- name: Cache
uses: actions/cache@v4
with:
Expand Down
3 changes: 3 additions & 0 deletions config/ktlint/baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<baseline version="1.0">
</baseline>
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ [email protected]
IOS_SIMULATOR_ID=iPhone 15 Pro
SWIFT_PATH=pubnub-kotlin/swift

ENABLE_TARGET_JS=false
ENABLE_TARGET_JS=true
ENABLE_TARGET_IOS_OTHER=false
ENABLE_TARGET_IOS_SIMULATOR_ARM64=true
# alternatively (e.g. for release):
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[versions]
nexus = "2.0.0"
kotlin = "2.0.20"
kotlin = "2.0.21"
vanniktech = "0.29.0"
ktlint = "12.1.0"
dokka = "1.9.20"
Expand Down
2,343 changes: 2,329 additions & 14 deletions kotlin-js-store/yarn.lock

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions pubnub-chat-api/api/pubnub-chat-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ public abstract interface class com/pubnub/chat/Message {
public abstract fun getChat ()Lcom/pubnub/chat/Chat;
public abstract fun getContent ()Lcom/pubnub/chat/types/EventContent$TextMessageContent;
public abstract fun getDeleted ()Z
public abstract fun getError ()Lcom/pubnub/api/PubNubError;
public abstract fun getFiles ()Ljava/util/List;
public abstract fun getHasThread ()Z
public abstract fun getMentionedUsers ()Ljava/util/Map;
Expand Down Expand Up @@ -411,10 +412,10 @@ public final class com/pubnub/chat/membership/MembersResponse {
}

public final class com/pubnub/chat/membership/MembershipsResponse {
public fun <init> (Lcom/pubnub/api/models/consumer/objects/PNPage;Lcom/pubnub/api/models/consumer/objects/PNPage;IILjava/util/List;)V
public fun <init> (Lcom/pubnub/api/models/consumer/objects/PNPage$PNNext;Lcom/pubnub/api/models/consumer/objects/PNPage$PNPrev;IILjava/util/List;)V
public final fun getMemberships ()Ljava/util/List;
public final fun getNext ()Lcom/pubnub/api/models/consumer/objects/PNPage;
public final fun getPrev ()Lcom/pubnub/api/models/consumer/objects/PNPage;
public final fun getNext ()Lcom/pubnub/api/models/consumer/objects/PNPage$PNNext;
public final fun getPrev ()Lcom/pubnub/api/models/consumer/objects/PNPage$PNPrev;
public final fun getStatus ()I
public final fun getTotal ()I
}
Expand Down Expand Up @@ -861,9 +862,17 @@ public final class com/pubnub/chat/types/QuotedMessage$Companion {
public final class com/pubnub/chat/types/TextLink {
public static final field Companion Lcom/pubnub/chat/types/TextLink$Companion;
public fun <init> (IILjava/lang/String;)V
public final fun component1 ()I
public final fun component2 ()I
public final fun component3 ()Ljava/lang/String;
public final fun copy (IILjava/lang/String;)Lcom/pubnub/chat/types/TextLink;
public static synthetic fun copy$default (Lcom/pubnub/chat/types/TextLink;IILjava/lang/String;ILjava/lang/Object;)Lcom/pubnub/chat/types/TextLink;
public fun equals (Ljava/lang/Object;)Z
public final fun getEndIndex ()I
public final fun getLink ()Ljava/lang/String;
public final fun getStartIndex ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public synthetic class com/pubnub/chat/types/TextLink$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
Expand Down
3 changes: 3 additions & 0 deletions pubnub-chat-api/config/ktlint/baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<baseline version="1.0">
</baseline>
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ interface Channel {
* }
* ```
*/
fun startTyping(): PNFuture<Unit>
fun startTyping(): PNFuture<PNPublishResult?>

/**
* Deactivates a typing indicator on a given channel.
Expand All @@ -160,7 +160,7 @@ interface Channel {
* }
* ```
*/
fun stopTyping(): PNFuture<Unit>
fun stopTyping(): PNFuture<PNPublishResult?>

/**
* Enables continuous tracking of typing activity within the [Channel].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ interface Membership {
* @param custom Any custom properties or metadata associated with the channel-user membership in a `Map`. Values must be scalar only; arrays or objects are not supported. App Context filtering language doesn’t support filtering by custom properties.
* @return A [PNFuture] that returns an updated [Membership] object.
*/
fun update(custom: CustomObject): PNFuture<Membership>
fun update(custom: CustomObject?): PNFuture<Membership>

/**
* Setting the last read message for users lets you implement the Read Receipts feature and monitor which channel member read which message.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.pubnub.chat

import com.pubnub.api.PubNubError
import com.pubnub.api.models.consumer.PNPublishResult
import com.pubnub.api.models.consumer.history.PNFetchMessageItem.Action
import com.pubnub.api.models.consumer.message_actions.PNRemoveMessageActionResult
Expand Down Expand Up @@ -89,6 +90,11 @@ interface Message {
*/
val reactions: Map<String, List<Action>>

/**
* Error associated with the message, if any.
*/
val error: PubNubError?

/**
* List of included text links and their position.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ interface ChatConfiguration {
}

fun ChatConfiguration(
logLevel: LogLevel = LogLevel.OFF,
logLevel: LogLevel = LogLevel.WARN,
typingTimeout: Duration = 5.seconds,
storeUserActivityInterval: Duration = 600.seconds,
storeUserActivityTimestamps: Boolean = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import com.pubnub.chat.Membership
* @property memberships A list of [Membership] objects representing the channels the user is a member of.
*/
class MembershipsResponse(
val next: PNPage?,
val prev: PNPage?,
val next: PNPage.PNNext?,
val prev: PNPage.PNPrev?,
val total: Int,
val status: Int,
val memberships: List<Membership>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.pubnub.chat.types

import kotlinx.serialization.Serializable
import kotlin.js.JsExport

@Serializable
@JsExport
class MessageMentionedUser(val id: String, val name: String)

typealias MessageMentionedUsers = Map<Int, MessageMentionedUser>
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
@file:OptIn(ExperimentalJsExport::class)

package com.pubnub.chat.types

import kotlinx.serialization.Serializable
import kotlin.js.ExperimentalJsExport
import kotlin.js.JsExport

@Serializable
@JsExport
class MessageReferencedChannel(val id: String, val name: String)

typealias MessageReferencedChannels = Map<Int, MessageReferencedChannel>
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
@file:OptIn(ExperimentalJsExport::class)

package com.pubnub.chat.types

import kotlinx.serialization.Serializable
import kotlin.js.ExperimentalJsExport
import kotlin.js.JsExport

@Serializable
class TextLink(val startIndex: Int, val endIndex: Int, val link: String)
@JsExport
data class TextLink(val startIndex: Int, val endIndex: Int, val link: String)
23 changes: 23 additions & 0 deletions pubnub-chat-impl/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
@file:OptIn(ExperimentalKotlinGradlePluginApi::class)

import com.pubnub.gradle.enableAnyIosTarget
import com.pubnub.gradle.enableJsTarget
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JsModuleKind
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension

plugins {
Expand All @@ -13,6 +17,25 @@ plugins {
}

kotlin {
if (enableJsTarget) {
js {
// keep this in here for ad-hoc testing
// browser {
// testTask {
// useMocha {
// timeout = "15s"
// }
// }
// }

compilerOptions {
target.set("es2015")
moduleKind.set(JsModuleKind.MODULE_UMD)
}
binaries.library()
}
}

sourceSets {
val commonMain by getting {
dependencies {
Expand Down
9 changes: 9 additions & 0 deletions pubnub-chat-impl/config/ktlint/baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<baseline version="1.0">
<file name="src/jsMain/kotlin/UserJs.kt">
<error line="46" column="53" source="standard:comment-wrapping" />
</file>
<file name="src/jsMain/kotlin/converters.kt">
<error line="137" column="14" source="standard:function-naming" />
</file>
</baseline>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.pubnub.chat.internal

import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid

@OptIn(ExperimentalUuidApi::class)
actual fun generateRandomUuid(): String = Uuid.random().toString()
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import platform.Foundation.NSTextCheckingResult
import platform.Foundation.matchesInString

private val userMentionRegex = NSRegularExpression(
pattern = """(?<=^|\p{Space})(@[\p{Alpha}\-]+)""",
pattern = """(?<=^|\p{Space})(@[\p{Alpha}\-\d]+)""",
options = 0u,
error = null
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlin.reflect.KClass
import kotlin.time.Duration.Companion.seconds
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid

class ChatImpl(
override val config: ChatConfiguration,
Expand Down Expand Up @@ -421,7 +419,7 @@ class ChatImpl(
if (!isValidId(channelId)) {
return log.logErrorAndReturnException(CHANNEL_ID_IS_REQUIRED).asFuture()
}
return pubNub.getChannelMetadata(channel = channelId)
return pubNub.getChannelMetadata(channel = channelId, includeCustom = true)
.then { pnChannelMetadataResult: PNChannelMetadataResult ->
ChannelImpl.fromDTO(this, pnChannelMetadataResult.data)
}.catch { exception ->
Expand Down Expand Up @@ -505,15 +503,14 @@ class ChatImpl(
}
}

@OptIn(ExperimentalUuidApi::class)
override fun createPublicConversation(
channelId: String?,
channelName: String?,
channelDescription: String?,
channelCustom: CustomObject?,
channelStatus: String?
): PNFuture<Channel> {
val finalChannelId: String = channelId ?: Uuid.random().toString()
val finalChannelId: String = channelId ?: generateRandomUuid()

return createChannel(
id = finalChannelId,
Expand Down Expand Up @@ -573,7 +570,6 @@ class ChatImpl(
}
}

@OptIn(ExperimentalUuidApi::class)
override fun createGroupConversation(
invitedUsers: Collection<User>,
channelId: String?,
Expand All @@ -584,7 +580,7 @@ class ChatImpl(
membershipCustom: CustomObject?
): PNFuture<CreateGroupConversationResult> {
val user = this.currentUser
val finalChannelId = channelId ?: Uuid.random().toString()
val finalChannelId = channelId ?: generateRandomUuid()
return getChannel(finalChannelId).thenAsync { channel ->
channel?.asFuture() ?: createChannel(
finalChannelId,
Expand Down Expand Up @@ -980,7 +976,8 @@ class ChatImpl(
).thenAsync { getEventsHistoryResult: GetEventsHistoryResult ->
isMore = getEventsHistoryResult.isMore
getEventsHistoryResult.events
.filterIsInstance<Event<EventContent.Mention>>()
.filter { it.payload is EventContent.Mention } // this performs actual filtering
.filterIsInstance<Event<EventContent.Mention>>() // this adjusts the type passed into map() below
.map { mentionEvent: Event<EventContent.Mention> ->
val mentionTimetoken = mentionEvent.payload.messageTimetoken
val mentionChannelId = mentionEvent.payload.channel
Expand Down Expand Up @@ -1249,3 +1246,5 @@ class ChatImpl(
}
}
}

internal expect fun generateRandomUuid(): String
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ data class MembershipImpl(
return setLastReadMessageTimetoken(message.timetoken)
}

override fun update(custom: CustomObject): PNFuture<Membership> {
override fun update(custom: CustomObject?): PNFuture<Membership> {
return exists().thenAsync { exists ->
if (!exists) {
log.pnError(NO_SUCH_MEMBERSHIP_EXISTS)
Expand Down
Loading

0 comments on commit a2fe6fa

Please sign in to comment.