import Foundation import SwiftUI /// 直播 ViewModel @MainActor class LiveViewModel: ObservableObject { /// 全部频道分组。 @Published var channelGroups: [LiveChannelGroup] = [] /// 当前选中分组索引。 @Published var selectedGroupIndex: Int = 0 /// 当前选中频道索引(相对于当前分组)。 @Published var selectedChannelIndex: Int = 0 /// 当前播放频道。 @Published var currentChannel: LiveChannelItem? /// 当前频道节目单(预留)。 @Published var epgList: [Epginfo] = [] /// 加载状态(预留,便于后续接入远程 EPG)。 @Published var isLoading = false /// 是否显示频道列表(预留给 TV 遥控交互)。 @Published var showChannelList = false /// 加载直播频道 func loadChannels() { self.channelGroups = ApiConfig.shared.liveChannelGroupList if let firstGroup = channelGroups.first, let firstChannel = firstGroup.channels.first { currentChannel = firstChannel } } /// 选择频道分组 func selectGroup(_ index: Int) { guard index >= 0, index < channelGroups.count else { return } selectedGroupIndex = index selectedChannelIndex = 0 if let first = channelGroups[index].channels.first { selectChannel(first) } } /// 选择频道 func selectChannel(_ channel: LiveChannelItem) { currentChannel = channel loadEPG(for: channel) } /// 上一个频道 func previousChannel() { guard !channelGroups.isEmpty else { return } if selectedChannelIndex > 0 { selectedChannelIndex -= 1 } else if selectedGroupIndex > 0 { selectedGroupIndex -= 1 selectedChannelIndex = channelGroups[selectedGroupIndex].channels.count - 1 } if let ch = channelGroups[selectedGroupIndex].channels[safe: selectedChannelIndex] { selectChannel(ch) } } /// 下一个频道 func nextChannel() { guard !channelGroups.isEmpty else { return } let group = channelGroups[selectedGroupIndex] if selectedChannelIndex < group.channels.count - 1 { selectedChannelIndex += 1 } else if selectedGroupIndex < channelGroups.count - 1 { selectedGroupIndex += 1 selectedChannelIndex = 0 } if let ch = channelGroups[selectedGroupIndex].channels[safe: selectedChannelIndex] { selectChannel(ch) } } /// 切换线路 func switchSource() { // `currentChannel` 为值类型,调用 mutating 方法会触发 @Published 重新发布。 currentChannel?.nextSource() } /// 当前频道列表 var currentChannels: [LiveChannelItem] { guard selectedGroupIndex < channelGroups.count else { return [] } return channelGroups[selectedGroupIndex].channels } /// 加载 EPG 节目单 private func loadEPG(for channel: LiveChannelItem) { // 预留:后续可在此按频道名/频道 ID 请求远程 EPG。 // 当前版本先清空,避免展示过期节目单。 epgList = [] } } // 安全数组下标访问 extension Collection { /// 安全下标读取,越界时返回 `nil`。 subscript(safe index: Index) -> Element? { indices.contains(index) ? self[index] : nil } }