// // LNPostShareImageGenerator.swift // Lanu // // Created by OneeChan on 2025/11/28. // import Foundation import UIKit import SnapKit class LNPostShareImageGenerator { fileprivate let container = UIImageView() private let newsView = UIView() private let newsLabel = UILabel() private let nameLabel = UILabel() private let genderView = LNGenderView() private let starLabel = UILabel() private let postView = UIImageView() private let bioLabel = UILabel() private let skillsView = UIStackView() private let qrCodeView = UIImageView() init() { setupViews() } func setInfo() { nameLabel.text = myUserInfo.nickname genderView.update(myUserInfo.gender, myUserInfo.age) starLabel.text = "\(myUserInfo.star)" bioLabel.text = myUserInfo.intro } func setAlbum(image: UIImage) { postView.image = image } func setOrderInfo(desc: String?) { newsLabel.text = desc?.isEmpty == false ? desc : .init(key: "A00218") } func setSkills(skills: [LNGameMateSkillVO]) { skillsView.arrangedSubviews.forEach { skillsView.removeArrangedSubview($0) $0.removeFromSuperview() } skills.prefix(3).forEach { let itemView = LNPostShareSkillItemView() itemView.icon.sd_setImage(with: URL(string: $0.icon)) itemView.nameLabel.text = $0.name skillsView.addArrangedSubview(itemView) } } func setShareQRCode(url: String) { qrCodeView.image = url.toQRCode(size: 88) } func generate() -> UIImage { let renderer = UIGraphicsImageRenderer(bounds: container.bounds) return renderer.image { _ in container.drawHierarchy( in: container.bounds, afterScreenUpdates: true ) } } } extension LNPostShareImageGenerator { private func setupViews() { let image: UIImage = .icPostShare container.image = image container.frame = .init(x: 0, y: 0, width: image.size.width, height: image.size.height) let record = buildRecord() container.addSubview(record) record.snp.makeConstraints { make in make.leading.top.equalToSuperview() make.trailing.equalToSuperview() } let post = buildPost() container.addSubview(post) post.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalToSuperview().offset(59) } let album = buildSkillView() container.addSubview(album) album.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.bottom.equalToSuperview().offset(-152) make.height.equalTo(100) } container.addSubview(qrCodeView) qrCodeView.snp.makeConstraints { make in make.trailing.equalToSuperview().offset(-74) make.bottom.equalToSuperview().offset(-33) } } private func buildRecord() -> UIView { newsView.snp.makeConstraints { make in make.height.equalTo(32) } let gradientLayer = CAGradientLayer() gradientLayer.frame = CGRect(origin: .zero, size: .init(width: self.container.bounds.size.width, height: 32)) gradientLayer.colors = [UIColor.init(hex: "#E0FFED").cgColor, UIColor.init(hex: "#FFFFFF00").cgColor] gradientLayer.locations = [0, 1] gradientLayer.startPoint = .init(x: 0, y: 0) gradientLayer.endPoint = .init(x: 1, y: 0) newsView.layer.insertSublayer(gradientLayer, at: 0) let ic = UIImageView() ic.image = .icPostShareNew newsView.addSubview(ic) ic.snp.makeConstraints { make in make.leading.equalToSuperview().offset(13) make.centerY.equalToSuperview() } newsLabel.font = .body_xs newsLabel.textColor = .init(hex: "#466811") newsView.addSubview(newsLabel) newsLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalTo(ic.snp.trailing).offset(6) } return newsView } private func buildPost() -> UIView { let container = UIView() let info = buildUserInfo() container.addSubview(info) info.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalToSuperview().offset(12) } postView.contentMode = .scaleAspectFill postView.layer.cornerRadius = 20 postView.clipsToBounds = true container.addSubview(postView) postView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalToSuperview().offset(44) make.height.equalTo(postView.snp.width).multipliedBy(317.0/311.0) } bioLabel.font = .body_m bioLabel.textColor = .text_4 bioLabel.numberOfLines = 3 container.addSubview(bioLabel) bioLabel.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(22) make.top.equalTo(postView.snp.bottom).offset(14) make.bottom.equalToSuperview().offset(-20) } return container } private func buildUserInfo() -> UIView { let container = UIView() container.snp.makeConstraints { make in make.height.equalTo(22) } nameLabel.font = .heading_h2 nameLabel.textColor = .text_5 container.addSubview(nameLabel) nameLabel.snp.makeConstraints { make in make.leading.centerY.equalToSuperview() } container.addSubview(genderView) genderView.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalTo(nameLabel.snp.trailing).offset(4) } starLabel.font = .heading_h2 starLabel.textColor = .text_5 container.addSubview(starLabel) starLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalToSuperview() } let star = LNStarScoreView() star.score = 1.0 star.icSize = 18 container.addSubview(star) star.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalTo(starLabel.snp.leading).offset(-4) } return container } private func buildSkillView() -> UIView { let container = UIView() skillsView.axis = .horizontal skillsView.spacing = 10 container.addSubview(skillsView) skillsView.snp.makeConstraints { make in make.leading.equalToSuperview().offset(113) make.bottom.equalToSuperview().offset(-18) } let ic = UIImageView() ic.image = .icHomeTabSelected ic.alpha = 0.5 container.addSubview(ic) ic.snp.makeConstraints { make in make.leading.equalToSuperview().offset(20) make.top.equalToSuperview().offset(31) } let tipsLabel = UILabel() tipsLabel.text = .init(key: "A00219") tipsLabel.font = .heading_h4 tipsLabel.textColor = .text_5 tipsLabel.numberOfLines = 0 container.addSubview(tipsLabel) tipsLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(30) make.width.equalTo(60) } return container } } #if DEBUG import SwiftUI struct LNPostShareImagePreview: UIViewRepresentable { func makeUIView(context: Context) -> some UIView { let container = UIView() container.backgroundColor = .lightGray let generator = LNPostShareImageGenerator() container.addSubview(generator.container) generator.container.snp.makeConstraints { make in make.center.equalToSuperview() } return container } func updateUIView(_ uiView: UIViewType, context: Context) { } } #Preview(body: { LNPostShareImagePreview() }) #endif // DEBUG