| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- //
- // LNGameMateCenterViewController.swift
- // Gami
- //
- // Created by OneeChan on 2026/1/22.
- //
- import Foundation
- import UIKit
- import SnapKit
- extension UIView {
- func pushToMateCenter() {
- let vc = LNGameMateCenterViewController()
- navigationController?.pushViewController(vc, animated: true)
- }
- }
- class LNGameMateCenterViewController: LNViewController {
- private let incomeLabel = UILabel()
- private let exposureLabel = UILabel()
- private let visitorLabel = UILabel()
-
- private let statusButton = UIButton()
- private let statusLabel = UILabel()
- private let statusDescLabel = UILabel()
-
- private let skillStackView = UIStackView()
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- setupViews()
-
- LNEventDeliver.addObserver(self)
-
- onUserInfoChanged(userInfo: myUserInfo)
- onGameMateManagerInfoChanged()
- }
- }
- extension LNGameMateCenterViewController: LNProfileManagerNotify, LNGameMateManagerNotify {
- func onUserInfoChanged(userInfo: LNUserProfileVO) {
- guard userInfo.userNo.isMyUid else { return }
-
- skillStackView.arrangedSubviews.forEach {
- skillStackView.removeArrangedSubview($0)
- $0.removeFromSuperview()
- }
- skillStackView.superview?.isHidden = userInfo.skills.isEmpty
-
- for skill in userInfo.skills {
- let view = buildSkillItem(skill)
- skillStackView.addArrangedSubview(view)
- }
- }
-
- func onGameMateManagerInfoChanged() {
- guard let myGameMateInfo else { return }
-
- incomeLabel.text = myGameMateInfo.weekBeanIncome.toDisplay
- exposureLabel.text = "\(myGameMateInfo.exposureCountDay)"
- visitorLabel.text = "\(myGameMateInfo.potentialUserCount)"
-
- if myGameMateInfo.playmateOpen {
- statusButton.setBackgroundImage(.primary_7, for: .normal)
- statusLabel.text = .init(key: "B00087")
- statusDescLabel.text = .init(key: "B00088")
- } else {
- statusButton.setBackgroundImage(.primary_8, for: .normal)
- statusLabel.text = .init(key: "B00089")
- statusDescLabel.text = .init(key: "B00090")
- }
- }
- }
- extension LNGameMateCenterViewController {
- private func setupViews() {
- navigationBarColor = .clear
- view.backgroundColor = .primary_1
- title = .init(key: "B00071")
-
- let topCover = UIImageView()
- topCover.image = .icHomeTopBg
- topCover.backgroundColor = .primary_1
- view.addSubview(topCover)
- topCover.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalTo(fakeNaviBgView)
- }
-
- let scrollView = UIScrollView()
- scrollView.showsVerticalScrollIndicator = false
- scrollView.showsHorizontalScrollIndicator = false
- scrollView.contentInset = .init(top: 0, left: 0, bottom: -view.commonBottomInset, right: 0)
- view.addSubview(scrollView)
- scrollView.snp.makeConstraints { make in
- make.verticalEdges.equalToSuperview()
- make.horizontalEdges.equalToSuperview().inset(16)
- }
-
- let stackView = UIStackView()
- stackView.axis = .vertical
- stackView.spacing = 12
- scrollView.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- make.width.equalToSuperview()
- }
-
- stackView.addArrangedSubview(buildRecordInfos())
- stackView.addArrangedSubview(buildSkillList())
- stackView.addArrangedSubview(buildOrderRecord())
- }
-
- private func buildRecordInfos() -> UIView {
- let container = UIView()
- container.layer.cornerRadius = 12
- container.backgroundColor = .fill
-
- let stackView = UIStackView()
- stackView.axis = .vertical
- stackView.spacing = 20
- container.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(10)
- make.verticalEdges.equalToSuperview().inset(20)
- }
-
- stackView.addArrangedSubview(buildIncome())
- stackView.addArrangedSubview(buildDataView())
- stackView.addArrangedSubview(buildOpenButton())
-
- return container
- }
-
- private func buildIncome() -> UIView {
- let container = UIView()
- container.onTap { [weak self] in
- guard let self else { return }
- view.pushToBeanView()
- }
-
- let incomeView = UIView()
- incomeView.isUserInteractionEnabled = false
- container.addSubview(incomeView)
- incomeView.snp.makeConstraints { make in
- make.top.equalToSuperview()
- make.centerX.equalToSuperview()
- }
-
- let beanIc = UIImageView.beanImageView()
- incomeView.addSubview(beanIc)
- beanIc.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview()
- make.width.height.equalTo(28)
- }
-
- incomeLabel.text = "0"
- incomeLabel.font = .systemFont(ofSize: 30, weight: .semibold)
- incomeLabel.textColor = .text_5
- incomeView.addSubview(incomeLabel)
- incomeLabel.snp.makeConstraints { make in
- make.verticalEdges.equalToSuperview()
- make.leading.equalTo(beanIc.snp.trailing)
- make.trailing.equalToSuperview()
- }
-
- let descView = UIView()
- descView.isUserInteractionEnabled = false
- container.addSubview(descView)
- descView.snp.makeConstraints { make in
- make.centerX.equalToSuperview()
- make.top.equalTo(incomeView.snp.bottom).offset(4)
- make.bottom.equalToSuperview()
- }
-
- let descLabel = UILabel()
- descLabel.text = .init(key: "B00072")
- descLabel.font = .body_m
- descLabel.textColor = .text_5
- descView.addSubview(descLabel)
- descLabel.snp.makeConstraints { make in
- make.leading.equalToSuperview()
- make.verticalEdges.equalToSuperview()
- }
-
- let arrow = UIImageView.arrowImageView(size: 12)
- arrow.tintColor = .text_4
- descView.addSubview(arrow)
- arrow.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview()
- make.leading.equalTo(descLabel.snp.trailing).offset(4)
- }
-
- return container
- }
-
- private func buildDataView() -> UIView {
- let container = UIView()
-
- let stackView = UIStackView()
- stackView.axis = .horizontal
- stackView.distribution = .fillEqually
- container.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(5)
- make.verticalEdges.equalToSuperview()
- }
-
- stackView.addArrangedSubview(buildDataItemView(.init(key: "B00073"), contentLabel: exposureLabel, showArrow: false))
-
- let visitorView = buildDataItemView(.init(key: "B00116"), contentLabel: visitorLabel)
- visitorView.onTap { [weak self] in
- guard let self else { return }
- view.pushToPotentialUsers()
- }
- stackView.addArrangedSubview(visitorView)
-
- let line = buildLine()
- stackView.addSubview(line)
- line.snp.makeConstraints { make in
- make.center.equalToSuperview()
- }
-
- return container
- }
-
- private func buildDataItemView(_ title: String, contentLabel: UILabel, showArrow: Bool = true) -> UIView {
- let container = UIView()
-
- contentLabel.text = "0"
- contentLabel.font = .heading_h2
- contentLabel.textColor = .text_5
- container.addSubview(contentLabel)
- contentLabel.snp.makeConstraints { make in
- make.top.equalToSuperview()
- make.centerX.equalToSuperview()
- }
-
- let descView = UIView()
- container.addSubview(descView)
- descView.snp.makeConstraints { make in
- make.centerX.equalToSuperview()
- make.top.equalTo(contentLabel.snp.bottom).offset(6)
- make.bottom.equalToSuperview()
- }
-
-
- let descLabel = UILabel()
- descLabel.text = title
- descLabel.font = .body_s
- descLabel.textColor = .text_4
- descView.addSubview(descLabel)
- descLabel.snp.makeConstraints { make in
- make.leading.equalToSuperview()
- make.verticalEdges.equalToSuperview()
- if !showArrow {
- make.trailing.equalToSuperview()
- }
- }
-
- if showArrow {
- let arrow = UIImageView.arrowImageView(size: 10)
- arrow.tintColor = .text_4
- descView.addSubview(arrow)
- arrow.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview()
- make.leading.equalTo(descLabel.snp.trailing).offset(4)
- }
- }
-
- return container
- }
-
- private func buildOpenButton() -> UIView {
- statusButton.layer.cornerRadius = 26
- statusButton.clipsToBounds = true
- statusButton.setBackgroundImage(.primary_8, for: .normal)
- statusButton.addAction(UIAction(handler: { _ in
- showLoading()
- let isOpen = myGameMateInfo?.playmateOpen == true
- LNGameMateManager.shared.enableGameMate(open: !isOpen) { success in
- dismissLoading()
- }
- }), for: .touchUpInside)
- statusButton.snp.makeConstraints { make in
- make.height.equalTo(56)
- }
-
- let container = UIView()
- container.isUserInteractionEnabled = false
- statusButton.addSubview(container)
- container.snp.makeConstraints { make in
- make.center.equalToSuperview()
- make.leading.greaterThanOrEqualToSuperview().offset(16)
- }
-
- statusLabel.font = .heading_h3
- statusLabel.textColor = .text_1
- statusLabel.textAlignment = .center
- container.addSubview(statusLabel)
- statusLabel.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview()
- }
-
- statusDescLabel.font = .body_xs
- statusDescLabel.textColor = .primary_1
- container.addSubview(statusDescLabel)
- statusDescLabel.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.bottom.equalToSuperview()
- make.top.equalTo(statusLabel.snp.bottom)
- }
-
- return statusButton
- }
-
- private func buildLine() -> UIView {
- let line = UIView()
- line.backgroundColor = .init(hex: "#D9D9D9")
- line.snp.makeConstraints { make in
- make.width.equalTo(1)
- make.height.equalTo(37)
- }
-
- return line
- }
-
- private func buildSkillList() -> UIView {
- let container = UIView()
- container.layer.cornerRadius = 12
- container.backgroundColor = .fill
-
- let stackView = UIStackView()
- stackView.axis = .vertical
- container.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
-
- let header = buildSkillHeader()
- stackView.addArrangedSubview(header)
-
- let skillContainer = UIView()
- stackView.addArrangedSubview(skillContainer)
-
- skillStackView.axis = .vertical
- skillStackView.spacing = 8
- skillContainer.addSubview(skillStackView)
- skillStackView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(12)
- make.top.equalToSuperview().offset(4)
- make.bottom.equalToSuperview().offset(-12)
- }
-
- return container
- }
-
- private func buildSkillHeader() -> UIView {
- let container = UIView()
- container.onTap { [weak self] in
- guard let self else { return }
- view.pushToSkillManager()
- }
- container.snp.makeConstraints { make in
- make.height.equalTo(40)
- }
-
- let titleLabel = UILabel()
- titleLabel.text = .init(key: "B00075")
- titleLabel.font = .heading_h3
- titleLabel.textColor = .text_5
- container.addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview().offset(16)
- }
-
- let arrow = UIImageView.arrowImageView(size: 12)
- arrow.tintColor = .text_4
- container.addSubview(arrow)
- arrow.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-16)
- }
-
- return container
- }
-
- private func buildSkillItem(_ skill: LNGameMateSkillVO) -> UIView {
- let container = UIView()
- container.layer.cornerRadius = 12
- container.layer.borderColor = .fill_4
- container.layer.borderWidth = 1
- container.snp.makeConstraints { make in
- make.height.equalTo(54)
- }
-
- let ic = UIImageView()
- ic.sd_setImage(with: URL(string: skill.icon))
- container.addSubview(ic)
- ic.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview().offset(10)
- make.width.height.equalTo(50)
- }
-
- let priceView = UIView()
- container.addSubview(priceView)
- priceView.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-10)
- }
-
- let coin = UIImageView.coinImageView()
- priceView.addSubview(coin)
- coin.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview()
- make.width.height.equalTo(16)
- }
-
- let priceLabel = UILabel()
- priceLabel.text = skill.price.toDisplay
- priceLabel.font = .heading_h4
- priceLabel.textColor = .text_5
- priceView.addSubview(priceLabel)
- priceLabel.snp.makeConstraints { make in
- make.verticalEdges.equalToSuperview()
- make.leading.equalTo(coin.snp.trailing).offset(1)
- }
-
- let unitLabel = UILabel()
- unitLabel.text = "/\(skill.unit)"
- unitLabel.font = .body_s
- unitLabel.textColor = .text_4
- priceView.addSubview(unitLabel)
- unitLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(priceLabel.snp.trailing).offset(1)
- make.trailing.equalToSuperview()
- }
-
- let nameLabel = UILabel()
- nameLabel.text = skill.name
- nameLabel.font = .heading_h4
- nameLabel.textColor = .text_5
- nameLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
- nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
- container.addSubview(nameLabel)
- nameLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(ic.snp.trailing).offset(4)
- make.trailing.lessThanOrEqualTo(priceView.snp.leading).offset(-20)
- }
-
- return container
- }
-
- private func buildOrderRecord() -> UIView {
- let container = UIView()
- container.layer.cornerRadius = 12
- container.backgroundColor = .fill
- container.onTap { [weak self] in
- guard let self else { return }
- view.pushToOrderRecord()
- }
- container.snp.makeConstraints { make in
- make.height.equalTo(40)
- }
-
- let titleLabel = UILabel()
- titleLabel.text = .init(key: "A00209")
- titleLabel.font = .heading_h3
- titleLabel.textColor = .text_5
- container.addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview().offset(16)
- }
-
- let arrow = UIImageView.arrowImageView(size: 12)
- arrow.tintColor = .text_4
- container.addSubview(arrow)
- arrow.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-16)
- }
-
- return container
- }
- }
|