import ExpoModulesCore enum ExpoShareType: String, Enumerable { case text case url case audio case image case video case file var isFileOrMedia: Bool { switch self { case .file, .audio, .image, .video: return true default: return false } } } enum ExpoContentType: String, Enumerable { case text case audio case image case video case file case website static func from(mimeType: String) -> ExpoContentType { let lowerMime = mimeType.lowercased() if lowerMime.contains("text/html") || lowerMime.contains("application/xhtml+xml") { return .website } if lowerMime.starts(with: "image") { return .image } if lowerMime.starts(with: "video") { return .video } if lowerMime.starts(with: "audio") { return .audio } if lowerMime.starts(with: "text") { return .text } return .file } } struct ExpoSharePayload: Record { @Field var value: String = "" @Field var shareType: ExpoShareType = .text @Field var mimeType: String = "text/plain" init() {} init(from payload: SharePayload) { self.shareType = ExpoShareType(rawValue: payload.type.rawValue) ?? .text self.value = payload.value self.mimeType = payload.mimeType } } // swiftlint:disable redundant_optional_initialization struct ExpoResolvedSharePayload: Record { @Field var value: String = "" @Field var shareType: ExpoShareType = .text @Field var mimeType: String = "text/plain" @Field var contentUri: URL? = nil @Field var contentType: ExpoContentType? = nil @Field var contentSize: Int? = nil @Field var contentMimeType: String? = nil @Field var originalName: String? = nil static func resolve(from payload: SharePayload) async throws -> Self { let expoSharePayload = ExpoSharePayload(from: payload) if expoSharePayload.shareType == .url, let url = URL(string: payload.value) { let contentDetails = try await resolveUrlContentDetails(url: url) return Self.init( // Base payload value: expoSharePayload.value, shareType: expoSharePayload.shareType, mimeType: expoSharePayload.mimeType, // Resolved data contentUri: contentDetails.uri, contentType: contentDetails.type, contentSize: contentDetails.size, contentMimeType: contentDetails.mimeType, originalName: contentDetails.originalName ) } if expoSharePayload.shareType.isFileOrMedia { let contentType: ExpoContentType = ExpoContentType(rawValue: payload.type.rawValue) ?? .file let contentUri = URL(string: payload.value) return Self.init( value: expoSharePayload.value, shareType: expoSharePayload.shareType, mimeType: expoSharePayload.mimeType, contentUri: contentUri, contentType: contentType, contentSize: payload.metadata?.size, contentMimeType: payload.mimeType, originalName: payload.metadata?.originalName ) } // text/fallback for unexpected types return Self.init( value: expoSharePayload.value, shareType: expoSharePayload.shareType, mimeType: expoSharePayload.mimeType ) } } // swiftlint:enable redundant_optional_initialization