| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- //
- // LNIMChatEmojiPanel.swift
- // Lanu
- //
- // Created by OneeChan on 2025/12/17.
- //
- import Foundation
- import UIKit
- import SnapKit
- protocol LNIMChatEmojiPanelDelegate: AnyObject {
- func onIMChatEmojiPanelDidClickDelete(view: LNIMChatEmojiPanel)
- func onIMChatEmojiPanel(view: LNIMChatEmojiPanel, didSelectEmoji emoji: LNEmojiData)
- }
- class LNIMChatEmojiPanel: UIView {
- private var emojiGroups: [LNEmojiGroup] = []
- private var collectionView: UICollectionView?
-
- private let menuView = UIView()
- private let deleteButton = UIButton()
-
- weak var delegate: LNIMChatEmojiPanelDelegate?
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- setupViews()
- }
-
- func reloadData() {
- var groups: [LNEmojiGroup] = []
- if let recent = LNIMEmojiManager.shared.recentGroup {
- groups.append(recent)
- }
- if let emojiGroup = LNIMEmojiManager.shared.emojiGroup {
- groups.append(emojiGroup)
- }
- emojiGroups = groups
-
- collectionView?.reloadData()
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNIMChatEmojiPanel: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
- func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LNIMChatEmojiCell.className, for: indexPath) as! LNIMChatEmojiCell
-
- let item = emojiGroups[indexPath.section].emojis[indexPath.row]
- cell.update(item)
- return cell
- }
-
- func numberOfSections(in collectionView: UICollectionView) -> Int {
- emojiGroups.count
- }
-
- func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- emojiGroups[section].emojis.count
- }
-
- func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
- let header = collectionView.dequeueReusableSupplementaryView(
- ofKind: UICollectionView.elementKindSectionHeader,
- withReuseIdentifier: "headerView", for: indexPath)
- header.subviews.forEach { $0.removeFromSuperview() }
- let titleLabel = UILabel()
- titleLabel.font = .systemFont(ofSize: 12)
- titleLabel.textColor = .init(hex: "#444444")
- header.addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(20)
- make.centerY.equalToSuperview()
- }
- let group = emojiGroups[indexPath.section]
- titleLabel.text = group.groupName
- return header
- }
-
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
- let group = emojiGroups[section]
- return if group.groupName.isEmpty {
- .zero
- } else {
- .init(width: collectionView.bounds.width, height: 20)
- }
- }
-
- func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- collectionView.deselectItem(at: indexPath, animated: false)
-
- let item = emojiGroups[indexPath.section].emojis[indexPath.row]
- delegate?.onIMChatEmojiPanel(view: self, didSelectEmoji: item)
- LNIMEmojiManager.shared.addRecentEmoji(name: item.name)
- }
- }
- extension LNIMChatEmojiPanel {
- private func setupViews() {
- let collectionView = buildCollectionView()
- addSubview(collectionView)
- collectionView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
-
- let line = UIView()
- line.backgroundColor = .init(hex: "#DBDBDB")
- addSubview(line)
- line.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview()
- make.height.equalTo(0.5)
- }
-
- let menu = buildMenu()
- addSubview(menu)
- menu.snp.makeConstraints { make in
- make.trailing.equalToSuperview().offset(-16)
- make.bottom.equalToSuperview().offset(20)
- }
- }
-
- private func buildCollectionView() -> UIView {
- let layout = UICollectionViewFlowLayout()
- layout.scrollDirection = .vertical
- layout.minimumLineSpacing = 10
- layout.minimumInteritemSpacing = 10
- layout.sectionInset = .init(top: 10, left: 20, bottom: 0, right: 20)
-
- let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
- collectionView.register(LNIMChatEmojiCell.self, forCellWithReuseIdentifier: LNIMChatEmojiCell.className)
- collectionView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerView")
- collectionView.isPagingEnabled = false
- collectionView.showsHorizontalScrollIndicator = false
- collectionView.showsVerticalScrollIndicator = false
- collectionView.backgroundColor = .clear
- collectionView.alwaysBounceVertical = true
- collectionView.delegate = self
- collectionView.dataSource = self
- collectionView.contentInset = .init(top: 10, left: 0, bottom: 0, right: 0)
- self.collectionView = collectionView
-
- return collectionView
- }
-
- private func buildMenu() -> UIView {
- menuView.snp.makeConstraints { make in
- make.height.equalTo(88)
- }
-
- deleteButton.setImage(.icImChatEmojiDelete, for: .normal)
- deleteButton.imageEdgeInsets = .init(top: 5, left: 5, bottom: 5, right: 5)
- deleteButton.imageView?.contentMode = .scaleAspectFit
- deleteButton.layer.cornerRadius = 2
- deleteButton.backgroundColor = .white
- deleteButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- delegate?.onIMChatEmojiPanelDidClickDelete(view: self)
- }), for: .touchUpInside)
- menuView.addSubview(deleteButton)
- deleteButton.snp.makeConstraints { make in
- make.trailing.equalToSuperview()
- make.leading.equalToSuperview()
- make.top.equalToSuperview()
- make.width.equalTo(50)
- make.height.equalTo(30)
- }
-
- return menuView
- }
- }
|