Files
e-party-iOS/yana/Utils/TCCos/Models/COSModels.swift
edwinQQQ b966e24532 feat: 更新COSManager和相关视图以增强图片上传功能
- 修改COSManagerAdapter以支持新的TCCos组件,确保与腾讯云COS的兼容性。
- 在CreateFeedFeature中新增图片上传相关状态和Action,优化图片选择与上传逻辑。
- 更新CreateFeedView以整合图片上传功能,提升用户体验。
- 在多个视图中添加键盘状态管理,改善用户交互体验。
- 新增COS相关的测试文件,确保功能的正确性和稳定性。
2025-07-31 11:41:56 +08:00

260 lines
7.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import QCloudCOSXML
import ComposableArchitecture
// MARK: - COS
/// COS Token
public struct TcTokenData: Codable, Equatable, Sendable {
///
public let bucket: String
///
public let sessionToken: String
///
public let region: String
///
public let customDomain: String
///
public let accelerate: Bool
/// ID
public let appId: String
///
public let secretKey: String
///
public let expireTime: Int64
///
public let startTime: Int64
/// ID
public let secretId: String
public init(
bucket: String,
sessionToken: String,
region: String,
customDomain: String,
accelerate: Bool,
appId: String,
secretKey: String,
expireTime: Int64,
startTime: Int64,
secretId: String
) {
self.bucket = bucket
self.sessionToken = sessionToken
self.region = region
self.customDomain = customDomain
self.accelerate = accelerate
self.appId = appId
self.secretKey = secretKey
self.expireTime = expireTime
self.startTime = startTime
self.secretId = secretId
}
}
/// Token
struct TcTokenRequest: APIRequestProtocol {
typealias Response = TcTokenResponse
let endpoint: String = APIEndpoint.tcToken.path
let method: HTTPMethod = .GET
let queryParameters: [String: String]? = nil
var bodyParameters: [String: Any]? { nil }
let timeout: TimeInterval = 30.0
let includeBaseParameters: Bool = true
let shouldShowLoading: Bool = false // loading
let shouldShowError: Bool = false //
}
/// Token
public struct TcTokenResponse: Codable, Equatable, Sendable {
public let code: Int
public let message: String
public let data: TcTokenData?
public let timestamp: Int64
public init(code: Int, message: String, data: TcTokenData?, timestamp: Int64) {
self.code = code
self.message = message
self.data = data
self.timestamp = timestamp
}
}
// MARK: -
///
public enum UploadStatus: Equatable, Sendable {
case idle
case uploading(progress: Double)
case success(url: String)
case failure(error: String)
}
///
public struct UploadTask: Equatable, Identifiable, Sendable {
public let id: UUID
public let imageData: Data
public let fileName: String
public let status: UploadStatus
public let createdAt: Date
public init(
id: UUID = UUID(),
imageData: Data,
fileName: String,
status: UploadStatus = .idle,
createdAt: Date = Date()
) {
self.id = id
self.imageData = imageData
self.fileName = fileName
self.status = status
self.createdAt = createdAt
}
}
///
public struct UploadProgress: Equatable, Sendable {
public let bytesSent: Int64
public let totalBytesSent: Int64
public let totalBytesExpectedToSend: Int64
public var progress: Double {
guard totalBytesExpectedToSend > 0 else { return 0.0 }
return Double(totalBytesSent) / Double(totalBytesExpectedToSend)
}
public init(
bytesSent: Int64,
totalBytesSent: Int64,
totalBytesExpectedToSend: Int64
) {
self.bytesSent = bytesSent
self.totalBytesSent = totalBytesSent
self.totalBytesExpectedToSend = totalBytesExpectedToSend
}
}
// MARK: -
/// COS
public struct COSConfiguration: Equatable, Sendable {
public let region: String
public let bucket: String
public let accelerate: Bool
public let customDomain: String
public let useHTTPS: Bool
public init(
region: String,
bucket: String,
accelerate: Bool = false,
customDomain: String = "",
useHTTPS: Bool = true
) {
self.region = region
self.bucket = bucket
self.accelerate = accelerate
self.customDomain = customDomain
self.useHTTPS = useHTTPS
}
}
/// COS
public enum COSServiceStatus: Equatable, Sendable {
case notInitialized
case initializing
case initialized(configuration: COSConfiguration)
case failed(error: String)
}
// MARK: -
/// COS
public enum COSError: Equatable, Sendable, LocalizedError {
case tokenExpired
case tokenInvalid
case serviceNotInitialized
case uploadFailed(String)
case configurationFailed(String)
case networkError(String)
case unknown(String)
public var errorDescription: String? {
switch self {
case .tokenExpired:
return "Token已过期"
case .tokenInvalid:
return "Token无效"
case .serviceNotInitialized:
return "服务未初始化"
case .uploadFailed(let message):
return "上传失败: \(message)"
case .configurationFailed(let message):
return "配置失败: \(message)"
case .networkError(let message):
return "网络错误: \(message)"
case .unknown(let message):
return "未知错误: \(message)"
}
}
}
// MARK: -
extension TcTokenData {
/// Token
public var isExpired: Bool {
let currentTime = Int64(Date().timeIntervalSince1970)
return currentTime >= expireTime
}
///
public var expirationDate: Date {
return Date(timeIntervalSince1970: TimeInterval(expireTime))
}
///
public var startDate: Date {
return Date(timeIntervalSince1970: TimeInterval(startTime))
}
///
public var remainingTime: Int64 {
let currentTime = Int64(Date().timeIntervalSince1970)
return max(0, expireTime - currentTime)
}
/// Token
public var isValid: Bool {
return !isExpired
}
/// TimeInterval
public var remainingValidTime: TimeInterval {
return max(0, expirationDate.timeIntervalSinceNow)
}
/// URL
public func buildCloudURL(for key: String) -> String {
let domain = customDomain.isEmpty
? "\(bucket).cos.\(region).myqcloud.com"
: customDomain
let prefix = domain.hasPrefix("http") ? "" : "https://"
return "\(prefix)\(domain)/\(key)"
}
}
extension UploadTask {
///
public func updatingStatus(_ newStatus: UploadStatus) -> UploadTask {
return UploadTask(
id: id,
imageData: imageData,
fileName: fileName,
status: newStatus,
createdAt: createdAt
)
}
}