diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 031c97a..0551844 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -2,6 +2,8 @@ name: Tests on: push: + branches-ignore: + - master workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/run-validations.yml b/.github/workflows/run-validations.yml index e5f2440..517772a 100644 --- a/.github/workflows/run-validations.yml +++ b/.github/workflows/run-validations.yml @@ -2,6 +2,8 @@ name: Validations on: push: + branches-ignore: + - master workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.pubnub.yml b/.pubnub.yml index a76d2c8..90963db 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,9 +1,26 @@ --- name: swift-chat-sdk scm: github.com/pubnub/swift-chat-sdk -version: "0.9.1" +version: "0.9.2" schema: 1 changelog: + - date: 2024-12-17 + version: 0.9.2 + changes: + - type: feature + text: "Add support for other Apple platforms." + - type: feature + text: "Lock moderated messages from editing." + - type: bug + text: "Remove `getChannelSuggestions(text:limit:completion:)` method from `Chat` interface." + - type: bug + text: "Remove `getUserSuggestions(text:limit:completion:)` method from `Chat` interface." + - type: bug + text: "Wrong user suggestion source for message draft created on ThreadChannel." + - type: bug + text: "Wrong type of last user activity time stored on the server (precision)." + - type: improvement + text: "Moderation events are now sent to a channel prefixed with `PUBNUB_INTERNAL_MODERATION.`." - date: 2024-12-05 version: 0.9.1 changes: @@ -51,7 +68,7 @@ sdks: - distribution-type: source distribution-repository: GitHub release package-name: PubNubSwiftChatSDK - location: https://github.com/pubnub/swift-chat-sdk/archive/refs/tags/0.9.1-dev.zip + location: https://github.com/pubnub/swift-chat-sdk/archive/refs/tags/0.9.2-dev.zip supported-platforms: supported-operating-systems: iOS: @@ -66,7 +83,31 @@ sdks: target-devices: - iPhone - iPad + macOS: + runtime-version: + - Swift 5.x + minimum-os-version: + - macOS 11.0 + maximum-os-version: + - macOS 15.0.1 + target-architecture: + - arm64 + - x86_64 + tvOS: + runtime-version: + - Swift 5.x + minimum-os-version: + - tvOS 14.0 + maximum-os-version: + - tvOS 18.0 + target-architecture: + - arm64 + target-devices: + - Apple TV + supported-platforms: - version: PubNub Swift Chat SDK platforms: - iOS 14.0 or higher + - macOS 11.0 or higher + - tvOS 14.0 or higher diff --git a/Package.swift b/Package.swift index a24dd04..47e00d4 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,11 @@ import PackageDescription let package = Package( name: "PubNubSwiftChatSDK", - platforms: [.iOS(.v14)], + platforms: [ + .iOS(.v14), + .macOS(.v11), + .tvOS(.v14) + ], products: [ // Products define the executables and libraries a package produces, making them visible to other packages. .library( @@ -14,8 +18,8 @@ let package = Package( ) ], dependencies: [ - .package(url: "https://github.com/pubnub/kmp-chat", exact: "0.9.0-dev"), - .package(url: "https://github.com/pubnub/swift", exact: "8.0.1") + .package(url: "https://github.com/pubnub/kmp-chat", exact: "0.9.3-dev"), + .package(url: "https://github.com/pubnub/swift", exact: "8.2.2") ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/PubNubSwiftChatSDK.xcodeproj/project.pbxproj b/PubNubSwiftChatSDK.xcodeproj/project.pbxproj index 7c14cfc..277aace 100644 --- a/PubNubSwiftChatSDK.xcodeproj/project.pbxproj +++ b/PubNubSwiftChatSDK.xcodeproj/project.pbxproj @@ -20,6 +20,8 @@ 3D2CA2482C621876008D2284 /* MessageActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D2CA2472C621876008D2284 /* MessageActionType.swift */; }; 3D334BD02C8EE9E500F8793C /* PubNub.PushService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D334BCF2C8EE9E500F8793C /* PubNub.PushService.swift */; }; 3D334BD22C8EEAA800F8793C /* PubNub.PushEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D334BD12C8EEAA800F8793C /* PubNub.PushEnvironment.swift */; }; + 3D5B58412D10B9A100CB74D1 /* PubNubChat in Frameworks */ = {isa = PBXBuildFile; productRef = 3D5B58402D10B9A100CB74D1 /* PubNubChat */; }; + 3D79EB862D0C40ED00F7AB56 /* PubNubChat.PubNubError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D79EB852D0C40ED00F7AB56 /* PubNubChat.PubNubError.swift */; }; 3D7BBF6F2C8893D400FBA623 /* ChatAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D7BBF6E2C8893D400FBA623 /* ChatAdapter.swift */; }; 3D83621A2CC7B35200A21B9A /* MessageDraftChangeListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D8362192CC7B35200A21B9A /* MessageDraftChangeListener.swift */; }; 3D842D242C9DC0AA005C0B55 /* ErrorConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D842D232C9DC0AA005C0B55 /* ErrorConstants.swift */; }; @@ -80,7 +82,6 @@ 3DB73A7D2C57EA94007FE249 /* Timetoken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB73A7C2C57EA94007FE249 /* Timetoken.swift */; }; 3DB73A7F2C58CCAE007FE249 /* GetCurrentUserMentionsResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB73A7E2C58CCAE007FE249 /* GetCurrentUserMentionsResult.swift */; }; 3DCF7DFC2CD0FFCC00889326 /* PubNubSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 3DCF7DFB2CD0FFCC00889326 /* PubNubSDK */; }; - 3DCF7DFF2CD1226100889326 /* PubNubChat in Frameworks */ = {isa = PBXBuildFile; productRef = 3DCF7DFE2CD1226100889326 /* PubNubChat */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -121,6 +122,7 @@ 3D2CA2472C621876008D2284 /* MessageActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageActionType.swift; sourceTree = ""; }; 3D334BCF2C8EE9E500F8793C /* PubNub.PushService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubNub.PushService.swift; sourceTree = ""; }; 3D334BD12C8EEAA800F8793C /* PubNub.PushEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubNub.PushEnvironment.swift; sourceTree = ""; }; + 3D79EB852D0C40ED00F7AB56 /* PubNubChat.PubNubError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubNubChat.PubNubError.swift; sourceTree = ""; }; 3D7BBF6E2C8893D400FBA623 /* ChatAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatAdapter.swift; sourceTree = ""; }; 3D8362192CC7B35200A21B9A /* MessageDraftChangeListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageDraftChangeListener.swift; sourceTree = ""; }; 3D842D232C9DC0AA005C0B55 /* ErrorConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorConstants.swift; sourceTree = ""; }; @@ -190,7 +192,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3DCF7DFF2CD1226100889326 /* PubNubChat in Frameworks */, + 3D5B58412D10B9A100CB74D1 /* PubNubChat in Frameworks */, 3DCF7DFC2CD0FFCC00889326 /* PubNubSDK in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -317,6 +319,7 @@ 3D2CA23D2C5BBCDB008D2284 /* PubNubChat.PNPushType.swift */, 3D2CA23F2C5BBDB6008D2284 /* PubNubChat.PNPushEnvironment.swift */, 3DB73A742C57D073007FE249 /* PubNubChat.Event.swift */, + 3D79EB852D0C40ED00F7AB56 /* PubNubChat.PubNubError.swift */, ); path = Extensions; sourceTree = ""; @@ -398,7 +401,7 @@ name = PubNubSwiftChatSDK; packageProductDependencies = ( 3DCF7DFB2CD0FFCC00889326 /* PubNubSDK */, - 3DCF7DFE2CD1226100889326 /* PubNubChat */, + 3D5B58402D10B9A100CB74D1 /* PubNubChat */, ); productName = PubNubChatSDK; productReference = 3DB73A072C4FE13C007FE249 /* PubNubSwiftChatSDK.framework */; @@ -452,7 +455,7 @@ mainGroup = 3DB739FD2C4FE13B007FE249; packageReferences = ( 3DCF7DFA2CD0FFCC00889326 /* XCRemoteSwiftPackageReference "swift" */, - 3DCF7DFD2CD1226100889326 /* XCRemoteSwiftPackageReference "kmp-chat" */, + 3D5B583F2D10B9A100CB74D1 /* XCRemoteSwiftPackageReference "kmp-chat" */, ); productRefGroup = 3DB73A082C4FE13C007FE249 /* Products */; projectDirPath = ""; @@ -522,6 +525,7 @@ 3DB73A652C57A782007FE249 /* CreateDirectConversationResult.swift in Sources */, 3DB73A5D2C53CC0A007FE249 /* ThreadChannelImpl.swift in Sources */, 3D334BD22C8EEAA800F8793C /* PubNub.PushEnvironment.swift in Sources */, + 3D79EB862D0C40ED00F7AB56 /* PubNubChat.PubNubError.swift in Sources */, 3DB73A4F2C52881A007FE249 /* PubNubChat.ChannelType.swift in Sources */, 3DB73A6B2C57B9D8007FE249 /* GetUnreadMessagesCount.swift in Sources */, 3DB49E212C761BD1006356ED /* AutoCloseable.swift in Sources */, @@ -728,8 +732,8 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 0.9.1; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 0.9.2; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS"; @@ -737,14 +741,14 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3"; TVOS_DEPLOYMENT_TARGET = 14.0; WATCHOS_DEPLOYMENT_TARGET = 8; XROS_DEPLOYMENT_TARGET = 1.1; @@ -777,8 +781,8 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 0.9.1; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 0.9.2; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS"; @@ -786,14 +790,14 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,3"; TVOS_DEPLOYMENT_TARGET = 14.0; WATCHOS_DEPLOYMENT_TARGET = 8; XROS_DEPLOYMENT_TARGET = 1.1; @@ -877,35 +881,35 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 3DCF7DFA2CD0FFCC00889326 /* XCRemoteSwiftPackageReference "swift" */ = { + 3D5B583F2D10B9A100CB74D1 /* XCRemoteSwiftPackageReference "kmp-chat" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/pubnub/swift"; + repositoryURL = "https://github.com/pubnub/kmp-chat/"; requirement = { kind = exactVersion; - version = 8.0.1; + version = "0.9.3-dev"; }; }; - 3DCF7DFD2CD1226100889326 /* XCRemoteSwiftPackageReference "kmp-chat" */ = { + 3DCF7DFA2CD0FFCC00889326 /* XCRemoteSwiftPackageReference "swift" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/pubnub/kmp-chat"; + repositoryURL = "https://github.com/pubnub/swift"; requirement = { kind = exactVersion; - version = "0.9.0-dev"; + version = 8.2.2; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 3D5B58402D10B9A100CB74D1 /* PubNubChat */ = { + isa = XCSwiftPackageProductDependency; + package = 3D5B583F2D10B9A100CB74D1 /* XCRemoteSwiftPackageReference "kmp-chat" */; + productName = PubNubChat; + }; 3DCF7DFB2CD0FFCC00889326 /* PubNubSDK */ = { isa = XCSwiftPackageProductDependency; package = 3DCF7DFA2CD0FFCC00889326 /* XCRemoteSwiftPackageReference "swift" */; productName = PubNubSDK; }; - 3DCF7DFE2CD1226100889326 /* PubNubChat */ = { - isa = XCSwiftPackageProductDependency; - package = 3DCF7DFD2CD1226100889326 /* XCRemoteSwiftPackageReference "kmp-chat" */; - productName = PubNubChat; - }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 3DB739FE2C4FE13C007FE249 /* Project object */; diff --git a/README.md b/README.md index c004acb..72e5be7 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ It exposes various PubNub APIs with twists: ## Requirements -* iOS 14.0+ (support for other platforms is coming in future releases) +* iOS 14.0+ / macOS 11.0+ / tvOS 14.0+ * Xcode 15+ * Swift 5+ @@ -37,7 +37,7 @@ You will need the publish and subscribe keys to authenticate your app. Get your 1. Create or open your project inside Xcode. 2. Navigate to **File -> Add Package Dependencies**. 3. Search for `https://github.com/pubnub/swift-chat-sdk` -4. From the **Dependency Rule** drop-down list, select **Exact**. In the version input field, type `0.9.1-dev` +4. From the **Dependency Rule** drop-down list, select **Exact**. In the version input field, type `0.9.2-dev` 5. Click the **Add Package** button. For more information see Apple's guide on [Adding Package Dependencies to Your App](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app) diff --git a/Sources/Chat.swift b/Sources/Chat.swift index 0c40278..ab4d42a 100644 --- a/Sources/Chat.swift +++ b/Sources/Chat.swift @@ -435,34 +435,6 @@ public protocol Chat: AnyObject { completion: ((Swift.Result<(memberships: [ChatMembershipType], page: PubNubHashedPage?), Error>) -> Void)? ) - /// Retrieves all channels that match the provided 3-letter string from your app's keyset. - /// - /// - Parameters: - /// - text: At least a 3-letter string typed in after `#` with the channel name you want to reference - /// - limit: Maximum number of returned channel names that match the typed 3-letter suggestion - /// - completion: The async `Result` of the method call - /// - **Success**: An array of ``Channel`` objects - /// - **Failure**: An `Error` describing the failure - func getChannelSuggestions( - text: String, - limit: Int, - completion: ((Swift.Result<[ChatChannelType], Error>) -> Void)? - ) - - /// Returns all suggested users that match the provided 3-letter string. - /// - /// - Parameters: - /// - text: At least a 3-letter string typed in after `@` with the user name you want to mention - /// - limit: Maximum number of returned usernames that match the typed 3-letter suggestion - /// - completion: The async `Result` of the method call - /// - **Success**: An array of ``Channel`` objects - /// - **Failure**: An `Error` describing the failure - func getUserSuggestions( - text: String, - limit: Int, - completion: ((Swift.Result<[ChatUserType], Error>) -> Void)? - ) - /// Retrieves all channels where your registered device receives push notifications. /// /// - Parameters: diff --git a/Sources/ChatImpl.swift b/Sources/ChatImpl.swift index a770f73..3dd678f 100644 --- a/Sources/ChatImpl.swift +++ b/Sources/ChatImpl.swift @@ -658,46 +658,6 @@ extension ChatImpl: Chat { } } - public func getChannelSuggestions( - text: String, - limit: Int = 10, - completion: ((Swift.Result<[ChannelImpl], Error>) -> Void)? = nil - ) { - chat.getChannelSuggestions( - text: text, - limit: Int32(limit) - ).async(caller: self) { (result: FutureResult) in - switch result.result { - case let .success(channels): - completion?(.success(channels.compactMap { - ChannelImpl(channel: $0) - })) - case let .failure(error): - completion?(.failure(error)) - } - } - } - - public func getUserSuggestions( - text: String, - limit: Int = 10, - completion: ((Swift.Result<[UserImpl], Error>) -> Void)? = nil - ) { - chat.getUserSuggestions( - text: text, - limit: Int32(limit) - ).async(caller: self) { (result: FutureResult) in - switch result.result { - case let .success(users): - completion?(.success(users.compactMap { - UserImpl(user: $0) - })) - case let .failure(error): - completion?(.failure(error)) - } - } - } - public func getPushChannels(completion: ((Swift.Result<[String], Error>) -> Void)? = nil) { chat.getPushChannels().async(caller: self) { (result: FutureResult) in switch result.result { diff --git a/Sources/Entities/BaseChannel.swift b/Sources/Entities/BaseChannel.swift index 161dc14..f7c7292 100644 --- a/Sources/Entities/BaseChannel.swift +++ b/Sources/Entities/BaseChannel.swift @@ -95,22 +95,22 @@ final class BaseChannel: Channel } } - func startTyping(completion: ((Swift.Result) -> Void)?) { - channel.startTyping().async(caller: self) { (result: FutureResult) in + func startTyping(completion: ((Swift.Result) -> Void)?) { + channel.startTyping().async(caller: self) { (result: FutureResult) in switch result.result { - case .success: - completion?(.success(())) + case let .success(publishRes): + completion?(.success(publishRes?.timetoken.asTimetoken())) case let .failure(error): completion?(.failure(error)) } } } - func stopTyping(completion: ((Swift.Result) -> Void)?) { - channel.stopTyping().async(caller: self) { (result: FutureResult) in + func stopTyping(completion: ((Swift.Result) -> Void)?) { + channel.stopTyping().async(caller: self) { (result: FutureResult) in switch result.result { - case .success: - completion?(.success(())) + case let .success(publishRes): + completion?(.success(publishRes?.timetoken.asTimetoken())) case let .failure(error): completion?(.failure(error)) } @@ -274,9 +274,7 @@ final class BaseChannel: Channel case let .success(response): completion?(.success( ( - memberships: response.members.compactMap { - $0 as? PubNubChat.Membership - }.map { + memberships: response.members.map { MembershipImpl(membership: $0) }, page: PubNubHashedPageBase( @@ -537,9 +535,7 @@ final class BaseChannel: Channel switch result.result { case let .success(response): completion?(.success(( - events: response.events.compactMap { - $0 as? PubNubChat.Event - }.compactMap { (event: PubNubChat.Event) -> EventWrapper? in + events: response.events.compactMap { (event: PubNubChat.Event) -> EventWrapper? in EventWrapper( event: EventImpl( chat: result.caller.chat, diff --git a/Sources/Entities/BaseMessage.swift b/Sources/Entities/BaseMessage.swift index b96161f..f3795c4 100644 --- a/Sources/Entities/BaseMessage.swift +++ b/Sources/Entities/BaseMessage.swift @@ -46,6 +46,7 @@ extension BaseMessage: Message { public var files: [File] { message.files.transform() } public var reactions: [String: [Action]] { message.reactions.transform() } public var textLinks: [TextLink]? { message.textLinks?.transform() } + public var error: Error? { message.error } static func streamUpdatesOn( messages: [BaseMessage], diff --git a/Sources/Entities/Channel.swift b/Sources/Entities/Channel.swift index bcd0980..549025a 100644 --- a/Sources/Entities/Channel.swift +++ b/Sources/Entities/Channel.swift @@ -97,20 +97,20 @@ public protocol Channel { /// /// - Parameters: /// - completion: The async `Result` of the method call - /// - **Success**: A `Void` indicating a success + /// - **Success**: A `Timetoken` indicating the action timestamp /// - **Failure**: An `Error` describing the failure func startTyping( - completion: ((Swift.Result) -> Void)? + completion: ((Swift.Result) -> Void)? ) /// Deactivates a typing indicator on a given channel. /// /// - Parameters: /// - completion: The async `Result` of the method call - /// - **Success**: A `Void` indicating a success + /// - **Success**: A `Timetoken` indicating the action timestamp /// - **Failure**: An `Error` describing the failure func stopTyping( - completion: ((Swift.Result) -> Void)? + completion: ((Swift.Result) -> Void)? ) /// Enables continuous tracking of typing activity within the ``Channel``. diff --git a/Sources/Entities/ChannelImpl.swift b/Sources/Entities/ChannelImpl.swift index 82666ea..01424be 100644 --- a/Sources/Entities/ChannelImpl.swift +++ b/Sources/Entities/ChannelImpl.swift @@ -123,13 +123,13 @@ extension ChannelImpl: Channel { ) } - public func startTyping(completion: ((Swift.Result) -> Void)? = nil) { + public func startTyping(completion: ((Swift.Result) -> Void)? = nil) { target.startTyping( completion: completion ) } - public func stopTyping(completion: ((Swift.Result) -> Void)? = nil) { + public func stopTyping(completion: ((Swift.Result) -> Void)? = nil) { target.stopTyping( completion: completion ) diff --git a/Sources/Entities/MembershipImpl.swift b/Sources/Entities/MembershipImpl.swift index f38a805..6021341 100644 --- a/Sources/Entities/MembershipImpl.swift +++ b/Sources/Entities/MembershipImpl.swift @@ -94,7 +94,7 @@ extension MembershipImpl: Membership { completion: ((Swift.Result) -> Void)? = nil ) { membership.update( - custom: CustomObject(value: custom) + custom: custom ).async(caller: self) { (result: FutureResult) in switch result.result { case let .success(membership): diff --git a/Sources/Entities/Message.swift b/Sources/Entities/Message.swift index 13f4355..fbe318f 100644 --- a/Sources/Entities/Message.swift +++ b/Sources/Entities/Message.swift @@ -58,6 +58,8 @@ public protocol Message { var files: [File] { get } /// List of reactions attached to the given ``Message`` var reactions: [String: [Action]] { get } + /// Error associated with the message, if any + var error: Error? { get } /// Receive updates when specific messages and related message reactions are added, edited, or removed. /// diff --git a/Sources/Entities/MessageImpl.swift b/Sources/Entities/MessageImpl.swift index 3d4440a..e234484 100644 --- a/Sources/Entities/MessageImpl.swift +++ b/Sources/Entities/MessageImpl.swift @@ -39,7 +39,8 @@ public final class MessageImpl { channelId: channelId, userId: userId, actions: actions?.transform(), - metaInternal: JsonElementImpl(value: meta?.compactMapValues { $0.rawValue }) + metaInternal: JsonElementImpl(value: meta?.compactMapValues { $0.rawValue }), + error: nil ) self.init( message: underlyingMessage @@ -77,6 +78,7 @@ extension MessageImpl: Message { public var files: [File] { target.files } public var reactions: [String: [Action]] { target.reactions } public var textLinks: [TextLink]? { target.textLinks } + public var error: Error? { target.error } public static func streamUpdatesOn( messages: [MessageImpl], diff --git a/Sources/Entities/ThreadChannelImpl.swift b/Sources/Entities/ThreadChannelImpl.swift index e585799..8d1d8d1 100644 --- a/Sources/Entities/ThreadChannelImpl.swift +++ b/Sources/Entities/ThreadChannelImpl.swift @@ -151,13 +151,13 @@ extension ThreadChannelImpl: ThreadChannel { ) } - public func startTyping(completion: ((Swift.Result) -> Void)? = nil) { + public func startTyping(completion: ((Swift.Result) -> Void)? = nil) { target.startTyping( completion: completion ) } - public func stopTyping(completion: ((Swift.Result) -> Void)? = nil) { + public func stopTyping(completion: ((Swift.Result) -> Void)? = nil) { target.stopTyping( completion: completion ) diff --git a/Sources/Entities/ThreadMessageImpl.swift b/Sources/Entities/ThreadMessageImpl.swift index d12a015..f73c52b 100644 --- a/Sources/Entities/ThreadMessageImpl.swift +++ b/Sources/Entities/ThreadMessageImpl.swift @@ -31,10 +31,7 @@ public final class ThreadMessageImpl { channelId: String, userId: String, actions: [String: [String: [Action]]]? = nil, - meta: [String: JSONCodable]? = nil, - mentionedUsers: MessageMentionedUsers? = nil, - referencedChannels: MessageReferencedChannels? = nil, - quotedMessage: QuotedMessage? = nil + meta: [String: JSONCodable]? = nil ) { let underlyingThreadMessage = PubNubChat.ThreadMessageImpl( chat: chat.chat, @@ -44,7 +41,8 @@ public final class ThreadMessageImpl { channelId: channelId, userId: userId, actions: actions?.transform(), - metaInternal: JsonElementImpl(value: meta?.compactMapValues { $0.rawValue }) + metaInternal: JsonElementImpl(value: meta?.compactMapValues { $0.rawValue }), + error: nil ) self.init( message: underlyingThreadMessage @@ -89,6 +87,7 @@ extension ThreadMessageImpl: ThreadMessage { public var reactions: [String: [Action]] { target.reactions } public var textLinks: [TextLink]? { target.textLinks } public var parentChannelId: String { target.message.parentChannelId } + public var error: Error? { target.message.error } public static func streamUpdatesOn( messages: [ThreadMessageImpl], diff --git a/Sources/Entities/UserImpl.swift b/Sources/Entities/UserImpl.swift index c5bf0ec..913266d 100644 --- a/Sources/Entities/UserImpl.swift +++ b/Sources/Entities/UserImpl.swift @@ -180,9 +180,7 @@ extension UserImpl: User { switch result.result { case let .success(response): completion?(.success(( - memberships: response.memberships.compactMap { - $0 as? PubNubChat.Membership - }.map { + memberships: response.memberships.map { MembershipImpl(membership: $0) }, page: PubNubHashedPageBase( diff --git a/Sources/Extensions/Dictionary.swift b/Sources/Extensions/Dictionary.swift index 8f2f295..22dc67f 100644 --- a/Sources/Extensions/Dictionary.swift +++ b/Sources/Extensions/Dictionary.swift @@ -44,8 +44,8 @@ extension [String: [String: [Action]]] { } extension [String: JSONCodableScalar] { - func asCustomObject() -> PubNubChat.CustomObject { - PubNubChat.CustomObject(value: self) + func asCustomObject() -> [String: Any] { + Factories_nonJvmKt.createCustomObject(map: self) } } diff --git a/Sources/Extensions/PubNub.MembershipSortField.swift b/Sources/Extensions/PubNub.MembershipSortField.swift index 3811f4f..b28b71b 100644 --- a/Sources/Extensions/PubNub.MembershipSortField.swift +++ b/Sources/Extensions/PubNub.MembershipSortField.swift @@ -26,7 +26,7 @@ extension PubNub.MembershipSortField { case .type, .status: return nil } - case .status: + case .type, .status: return nil case .updated: return ascending ? PNSortKeyPNAsc(key: PNMembershipKey.updated) : PNSortKeyPNDesc(key: .updated) diff --git a/Sources/Extensions/PubNubChat.PubNubError.swift b/Sources/Extensions/PubNubChat.PubNubError.swift new file mode 100644 index 0000000..d81c37c --- /dev/null +++ b/Sources/Extensions/PubNubChat.PubNubError.swift @@ -0,0 +1,16 @@ +// +// PubNubChat.PubNubError.swift +// +// Copyright (c) PubNub Inc. +// All rights reserved. +// +// This source code is licensed under the license found in the +// LICENSE file in the root directory of this source tree. +// + +import Foundation +import PubNubChat + +extension PubNubChat.PubNubError: Error { + +} diff --git a/Sources/Extensions/Timetoken.swift b/Sources/Extensions/Timetoken.swift index a255257..7074cbc 100644 --- a/Sources/Extensions/Timetoken.swift +++ b/Sources/Extensions/Timetoken.swift @@ -17,3 +17,9 @@ extension Timetoken { KotlinLong(value: Int64(self)) } } + +extension Int64 { + func asTimetoken() -> Timetoken { + Timetoken(self) + } +} diff --git a/Sources/Miscellaneous/Constants.swift b/Sources/Miscellaneous/Constants.swift index 7f7a511..8ec1889 100644 --- a/Sources/Miscellaneous/Constants.swift +++ b/Sources/Miscellaneous/Constants.swift @@ -10,4 +10,4 @@ import Foundation -let pubNubSwiftChatSDKVersion: String = "0.9.1" +let pubNubSwiftChatSDKVersion: String = "0.9.2" diff --git a/Tests/ChannelIntegrationTests.swift b/Tests/ChannelIntegrationTests.swift index 5a7e8ec..aa3973b 100644 --- a/Tests/ChannelIntegrationTests.swift +++ b/Tests/ChannelIntegrationTests.swift @@ -165,11 +165,9 @@ class ChannelIntegrationTests: PubNubSwiftChatSDKIntegrationTests { } func testChannel_StopTyping() throws { - XCTAssertNotNil( - try awaitResultValue { - channel.stopTyping(completion: $0) - } - ) + try awaitResultValue { + channel.stopTyping(completion: $0) + } } func testChannel_WhoIsPresent() throws { @@ -599,7 +597,7 @@ class ChannelIntegrationTests: PubNubSwiftChatSDKIntegrationTests { completion: $0 ) } - let anotherMembership = try awaitResultValue { + let anotherMembership = try awaitResultValue(delay: 1) { channel.invite( user: anotherUser, completion: $0 diff --git a/Tests/ChatIntegrationTests.swift b/Tests/ChatIntegrationTests.swift index a1375a6..4703450 100644 --- a/Tests/ChatIntegrationTests.swift +++ b/Tests/ChatIntegrationTests.swift @@ -796,94 +796,6 @@ class ChatIntegrationTests: PubNubSwiftChatSDKIntegrationTests { } } - func testChat_GetChannelSuggestions() throws { - let channelName = "chnl_\(randomString())" - let channelId = channelName - - let channel = try awaitResultValue { - chat.createChannel( - id: channelId, - name: channelName, - completion: $0 - ) - } - - let channelSuggestion = try XCTUnwrap( - try awaitResultValue { - chat.getChannelSuggestions( - text: "chnl_", - completion: $0 - ) - } - ) - - XCTAssertTrue(channelSuggestion.contains { - $0.name == channelName - }) - - addTeardownBlock { [unowned self] in - try awaitResult { - chat.deleteChannel( - id: channel.id, - completion: $0 - ) - } - } - } - - func testChat_GetUserSuggestions() throws { - let username = "someUser_\(randomString())" - let channelId = randomString() - - let channel = try awaitResultValue { - chat.createChannel( - id: channelId, - completion: $0 - ) - } - - let user = try awaitResultValue { - chat.createUser( - id: username, - name: username, - completion: $0 - ) - } - try awaitResultValue { - channel.invite( - user: user, - completion: $0 - ) - } - - let userSuggestion = try XCTUnwrap( - try awaitResultValue { - chat.getUserSuggestions( - text: "someUser_", - completion: $0 - ) - }.first - ) - - XCTAssertEqual(userSuggestion.id, user.id) - XCTAssertEqual(userSuggestion.name, user.name) - - addTeardownBlock { [unowned self] in - try awaitResult { - chat.deleteUser( - id: user.id, - completion: $0 - ) - } - try awaitResult { - chat.deleteChannel( - id: channel.id, - completion: $0 - ) - } - } - } - func testChat_GetEventsHistory() throws { let channel = try awaitResultValue { chat.createChannel(