Advance UIKit rewrite with AMap integration and core UI modules.
Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -47,25 +47,34 @@ enum LivePushNetworkState: Equatable {
|
||||
protocol LivePushAdapter {
|
||||
var name: String { get }
|
||||
var isAvailable: Bool { get }
|
||||
/// prepare 业务逻辑。
|
||||
func prepare(pushURL: URL) async throws
|
||||
/// start 业务逻辑。
|
||||
func start() async throws
|
||||
/// stop 业务逻辑。
|
||||
func stop() async throws
|
||||
/// dispose 业务逻辑。
|
||||
func dispose() async
|
||||
}
|
||||
|
||||
/// 权限提供者协议,隔离 AVFoundation 便于测试。
|
||||
protocol LivePermissionProviding {
|
||||
/// camera权限相关逻辑。
|
||||
func cameraPermission() async -> LivePushPermissionState
|
||||
/// microphone权限相关逻辑。
|
||||
func microphonePermission() async -> LivePushPermissionState
|
||||
}
|
||||
|
||||
/// 网络监听协议,隔离 NWPathMonitor 便于测试。
|
||||
protocol LiveNetworkMonitoring: AnyObject {
|
||||
var currentState: LivePushNetworkState { get }
|
||||
/// start 业务逻辑。
|
||||
func start(_ onChange: @escaping @Sendable (LivePushNetworkState) -> Void)
|
||||
/// stop 业务逻辑。
|
||||
func stop()
|
||||
}
|
||||
|
||||
/// LivePushReadiness错误类型定义。
|
||||
enum LivePushReadinessError: LocalizedError, Equatable {
|
||||
case missingPushURL
|
||||
case invalidPushURL
|
||||
@ -89,32 +98,41 @@ enum LivePushReadinessError: LocalizedError, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/// UnsupportedLivePushAdapter,业务类型定义。
|
||||
struct UnsupportedLivePushAdapter: LivePushAdapter {
|
||||
let name = "未接入推流 SDK"
|
||||
let isAvailable = false
|
||||
|
||||
/// prepare 业务逻辑。
|
||||
func prepare(pushURL: URL) async throws {
|
||||
throw LivePushReadinessError.sdkUnavailable
|
||||
}
|
||||
|
||||
/// start 业务逻辑。
|
||||
func start() async throws {
|
||||
throw LivePushReadinessError.sdkUnavailable
|
||||
}
|
||||
|
||||
/// stop 业务逻辑。
|
||||
func stop() async throws {}
|
||||
|
||||
/// dispose 业务逻辑。
|
||||
func dispose() async {}
|
||||
}
|
||||
|
||||
/// SystemLivePermission能力提供者,封装外部依赖。
|
||||
struct SystemLivePermissionProvider: LivePermissionProviding {
|
||||
/// camera权限相关逻辑。
|
||||
func cameraPermission() async -> LivePushPermissionState {
|
||||
await permission(for: .video)
|
||||
}
|
||||
|
||||
/// microphone权限相关逻辑。
|
||||
func microphonePermission() async -> LivePushPermissionState {
|
||||
await permission(for: .audio)
|
||||
}
|
||||
|
||||
/// permission 业务逻辑。
|
||||
private func permission(for mediaType: AVMediaType) async -> LivePushPermissionState {
|
||||
switch AVCaptureDevice.authorizationStatus(for: mediaType) {
|
||||
case .authorized:
|
||||
@ -130,6 +148,7 @@ struct SystemLivePermissionProvider: LivePermissionProviding {
|
||||
}
|
||||
}
|
||||
|
||||
/// SystemLiveNetworkMonitor 类型定义。
|
||||
final class SystemLiveNetworkMonitor: LiveNetworkMonitoring {
|
||||
|
||||
var onChange: (() -> Void)?
|
||||
@ -137,6 +156,7 @@ final class SystemLiveNetworkMonitor: LiveNetworkMonitoring {
|
||||
private let queue = DispatchQueue(label: "com.suixinkan.live.network")
|
||||
private(set) var currentState: LivePushNetworkState = .unknown
|
||||
|
||||
/// start 业务逻辑。
|
||||
func start(_ onChange: @escaping @Sendable (LivePushNetworkState) -> Void) {
|
||||
monitor.pathUpdateHandler = { [weak self] path in
|
||||
let state = Self.state(from: path)
|
||||
@ -146,10 +166,12 @@ final class SystemLiveNetworkMonitor: LiveNetworkMonitoring {
|
||||
monitor.start(queue: queue)
|
||||
}
|
||||
|
||||
/// stop 业务逻辑。
|
||||
func stop() {
|
||||
monitor.cancel()
|
||||
}
|
||||
|
||||
/// state 业务逻辑。
|
||||
private static func state(from path: NWPath) -> LivePushNetworkState {
|
||||
guard path.status == .satisfied else { return .unavailable }
|
||||
if path.usesInterfaceType(.wifi) { return .wifi }
|
||||
@ -177,6 +199,7 @@ final class LivePushReadinessViewModel {
|
||||
private let adapter: any LivePushAdapter
|
||||
private var pushURL: URL?
|
||||
|
||||
/// 初始化实例。
|
||||
init(
|
||||
permissionProvider: any LivePermissionProviding = SystemLivePermissionProvider(),
|
||||
networkMonitor: any LiveNetworkMonitoring = SystemLiveNetworkMonitor(),
|
||||
@ -190,6 +213,7 @@ final class LivePushReadinessViewModel {
|
||||
self.networkState = networkMonitor.currentState
|
||||
}
|
||||
|
||||
/// 配置展示内容。
|
||||
func configure(pushURL rawValue: String) {
|
||||
let value = rawValue.liveTrimmed
|
||||
guard !value.isEmpty else {
|
||||
@ -206,6 +230,7 @@ final class LivePushReadinessViewModel {
|
||||
errorMessage = nil
|
||||
}
|
||||
|
||||
/// startMonitoring相关逻辑。
|
||||
func startMonitoring() {
|
||||
networkState = networkMonitor.currentState
|
||||
networkMonitor.start { [weak self] state in
|
||||
@ -215,10 +240,12 @@ final class LivePushReadinessViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
/// stopMonitoring相关逻辑。
|
||||
func stopMonitoring() {
|
||||
networkMonitor.stop()
|
||||
}
|
||||
|
||||
/// refreshPermissions相关逻辑。
|
||||
func refreshPermissions() async {
|
||||
async let camera = permissionProvider.cameraPermission()
|
||||
async let microphone = permissionProvider.microphonePermission()
|
||||
@ -226,6 +253,7 @@ final class LivePushReadinessViewModel {
|
||||
microphonePermission = await microphone
|
||||
}
|
||||
|
||||
/// runDiagnostics相关逻辑。
|
||||
func runDiagnostics() throws {
|
||||
do {
|
||||
try validateReadiness()
|
||||
@ -240,6 +268,7 @@ final class LivePushReadinessViewModel {
|
||||
errorMessage = nil
|
||||
}
|
||||
|
||||
/// prepare 业务逻辑。
|
||||
func prepare() async throws {
|
||||
try validateReadiness()
|
||||
guard let pushURL else { throw LivePushReadinessError.missingPushURL }
|
||||
@ -253,6 +282,7 @@ final class LivePushReadinessViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
/// start推送相关逻辑。
|
||||
func startPush() async throws {
|
||||
try validateReadiness()
|
||||
guard adapter.isAvailable else {
|
||||
@ -265,11 +295,13 @@ final class LivePushReadinessViewModel {
|
||||
errorMessage = nil
|
||||
}
|
||||
|
||||
/// stop推送相关逻辑。
|
||||
func stopPush() async {
|
||||
try? await adapter.stop()
|
||||
running = false
|
||||
}
|
||||
|
||||
/// dispose 业务逻辑。
|
||||
func dispose() async {
|
||||
stopMonitoring()
|
||||
await adapter.dispose()
|
||||
@ -277,6 +309,7 @@ final class LivePushReadinessViewModel {
|
||||
prepared = false
|
||||
}
|
||||
|
||||
/// 校验Readiness输入或状态。
|
||||
private func validateReadiness() throws {
|
||||
guard pushURL != nil else {
|
||||
throw LivePushReadinessError.missingPushURL
|
||||
|
||||
Reference in New Issue
Block a user