// // LNHomeViewController.swift // Lanu // // Created by OneeChan on 2025/11/6. // import Foundation import UIKit import SnapKit class LNHomeViewController: UIViewController { private let topTab = LNHomeTopTabView() private let container = UIScrollView() private let stackView = UIStackView() private var panels: [LNHomeGameMatePanel] = [] private var loading = false override func viewDidLoad() { super.viewDidLoad() setupViews() LNEventDeliver.addObserver(self) loadGameTypes() } } extension LNHomeViewController: LNHomeTopTabViewDelegate { func homeTopTabView(view: LNHomeTopTabView, didSelectAt index: Int, type: LNGameTypeItemVO) { let offsetX: CGFloat = container.bounds.width * CGFloat(index) container.setContentOffset(.init(x: offsetX, y: 0), animated: true) } } extension LNHomeViewController: UIScrollViewDelegate { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let page = scrollView.contentOffset.x / scrollView.bounds.width topTab.selectTab(at: Int(page)) panels[Int(page)].onShow() } func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { let page = scrollView.contentOffset.x / scrollView.bounds.width topTab.selectTab(at: Int(page)) panels[Int(page)].onShow() } } extension LNHomeViewController: LNAccountManagerNotify, LNNetworkMonitorNotify, LNGameMateManagerNotify { func onUserLogin() { if stackView.arrangedSubviews.isEmpty { loadGameTypes() } } func onNetworkStateChanged(state: LNNetworkState) { if state == .available, stackView.arrangedSubviews.isEmpty { loadGameTypes() } } func onGameTypesChanged() { updateContent() } } extension LNHomeViewController { private func loadGameTypes() { guard !loading else { return } loading = true LNGameMateManager.shared.getGameTypeList { [weak self] list in guard let self else { return } loading = false } } } extension LNHomeViewController { private func updateContent() { let list = LNGameMateManager.shared.curGameTypes guard !list.isEmpty else { return } let old = self.stackView.arrangedSubviews old.forEach { self.stackView.removeArrangedSubview($0) $0.removeFromSuperview() } list.forEach { let panel = LNHomeGameMatePanel(item: $0) self.stackView.addArrangedSubview(panel) self.panels.append(panel) panel.snp.makeConstraints { make in make.height.equalToSuperview() make.width.equalTo(self.container) } } self.view.layoutIfNeeded() self.topTab.update(list) self.panels.first?.onShow() } private func setupViews() { view.backgroundColor = .primary_1 let topCover = UIImageView() topCover.image = .icHomeTopBg view.addSubview(topCover) topCover.snp.makeConstraints { make in make.top.leading.trailing.equalToSuperview() } let topMenu = buildTopMenu() view.addSubview(topMenu) topMenu.snp.makeConstraints { make in make.leading.trailing.equalToSuperview() make.top.equalToSuperview().offset(UIView.statusBarHeight) } let topTab = buildTopTab() view.addSubview(topTab) topTab.snp.makeConstraints { make in make.leading.equalToSuperview().offset(16) make.trailing.equalToSuperview().offset(-16) make.top.equalTo(topMenu.snp.bottom).offset(4) } let container = buildContainer() view.addSubview(container) container.snp.makeConstraints { make in make.leading.equalToSuperview() make.trailing.equalToSuperview() make.top.equalTo(topTab.snp.bottom).offset(10) make.bottom.equalToSuperview() } } private func buildContainer() -> UIView { container.delegate = self container.isPagingEnabled = true container.showsVerticalScrollIndicator = false container.showsHorizontalScrollIndicator = false let fakeView = UIView() container.addSubview(fakeView) fakeView.snp.makeConstraints { make in make.leading.top.bottom.equalToSuperview() make.height.equalToSuperview() make.width.equalTo(0) } stackView.axis = .horizontal stackView.spacing = 0 container.addSubview(stackView) stackView.snp.makeConstraints { make in make.edges.equalToSuperview() } return container } private func buildTopMenu() -> UIView { let menu = LNHomeTopMenuView() return menu } private func buildTopTab() -> UIView { topTab.delegate = self return topTab } } #if DEBUG import SwiftUI struct LNHomeViewControllerPreview: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> some UIViewController { LNNavigationController(rootViewController: LNHomeViewController()) } func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { } } #Preview(body: { LNHomeViewControllerPreview() }) #endif