Files
tvbox-Swift/tvbox/ViewModels/LiveViewModel.swift
T
2026-03-01 22:23:38 +08:00

102 lines
3.4 KiB
Swift

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
}
}