diff --git a/.github/workflows/commands-handler.yml b/.github/workflows/commands-handler.yml index 48f71d24..a38ac9a8 100644 --- a/.github/workflows/commands-handler.yml +++ b/.github/workflows/commands-handler.yml @@ -27,6 +27,7 @@ jobs: uses: actions/checkout@v4 with: token: ${{ secrets.GH_TOKEN }} + submodules: recursive - name: Checkout release actions if: steps.user-check.outputs.expected-user == 'true' uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e5850a79..228366ca 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,6 +38,7 @@ jobs: with: # This should be the same as the one specified for on.pull_request.branches ref: master + submodules: recursive - name: Checkout actions uses: actions/checkout@v4 with: diff --git a/.github/workflows/release/chat-maven-build.sh b/.github/workflows/release/chat-maven-build.sh index be41994a..5587166f 100644 --- a/.github/workflows/release/chat-maven-build.sh +++ b/.github/workflows/release/chat-maven-build.sh @@ -1,2 +1,2 @@ echo "Build Chat SDK module artifacts" -./gradlew jar --no-configuration-cache \ No newline at end of file +./gradlew jar \ No newline at end of file diff --git a/.github/workflows/release/chat-maven-publish.sh b/.github/workflows/release/chat-maven-publish.sh index 15db904b..04a7637a 100644 --- a/.github/workflows/release/chat-maven-publish.sh +++ b/.github/workflows/release/chat-maven-publish.sh @@ -1 +1 @@ -./gradlew publishToSonatype closeSonatypeStagingRepository --no-configuration-cache +./gradlew publishToSonatype closeSonatypeStagingRepository diff --git a/.github/workflows/release/pre-github-pages-publish.sh b/.github/workflows/release/pre-github-pages-publish.sh index 0e289f10..fb521b17 100644 --- a/.github/workflows/release/pre-github-pages-publish.sh +++ b/.github/workflows/release/pre-github-pages-publish.sh @@ -1 +1 @@ -./gradlew :dokkaGfmMultiModule --no-configuration-cache \ No newline at end of file +./gradlew :dokkaGfmMultiModule \ No newline at end of file diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4a61801f..601e52ec 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: recursive - name: Checkout actions uses: actions/checkout@v4 with: @@ -31,6 +33,12 @@ jobs: - name: Build and run tests run: | ./gradlew check + env: + SDK_PUB_KEY: ${{ secrets.SDK_PUB_KEY }} + SDK_SUB_KEY: ${{ secrets.SDK_SUB_KEY }} + SDK_PAM_SUB_KEY: ${{ secrets.SDK_PAM_SUB_KEY }} + SDK_PAM_PUB_KEY: ${{ secrets.SDK_PAM_PUB_KEY }} + SDK_PAM_SEC_KEY: ${{ secrets.SDK_PAM_SEC_KEY }} - name: Cancel workflow runs for commit on error if: failure() uses: ./.github/.release/actions/actions/utils/fast-jobs-failure diff --git a/.github/workflows/run-validations.yml b/.github/workflows/run-validations.yml index 5b7fc9cc..e19268d7 100644 --- a/.github/workflows/run-validations.yml +++ b/.github/workflows/run-validations.yml @@ -18,6 +18,8 @@ jobs: steps: - name: Checkout project uses: actions/checkout@v4 + with: + submodules: recursive - name: Checkout validator action uses: actions/checkout@v4 with: @@ -39,6 +41,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: recursive - name: Cache uses: actions/cache@v4 with: @@ -49,7 +53,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Validate clean build - run: ./gradlew build + run: ./gradlew apiCheck ktlintFormat publishAllPublicationsToRepoRepository -PRELEASE_SIGNING_ENABLED=false - name: Cancel workflow runs for commit on error if: failure() uses: ./.github/.release/actions/actions/utils/fast-jobs-failure diff --git a/build.gradle.kts b/build.gradle.kts index 9f89929b..7191f392 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,82 +1,23 @@ +import com.pubnub.gradle.enableAnyIosTarget import com.pubnub.gradle.tasks.GenerateVersionTask -import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType -import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport -import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn +import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension plugins { - kotlin("multiplatform") version "2.0.0" - kotlin("plugin.serialization") version "2.0.0" - kotlin("native.cocoapods") version "2.0.0" - id("dev.mokkery") version "2.0.0" + kotlin("multiplatform") version "2.0.0" apply false + kotlin("plugin.serialization") version "2.0.0" apply false + kotlin("native.cocoapods") version "2.0.0" apply false + id("org.jlleitschuh.gradle.ktlint") version "12.1.0" apply false id("org.jetbrains.kotlin.plugin.atomicfu") version "2.0.0" - id("org.jlleitschuh.gradle.ktlint") version "12.1.0" - id("pubnub.dokka") apply false + id("com.vanniktech.maven.publish") version "0.29.0" apply false + id("org.jetbrains.dokka") version "1.9.20" apply false + id("pubnub.shared") + id("pubnub.dokka") + id("pubnub.multiplatform") id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.16.2" } -group = "com.pubnub" -version = "1.0-SNAPSHOT" - -ktlint { - outputToConsole.set(true) - verbose.set(true) - additionalEditorconfig.set( - mapOf( - "ij_kotlin_imports_layout" to "*,java.**,javax.**,kotlin.**,^", - "indent_size" to "4", - "ktlint_standard_multiline-expression-wrapping" to "disabled", - "ktlint_standard_string-template-indent" to "disabled", - "ktlint_standard_max-line-length" to "disabled", - "ktlint_standard_if-else-wrapping" to "disabled", - "ktlint_standard_discouraged-comment-location" to "disabled", - "ktlint_standard_trailing-comma-on-declaration-site" to "disabled", - "ktlint_standard_trailing-comma-on-call-site" to "disabled", - "ktlint_standard_function-signature" to "disabled", - "ktlint_standard_filename" to "disabled", - "ktlint_standard_function-naming" to "disabled", - ) - ) -} - kotlin { - jvmToolchain(8) - js { - useEsModules() -// browser { -// testTask { -// // useMocha { -// // timeout = "30s" -// // } -// useKarma { -// useChrome() -// } -// } -// } - nodejs { - testTask { - useMocha { - timeout = "20s" - } - } - } - } - jvm() - - listOf( -// iosArm64(), - iosSimulatorArm64(), - ).forEach { -// it.binaries { -// framework { -// baseName = "PubNubChat" -// isStatic = true -// } -// } - } - - applyDefaultHierarchyTemplate() - sourceSets { val commonMain by getting { dependencies { @@ -85,9 +26,11 @@ kotlin { } } - val iosMain by getting { - dependencies { - api(project(":pubnub-chat-impl")) + if (enableAnyIosTarget) { + val iosMain by getting { + dependencies { + api(project(":pubnub-chat-impl")) + } } } @@ -99,50 +42,20 @@ kotlin { } } - cocoapods { - ios.deploymentTarget = "14" - - // Required properties - // Specify the required Pod version here. Otherwise, the Gradle project version is used. - version = "1.0" - summary = "Some description for a Kotlin/Native module" - homepage = "Link to a Kotlin/Native module homepage" - - // Maps custom Xcode configuration to NativeBuildType - xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG - xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE - -// podfile = project.file(project.file("Sample Chat app/Podfile")) + if (enableAnyIosTarget) { + (this as ExtensionAware).extensions.configure { + summary = "Some description for a Kotlin/Native module" + homepage = "Link to a Kotlin/Native module homepage" - framework { - // Required properties - // Framework name configuration. Use this property instead of deprecated 'frameworkName' - baseName = "PubNubChat" - // Optional properties - // Specify the framework linking type. It's dynamic by default. - isStatic = true - export(project(":pubnub-chat-api")) - export(project(":pubnub-chat-impl")) - transitiveExport = true - } - - pod("PubNubSwift") { - // source = git("https://github.com/pubnub/swift") { - // branch = "feat/kmp" - // } - // headers = "PubNub/PubNub.h" - source = path(rootProject.file("pubnub-kotlin/swift")) - // version = "7.1.0" - - moduleName = "PubNub" - extraOpts += listOf("-compiler-option", "-fmodules") + framework { + baseName = "PubNubChat" + export(project(":pubnub-chat-api")) + export(project(":pubnub-chat-impl")) + } } } } -yarn.yarnLockMismatchReport = YarnLockMismatchReport.WARNING -yarn.yarnLockAutoReplace = true - val generateVersion = tasks.register("generateVersion") { fileName.set("ChatVersion") diff --git a/gradle.properties b/gradle.properties index 839fd39c..c01d2dea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,37 @@ kotlin.code.style=official -org.gradle.configuration-cache=true org.gradle.caching=true +org.gradle.parallel=true kotlin.mpp.applyDefaultHierarchyTemplate=false -#kotlin.mpp.import.enableKgpDependencyResolution=true - -#kotlin.native.cacheKind.iosSimulatorArm64=none -#kotlin.native.cacheKind.iosArm64=none org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +RELEASE_SIGNING_ENABLED=true +SONATYPE_HOST=DEFAULT +SONATYPE_AUTOMATIC_RELEASE=false +GROUP=com.pubnub +POM_PACKAGING=jar VERSION_NAME=0.8.0-DEV + +POM_NAME=PubNub Chat SDK +POM_DESCRIPTION=This SDK offers a set of handy methods to create your own feature-rich chat or add a chat to your existing application. +POM_INCEPTION_YEAR=2024 +POM_URL=https://github.com/pubnub/kmp-chat + +POM_LICENSE_NAME=PubNub Software Development Kit License +POM_LICENSE_URL=https://github.com/pubnub/kotlin/blob/master/LICENSE +POM_LICENSE_DIST=repo + +POM_SCM_URL=https://github.com/pubnub/kmp-chat +POM_SCM_CONNECTION=scm:git:git://github.com/pubnub/kmp-chat +POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/pubnub/kmp-chat + +POM_DEVELOPER_ID=PubNub +POM_DEVELOPER_NAME=PubNub +POM_DEVELOPER_URL=support@pubnub.com + +IOS_SIMULATOR_ID=iPhone 15 Pro +SWIFT_PATH=pubnub-kotlin/swift + +ENABLE_TARGET_JS=false +ENABLE_TARGET_IOS=false +ENABLE_TARGET_IOS_SIMULATOR=false \ No newline at end of file diff --git a/pubnub-chat-api/build.gradle.kts b/pubnub-chat-api/build.gradle.kts index a345e1ff..62336c03 100644 --- a/pubnub-chat-api/build.gradle.kts +++ b/pubnub-chat-api/build.gradle.kts @@ -1,75 +1,12 @@ -import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport -import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn - plugins { - kotlin("multiplatform") version "2.0.0" kotlin("plugin.serialization") version "2.0.0" id("org.jetbrains.kotlin.plugin.atomicfu") version "2.0.0" - id("org.jlleitschuh.gradle.ktlint") version "12.1.0" -} - -group = "com.pubnub" -version = "1.0-SNAPSHOT" - -ktlint { - outputToConsole.set(true) - verbose.set(true) - additionalEditorconfig.set( - mapOf( - "ij_kotlin_imports_layout" to "*,java.**,javax.**,kotlin.**,^", - "indent_size" to "4", - "ktlint_standard_multiline-expression-wrapping" to "disabled", - "ktlint_standard_string-template-indent" to "disabled", - "ktlint_standard_max-line-length" to "disabled", - "ktlint_standard_if-else-wrapping" to "disabled", - "ktlint_standard_discouraged-comment-location" to "disabled", - "ktlint_standard_trailing-comma-on-declaration-site" to "disabled", - "ktlint_standard_trailing-comma-on-call-site" to "disabled", - "ktlint_standard_function-signature" to "disabled", - "ktlint_standard_filename" to "disabled", - "ktlint_standard_function-naming" to "disabled", - ) - ) + id("pubnub.shared") + id("pubnub.dokka") + id("pubnub.multiplatform") } kotlin { - jvmToolchain(8) - js { - useEsModules() -// browser { -// testTask { -// // useMocha { -// // timeout = "30s" -// // } -// useKarma { -// useChrome() -// } -// } -// } - nodejs { - testTask { - useMocha { - timeout = "20s" - } - } - } - } - jvm() - - listOf( -// iosArm64(), - iosSimulatorArm64(), - ).forEach { -// it.binaries { -// framework { -// baseName = "PubNubChat" -// isStatic = true -// } -// } - } - - applyDefaultHierarchyTemplate() - sourceSets { val commonMain by getting { dependencies { @@ -78,12 +15,5 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.0-RC") } } - - val nonJvm by creating { - dependsOn(commonMain) - } } } - -yarn.yarnLockMismatchReport = YarnLockMismatchReport.WARNING -yarn.yarnLockAutoReplace = true diff --git a/pubnub-chat-api/pubnub_chat_api.podspec b/pubnub-chat-api/pubnub_chat_api.podspec new file mode 100644 index 00000000..e570a180 --- /dev/null +++ b/pubnub-chat-api/pubnub_chat_api.podspec @@ -0,0 +1,54 @@ +Pod::Spec.new do |spec| + spec.name = 'pubnub_chat_api' + spec.version = '0.8.0-DEV' + spec.homepage = '' + spec.source = { :http=> ''} + spec.authors = '' + spec.license = '' + spec.summary = '' + spec.vendored_frameworks = 'build/cocoapods/framework/pubnub_chat_api.framework' + spec.libraries = 'c++' + spec.ios.deployment_target = '14' + spec.dependency 'PubNubSwift' + + if !Dir.exist?('build/cocoapods/framework/pubnub_chat_api.framework') || Dir.empty?('build/cocoapods/framework/pubnub_chat_api.framework') + raise " + + Kotlin framework 'pubnub_chat_api' doesn't exist yet, so a proper Xcode project can't be generated. + 'pod install' should be executed after running ':generateDummyFramework' Gradle task: + + ./gradlew :pubnub-chat-api:generateDummyFramework + + Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)" + end + + spec.xcconfig = { + 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO', + } + + spec.pod_target_xcconfig = { + 'KOTLIN_PROJECT_PATH' => ':pubnub-chat-api', + 'PRODUCT_MODULE_NAME' => 'pubnub_chat_api', + } + + spec.script_phases = [ + { + :name => 'Build pubnub_chat_api', + :execution_position => :before_compile, + :shell_path => '/bin/sh', + :script => <<-SCRIPT + if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then + echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"" + exit 0 + fi + set -ev + REPO_ROOT="$PODS_TARGET_SRCROOT" + "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \ + -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \ + -Pkotlin.native.cocoapods.archs="$ARCHS" \ + -Pkotlin.native.cocoapods.configuration="$CONFIGURATION" + SCRIPT + } + ] + +end \ No newline at end of file diff --git a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/types/Types.kt b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/types/Types.kt index 073704a4..f82859e1 100644 --- a/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/types/Types.kt +++ b/pubnub-chat-api/src/commonMain/kotlin/com/pubnub/chat/types/Types.kt @@ -63,11 +63,19 @@ sealed class EventContent { val files: List? = null, ) : EventContent() { override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is TextMessageContent) return false - - if (text != other.text) return false - if (files != other.files) return false + if (this === other) { + return true + } + if (other !is TextMessageContent) { + return false + } + + if (text != other.text) { + return false + } + if (files != other.files) { + return false + } return true } diff --git a/pubnub-chat-impl/build.gradle.kts b/pubnub-chat-impl/build.gradle.kts index e6e6f512..c01c59da 100644 --- a/pubnub-chat-impl/build.gradle.kts +++ b/pubnub-chat-impl/build.gradle.kts @@ -1,80 +1,18 @@ -import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType -import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport -import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn +import com.pubnub.gradle.enableAnyIosTarget +import com.pubnub.gradle.enableJsTarget +import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension plugins { - kotlin("multiplatform") version "2.0.0" kotlin("plugin.serialization") version "2.0.0" - kotlin("native.cocoapods") version "2.0.0" - id("dev.mokkery") version "2.0.0" id("org.jetbrains.kotlin.plugin.atomicfu") version "2.0.0" - id("org.jlleitschuh.gradle.ktlint") version "12.1.0" - id("pubnub.ios-simulator-test") -} - -group = "com.pubnub" -version = "1.0-SNAPSHOT" - -ktlint { - outputToConsole.set(true) - verbose.set(true) - additionalEditorconfig.set( - mapOf( - "ij_kotlin_imports_layout" to "*,java.**,javax.**,kotlin.**,^", - "indent_size" to "4", - "ktlint_standard_multiline-expression-wrapping" to "disabled", - "ktlint_standard_string-template-indent" to "disabled", - "ktlint_standard_max-line-length" to "disabled", - "ktlint_standard_if-else-wrapping" to "disabled", - "ktlint_standard_discouraged-comment-location" to "disabled", - "ktlint_standard_trailing-comma-on-declaration-site" to "disabled", - "ktlint_standard_trailing-comma-on-call-site" to "disabled", - "ktlint_standard_function-signature" to "disabled", - "ktlint_standard_filename" to "disabled", - "ktlint_standard_function-naming" to "disabled", - ) - ) + id("pubnub.shared") + id("pubnub.dokka") + id("pubnub.multiplatform") + id("dev.mokkery") version "2.0.0" } kotlin { - jvmToolchain(8) - js { - useEsModules() -// browser { -// testTask { -// // useMocha { -// // timeout = "30s" -// // } -// useKarma { -// useChrome() -// } -// } -// } - nodejs { - testTask { - useMocha { - timeout = "20s" - } - } - } - } - jvm() - - listOf( -// iosArm64(), - iosSimulatorArm64(), - ).forEach { -// it.binaries { -// framework { -// baseName = "PubNubChat" -// isStatic = true -// } -// } - } - - applyDefaultHierarchyTemplate() - sourceSets { val commonMain by getting { dependencies { @@ -102,114 +40,19 @@ kotlin { } } - val nonJvm by creating { - dependsOn(commonMain) - } - - val jsMain by getting { - dependsOn(nonJvm) - } - - val jsTest by getting { - dependencies { - implementation(kotlin("test-js")) + if (enableJsTarget) { + val jsTest by getting { + dependencies { + implementation(kotlin("test-js")) + } } } } -// cocoapods { -// ios.deploymentTarget = "14" -// -// // Required properties -// // Specify the required Pod version here. Otherwise, the Gradle project version is used. -// version = "1.0" -// summary = "Some description for a Kotlin/Native module" -// homepage = "Link to a Kotlin/Native module homepage" -// -// // Optional properties -// // Configure the Pod name here instead of changing the Gradle project name -// name = "PubNubChat" -// -// // Maps custom Xcode configuration to NativeBuildType -// xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG -// xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE -// -// podfile = project.file(project.file("Sample Chat app/Podfile")) -// -// framework { -// // Required properties -// // Framework name configuration. Use this property instead of deprecated 'frameworkName' -// baseName = "PubNubChat" -// -// // Optional properties -// // Specify the framework linking type. It's dynamic by default. -// isStatic = true -// } -// -// pod("PubNubSwift") { -// source = git("https://github.com/pubnub/swift") { -// branch = "feat/kmp" -// } -// // headers = "PubNub/PubNub.h" -// // source = path(project.file("swift")) -// // version = "7.1.0" -// -// moduleName = "PubNub" -// extraOpts += listOf("-compiler-option", "-fmodules") -// } -// -// // pod("PubNubSwift") { -// //// headers = "PubNub/PubNub.h" -// // source = git("https://github.com/pubnub/objective-c") { -// // branch = "feat/kmp" -// // } -// //// source = path(project.file("swift")) -// // -// //// version = "7.1.0" -// //// version = "5.3.0" -// // moduleName = "PubNub" -// // extraOpts += listOf("-compiler-option", "-fmodules") -// // } -// } -} - -yarn.yarnLockMismatchReport = YarnLockMismatchReport.WARNING -yarn.yarnLockAutoReplace = true - -kotlin.cocoapods { - ios.deploymentTarget = "14" - - // Required properties - // Specify the required Pod version here. Otherwise, the Gradle project version is used. - version = "1.0" - summary = "Some description for a Kotlin/Native module" - homepage = "Link to a Kotlin/Native module homepage" - - // Maps custom Xcode configuration to NativeBuildType - xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG - xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE - -// podfile = project.file(project.file("Sample Chat app/Podfile")) - - framework { - // Required properties - // Framework name configuration. Use this property instead of deprecated 'frameworkName' - - // Optional properties - // Specify the framework linking type. It's dynamic by default. - isStatic = true - transitiveExport = true - } - - pod("PubNubSwift") { -// source = git("https://github.com/pubnub/swift") { -// branch = "feat/kmp" -// } -// headers = "PubNub/PubNub.h" - source = path(rootProject.file("pubnub-kotlin/swift")) -// version = "7.1.0" - - moduleName = "PubNub" - extraOpts += listOf("-compiler-option", "-fmodules") + if (enableAnyIosTarget) { + (this as ExtensionAware).extensions.configure { + summary = "Some description for a Kotlin/Native module" + homepage = "Link to a Kotlin/Native module homepage" + } } } diff --git a/pubnub-chat-impl/pubnub_chat_impl.podspec b/pubnub-chat-impl/pubnub_chat_impl.podspec index 7a65aeaf..3f33a7e7 100644 --- a/pubnub-chat-impl/pubnub_chat_impl.podspec +++ b/pubnub-chat-impl/pubnub_chat_impl.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'pubnub_chat_impl' - spec.version = '1.0' + spec.version = '0.8.0-DEV' spec.homepage = 'Link to a Kotlin/Native module homepage' spec.source = { :http=> ''} spec.authors = '' diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt index 9d34f42c..8a649f14 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/ChatImpl.kt @@ -574,7 +574,9 @@ class ChatImpl( callback: (event: Event) -> Unit ): AutoCloseable { val handler = fun(_: PubNub, pnEvent: PNEvent) { - if (pnEvent.channel != channelId) return + if (pnEvent.channel != channelId) { + return + } val message = (pnEvent as? MessageResult)?.message ?: return val eventContent: EventContent = PNDataEncoder.decode(message) @@ -593,8 +595,16 @@ class ChatImpl( val method = type.getEmitMethod() ?: customMethod val listener = createEventListener( pubNub, - onMessage = if (method == EmitEventMethod.PUBLISH) handler else { _, _ -> }, - onSignal = if (method == EmitEventMethod.SIGNAL) handler else { _, _ -> }, + onMessage = if (method == EmitEventMethod.PUBLISH) { + handler + } else { + { _, _ -> } + }, + onSignal = if (method == EmitEventMethod.SIGNAL) { + handler + } else { + { _, _ -> } + }, ) val channelEntity = pubNub.channel(channelId) val subscription = channelEntity.subscription() @@ -637,7 +647,11 @@ class ChatImpl( channelId = userId, payload = EventContent.Moderation( channelId = channel, - restriction = if (restriction.ban) RestrictionType.BAN else RestrictionType.MUTE, + restriction = if (restriction.ban) { + RestrictionType.BAN + } else { + RestrictionType.MUTE + }, reason = restriction.reason ), ) diff --git a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt index 2a3750ed..cd613bb8 100644 --- a/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt +++ b/pubnub-chat-impl/src/commonMain/kotlin/com/pubnub/chat/internal/message/BaseMessage.kt @@ -236,7 +236,9 @@ abstract class BaseMessage( val listener = createEventListener(chat.pubNub, onMessageAction = { _, event -> val message = latestMessages.find { it.timetoken == event.messageAction.messageTimetoken } ?: return@createEventListener - if (message.channelId != event.channel) return@createEventListener + if (message.channelId != event.channel) { + return@createEventListener + } val actions = if (event.event == "added") { assignAction( message.actions, diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt index 34d49a15..969a12cb 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/BaseChatIntegrationTest.kt @@ -95,7 +95,7 @@ abstract class BaseChatIntegrationTest : BaseIntegrationTest() { } @AfterTest - fun afterTest() = runTest(timeout = defaultTimeout) { + fun afterTest() = runTest { pubnub.removeUUIDMetadata(someUser.id).await() pubnub.removeUUIDMetadata(userPam.id).await() pubnub.removeChannelMetadata(channel01.id).await() diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChannelIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChannelIntegrationTest.kt index 2f2eb767..3913be48 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChannelIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChannelIntegrationTest.kt @@ -22,7 +22,7 @@ import kotlin.time.Duration.Companion.seconds class ChannelIntegrationTest : BaseChatIntegrationTest() { @Test - fun join() = runTest(timeout = defaultTimeout) { + fun join() = runTest { val channel = chat.createChannel(randomString()).await() val result = channel.join {}.await() @@ -32,31 +32,31 @@ class ChannelIntegrationTest : BaseChatIntegrationTest() { } @Test - fun join_receivesMessages() = runTest(timeout = defaultTimeout) { + fun join_receivesMessages() = runTest { } @Test - fun join_close_disconnects() = runTest(timeout = defaultTimeout) { + fun join_close_disconnects() = runTest { } @Test - fun join_updates_lastReadMessageTimetoken() = runTest(timeout = defaultTimeout) { + fun join_updates_lastReadMessageTimetoken() = runTest { } @Test - fun connect() = runTest(timeout = defaultTimeout) { + fun connect() = runTest { } @Test - fun connect_receivesMessages() = runTest(timeout = defaultTimeout) { + fun connect_receivesMessages() = runTest { } @Test - fun connect_close_disconnects() = runTest(timeout = defaultTimeout) { + fun connect_close_disconnects() = runTest { } @Test - fun getUserRestrictions() = runTest(timeout = defaultTimeout) { + fun getUserRestrictions() = runTest { val userId = "userId" val user = UserImpl(chat = chatPam, id = userId) val ban = true @@ -74,7 +74,7 @@ class ChannelIntegrationTest : BaseChatIntegrationTest() { } @Test - fun getUsersRestrictions() = runTest(timeout = defaultTimeout) { + fun getUsersRestrictions() = runTest { val userId01 = "userId01" val userId02 = "userId02" val ban = true @@ -108,13 +108,13 @@ class ChannelIntegrationTest : BaseChatIntegrationTest() { } @Test - fun shouldReturnNoUserSuggestions_whenNoDatInCacheAndNoChannelsInChat() = runTest(timeout = defaultTimeout) { + fun shouldReturnNoUserSuggestions_whenNoDatInCacheAndNoChannelsInChat() = runTest { val userSuggestions = channel01.getUserSuggestions("sas@las").await() assertEquals(0, userSuggestions.size) } @Test - fun shouldReturnUserSuggestions_whenNoDataInCacheButUserAvailableInChat() = runTest(timeout = defaultTimeout) { + fun shouldReturnUserSuggestions_whenNoDataInCacheButUserAvailableInChat() = runTest { // given val userName = "userName_${someUser.id}" val user: User = chat.createUser(id = someUser.id, name = userName).await() @@ -173,7 +173,7 @@ class ChannelIntegrationTest : BaseChatIntegrationTest() { } @Test - fun streamUpdatesOn() = runTest(timeout = defaultTimeout) { + fun streamUpdatesOn() = runTest { val newName = "newName" chat.createChannel( channel01.id, diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChatIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChatIntegrationTest.kt index dc16ca51..0873a9ef 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChatIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/ChatIntegrationTest.kt @@ -46,7 +46,7 @@ import kotlin.test.assertTrue class ChatIntegrationTest : BaseChatIntegrationTest() { @Test - fun createUser() = runTest(timeout = defaultTimeout) { + fun createUser() = runTest { val user = chat.createUser(someUser).await() assertEquals(someUser, user.asImpl().copy(updated = null, lastActiveTimestamp = null)) @@ -54,7 +54,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun updateUser() = runTest(timeout = defaultTimeout) { + fun updateUser() = runTest { val user = chat.createUser(someUser).await() val expectedUser = user.asImpl().copy( name = randomString(), @@ -84,7 +84,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun updateUser_doesntExist() = runTest(timeout = defaultTimeout) { + fun updateUser_doesntExist() = runTest { val e = assertFailsWith { chat.updateUser(someUser.id, name = randomString()).await() } @@ -94,7 +94,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun createDirectConversation() = runTest(timeout = defaultTimeout) { + fun createDirectConversation() = runTest { chat.initialize().await() // when val result = chat.createDirectConversation(someUser).await() @@ -114,7 +114,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun createGroupConversation() = runTest(timeout = defaultTimeout) { + fun createGroupConversation() = runTest { val otherUsers = listOf(UserImpl(chat, randomString()), UserImpl(chat, randomString())) // when @@ -138,7 +138,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun can_markAllMessagesAsRead() = runTest(timeout = defaultTimeout) { + fun can_markAllMessagesAsRead() = runTest { // create two membership for user one with "lastReadMessageTimetoken" and second without. val lastReadMessageTimetokenValue: Long = 17195737006492403 val custom: CustomObject = @@ -219,7 +219,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { @Ignore // fails from time to time @Test - fun can_getUnreadMessagesCount_onMembership() = runTest(timeout = defaultTimeout) { + fun can_getUnreadMessagesCount_onMembership() = runTest { val channelId01 = channel01.id // send message @@ -253,7 +253,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { @Ignore // fails from time to time @Test - fun can_getUnreadMessageCounts_global() = runTest(timeout = defaultTimeout) { + fun can_getUnreadMessageCounts_global() = runTest { val channelId01 = channel01.id val channelId02 = channel02.id @@ -302,14 +302,14 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun shouldReturnNoChannelSuggestions_whenNoDataInCacheAndNoChannelsInChat() = runTest(timeout = defaultTimeout) { + fun shouldReturnNoChannelSuggestions_whenNoDataInCacheAndNoChannelsInChat() = runTest { val channelSuggestions: Set = chat.getChannelSuggestions("sas#las").await() assertEquals(0, channelSuggestions.size) } @Test fun shouldReturnChannelSuggestions_whenNoDataInCacheButChannelAvailableInChat() = - runTest(timeout = defaultTimeout) { + runTest { val channelName = "channelName_${channel01.id}" chat.createChannel(id = channel01.id, name = channelName).await() @@ -321,13 +321,13 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun shouldReturnNoUserSuggestions_whenNoDatInCacheAndNoChannelsInChat() = runTest(timeout = defaultTimeout) { + fun shouldReturnNoUserSuggestions_whenNoDatInCacheAndNoChannelsInChat() = runTest { val userSuggestions = chat.getUserSuggestions("sas@las").await() assertEquals(0, userSuggestions.size) } @Test - fun shouldReturnUserSuggestions_whenNoDataInCacheButUserAvailableInChat() = runTest(timeout = defaultTimeout) { + fun shouldReturnUserSuggestions_whenNoDataInCacheButUserAvailableInChat() = runTest { val userName = "userName_${someUser.id}" chat.createUser(id = someUser.id, name = userName).await() @@ -339,7 +339,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun register_unregister_list_pushNotificationOnChannel() = runTest(timeout = defaultTimeout) { + fun register_unregister_list_pushNotificationOnChannel() = runTest { // set up push config val chatConfig = ChatConfiguration( pushNotifications = PushNotificationsConfig( @@ -385,7 +385,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { } @Test - fun can_getEventsHistory() = runTest(timeout = defaultTimeout) { + fun can_getEventsHistory() = runTest { // given val channelId01 = channel01.id val userId = someUser.id @@ -427,6 +427,7 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { // send messages with user mentions channel01.sendText(text = message, mentionedUsers = messageMentionedUsers).await() + delayInMillis(1000) // when val currentUserMentionsResult: GetCurrentUserMentionsResult = chat.getCurrentUserMentions().await() @@ -437,7 +438,6 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { assertEquals(1, currentUserMentionsResult.enhancedMentionsData.size) assertEquals(userId, userMentionData.userId) assertEquals(channelId01, userMentionData.channelId) - assertTrue(userMentionData.event.payload is EventContent.Mention) assertEquals(message, userMentionData.message?.content?.text) // remove messages @@ -463,9 +463,8 @@ class ChatIntegrationTest : BaseChatIntegrationTest() { assertEquals(1, currentUserMentionsResult.enhancedMentionsData.size) val userMentionData = currentUserMentionsResult.enhancedMentionsData.first() as ThreadMentionData assertEquals(userId, userMentionData.userId) - assertEquals(true, userMentionData.parentChannelId?.contains(CHANNEL_ID_OF_PARENT_MESSAGE_PREFIX)) - assertEquals(true, userMentionData.threadChannelId?.contains(THREAD_CHANNEL_ID_PREFIX)) - assertTrue(userMentionData.event.payload is EventContent.Mention) + assertEquals(true, userMentionData.parentChannelId.contains(CHANNEL_ID_OF_PARENT_MESSAGE_PREFIX)) + assertEquals(true, userMentionData.threadChannelId.contains(THREAD_CHANNEL_ID_PREFIX)) assertEquals(message, userMentionData.message?.content?.text) // remove messages diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MembershipIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MembershipIntegrationTest.kt index cda8bf8e..ea20abaf 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MembershipIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MembershipIntegrationTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertEquals class MembershipIntegrationTest : BaseChatIntegrationTest() { @Test - fun streamUpdatesOn() = runTest(timeout = defaultTimeout) { + fun streamUpdatesOn() = runTest { chat.createChannel( channel01.id, channel01.name, diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MessageIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MessageIntegrationTest.kt index 503a5879..4eb2dc43 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MessageIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/MessageIntegrationTest.kt @@ -15,7 +15,7 @@ import kotlin.test.assertEquals class MessageIntegrationTest : BaseChatIntegrationTest() { @Test - fun streamUpdatesOn() = runTest(timeout = defaultTimeout) { + fun streamUpdatesOn() = runTest { chat.createChannel( channel01.id, channel01.name, diff --git a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/UserIntegrationTest.kt b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/UserIntegrationTest.kt index 68f44926..845a73f4 100644 --- a/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/UserIntegrationTest.kt +++ b/pubnub-chat-impl/src/commonTest/kotlin/com/pubnub/integration/UserIntegrationTest.kt @@ -26,7 +26,7 @@ import kotlin.test.assertTrue class UserIntegrationTest : BaseChatIntegrationTest() { @Test - fun getChannelRestrictions() = runTest(timeout = defaultTimeout) { + fun getChannelRestrictions() = runTest { val channelId = "channelId01" val channel = ChannelImpl(chat = chatPam, id = channelId) val ban = true @@ -44,7 +44,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun getChannelsRestrictions_sortAsc() = runTest(timeout = defaultTimeout) { + fun getChannelsRestrictions_sortAsc() = runTest { val channelId01 = "channelId01" val channelId02 = "channelId02" val ban = true @@ -84,7 +84,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun getChannelsRestrictions_sortDsc() = runTest(timeout = defaultTimeout) { + fun getChannelsRestrictions_sortDsc() = runTest { val channelId01 = "channelId01" val channelId02 = "channelId02" val ban = true @@ -117,7 +117,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun streamUpdatesOn() = runTest(timeout = defaultTimeout) { + fun streamUpdatesOn() = runTest { val newName = "newName" val expectedUpdates = listOf( listOf(someUser), @@ -148,7 +148,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun calling_active_should_throw_exception_when_storeUserActivityTimestamps_is_false() = runTest(timeout = defaultTimeout) { + fun calling_active_should_throw_exception_when_storeUserActivityTimestamps_is_false() = runTest { val e = assertFailsWith { someUser.active().await() } @@ -160,7 +160,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun whenUserDoesNotExist_init_should_create_it_with_lastActiveTimestamp() = runTest(timeout = defaultTimeout) { + fun whenUserDoesNotExist_init_should_create_it_with_lastActiveTimestamp() = runTest { // set up storeUserActivityTimestamps val chatConfig = ChatConfiguration( storeUserActivityTimestamps = true @@ -176,7 +176,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun whenUserExists_init_should_update_lastActiveTimestamp() = runTest(timeout = defaultTimeout) { + fun whenUserExists_init_should_update_lastActiveTimestamp() = runTest { // set up storeUserActivityTimestamps val chatConfig = ChatConfiguration( storeUserActivityTimestamps = true @@ -196,7 +196,7 @@ class UserIntegrationTest : BaseChatIntegrationTest() { } @Test - fun adminCanSubscribeToInternalChannelAndGetReportedUserEvent() = runTest(timeout = defaultTimeout) { + fun adminCanSubscribeToInternalChannelAndGetReportedUserEvent() = runTest { val reason = "rude" val assertionErrorInListener01 = CompletableDeferred() val removeListenerAndUnsubscribe: AutoCloseable = chat.listenForEvents( diff --git a/pubnub-kotlin b/pubnub-kotlin index f2c4f8e6..8b7eb393 160000 --- a/pubnub-kotlin +++ b/pubnub-kotlin @@ -1 +1 @@ -Subproject commit f2c4f8e6328f69614ed4e052d392fc8a53087d7b +Subproject commit 8b7eb393d98b2e98728e3e09a040dbbea0d73441 diff --git a/pubnub_chat.podspec b/pubnub_chat.podspec index 3d620a1b..b3d63a43 100644 --- a/pubnub_chat.podspec +++ b/pubnub_chat.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'pubnub_chat' - spec.version = '1.0' + spec.version = '0.8.0-DEV' spec.homepage = 'Link to a Kotlin/Native module homepage' spec.source = { :http=> ''} spec.authors = '' diff --git a/settings.gradle.kts b/settings.gradle.kts index c78f9e4e..2c772540 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,5 +22,7 @@ includeBuild("pubnub-kotlin") { name = "pubnub" } +includeBuild("pubnub-kotlin/build-logic/ktlint-custom-rules") + include(":pubnub-chat-api") include(":pubnub-chat-impl")