// // ChannelSelectPopView.swift // RoderickRalph // // Created by Neoa on 2025/9/2. // import Foundation import UIKit // MARK: - Channel Models & Popup struct Channel: Codable, Hashable { let id: String let name: String } protocol RoutePickerAgent: AnyObject { func routePicker(_ panel: RoutePickerView, didPick channel: Channel) } class RoutePickerView: UIView { weak var delegate: RoutePickerAgent? private let channels: [Channel] private let backdropView: UIView = { let v = UIView() v.backgroundColor = UIColor.black.withAlphaComponent(0.5) v.translatesAutoresizingMaskIntoConstraints = false return v }() private let cardImageView: UIImageView = { let imageView = UIImageView() imageView.image = UIImage(named: "res_ew6zkg25") imageView.contentMode = .scaleToFill imageView.translatesAutoresizingMaskIntoConstraints = false return imageView }() private let titleRibbon: UIButton = { let button = UIButton(type: .system) button.setBackgroundImage(UIImage(named: "res_x8brwne3"), for: .normal) button.setTitle("请选择渠道", for: .normal) button.setTitleColor(.white, for: .normal) button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18) button.translatesAutoresizingMaskIntoConstraints = false button.isUserInteractionEnabled = false return button }() private let scroller: UIScrollView = { let sv = UIScrollView() sv.translatesAutoresizingMaskIntoConstraints = false return sv }() private let stacker: UIStackView = { let sv = UIStackView() sv.axis = .vertical sv.spacing = 10 sv.alignment = .fill sv.distribution = .fill sv.translatesAutoresizingMaskIntoConstraints = false return sv }() private let dismissBtn: UIButton = { let button = UIButton(type: .custom) button.setImage(UIImage(named: "res_9mx2yiyi"), for: .normal) button.translatesAutoresizingMaskIntoConstraints = false return button }() init(channels: [Channel]) { self.channels = channels super.init(frame: .zero) buildUI() applyLayout() inflateChannels() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func buildUI() { addSubview(backdropView) addSubview(cardImageView) addSubview(titleRibbon) addSubview(scroller) scroller.addSubview(stacker) addSubview(dismissBtn) dismissBtn.isHidden = true dismissBtn.addTarget(self, action: #selector(closePanel), for: .touchUpInside) // Tap to dismiss on the dim background let tapGesture = UITapGestureRecognizer(target: self, action: #selector(closePanel)) backdropView.addGestureRecognizer(tapGesture) } private func applyLayout() { NSLayoutConstraint.activate([ backdropView.topAnchor.constraint(equalTo: topAnchor), backdropView.bottomAnchor.constraint(equalTo: bottomAnchor), backdropView.leadingAnchor.constraint(equalTo: leadingAnchor), backdropView.trailingAnchor.constraint(equalTo: trailingAnchor), cardImageView.centerXAnchor.constraint(equalTo: centerXAnchor), cardImageView.centerYAnchor.constraint(equalTo: centerYAnchor), cardImageView.widthAnchor.constraint(equalToConstant: 333), cardImageView.heightAnchor.constraint(equalToConstant: 333), titleRibbon.topAnchor.constraint(equalTo: cardImageView.topAnchor, constant: 10), titleRibbon.centerXAnchor.constraint(equalTo: cardImageView.centerXAnchor), titleRibbon.widthAnchor.constraint(equalToConstant: 132), titleRibbon.heightAnchor.constraint(equalToConstant: 37), scroller.topAnchor.constraint(equalTo: titleRibbon.bottomAnchor, constant: 12), scroller.leadingAnchor.constraint(equalTo: cardImageView.leadingAnchor, constant: 20), scroller.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: -20), scroller.bottomAnchor.constraint(equalTo: cardImageView.bottomAnchor, constant: -20), stacker.topAnchor.constraint(equalTo: scroller.topAnchor), stacker.leadingAnchor.constraint(equalTo: scroller.leadingAnchor), stacker.trailingAnchor.constraint(equalTo: scroller.trailingAnchor), stacker.bottomAnchor.constraint(equalTo: scroller.bottomAnchor), stacker.widthAnchor.constraint(equalTo: scroller.widthAnchor), dismissBtn.topAnchor.constraint(equalTo: cardImageView.topAnchor, constant: -12), dismissBtn.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: 12), dismissBtn.widthAnchor.constraint(equalToConstant: 24), dismissBtn.heightAnchor.constraint(equalToConstant: 24) ]) } private func makeChannelButton(title: String) -> UIButton { let button = UIButton(type: .system) button.setBackgroundImage(UIImage(named: "res_ux9fin4y"), for: .normal) button.setTitle(title, for: .normal) button.setTitleColor(.white, for: .normal) button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16) button.contentHorizontalAlignment = .center button.heightAnchor.constraint(equalToConstant: 45).isActive = true return button } private func inflateChannels() { for (idx, channel) in channels.enumerated() { let button = makeChannelButton(title: channel.name) button.tag = idx button.addTarget(self, action: #selector(didTapChannel(_:)), for: .touchUpInside) stacker.addArrangedSubview(button) } } @objc private func didTapChannel(_ sender: UIButton) { let idx = sender.tag guard idx >= 0 && idx < channels.count else { return } let channel = channels[idx] delegate?.routePicker(self, didPick: channel) } @objc private func closePanel() { // removeFromSuperview() } }