// // LNSkillBottomMenuView.swift // Lanu // // Created by OneeChan on 2025/12/15. // import Foundation import UIKit import SnapKit import Combine class LNSkillBottomMenuView: UIView { private let priceLabel = UILabel() private let unitLabel = UILabel() private let discountView = UIView() private let newbieDiscountView = LNNewbieDiscountView() private var curDetail: LNGameMateSkillDetailVO? override init(frame: CGRect) { super.init(frame: frame) setupViews() LNEventDeliver.addObserver(self) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func update(_ detail: LNGameMateSkillDetailVO) { isHidden = false priceLabel.text = detail.price.toDisplay unitLabel.text = "/\(detail.unit)" if curDetail == nil { if detail.userNo.isMyUid { let editView = buildEditView() addSubview(editView) editView.snp.makeConstraints { make in make.leading.equalToSuperview().inset(16) make.bottom.equalToSuperview().offset(commonBottomInset) make.top.equalToSuperview().offset(16) } let settingView = buildSettingsView() addSubview(settingView) settingView.snp.makeConstraints { make in make.leading.equalTo(editView.snp.trailing).offset(10) make.centerY.equalTo(editView) make.trailing.equalToSuperview().offset(-16) } } else { let orderView = buildOrderView() addSubview(orderView) orderView.snp.makeConstraints { make in make.leading.equalToSuperview().inset(16) make.bottom.equalToSuperview().offset(commonBottomInset) make.top.equalToSuperview().offset(16) } let discountView = buildDiscountView() addSubview(discountView) discountView.snp.makeConstraints { make in make.leading.equalTo(orderView) make.bottom.equalTo(orderView.snp.top).offset(10) } let chatView = buildChatView() addSubview(chatView) chatView.snp.makeConstraints { make in make.leading.equalTo(orderView.snp.trailing).offset(10) make.centerY.equalTo(orderView) make.trailing.equalToSuperview().offset(-16) } } } curDetail = detail updateDiscount() } } extension LNSkillBottomMenuView: LNOrderManagerNotify { func onMyDiscountInfoChanged(info: LNOrderDiscountVO?) { updateDiscount() } private func updateDiscount() { guard let curDetail else { return } if let discount = LNOrderManager.shared.discountFor(curDetail.price) { discountView.isHidden = false newbieDiscountView.update(1 - discount) priceLabel.text = (curDetail.price * discount).toDisplay } else { discountView.isHidden = true priceLabel.text = curDetail.price.toDisplay } } } extension LNSkillBottomMenuView { private func setupViews() { isHidden = true let bottomGradient = CAGradientLayer() bottomGradient.colors = [ UIColor.white.withAlphaComponent(0).cgColor, UIColor.white.cgColor, UIColor.white.cgColor ] bottomGradient.locations = [0, 0.5, 1] bottomGradient.startPoint = .init(x: 0, y: 0) bottomGradient.endPoint = .init(x: 0, y: 1) layer.addSublayer(bottomGradient) publisher(for: \.bounds).removeDuplicates().sink { [weak bottomGradient] newValue in guard let bottomGradient else { return } bottomGradient.frame = newValue }.store(in: &cancellables) } private func buildOrderView() -> UIView { let container = UIView() container.backgroundColor = .init(hex: "#ECF6FF") container.layer.cornerRadius = 23.5 container.snp.makeConstraints { make in make.height.equalTo(47) } let orderButton = UIButton() orderButton.setBackgroundImage(.icSkillOrder, for: .normal) orderButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } guard let curDetail else { return } pushToCreateOrder(curDetail) }), for: .touchUpInside) container.addSubview(orderButton) orderButton.snp.makeConstraints { make in make.trailing.equalToSuperview() make.verticalEdges.equalToSuperview() } let titleLabel = UILabel() titleLabel.font = .heading_h3 titleLabel.textColor = .text_1 titleLabel.text = .init(key: "A00280") titleLabel.isUserInteractionEnabled = false orderButton.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.centerX.equalToSuperview().offset(4) } let descView = UIView() container.addSubview(descView) descView.snp.makeConstraints { make in make.leading.verticalEdges.equalToSuperview() make.trailing.equalTo(orderButton.snp.leading) } let priceView = UIView() descView.addSubview(priceView) priceView.snp.makeConstraints { make in make.center.equalToSuperview() } let coin = UIImageView.coinImageView() priceView.addSubview(coin) coin.snp.makeConstraints { make in make.leading.centerY.equalToSuperview() make.width.height.equalTo(20) } priceLabel.font = .heading_h2 priceLabel.textColor = .text_5 priceView.addSubview(priceLabel) priceLabel.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.leading.equalTo(coin.snp.trailing).offset(4) } unitLabel.font = .body_s unitLabel.textColor = .text_5 priceView.addSubview(unitLabel) unitLabel.snp.makeConstraints { make in make.leading.equalTo(priceLabel.snp.trailing) make.centerY.equalToSuperview() make.trailing.equalToSuperview() } return container } private func buildChatView() -> UIView { let button = UIButton() button.setBackgroundImage(.primary_3, for: .normal) button.layer.cornerRadius = 23.5 button.clipsToBounds = true button.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } guard let curDetail else { return } pushToChat(uid: curDetail.userNo, action: .locateSkill(id: curDetail.id)) LNStatisticManager.shared.reportClickChat(uid: curDetail.userNo) }), for: .touchUpInside) button.snp.makeConstraints { make in make.height.equalTo(47) } let container = UIView() container.isUserInteractionEnabled = false button.addSubview(container) container.snp.makeConstraints { make in make.center.equalToSuperview() make.leading.equalToSuperview().offset(28) } let faceIc = UIImageView() faceIc.image = .icSkillChatFace container.addSubview(faceIc) faceIc.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.leading.equalToSuperview() make.width.height.equalTo(24) } let chatLabel = UILabel() chatLabel.text = .init(key: "A00042") chatLabel.font = .heading_h3 chatLabel.textColor = .text_1 container.addSubview(chatLabel) chatLabel.snp.makeConstraints { make in make.leading.equalTo(faceIc.snp.trailing).offset(4) make.centerY.equalToSuperview() make.trailing.equalToSuperview() } return button } private func buildEditView() -> UIView { let container = UIView() container.backgroundColor = .init(hex: "#ECF6FF") container.layer.cornerRadius = 23.5 container.snp.makeConstraints { make in make.height.equalTo(47) } let editButton = UIButton() editButton.setBackgroundImage(.icSkillEdit, for: .normal) editButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } guard let curDetail else { return } showLoading() LNGameMateManager.shared.getSkillEditFields(id: curDetail.id) { [weak self] info in dismissLoading() guard let self else { return } guard let info, !info.fields.isEmpty else { return } info.skillId = curDetail.id pushToSkillEdit(info) } }), for: .touchUpInside) container.addSubview(editButton) editButton.snp.makeConstraints { make in make.trailing.equalToSuperview() make.verticalEdges.equalToSuperview() } let editView = UIView() editView.isUserInteractionEnabled = false editButton.addSubview(editView) editView.snp.makeConstraints { make in make.centerY.equalToSuperview() make.centerX.equalToSuperview().offset(4) } let editIc = UIImageView() editIc.image = .icEditClear.withRenderingMode(.alwaysTemplate) editIc.tintColor = .fill editView.addSubview(editIc) editIc.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.leading.equalToSuperview() make.width.height.equalTo(24) } let titleLabel = UILabel() titleLabel.font = .heading_h3 titleLabel.textColor = .text_1 titleLabel.text = .init(key: "A00226") titleLabel.isUserInteractionEnabled = false editView.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalToSuperview() make.leading.equalTo(editIc.snp.trailing).offset(2) } let descView = UIView() container.addSubview(descView) descView.snp.makeConstraints { make in make.leading.verticalEdges.equalToSuperview() make.trailing.equalTo(editButton.snp.leading) } let priceView = UIView() descView.addSubview(priceView) priceView.snp.makeConstraints { make in make.center.equalToSuperview() } let coin = UIImageView.coinImageView() priceView.addSubview(coin) coin.snp.makeConstraints { make in make.leading.centerY.equalToSuperview() make.width.height.equalTo(20) } priceLabel.font = .heading_h2 priceLabel.textColor = .text_5 priceView.addSubview(priceLabel) priceLabel.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.leading.equalTo(coin.snp.trailing).offset(4) } unitLabel.font = .body_s unitLabel.textColor = .text_5 priceView.addSubview(unitLabel) unitLabel.snp.makeConstraints { make in make.leading.equalTo(priceLabel.snp.trailing) make.centerY.equalToSuperview() make.trailing.equalToSuperview() } return container } private func buildSettingsView() -> UIView { let button = UIButton() button.setBackgroundImage(.primary_3, for: .normal) button.layer.cornerRadius = 23.5 button.clipsToBounds = true button.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } guard let curDetail else { return } showLoading() LNGameMateManager.shared.getSkillSwitchInfo(id: curDetail.id) { [weak self] res in dismissLoading() guard self != nil else { return } guard let res else { return } let panel = LNSkillSettingMenu(skill: curDetail, switchInfo: res) panel.popup() } }), for: .touchUpInside) button.snp.makeConstraints { make in make.height.equalTo(47) make.width.greaterThanOrEqualTo(90) } let settingLabel = UILabel() settingLabel.text = .init(key: "B00095") settingLabel.font = .heading_h3 settingLabel.textColor = .text_1 settingLabel.textAlignment = .center button.addSubview(settingLabel) settingLabel.snp.makeConstraints { make in make.center.equalToSuperview() make.leading.equalToSuperview().offset(16) } return button } private func buildDiscountView() -> UIView { let triangle = UIImageView() triangle.image = .icTriangleDown.withRenderingMode(.alwaysTemplate) triangle.tintColor = .init(hex: "#FF6F32") discountView.addSubview(triangle) triangle.snp.makeConstraints { make in make.leading.equalToSuperview().offset(13) make.bottom.equalToSuperview() make.width.equalTo(10) make.height.equalTo(4) } discountView.addSubview(newbieDiscountView) newbieDiscountView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalToSuperview() make.bottom.equalTo(triangle.snp.top) } return discountView } }