ReaderHive/ReaderHive/Class/Novel/V/NRNovelDetailBottomView.swift
2026-01-27 15:55:28 +08:00

161 lines
5.4 KiB
Swift

//
// NRNovelDetailBottomView.swift
// ReaderHive
//
// Created by on 2025/11/26.
//
import UIKit
import SnapKit
import YYCategories
class NRNovelDetailBottomView: UIView {
override var intrinsicContentSize: CGSize {
return .init(width: UIScreen.width, height: UIScreen.safeBottom + 64)
}
weak var viewModel: NRNovelDetailViewModel? {
didSet {
viewModel?.addObserver(self, forKeyPath: "novelModel", context: nil)
}
}
lazy var lineView: UIView = {
let view = UIView()
view.backgroundColor = .F_2_EFEE
return view
}()
lazy var readBgView: UIView = {
let view = NRGradientView()
view.colors = [UIColor.F_3912_F.cgColor, UIColor.FF_4_A_4_A.cgColor, UIColor.FA_9_B_1_F.cgColor]
view.startPoint = .init(x: 0, y: 0.5)
view.endPoint = .init(x: 1, y: 0.5)
view.layer.cornerRadius = 24
view.layer.masksToBounds = true
return view
}()
lazy var readButton: UIButton = {
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
guard let id = self.viewModel?.novelId else { return }
let vc = NRNovelReaderViewController()
vc.novelId = id
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}))
button.setTitle("reader_book_startReading".localized, for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
return button
}()
lazy var collectButton: UIButton = {
var configuration = UIButton.Configuration.plain()
configuration.background.backgroundColor = .clear
configuration.contentInsets = .zero
configuration.imagePadding = 4
configuration.imagePlacement = .top
configuration.attributedTitle = AttributedString("reader_book_collects".localized, attributes: AttributeContainer([
.font : UIFont.font(ofSize: 10, weight: .regular),
.foregroundColor : UIColor.black
]))
let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
guard let model = self.viewModel?.novelModel else { return }
let isCollect = !(model.is_collect ?? false)
Task {
await NRNovelAPI.requestCollect(isCollect: isCollect, id: self.viewModel?.novelId ?? "")
}
}))
button.configurationUpdateHandler = { [weak self] button in
guard let self = self else { return }
if button.isSelected {
button.configuration?.image = UIImage(named: "collect_icon_01_selected")
} else {
button.configuration?.image = UIImage(named: "collect_icon_01")
}
}
return button
}()
deinit {
self.viewModel?.removeObserver(self, forKeyPath: "novelModel")
NotificationCenter.default.removeObserver(self)
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .white
NotificationCenter.default.addObserver(self, selector: #selector(updateCollectStateNotification), name: NRNovelAPI.updateCollectStateNotification, object: nil)
nr_setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "novelModel" {
didChangeCollectState()
}
}
@objc private func updateCollectStateNotification(sender: Notification) {
guard let userInfo = sender.userInfo else { return }
guard let id = userInfo["id"] as? String else { return }
guard let state = userInfo["state"] as? Bool else { return }
guard id == self.viewModel?.novelId else { return }
self.viewModel?.novelModel?.is_collect = state
didChangeCollectState()
}
private func didChangeCollectState() {
self.collectButton.isSelected = self.viewModel?.novelModel?.is_collect ?? false
}
}
extension NRNovelDetailBottomView {
private func nr_setupUI() {
addSubview(lineView)
addSubview(readBgView)
readBgView.addSubview(readButton)
addSubview(collectButton)
lineView.snp.makeConstraints { make in
make.left.right.top.equalToSuperview()
make.height.equalTo(1)
}
readBgView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(8)
make.height.equalTo(48)
make.right.equalToSuperview().offset(-16)
// make.left.equalToSuperview().offset(16)
make.left.equalTo(collectButton.snp.right).offset(12)
}
readButton.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
collectButton.snp.makeConstraints { make in
make.centerX.equalTo(self.snp.left).offset(40)
make.centerY.equalTo(readBgView)
}
}
}