diff --git a/Scripts/openapi_generate.sh b/Scripts/openapi_generate.sh index 5db907568fe..ce5b2720391 100755 --- a/Scripts/openapi_generate.sh +++ b/Scripts/openapi_generate.sh @@ -160,12 +160,26 @@ prune_models # pollution / collisions with hand-written SDK types. Runs AFTER prune_models # so allowed_models above still matches the generator's original names. rename_generated Action AttachmentActionPayload +rename_generated AppResponseFields AppSettings rename_generated Field AttachmentFieldPayload +rename_generated FileUploadConfig UploadConfig rename_generated ImageData GiphyImageData rename_generated Images GiphyImages rename_generated_type Response EmptyResponse +# 4c. Expose selected generated models as public API. The class and its stored +# properties become public; the memberwise init and CodingKeys stay internal. +publicize_model() { + local file="$OUTPUT_DIR_CHAT/models/$1.swift" + sed -i '' -E \ + -e 's/^final class /public final class /' \ + -e 's/^ let / public let /' \ + "$file" +} +publicize_model AppSettings +publicize_model UploadConfig + # 5. Format. swiftformat --config "$REPO_ROOT/.swiftformat" "$OUTPUT_DIR_CHAT" diff --git a/Sources/StreamChat/ChatClient.swift b/Sources/StreamChat/ChatClient.swift index f4fa376265b..0ab2aadd635 100644 --- a/Sources/StreamChat/ChatClient.swift +++ b/Sources/StreamChat/ChatClient.swift @@ -639,7 +639,7 @@ public class ChatClient: @unchecked Sendable { apiClient.request(endpoint: .getApp()) { [weak self] result in switch result { case let .success(payload): - let appSettings = payload.asModel() + let appSettings = payload.app self?.appSettings = appSettings try? self?.backgroundWorker(of: AttachmentQueueUploader.self) .setAppSettings(appSettings) diff --git a/Sources/StreamChat/Generated/OpenAPI/models/AppResponseFields.swift b/Sources/StreamChat/Generated/OpenAPI/models/AppSettings.swift similarity index 64% rename from Sources/StreamChat/Generated/OpenAPI/models/AppResponseFields.swift rename to Sources/StreamChat/Generated/OpenAPI/models/AppSettings.swift index f4c2f922583..d5144eb0268 100644 --- a/Sources/StreamChat/Generated/OpenAPI/models/AppResponseFields.swift +++ b/Sources/StreamChat/Generated/OpenAPI/models/AppSettings.swift @@ -4,16 +4,16 @@ import Foundation -final class AppResponseFields: Sendable, Codable, JSONEncodable { - let asyncUrlEnrichEnabled: Bool - let autoTranslationEnabled: Bool - let fileUploadConfig: FileUploadConfig - let id: Int - let imageUploadConfig: FileUploadConfig - let name: String - let placement: String +public final class AppSettings: Sendable, Codable, JSONEncodable { + public let asyncUrlEnrichEnabled: Bool + public let autoTranslationEnabled: Bool + public let fileUploadConfig: UploadConfig + public let id: Int + public let imageUploadConfig: UploadConfig + public let name: String + public let placement: String - init(asyncUrlEnrichEnabled: Bool, autoTranslationEnabled: Bool, fileUploadConfig: FileUploadConfig, id: Int, imageUploadConfig: FileUploadConfig, name: String, placement: String) { + init(asyncUrlEnrichEnabled: Bool, autoTranslationEnabled: Bool, fileUploadConfig: UploadConfig, id: Int, imageUploadConfig: UploadConfig, name: String, placement: String) { self.asyncUrlEnrichEnabled = asyncUrlEnrichEnabled self.autoTranslationEnabled = autoTranslationEnabled self.fileUploadConfig = fileUploadConfig diff --git a/Sources/StreamChat/Generated/OpenAPI/models/GetApplicationResponse.swift b/Sources/StreamChat/Generated/OpenAPI/models/GetApplicationResponse.swift index b86a969b824..3a039d57a26 100644 --- a/Sources/StreamChat/Generated/OpenAPI/models/GetApplicationResponse.swift +++ b/Sources/StreamChat/Generated/OpenAPI/models/GetApplicationResponse.swift @@ -5,11 +5,11 @@ import Foundation final class GetApplicationResponse: Sendable, Codable, JSONEncodable { - let app: AppResponseFields + let app: AppSettings /// Duration of the request in milliseconds let duration: String - init(app: AppResponseFields, duration: String) { + init(app: AppSettings, duration: String) { self.app = app self.duration = duration } diff --git a/Sources/StreamChat/Generated/OpenAPI/models/FileUploadConfig.swift b/Sources/StreamChat/Generated/OpenAPI/models/UploadConfig.swift similarity index 74% rename from Sources/StreamChat/Generated/OpenAPI/models/FileUploadConfig.swift rename to Sources/StreamChat/Generated/OpenAPI/models/UploadConfig.swift index 6852a3e2171..c7847acb882 100644 --- a/Sources/StreamChat/Generated/OpenAPI/models/FileUploadConfig.swift +++ b/Sources/StreamChat/Generated/OpenAPI/models/UploadConfig.swift @@ -4,12 +4,12 @@ import Foundation -final class FileUploadConfig: Sendable, Codable, JSONEncodable { - let allowedFileExtensions: [String] - let allowedMimeTypes: [String] - let blockedFileExtensions: [String] - let blockedMimeTypes: [String] - let sizeLimit: Int +public final class UploadConfig: Sendable, Codable, JSONEncodable { + public let allowedFileExtensions: [String] + public let allowedMimeTypes: [String] + public let blockedFileExtensions: [String] + public let blockedMimeTypes: [String] + public let sizeLimit: Int init(allowedFileExtensions: [String], allowedMimeTypes: [String], blockedFileExtensions: [String], blockedMimeTypes: [String], sizeLimit: Int) { self.allowedFileExtensions = allowedFileExtensions diff --git a/Sources/StreamChat/Models/AppSettings.swift b/Sources/StreamChat/Models/AppSettings+Extensions.swift similarity index 59% rename from Sources/StreamChat/Models/AppSettings.swift rename to Sources/StreamChat/Models/AppSettings+Extensions.swift index d6c2eee2cb3..1ff385cad69 100644 --- a/Sources/StreamChat/Models/AppSettings.swift +++ b/Sources/StreamChat/Models/AppSettings+Extensions.swift @@ -5,82 +5,40 @@ import CoreServices import Foundation -/// A type representing the app settings. -public struct AppSettings: Sendable { - /// The name of the app. - public let name: String - /// The the file uploading configuration. - public let fileUploadConfig: UploadConfig - /// The the image uploading configuration. - public let imageUploadConfig: UploadConfig - /// A boolean value determining if auto translation is enabled. - public let autoTranslationEnabled: Bool - /// A boolean value determining if async url enrichment is enabled. - public let asyncUrlEnrichEnabled: Bool - - public struct UploadConfig: Sendable { - /// The allowed file extensions. - public let allowedFileExtensions: [String] - /// The blocked file extensions. - public let blockedFileExtensions: [String] - /// The allowed mime types. - public let allowedMimeTypes: [String] - /// The blocked mime types. - public let blockedMimeTypes: [String] - /// The file size limit allowed in Bytes. - /// This value is configurable from Stream's Dashboard App Settings. - public let sizeLimitInBytes: Int64? - } -} - -// MARK: - Response -> Model - -extension GetApplicationResponse { - func asModel() -> AppSettings { - .init( - name: app.name, - fileUploadConfig: app.fileUploadConfig.asModel(), - imageUploadConfig: app.imageUploadConfig.asModel(), - autoTranslationEnabled: app.autoTranslationEnabled, - asyncUrlEnrichEnabled: app.asyncUrlEnrichEnabled - ) - } +extension AppSettings { + /// The upload configuration. + public typealias UploadConfig = StreamChat.UploadConfig } -extension FileUploadConfig { - func asModel() -> AppSettings.UploadConfig { - .init( - allowedFileExtensions: allowedFileExtensions, - blockedFileExtensions: blockedFileExtensions, - allowedMimeTypes: allowedMimeTypes, - blockedMimeTypes: blockedMimeTypes, - sizeLimitInBytes: Int64(sizeLimit) - ) - } +extension AppSettings.UploadConfig { + /// The file size limit allowed in Bytes. + /// This value is configurable from Stream's Dashboard App Settings. + @available(*, deprecated, renamed: "sizeLimit") + public var sizeLimitInBytes: Int64? { Int64(sizeLimit) } } // MARK: - Validation extension AppSettings.UploadConfig { // MARK: - UTI Validation - + /// Returns an array of allowed UTI identifiers based on allowed mime types and file extensions. public var allowedUTITypes: [String] { allowedMimeTypes.compactMap { $0.utiType(mime: true) } + allowedFileExtensions.compactMap { $0.utiType(mime: false) } } - + /// Returns an array of blocked UTI identifiers based on allowed mime types and file extensions. public var blockedUTITypes: [String] { blockedMimeTypes.compactMap { $0.utiType(mime: true) } + blockedFileExtensions.compactMap { $0.utiType(mime: false) } } - + // MARK: - URL Validation - + func isAllowed(localURL: URL) -> Bool { guard !localURL.pathExtension.isEmpty else { return true } - + if !allowedFileExtensions.isEmpty || !blockedFileExtensions.isEmpty { if !isAllowed(pathExtension: localURL.pathExtension.lowercased()) { return false @@ -94,7 +52,7 @@ extension AppSettings.UploadConfig { } return true } - + private func isAllowed(pathExtension: String) -> Bool { let isBlocked = blockedFileExtensions.contains { blocked in blocked.drop(while: { $0 == Character(".") }).caseInsensitiveCompare(pathExtension) == .orderedSame @@ -105,7 +63,7 @@ extension AppSettings.UploadConfig { allowed.drop(while: { $0 == Character(".") }).caseInsensitiveCompare(pathExtension) == .orderedSame } } - + private func isAllowed(mimeType: String) -> Bool { let isBlocked = blockedMimeTypes.contains { blocked in blocked.caseInsensitiveCompare(mimeType) == .orderedSame diff --git a/Sources/StreamChatUI/Composer/ComposerVC.swift b/Sources/StreamChatUI/Composer/ComposerVC.swift index 4275b45afb3..1947f0c6339 100644 --- a/Sources/StreamChatUI/Composer/ComposerVC.swift +++ b/Sources/StreamChatUI/Composer/ComposerVC.swift @@ -1505,19 +1505,19 @@ open class ComposerVC: _ViewController, return Components.default.maxAttachmentSize } - let maxAttachmentSize: Int64? + let maxAttachmentSize: Int switch attachmentType { case .image: - maxAttachmentSize = client.appSettings?.imageUploadConfig.sizeLimitInBytes + maxAttachmentSize = client.appSettings?.imageUploadConfig.sizeLimit ?? 0 default: - maxAttachmentSize = client.appSettings?.fileUploadConfig.sizeLimitInBytes + maxAttachmentSize = client.appSettings?.fileUploadConfig.sizeLimit ?? 0 } - guard let maxSize = maxAttachmentSize, maxSize > 0 else { + guard maxAttachmentSize > 0 else { return Components.default.maxAttachmentSize } - return maxSize + return Int64(maxAttachmentSize) } /// Shows an alert for the error thrown when adding attachment to a composer. diff --git a/TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift b/TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift index e129bef8f68..65436a6e0e6 100644 --- a/TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift +++ b/TestTools/StreamChatTestTools/Mocks/StreamChat/ChatClient_Mock.swift @@ -425,11 +425,13 @@ extension AppSettings { asyncUrlEnrichEnabled: Bool = false ) -> AppSettings { .init( - name: name, + asyncUrlEnrichEnabled: asyncUrlEnrichEnabled, + autoTranslationEnabled: autoTranslationEnabled, fileUploadConfig: fileUploadConfig ?? .mock(), + id: 1, imageUploadConfig: imageUploadConfig ?? .mock(), - autoTranslationEnabled: autoTranslationEnabled, - asyncUrlEnrichEnabled: asyncUrlEnrichEnabled + name: name, + placement: "" ) } } @@ -444,10 +446,10 @@ extension AppSettings.UploadConfig { ) -> AppSettings.UploadConfig { .init( allowedFileExtensions: allowedFileExtensions, - blockedFileExtensions: blockedFileExtensions, allowedMimeTypes: allowedMimeTypes, + blockedFileExtensions: blockedFileExtensions, blockedMimeTypes: blockedMimeTypes, - sizeLimitInBytes: sizeLimitInBytes + sizeLimit: sizeLimitInBytes.map(Int.init) ?? 0 ) } }