From eb42f1017c1c9754e06cd9f2950c66202e18eced Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:28:36 +0900 Subject: [PATCH 01/12] =?UTF-8?q?[Refactor]=20#195=20-=20=EB=82=B4=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20UI=20=EB=AA=A8=EB=8D=B8=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyInfo/Model/MyInfoModel.swift | 51 +++++++------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift index 396aabba..0a1845f4 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift @@ -7,36 +7,23 @@ import UIKit -struct InfoModelOne: Hashable { - var image: UIImage - var user: String - var email: String -} - -struct InfoModelTwo: Hashable { - var image: UIImage - var title: String -} -extension InfoModelTwo { - static let items: [InfoModelTwo] = [InfoModelTwo(image: .icGuide, title: "낫투두 가이드"), - InfoModelTwo(image: .icQuestion1, title: "자주 묻는 질문") - ] -} - -struct InfoModelThree: Hashable { - var title: String -} -extension InfoModelThree { - static let items: [InfoModelThree] = [InfoModelThree(title: "공지사항"), - InfoModelThree(title: "문의하기"), - InfoModelThree(title: "약관 및 정책") - ] -} - -struct InfoModelFour: Hashable { - var title: String -} -extension InfoModelFour { - - static let item: [InfoModelFour] = [InfoModelFour(title: "버전 정보 "+(Utils.version ?? "1.0.0"))] +struct InfoModel: Hashable { + + var image: UIImage? + var user: String? + var email: String? + var title: String? + + static var profile: [InfoModel] = [InfoModel(image: .imgUser, + user: UserDefaults.standard.bool(forKey: DefaultKeys.isAppleLogin) ? KeychainUtil.getAppleUsername() : KeychainUtil.getKakaoNickname(), + email: UserDefaults.standard.bool(forKey: DefaultKeys.isAppleLogin) ? KeychainUtil.getAppleEmail() : KeychainUtil.getKakaoEmail())] + + static let support: [InfoModel] = [InfoModel(image: .icGuide, title: "낫투두 가이드"), + InfoModel(image: .icQuestion1, title: "자주 묻는 질문") + ] + static let info: [InfoModel] = [InfoModel(title: "공지사항"), + InfoModel(title: "문의하기"), + InfoModel(title: "약관 및 정책") + ] + static func version() -> [InfoModel] { return [InfoModel(title: "버전 정보 "+(Utils.version ?? "1.0.0"))] } } From e570acb42526fb7e7fae6b889ef46914a275bb43 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:28:52 +0900 Subject: [PATCH 02/12] =?UTF-8?q?[Fix]=20#195=20-=20=EB=82=B4=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20info=20cell=20UI=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyInfo/Cell/InfoCollectionViewCell.swift | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift index 84e7c230..5aaf5c92 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift @@ -7,7 +7,10 @@ import UIKit -class InfoCollectionViewCell: UICollectionViewCell { +import SnapKit +import Then + +final class InfoCollectionViewCell: UICollectionViewCell { // MARK: - Properties @@ -20,6 +23,9 @@ class InfoCollectionViewCell: UICollectionViewCell { private let titleLabel = UILabel() private let arrowImage = UIImageView() + + // MARK: - Life Cycle + override init(frame: CGRect) { super.init(frame: .zero) setUI() @@ -34,6 +40,7 @@ class InfoCollectionViewCell: UICollectionViewCell { // MARK: - Methods extension InfoCollectionViewCell { + private func setUI() { backgroundColor = .gray1 @@ -47,6 +54,7 @@ extension InfoCollectionViewCell { $0.axis = .horizontal $0.spacing = 6 } + arrowImage.do { $0.isHidden = true $0.image = .icRightArrow @@ -73,7 +81,8 @@ extension InfoCollectionViewCell { } } - func configureWithIcon(model: InfoModelTwo) { + func configureWithIcon(with model: InfoModel) { + iconImage.image = model.image titleLabel.text = model.title @@ -82,17 +91,10 @@ extension InfoCollectionViewCell { } } - func configureWithArrow(model: InfoModelThree) { - horizontalStackView.removeArrangedSubview(iconImage) - iconImage.removeFromSuperview() - titleLabel.text = model.title - arrowImage.isHidden = false - } - - func configure(model: InfoModelFour) { + func configure(with model: InfoModel, isHidden: Bool) { horizontalStackView.removeArrangedSubview(iconImage) iconImage.removeFromSuperview() titleLabel.text = model.title - arrowImage.isHidden = true + arrowImage.isHidden = isHidden } } From 35a4c41df1b31164ef2f0379d36d59ce45178910 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:30:13 +0900 Subject: [PATCH 03/12] =?UTF-8?q?[Fix]=20#195=20-=20=EB=82=B4=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20profile=20cell=20UI=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyInfo/Cell/MyProfileCollectionViewCell.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift index 95ded053..e0661fce 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift @@ -7,7 +7,10 @@ import UIKit -class MyProfileCollectionViewCell: UICollectionViewCell { +import SnapKit +import Then + +final class MyProfileCollectionViewCell: UICollectionViewCell { // MARK: - Properties @@ -19,6 +22,8 @@ class MyProfileCollectionViewCell: UICollectionViewCell { private let verticalStackView = UIStackView() private let userLabel = UILabel() private let emailLabel = UILabel() + + // MARK: - Life Cycle override init(frame: CGRect) { super.init(frame: .zero) @@ -34,6 +39,7 @@ class MyProfileCollectionViewCell: UICollectionViewCell { // MARK: - Methods extension MyProfileCollectionViewCell { + private func setUI() { backgroundColor = .gray1 @@ -43,12 +49,14 @@ extension MyProfileCollectionViewCell { $0.textColor = .white $0.font = .Pretendard(.regular, size: 15) } + emailLabel.do { $0.textAlignment = .left $0.numberOfLines = 1 $0.textColor = .gray4 $0.font = .Pretendard(.regular, size: 12) } + verticalStackView.do { $0.addArrangedSubviews(userLabel, emailLabel) $0.axis = .vertical @@ -73,7 +81,7 @@ extension MyProfileCollectionViewCell { } } - func configure(model: InfoModelOne) { + func configure(model: InfoModel) { logoImage.image = model.image userLabel.text = model.user emailLabel.text = model.email From 463f8bf1018be414ebb149b347accf0710f1438a Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:38:51 +0900 Subject: [PATCH 04/12] =?UTF-8?q?[Chore]=20#195=20-=20=EB=82=B4=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20header=20UI=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cell/MyInfoHeaderCollectionReusableView.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderCollectionReusableView.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderCollectionReusableView.swift index e29784e4..aecc8d6d 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderCollectionReusableView.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderCollectionReusableView.swift @@ -10,18 +10,21 @@ import UIKit import Then import SnapKit -class MyInfoHeaderReusableView: UICollectionReusableView { +final class MyInfoHeaderView: UICollectionReusableView { // MARK: - Properties - static let identifier = "MyInfoHeaderReusableView" + static let identifier = "MyInfoHeaderView" // MARK: - UI Components private let myInfoLabel = UILabel() + // MARK: - Life Cycle + override init(frame: CGRect) { super.init(frame: .zero) + setUI() setLayout() } @@ -33,7 +36,8 @@ class MyInfoHeaderReusableView: UICollectionReusableView { // MARK: - Methods -extension MyInfoHeaderReusableView { +extension MyInfoHeaderView { + private func setUI() { myInfoLabel.do { $0.text = I18N.myInfo @@ -41,6 +45,7 @@ extension MyInfoHeaderReusableView { $0.textColor = .white } } + private func setLayout() { addSubview(myInfoLabel) From bca1f67abe07a69bb9027aa78bdb2a1135c81f3e Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:39:14 +0900 Subject: [PATCH 05/12] =?UTF-8?q?[Fix]=20#195=20-=20lint=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/MyInfo/Cell/InfoCollectionViewCell.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift index 5aaf5c92..96120628 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift @@ -23,7 +23,6 @@ final class InfoCollectionViewCell: UICollectionViewCell { private let titleLabel = UILabel() private let arrowImage = UIImageView() - // MARK: - Life Cycle override init(frame: CGRect) { From 787f9ca40a4df6b44de99fd2e9053aab30e20a3a Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:39:39 +0900 Subject: [PATCH 06/12] =?UTF-8?q?[Fix]=20#195=20-=20=EB=82=B4=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20URL=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS-NOTTODO/iOS-NOTTODO/Global/Enum/MyInfoURL.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Global/Enum/MyInfoURL.swift b/iOS-NOTTODO/iOS-NOTTODO/Global/Enum/MyInfoURL.swift index a530036c..b8b554f4 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Global/Enum/MyInfoURL.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Global/Enum/MyInfoURL.swift @@ -10,16 +10,16 @@ import Foundation import SafariServices enum MyInfoURL { - case guid, quesition, notice, contact, service, personalInfo, googleForm, opensource + case guid, faq, notice, question, service, personalInfo, googleForm var url: String { switch self { case .guid: return "https://teamnottodo.notion.site/f35a7f2d6d5c4b33b4d0949f6077e6cd" - case .quesition: + case .faq: return "https://teamnottodo.notion.site/a6ef7036bde24e289e576ace099f39dc" case .notice: return "https://teamnottodo.notion.site/a5dbb310ec1d43baae02b7e9bf0b3411" - case .contact: + case .question: return "http://pf.kakao.com/_fUIQxj/chat" case .service: return "https://teamnottodo.notion.site/81594da775614d23900cdb2475eadb73?pvs=4" @@ -27,8 +27,6 @@ enum MyInfoURL { return "https://teamnottodo.notion.site/5af34df7da3649fc941312c5f533c1eb" case .googleForm: return "https://forms.gle/gwBJ4hL4bCTjXRTP6" - case .opensource: - return "https://teamnottodo.notion.site/a391274a627643f6a4d1f2412d4cf170?pvs=4" } } From 7427d02e8f994d9f972c715dc35046f289d01f93 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:51:21 +0900 Subject: [PATCH 07/12] =?UTF-8?q?[Fix]=20#195=20-=20Custom=20Layout=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/Layout/CompositionalLayout.swift | 40 ++++++++++++------- .../ViewControllers/HomeViewController.swift | 2 +- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Layout/CompositionalLayout.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Layout/CompositionalLayout.swift index bf78e680..5ff7e31a 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Layout/CompositionalLayout.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Layout/CompositionalLayout.swift @@ -7,31 +7,41 @@ import UIKit -final class CompositionalLayout { +struct CompositionalLayout { - class func _vertical(_ itemWidth: NSCollectionLayoutDimension, _ itemHeight: NSCollectionLayoutDimension, _ groupWidth: NSCollectionLayoutDimension, _ groupHeight: NSCollectionLayoutDimension, count: Int, edge: NSDirectionalEdgeInsets?) -> NSCollectionLayoutSection { + static func vertical(itemWidth: NSCollectionLayoutDimension = .fractionalWidth(1), + itemHeight: NSCollectionLayoutDimension = .fractionalHeight(1), + groupWidth: NSCollectionLayoutDimension = .fractionalWidth(1), + groupHeight: NSCollectionLayoutDimension = .fractionalHeight(1), + count: Int, + edge: NSDirectionalEdgeInsets = .zero) -> NSCollectionLayoutSection { let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: itemWidth, heightDimension: itemHeight)) - let group = NSCollectionLayoutGroup.vertical(layoutSize: .init(widthDimension: groupWidth, heightDimension: groupHeight), subitem: item, count: count ) - return section(group, edge ?? NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + let group = NSCollectionLayoutGroup.vertical(layoutSize: .init(widthDimension: groupWidth, heightDimension: groupHeight), subitem: item, count: count) + return createSection(group, edge) } - class func section(_ group: NSCollectionLayoutGroup, _ edge: NSDirectionalEdgeInsets) -> NSCollectionLayoutSection { + static func createSection(_ group: NSCollectionLayoutGroup, _ edge: NSDirectionalEdgeInsets) -> NSCollectionLayoutSection { let section = NSCollectionLayoutSection(group: group) section.contentInsets = edge return section } - class func setUpSection(layoutEnvironment: NSCollectionLayoutEnvironment, mode: UICollectionLayoutListConfiguration.HeaderMode, _ top: CGFloat, _ bottom: CGFloat) -> NSCollectionLayoutSection { - var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) - config.headerMode = mode - config.showsSeparators = true - config.separatorConfiguration.color = UIColor.gray2! - config.backgroundColor = .clear - config.headerTopPadding = 22 + static func setUpSection(layoutEnvironment: NSCollectionLayoutEnvironment, + mode: UICollectionLayoutListConfiguration.HeaderMode = .none, + topContentInset: CGFloat = 0, + bottomContentInset: CGFloat = 0) + -> NSCollectionLayoutSection { + var listConfig = UICollectionLayoutListConfiguration(appearance: .insetGrouped) + listConfig.headerMode = mode + listConfig.showsSeparators = true + listConfig.separatorConfiguration.color = UIColor.gray2! + listConfig.backgroundColor = .clear + listConfig.headerTopPadding = 22 - let section = NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment) - section.contentInsets = NSDirectionalEdgeInsets(top: top, leading: 0, bottom: bottom, trailing: 0) - if config.headerMode == .supplementary { + let section = NSCollectionLayoutSection.list(using: listConfig, layoutEnvironment: layoutEnvironment) + section.contentInsets = NSDirectionalEdgeInsets(top: topContentInset, leading: 0, bottom: bottomContentInset, trailing: 0) + + if listConfig.headerMode == .supplementary { let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(22)) let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top) section.boundarySupplementaryItems = [header] diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Home/ViewControllers/HomeViewController.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Home/ViewControllers/HomeViewController.swift index 8d75533a..0f1b194c 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Home/ViewControllers/HomeViewController.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Home/ViewControllers/HomeViewController.swift @@ -205,7 +205,7 @@ extension HomeViewController { return layoutSection case .empty: - return CompositionalLayout._vertical(.fractionalWidth(1), .fractionalWidth(1), .fractionalWidth(1), .fractionalWidth(1), count: 1, edge: .init(top: 30, leading: 0, bottom: 0, trailing: 0)) + return CompositionalLayout.vertical(itemWidth: .fractionalWidth(1), itemHeight: .fractionalWidth(1), groupWidth: .fractionalWidth(1), groupHeight: .fractionalWidth(1), count: 1, edge: .init(top: 30, leading: 0, bottom: 0, trailing: 0)) } } return layout From bdb7aab42bfc23acd6446e43a2961973f2583dac Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 15:51:49 +0900 Subject: [PATCH 08/12] =?UTF-8?q?[Refactor]=20#195=20-=20=EB=82=B4=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20VC=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyInfoViewController.swift | 197 ++++++++++-------- 1 file changed, 115 insertions(+), 82 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift index 6435c13b..311e7226 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift @@ -14,48 +14,45 @@ final class MyInfoViewController: UIViewController { // MARK: - Properties - private var infoOne: [InfoModelOne] = [InfoModelOne(image: .imgUser, user: UserDefaults.standard.bool(forKey: DefaultKeys.isAppleLogin) ? KeychainUtil.getAppleUsername() : KeychainUtil.getKakaoNickname(), email: UserDefaults.standard.bool(forKey: DefaultKeys.isAppleLogin) ? KeychainUtil.getAppleEmail() : KeychainUtil.getKakaoEmail())] - private let infoTwo: [InfoModelTwo] = InfoModelTwo.items - private let infoThree: [InfoModelThree] = InfoModelThree.items - private let infoFour: [InfoModelFour] = InfoModelFour.item + typealias CellRegistration = UICollectionView.CellRegistration + typealias HeaderRegistration = UICollectionView.SupplementaryRegistration + typealias DataSource = UICollectionViewDiffableDataSource + typealias SnapShot = NSDiffableDataSourceSnapshot - enum Sections: Int, Hashable { - case one, two, three, four + enum Sections: Int, CaseIterable { + case profile, support, info, version } - typealias DataSource = UICollectionViewDiffableDataSource - var dataSource: DataSource? + + private var dataSource: DataSource? + private lazy var safeArea = self.view.safeAreaLayoutGuide // MARK: - UI Components - private lazy var myInfoCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout()) + private let myInfoCollectionView = UICollectionView(frame: .zero, collectionViewLayout: .init()) // MARK: - Life Cycle - + override func viewDidLoad() { super.viewDidLoad() + AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.viewMyInfo) setUI() - register() setLayout() setupDataSource() - reloadData() + setSanpShot() } } // MARK: - Methods extension MyInfoViewController { - private func register() { - myInfoCollectionView.register(MyProfileCollectionViewCell.self, forCellWithReuseIdentifier: MyProfileCollectionViewCell.identifier) - myInfoCollectionView.register(InfoCollectionViewCell.self, forCellWithReuseIdentifier: InfoCollectionViewCell.identifier) - myInfoCollectionView.register(MyInfoHeaderReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MyInfoHeaderReusableView.identifier) - } private func setUI() { view.backgroundColor = .ntdBlack myInfoCollectionView.do { + $0.collectionViewLayout = layout() $0.backgroundColor = .clear $0.bounces = false $0.autoresizingMask = [.flexibleWidth, .flexibleHeight] @@ -73,100 +70,136 @@ extension MyInfoViewController { } } - // MARK: - Data - private func setupDataSource() { + + let profileCellRegistration = CellRegistration {cell, _, item in + cell.configure(model: item) + } + + let infoCellRegistration = CellRegistration {cell, indexPath, item in + + guard let section = Sections(rawValue: indexPath.section) else { return } + + switch section { + case .support: + cell.configureWithIcon(with: item) + case .info: + cell.configure(with: item, isHidden: false) + default: + cell.configure(with: item, isHidden: true) + } + } + + let headerRegistration = HeaderRegistration(elementKind: UICollectionView.elementKindSectionHeader) { _, _, _ in } + dataSource = DataSource(collectionView: myInfoCollectionView, cellProvider: { collectionView, indexPath, item in - let section = self.dataSource?.snapshot().sectionIdentifiers[indexPath.section] + + guard let section = Sections(rawValue: indexPath.section) else { return UICollectionViewCell() } + switch section { - case .one: - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyProfileCollectionViewCell.identifier, for: indexPath) as! MyProfileCollectionViewCell - cell.configure(model: item as! InfoModelOne ) - return cell - case .two: - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: InfoCollectionViewCell.identifier, for: indexPath) as! InfoCollectionViewCell - cell.configureWithIcon(model: item as! InfoModelTwo ) - return cell - case .three: - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: InfoCollectionViewCell.identifier, for: indexPath) as! InfoCollectionViewCell - cell.configureWithArrow(model: item as! InfoModelThree) - return cell - case .four, .none: - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: InfoCollectionViewCell.identifier, for: indexPath) as! InfoCollectionViewCell - cell.configure(model: item as! InfoModelFour) - return cell + case .profile: + return collectionView.dequeueConfiguredReusableCell(using: profileCellRegistration, + for: indexPath, + item: item) + case .support, .info, .version: + return collectionView.dequeueConfiguredReusableCell(using: infoCellRegistration, + for: indexPath, + item: item) } }) + + dataSource?.supplementaryViewProvider = { collectionView, _, indexPath in + return collectionView.dequeueConfiguredReusableSupplementary(using: headerRegistration, + for: indexPath) + } } - private func reloadData() { - var snapShot = NSDiffableDataSourceSnapshot() + private func setSanpShot() { + + var snapShot = SnapShot() + defer { dataSource?.apply(snapShot, animatingDifferences: false) } - snapShot.appendSections([.one, .two, .three, .four]) - snapShot.appendItems(infoOne, toSection: .one) - snapShot.appendItems(infoTwo, toSection: .two) - snapShot.appendItems(infoThree, toSection: .three) - snapShot.appendItems(infoFour, toSection: .four) - dataSource?.supplementaryViewProvider = { (collectionView, _, indexPath) in - guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: MyInfoHeaderReusableView.identifier, for: indexPath) as? MyInfoHeaderReusableView else { return UICollectionReusableView() } - return header - } + snapShot.appendSections(Sections.allCases) + snapShot.appendItems(InfoModel.profile, toSection: .profile) + snapShot.appendItems(InfoModel.support, toSection: .support) + snapShot.appendItems(InfoModel.info, toSection: .info) + snapShot.appendItems(InfoModel.version(), toSection: .version) + } - // MARK: - Layout - private func layout() -> UICollectionViewLayout { + let layout = UICollectionViewCompositionalLayout { sectionIndex, env in - let section = self.dataSource?.snapshot().sectionIdentifiers[sectionIndex] + + let section = Sections(rawValue: sectionIndex) switch section { - case .one: - return CompositionalLayout.setUpSection(layoutEnvironment: env, mode: .supplementary, 24, 0) - case .two, .three: - return CompositionalLayout.setUpSection(layoutEnvironment: env, mode: .none, 18, 0) - case .four, .none: - return CompositionalLayout.setUpSection(layoutEnvironment: env, mode: .none, 18, 60) + case .profile: + return CompositionalLayout.setUpSection(layoutEnvironment: env, + mode: .supplementary, + topContentInset: 24) + case .support, .info: + return CompositionalLayout.setUpSection(layoutEnvironment: env, + topContentInset: 18) + case .version, .none: + return CompositionalLayout.setUpSection(layoutEnvironment: env, + topContentInset: 18, + bottomContentInset: 60) + } + } return layout } } + +// MARK: - CollectionViewDelegate + extension MyInfoViewController: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { switch indexPath.section { case 0: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickMyInfo) - let nextViewController = MyInfoAccountViewController() - nextViewController.hidesBottomBarWhenPushed = false - navigationController?.pushViewController(nextViewController, animated: true) + ProfileSectionSelection() case 1: - switch indexPath.item { - case 0: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickGuide) - Utils.myInfoUrl(vc: self, url: MyInfoURL.guid.url) - default: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickFaq) - Utils.myInfoUrl(vc: self, url: MyInfoURL.quesition.url) - } + InfoSectionSelection(for: indexPath, + events: [.clickGuide, .clickFaq], + urls: [.guid, .faq]) case 2: - switch indexPath.item { - case 0: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickNotice) - Utils.myInfoUrl(vc: self, url: MyInfoURL.notice.url) - case 1: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickQuestion) - Utils.myInfoUrl(vc: self, url: MyInfoURL.contact.url) - case 2: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickTerms) - Utils.myInfoUrl(vc: self, url: MyInfoURL.service.url) - default: - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.MyInfo.clickOpenSource) - Utils.myInfoUrl(vc: self, url: MyInfoURL.opensource.url) - } + InfoSectionSelection(for: indexPath, + events: [.clickNotice, .clickQuestion, .clickTerms], + urls: [.notice, .question, .service]) default: return } } + + private func ProfileSectionSelection() { + sendAnalyticsEvent(.clickMyInfo) { + + let nextViewController = MyInfoAccountViewController() + nextViewController.hidesBottomBarWhenPushed = false + navigationController?.pushViewController(nextViewController, animated: true) + } + } + + private func InfoSectionSelection(for indexPath: IndexPath, + events: [AnalyticsEvent.MyInfo], + urls: [MyInfoURL]) { + guard let item = urls.indices.contains(indexPath.item) ? urls[indexPath.item] : nil, + let event = events.indices.contains(indexPath.item) ? events[indexPath.item] : nil else { + return + } + + sendAnalyticsEvent(event) { + Utils.myInfoUrl(vc: self, url: item.url) + } + } + + private func sendAnalyticsEvent(_ event: AnalyticsEvent.MyInfo, action: () -> Void) { + AmplitudeAnalyticsService.shared.send(event: event) + action() + } } From 9173fdc8263a50b9edcb0fa57675efe67e95f22a Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 17:05:12 +0900 Subject: [PATCH 09/12] =?UTF-8?q?[Chore]=20#195=20-=20=EB=82=B4=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20header=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS-NOTTODO/iOS-NOTTODO.xcodeproj/project.pbxproj | 8 ++++---- ...ollectionReusableView.swift => MyInfoHeaderView.swift} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/{MyInfoHeaderCollectionReusableView.swift => MyInfoHeaderView.swift} (100%) diff --git a/iOS-NOTTODO/iOS-NOTTODO.xcodeproj/project.pbxproj b/iOS-NOTTODO/iOS-NOTTODO.xcodeproj/project.pbxproj index 92673262..fc3ebb73 100644 --- a/iOS-NOTTODO/iOS-NOTTODO.xcodeproj/project.pbxproj +++ b/iOS-NOTTODO/iOS-NOTTODO.xcodeproj/project.pbxproj @@ -38,7 +38,7 @@ 098BFD5929B7999E008E80F9 /* MyProfileCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098BFD5829B7999E008E80F9 /* MyProfileCollectionViewCell.swift */; }; 098BFD5B29B79B6A008E80F9 /* MyInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098BFD5A29B79B6A008E80F9 /* MyInfoModel.swift */; }; 098BFD5D29B79CE3008E80F9 /* InfoCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098BFD5C29B79CE3008E80F9 /* InfoCollectionViewCell.swift */; }; - 098BFD5F29B7AECF008E80F9 /* MyInfoHeaderCollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098BFD5E29B7AECF008E80F9 /* MyInfoHeaderCollectionReusableView.swift */; }; + 098BFD5F29B7AECF008E80F9 /* MyInfoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098BFD5E29B7AECF008E80F9 /* MyInfoHeaderView.swift */; }; 099FC98129B3094F005B37E6 /* WeekMonthFSCalendar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099FC98029B3094F005B37E6 /* WeekMonthFSCalendar.swift */; }; 099FC98329B30A2E005B37E6 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099FC98229B30A2E005B37E6 /* Utils.swift */; }; 099FC98929B3233D005B37E6 /* CalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099FC98829B3233D005B37E6 /* CalendarView.swift */; }; @@ -196,7 +196,7 @@ 098BFD5829B7999E008E80F9 /* MyProfileCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyProfileCollectionViewCell.swift; sourceTree = ""; }; 098BFD5A29B79B6A008E80F9 /* MyInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoModel.swift; sourceTree = ""; }; 098BFD5C29B79CE3008E80F9 /* InfoCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoCollectionViewCell.swift; sourceTree = ""; }; - 098BFD5E29B7AECF008E80F9 /* MyInfoHeaderCollectionReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoHeaderCollectionReusableView.swift; sourceTree = ""; }; + 098BFD5E29B7AECF008E80F9 /* MyInfoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoHeaderView.swift; sourceTree = ""; }; 099FC98029B3094F005B37E6 /* WeekMonthFSCalendar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeekMonthFSCalendar.swift; sourceTree = ""; }; 099FC98229B30A2E005B37E6 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 099FC98829B3233D005B37E6 /* CalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarView.swift; sourceTree = ""; }; @@ -424,7 +424,7 @@ 098BFD6029B80137008E80F9 /* Cell */ = { isa = PBXGroup; children = ( - 098BFD5E29B7AECF008E80F9 /* MyInfoHeaderCollectionReusableView.swift */, + 098BFD5E29B7AECF008E80F9 /* MyInfoHeaderView.swift */, 098BFD5829B7999E008E80F9 /* MyProfileCollectionViewCell.swift */, 098BFD5C29B79CE3008E80F9 /* InfoCollectionViewCell.swift */, ); @@ -1290,7 +1290,7 @@ 3B892ABB2A2FBD4C00A316BC /* RecommendSituationResponseDTO.swift in Sources */, 3B14A13B29A694C000F92897 /* UITextView+.swift in Sources */, 093DB0372A146BF900ECA5F6 /* MyInfoURL.swift in Sources */, - 098BFD5F29B7AECF008E80F9 /* MyInfoHeaderCollectionReusableView.swift in Sources */, + 098BFD5F29B7AECF008E80F9 /* MyInfoHeaderView.swift in Sources */, 3B482FA7299EB8FD00BCF424 /* UIViewController+.swift in Sources */, 0960C0D42A38BC6500A3D8DB /* KeychainUtil.swift in Sources */, 6CA208302A1925EE001C4247 /* RecommendActionResponseDTO.swift in Sources */, diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderCollectionReusableView.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderView.swift similarity index 100% rename from iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderCollectionReusableView.swift rename to iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyInfoHeaderView.swift From fa21ba41e683ec07e75d4ae7a33c679533e38fda Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Sun, 19 Nov 2023 17:05:36 +0900 Subject: [PATCH 10/12] =?UTF-8?q?[Fix]=20#195=20-=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyInfo/Cell/InfoCollectionViewCell.swift | 1 + .../MyInfo/Cell/MyProfileCollectionViewCell.swift | 9 +++++---- .../Presentation/MyInfo/Model/MyInfoModel.swift | 4 ++-- .../MyInfo/Viewcontrollers/MyInfoViewController.swift | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift index 96120628..b667cb6d 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/InfoCollectionViewCell.swift @@ -27,6 +27,7 @@ final class InfoCollectionViewCell: UICollectionViewCell { override init(frame: CGRect) { super.init(frame: .zero) + setUI() setLayout() } diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift index e0661fce..2bdefe65 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Cell/MyProfileCollectionViewCell.swift @@ -13,9 +13,9 @@ import Then final class MyProfileCollectionViewCell: UICollectionViewCell { // MARK: - Properties - + static let identifier = "MyProfileCollectionViewCell" - + // MARK: - UI Components private let logoImage = UIImageView() @@ -24,13 +24,14 @@ final class MyProfileCollectionViewCell: UICollectionViewCell { private let emailLabel = UILabel() // MARK: - Life Cycle - + override init(frame: CGRect) { super.init(frame: .zero) + setUI() setLayout() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift index 0a1845f4..7396ce45 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Model/MyInfoModel.swift @@ -20,10 +20,10 @@ struct InfoModel: Hashable { static let support: [InfoModel] = [InfoModel(image: .icGuide, title: "낫투두 가이드"), InfoModel(image: .icQuestion1, title: "자주 묻는 질문") - ] + ] static let info: [InfoModel] = [InfoModel(title: "공지사항"), InfoModel(title: "문의하기"), InfoModel(title: "약관 및 정책") - ] + ] static func version() -> [InfoModel] { return [InfoModel(title: "버전 정보 "+(Utils.version ?? "1.0.0"))] } } diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift index 311e7226..e9c2e971 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift @@ -134,7 +134,7 @@ extension MyInfoViewController { let layout = UICollectionViewCompositionalLayout { sectionIndex, env in - let section = Sections(rawValue: sectionIndex) + guard let section = Sections(rawValue: sectionIndex) else { return nil } switch section { case .profile: return CompositionalLayout.setUpSection(layoutEnvironment: env, @@ -143,7 +143,7 @@ extension MyInfoViewController { case .support, .info: return CompositionalLayout.setUpSection(layoutEnvironment: env, topContentInset: 18) - case .version, .none: + case .version: return CompositionalLayout.setUpSection(layoutEnvironment: env, topContentInset: 18, bottomContentInset: 60) From 5b51c9dc86d6ea73ed969c57c7dda82a4746c207 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 20 Nov 2023 00:57:10 +0900 Subject: [PATCH 11/12] =?UTF-8?q?[Fix]=20#195=20-=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Viewcontrollers/MyInfoViewController.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift index e9c2e971..21529966 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift @@ -40,7 +40,7 @@ final class MyInfoViewController: UIViewController { setUI() setLayout() setupDataSource() - setSanpShot() + setSnapShot() } } @@ -114,7 +114,7 @@ extension MyInfoViewController { } } - private func setSanpShot() { + private func setSnapShot() { var snapShot = SnapShot() @@ -162,9 +162,9 @@ extension MyInfoViewController: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { switch indexPath.section { case 0: - ProfileSectionSelection() + profileSectionSelection() case 1: - InfoSectionSelection(for: indexPath, + infoSectionSelection(for: indexPath, events: [.clickGuide, .clickFaq], urls: [.guid, .faq]) case 2: @@ -176,7 +176,7 @@ extension MyInfoViewController: UICollectionViewDelegate { } } - private func ProfileSectionSelection() { + private func profileSectionSelection() { sendAnalyticsEvent(.clickMyInfo) { let nextViewController = MyInfoAccountViewController() @@ -185,7 +185,7 @@ extension MyInfoViewController: UICollectionViewDelegate { } } - private func InfoSectionSelection(for indexPath: IndexPath, + private func infoSectionSelection(for indexPath: IndexPath, events: [AnalyticsEvent.MyInfo], urls: [MyInfoURL]) { guard let item = urls.indices.contains(indexPath.item) ? urls[indexPath.item] : nil, From 6d4feaa990d80769f3bbc2e8c6f0656a283b65c2 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 20 Nov 2023 00:59:08 +0900 Subject: [PATCH 12/12] =?UTF-8?q?[Fix]=20#195=20-=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyInfo/Viewcontrollers/MyInfoViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift index 21529966..27fc26d9 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/MyInfo/Viewcontrollers/MyInfoViewController.swift @@ -168,7 +168,7 @@ extension MyInfoViewController: UICollectionViewDelegate { events: [.clickGuide, .clickFaq], urls: [.guid, .faq]) case 2: - InfoSectionSelection(for: indexPath, + infoSectionSelection(for: indexPath, events: [.clickNotice, .clickQuestion, .clickTerms], urls: [.notice, .question, .service]) default: