From 6d1b84798035f93ad5285d7d6f6ae19c4c2e4870 Mon Sep 17 00:00:00 2001 From: loinsir Date: Fri, 17 Nov 2023 01:55:47 +0900 Subject: [PATCH] =?UTF-8?q?:sparkles:=20feat:=20HomeViewController=20?= =?UTF-8?q?=EC=BA=90=EB=9F=AC=EC=85=80=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 26 +++- iOS/Layover/Layover/Extensions/UIView+.swift | 5 + .../Layover/Scenes/BaseViewController.swift | 3 +- .../Cell/HomeCarouselCollectionViewCell.swift | 42 ++++++ .../Home/Cell/ZoomAndSnapFlowLayout.swift | 114 ++++++++++++++++ .../Scenes/Home/HomeConfigurator.swift | 31 +++++ .../Layover/Scenes/Home/HomeInteractor.swift | 1 - .../Scenes/Home/HomeViewController.swift | 123 +++++++++++------- .../SignUpConfigurator.swift | 0 .../SignUpInteractor.swift | 0 .../SignUpModels.swift | 0 .../SignUpPresenter.swift | 0 12 files changed, 294 insertions(+), 51 deletions(-) create mode 100644 iOS/Layover/Layover/Scenes/Home/Cell/HomeCarouselCollectionViewCell.swift create mode 100644 iOS/Layover/Layover/Scenes/Home/Cell/ZoomAndSnapFlowLayout.swift create mode 100644 iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift rename iOS/Layover/Layover/Scenes/{SingUpScene => SignUpScene}/SignUpConfigurator.swift (100%) rename iOS/Layover/Layover/Scenes/{SingUpScene => SignUpScene}/SignUpInteractor.swift (100%) rename iOS/Layover/Layover/Scenes/{SingUpScene => SignUpScene}/SignUpModels.swift (100%) rename iOS/Layover/Layover/Scenes/{SingUpScene => SignUpScene}/SignUpPresenter.swift (100%) diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index 133fd2f..248b99c 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -28,6 +28,9 @@ 194552282B0479B600299768 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194552272B0479B600299768 /* BaseViewController.swift */; }; 1945522A2B04883800299768 /* UIView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194552292B04883800299768 /* UIView+.swift */; }; 194552312B04DA1A00299768 /* LOCircleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194552302B04DA1A00299768 /* LOCircleButton.swift */; }; + 194552392B05230E00299768 /* HomeCarouselCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194552382B05230E00299768 /* HomeCarouselCollectionViewCell.swift */; }; + 1945523B2B05258200299768 /* HomeConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1945523A2B05258200299768 /* HomeConfigurator.swift */; }; + 1945523D2B05338B00299768 /* ZoomAndSnapFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1945523C2B05338B00299768 /* ZoomAndSnapFlowLayout.swift */; }; 19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */; }; 19C7AFD62B02584D003B35F2 /* KeychainStored.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */; }; FC2511A02B045C0A004717BC /* SignUpInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC25119F2B045C0A004717BC /* SignUpInteractor.swift */; }; @@ -101,6 +104,9 @@ 194552272B0479B600299768 /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; 194552292B04883800299768 /* UIView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+.swift"; sourceTree = ""; }; 194552302B04DA1A00299768 /* LOCircleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOCircleButton.swift; sourceTree = ""; }; + 194552382B05230E00299768 /* HomeCarouselCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCarouselCollectionViewCell.swift; sourceTree = ""; }; + 1945523A2B05258200299768 /* HomeConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeConfigurator.swift; sourceTree = ""; }; + 1945523C2B05338B00299768 /* ZoomAndSnapFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoomAndSnapFlowLayout.swift; sourceTree = ""; }; 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = ""; }; 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainStored.swift; sourceTree = ""; }; FC25119F2B045C0A004717BC /* SignUpInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpInteractor.swift; sourceTree = ""; }; @@ -192,16 +198,27 @@ 1945521A2B0478A100299768 /* Home */ = { isa = PBXGroup; children = ( + 194552322B04FF2900299768 /* Cell */, 1945521E2B0478B400299768 /* HomeModels.swift */, 1945521F2B0478B400299768 /* HomeViewController.swift */, 194552202B0478B400299768 /* HomeInteractor.swift */, 1945521B2B0478B400299768 /* HomePresenter.swift */, 1945521C2B0478B400299768 /* HomeWorker.swift */, 1945521D2B0478B400299768 /* HomeRouter.swift */, + 1945523A2B05258200299768 /* HomeConfigurator.swift */, ); path = Home; sourceTree = ""; }; + 194552322B04FF2900299768 /* Cell */ = { + isa = PBXGroup; + children = ( + 194552382B05230E00299768 /* HomeCarouselCollectionViewCell.swift */, + 1945523C2B05338B00299768 /* ZoomAndSnapFlowLayout.swift */, + ); + path = Cell; + sourceTree = ""; + }; 19C7AFCF2B02441C003B35F2 /* Common */ = { isa = PBXGroup; children = ( @@ -344,7 +361,7 @@ isa = PBXGroup; children = ( 1945520E2B03AEA400299768 /* Configurator.swift */, - FCEE0FFB2B03AFAA00195BBE /* SingUpScene */, + FCEE0FFB2B03AFAA00195BBE /* SignUpScene */, 194552032B038FC400299768 /* Tabbar */, 194551EB2B037F1E00299768 /* Login */, 1945521A2B0478A100299768 /* Home */, @@ -385,7 +402,7 @@ path = Resources; sourceTree = ""; }; - FCEE0FFB2B03AFAA00195BBE /* SingUpScene */ = { + FCEE0FFB2B03AFAA00195BBE /* SignUpScene */ = { isa = PBXGroup; children = ( FCEE0FF92B03AF8400195BBE /* SignUpViewController.swift */, @@ -394,7 +411,7 @@ FC2511A32B045D6C004717BC /* SignUpModels.swift */, FC2511A52B049020004717BC /* SignUpConfigurator.swift */, ); - path = SingUpScene; + path = SignUpScene; sourceTree = ""; }; /* End PBXGroup section */ @@ -549,10 +566,13 @@ 194552282B0479B600299768 /* BaseViewController.swift in Sources */, 194552212B0478B400299768 /* HomePresenter.swift in Sources */, 1945520D2B0399E500299768 /* MainTabBarViewController.swift in Sources */, + 1945523D2B05338B00299768 /* ZoomAndSnapFlowLayout.swift in Sources */, + 1945523B2B05258200299768 /* HomeConfigurator.swift in Sources */, 194551F62B037F2D00299768 /* LoginViewController.swift in Sources */, FC7E458E2AFF7462004F155A /* DummyService.swift in Sources */, FCEE0FF22B036B6000195BBE /* LOButton.swift in Sources */, FC2511A62B049020004717BC /* SignUpConfigurator.swift in Sources */, + 194552392B05230E00299768 /* HomeCarouselCollectionViewCell.swift in Sources */, 194552132B03AFFC00299768 /* DummyViewController.swift in Sources */, 194551F22B037F2D00299768 /* LoginPresenter.swift in Sources */, 194552242B0478B400299768 /* HomeModels.swift in Sources */, diff --git a/iOS/Layover/Layover/Extensions/UIView+.swift b/iOS/Layover/Layover/Extensions/UIView+.swift index 1309511..9184429 100644 --- a/iOS/Layover/Layover/Extensions/UIView+.swift +++ b/iOS/Layover/Layover/Extensions/UIView+.swift @@ -9,6 +9,11 @@ import UIKit extension UIView { + + static var identifier: String { + return String(describing: self) + } + func addSubviews(_ views: UIView...) { views.forEach { addSubview($0) } } diff --git a/iOS/Layover/Layover/Scenes/BaseViewController.swift b/iOS/Layover/Layover/Scenes/BaseViewController.swift index a8f4e05..8207f91 100644 --- a/iOS/Layover/Layover/Scenes/BaseViewController.swift +++ b/iOS/Layover/Layover/Scenes/BaseViewController.swift @@ -25,12 +25,13 @@ class BaseViewController: UIViewController { // MARK: - Methods + /// Call when ViewDidLoad func setConstraints() { // Set AutoLayout } + /// Call when ViewDidLoad After setConstraints() func setUI() { - // Set UI view.backgroundColor = UIColor.background } } diff --git a/iOS/Layover/Layover/Scenes/Home/Cell/HomeCarouselCollectionViewCell.swift b/iOS/Layover/Layover/Scenes/Home/Cell/HomeCarouselCollectionViewCell.swift new file mode 100644 index 0000000..5b30e92 --- /dev/null +++ b/iOS/Layover/Layover/Scenes/Home/Cell/HomeCarouselCollectionViewCell.swift @@ -0,0 +1,42 @@ +// +// HomeCarouselCollectionViewCell.swift +// Layover +// +// Created by 김인환 on 11/16/23. +// Copyright © 2023 CodeBomber. All rights reserved. +// + +import UIKit + +final class HomeCarouselCollectionViewCell: UICollectionViewCell { + + // MARK: - Properties + + // MARK: - UI Components + + // MARK: - Object lifecycle + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + setConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + setConstraints() + } + + // MARK: - Setup + + private func setup() { + backgroundColor = .white + } + + private func setConstraints() { + + } + + // MARK: - Methods +} diff --git a/iOS/Layover/Layover/Scenes/Home/Cell/ZoomAndSnapFlowLayout.swift b/iOS/Layover/Layover/Scenes/Home/Cell/ZoomAndSnapFlowLayout.swift new file mode 100644 index 0000000..fcfb50d --- /dev/null +++ b/iOS/Layover/Layover/Scenes/Home/Cell/ZoomAndSnapFlowLayout.swift @@ -0,0 +1,114 @@ +// +// ZoomAndSnapFlowLayout.swift +// Layover +// +// Created by 김인환 on 11/16/23. +// Copyright © 2023 CodeBomber. All rights reserved. +// + +import UIKit + +final class ZoomAndSnapFlowLayout: UICollectionViewFlowLayout { + + // MARK: Properties + + private let activeDistance: CGFloat = 100 + private let zoomFactor: CGFloat + + // MARK: Initializer + + init(zoomFactor: CGFloat = 1.0) { + self.zoomFactor = zoomFactor + super.init() + } + + required init?(coder: NSCoder) { + self.zoomFactor = 1.0 + super.init(coder: coder) + } + + // MARK: Methods + + override func prepare() { + guard let collectionView else { + super.prepare() + return + } + + let verticalInsets = (collectionView.frame.height - collectionView.adjustedContentInset.top - collectionView.adjustedContentInset.bottom - itemSize.height) / 2 + let horizontalInsets = (collectionView.frame.width - collectionView.adjustedContentInset.right - collectionView.adjustedContentInset.left - itemSize.width) / 2 + sectionInset = UIEdgeInsets(top: verticalInsets, left: horizontalInsets, bottom: verticalInsets, right: horizontalInsets) + super.prepare() + } + + override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + guard let collectionView = collectionView else { return nil } + let rectAttributes = super.layoutAttributesForElements(in: rect)?.compactMap { $0.copy() as? UICollectionViewLayoutAttributes } ?? [] + let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.frame.size) + let visibleAttributes = rectAttributes.filter { $0.frame.intersects(visibleRect) } + + // Keep the spacing between cells the same. + // Each cell shifts the next cell by half of it's enlarged size. + // Calculated separately for each direction. + func adjustXPosition(_ toProcess: [UICollectionViewLayoutAttributes], direction: CGFloat, zoom: Bool = false) { + var xDiff: CGFloat = 0 + + for attributes in toProcess { + let distance = visibleRect.midX - attributes.center.x + attributes.frame.origin.x += xDiff + + if distance.magnitude < activeDistance { + let normalizedDistance = distance / activeDistance + let zoomAddition = zoomFactor * (1 - normalizedDistance.magnitude) + let widthAddition = attributes.frame.width * zoomAddition / 2 + xDiff += widthAddition * direction + + if zoom { + let scale = 1 + zoomAddition + attributes.transform3D = CATransform3DMakeScale(scale, scale, 1) + } + } + } + } + + // Adjust the x position first from left to right. + // Then adjust the x position from right to left. + // Lastly zoom the cells when they reach the center of the screen (zoom: true). + adjustXPosition(visibleAttributes, direction: +1) + adjustXPosition(visibleAttributes.reversed(), direction: -1, zoom: true) + + return rectAttributes + } + + override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { + guard let collectionView else { return .zero } + + // Add some snapping behaviour so that the zoomed cell is always centered + let targetRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.frame.width, height: collectionView.frame.height) + guard let rectAttributes = super.layoutAttributesForElements(in: targetRect) else { return .zero } + + var offsetAdjustment = CGFloat.greatestFiniteMagnitude + let horizontalCenter = proposedContentOffset.x + collectionView.frame.width / 2 + + for layoutAttributes in rectAttributes { + let itemHorizontalCenter = layoutAttributes.center.x + if (itemHorizontalCenter - horizontalCenter).magnitude < offsetAdjustment.magnitude { + offsetAdjustment = itemHorizontalCenter - horizontalCenter + } + } + + return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y) + } + + override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { + // Invalidate layout so that every cell get a chance to be zoomed when it reaches the center of the screen + return true + } + + override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext { + let context = super.invalidationContext(forBoundsChange: newBounds) + guard let invalidationContext = context as? UICollectionViewFlowLayoutInvalidationContext else { return context } + invalidationContext.invalidateFlowLayoutDelegateMetrics = newBounds.size != collectionView?.bounds.size + return context + } +} diff --git a/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift b/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift new file mode 100644 index 0000000..d762ed0 --- /dev/null +++ b/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift @@ -0,0 +1,31 @@ +// +// HomeConfigurator.swift +// Layover +// +// Created by 김인환 on 11/16/23. +// Copyright © 2023 CodeBomber. All rights reserved. +// + +import UIKit + +final class HomeConfigurator: Configurator { + + static let shared = HomeConfigurator() + + private init() { } + + func configure(_ viewController: HomeViewController) { + let router = HomeRouter() + router.viewController = viewController + + let presenter = HomePresenter() + presenter.viewController = viewController + + let interactor = HomeInteractor() + interactor.presenter = presenter + interactor.worker = HomeWorker() + + viewController.router = router + viewController.interactor = interactor + } +} diff --git a/iOS/Layover/Layover/Scenes/Home/HomeInteractor.swift b/iOS/Layover/Layover/Scenes/Home/HomeInteractor.swift index e794405..30778fd 100644 --- a/iOS/Layover/Layover/Scenes/Home/HomeInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Home/HomeInteractor.swift @@ -54,7 +54,6 @@ class HomeInteractor: HomeBusinessLogic, HomeDataStore { // <#Analytics Worker Instance#>.trackAnalytics(event: request.event) let response = Models.TrackAnalytics.Response() -// presenter?.presentTrackAnalytics(with: response) } // MARK: - Use Case - Home diff --git a/iOS/Layover/Layover/Scenes/Home/HomeViewController.swift b/iOS/Layover/Layover/Scenes/Home/HomeViewController.swift index 16442c8..9e9e407 100644 --- a/iOS/Layover/Layover/Scenes/Home/HomeViewController.swift +++ b/iOS/Layover/Layover/Scenes/Home/HomeViewController.swift @@ -9,10 +9,7 @@ import UIKit protocol HomeDisplayLogic: AnyObject { -// func displayFetchFromLocalDataStore(with viewModel: HomeModels.FetchFromLocalDataStore.ViewModel) -// func displayFetchFromRemoteDataStore(with viewModel: HomeModels.FetchFromRemoteDataStore.ViewModel) -// func displayTrackAnalytics(with viewModel: HomeModels.TrackAnalytics.ViewModel) -// func displayPerformHome(with viewModel: HomeModels.PerformHome.ViewModel) + } final class HomeViewController: BaseViewController, HomeDisplayLogic { @@ -27,6 +24,22 @@ final class HomeViewController: BaseViewController, HomeDisplayLogic { private let uploadButton: LOCircleButton = LOCircleButton(style: .add, diameter: 52) + private lazy var carouselCollectionView: UICollectionView = { + let layout = makeCarouselLayout() + let collectionView = UICollectionView(frame: .init(), collectionViewLayout: layout) + collectionView.register(HomeCarouselCollectionViewCell.self, forCellWithReuseIdentifier: HomeCarouselCollectionViewCell.identifier) + collectionView.backgroundColor = .clear + collectionView.contentInsetAdjustmentBehavior = .always + return collectionView + }() + + private lazy var carouselDatasource = UICollectionViewDiffableDataSource(collectionView: carouselCollectionView) { collectionView, indexPath, _ in + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: HomeCarouselCollectionViewCell.identifier, + for: indexPath) as? HomeCarouselCollectionViewCell else { return UICollectionViewCell() } + cell.layer.cornerRadius = 10 + return cell + } + // MARK: - Object lifecycle override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { @@ -42,17 +55,7 @@ final class HomeViewController: BaseViewController, HomeDisplayLogic { // MARK: - Setup private func setup() { - let viewController = self - let interactor = HomeInteractor() - let presenter = HomePresenter() - let router = HomeRouter() - - viewController.router = router - viewController.interactor = interactor - interactor.presenter = presenter - presenter.viewController = viewController - router.viewController = viewController - router.dataStore = interactor + } // MARK: - View Lifecycle @@ -60,53 +63,81 @@ final class HomeViewController: BaseViewController, HomeDisplayLogic { // MARK: - UI override func setConstraints() { - uploadButton.translatesAutoresizingMaskIntoConstraints = false + super.setConstraints() + + [carouselCollectionView, uploadButton].forEach { + $0.translatesAutoresizingMaskIntoConstraints = false + } - view.addSubviews(uploadButton) + view.addSubviews(carouselCollectionView, uploadButton) NSLayoutConstraint.activate([ - uploadButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -(tabBarController?.tabBar.bounds.height ?? 83) - 20), + carouselCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + carouselCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + carouselCollectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 42), + carouselCollectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -109), + + uploadButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20), uploadButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20) ]) } - // MARK: - Use Case - - // MARK: - Use Case - Fetch From Remote DataStore - - @IBOutlet var exampleRemoteLabel: UILabel! = UILabel() - func setupFetchFromRemoteDataStore() { - let request = Models.FetchFromRemoteDataStore.Request() - interactor?.fetchFromRemoteDataStore(with: request) + override func setUI() { + super.setUI() + setCarouselCollectionView() } - func displayFetchFromRemoteDataStore(with viewModel: HomeModels.FetchFromRemoteDataStore.ViewModel) { - exampleRemoteLabel.text = viewModel.exampleVariable + private func setCarouselCollectionView() { + carouselCollectionView.dataSource = carouselDatasource + var snapshot = NSDiffableDataSourceSnapshot() + // sample data + snapshot.appendSections([UUID()]) + snapshot.appendItems([1, 2, 3, 4]) + carouselDatasource.apply(snapshot) } - // MARK: - Use Case - Track Analytics - - @objc - func trackScreenViewAnalytics() { - trackAnalytics(event: .screenView) + private func makeCarouselLayout() -> UICollectionViewCompositionalLayout { + let layout = UICollectionViewCompositionalLayout { _, _ in + let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), + heightDimension: .fractionalHeight(1)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(314/375), + heightDimension: .fractionalHeight(473/534)) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, + subitems: [item]) + + let section = NSCollectionLayoutSection(group: group) + section.interGroupSpacing = 0 + section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 30, bottom: 0, trailing: 30) + section.orthogonalScrollingBehavior = .groupPagingCentered + + section.visibleItemsInvalidationHandler = { items, offset, environment in + let containerWidth = environment.container.contentSize.width + + items.forEach { item in + let itemCenterRelativeToOffset = item.frame.midX - offset.x // 아이템 중심점과 container offset(왼쪽)의 거리 + let distanceFromCenter = abs(itemCenterRelativeToOffset - containerWidth / 2.0) // container 중심점과 아이템 중심점의 거리 + let minScale: CGFloat = 473/534 // 최소 비율 + let maxScale: CGFloat = 1 + let scale = max(maxScale - (distanceFromCenter / containerWidth), minScale) // 최대 비율에서 거리에 따라 비율을 줄임, 최소 비율보다 작아지지 않도록 함 + item.transform = CGAffineTransform(scaleX: scale, y: scale) + } + } + return section + } + return layout } - func trackAnalytics(event: HomeModels.AnalyticsEvents) { - let request = Models.TrackAnalytics.Request(event: event) - interactor?.trackAnalytics(with: request) - } - - func displayTrackAnalytics(with viewModel: HomeModels.TrackAnalytics.ViewModel) { - // do something after tracking analytics (if needed) - } + // MARK: - Use Case - // MARK: - Use Case - Home + // MARK: - Use Case - Fetch From Remote DataStore - func performHome(_ sender: Any) { + // MARK: - Use Case - Track Analytics - } + // MARK: - Use Case - Home - func displayPerformHome(with viewModel: HomeModels.PerformHome.ViewModel) { +} - } +#Preview { + HomeViewController() } diff --git a/iOS/Layover/Layover/Scenes/SingUpScene/SignUpConfigurator.swift b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpConfigurator.swift similarity index 100% rename from iOS/Layover/Layover/Scenes/SingUpScene/SignUpConfigurator.swift rename to iOS/Layover/Layover/Scenes/SignUpScene/SignUpConfigurator.swift diff --git a/iOS/Layover/Layover/Scenes/SingUpScene/SignUpInteractor.swift b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpInteractor.swift similarity index 100% rename from iOS/Layover/Layover/Scenes/SingUpScene/SignUpInteractor.swift rename to iOS/Layover/Layover/Scenes/SignUpScene/SignUpInteractor.swift diff --git a/iOS/Layover/Layover/Scenes/SingUpScene/SignUpModels.swift b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpModels.swift similarity index 100% rename from iOS/Layover/Layover/Scenes/SingUpScene/SignUpModels.swift rename to iOS/Layover/Layover/Scenes/SignUpScene/SignUpModels.swift diff --git a/iOS/Layover/Layover/Scenes/SingUpScene/SignUpPresenter.swift b/iOS/Layover/Layover/Scenes/SignUpScene/SignUpPresenter.swift similarity index 100% rename from iOS/Layover/Layover/Scenes/SingUpScene/SignUpPresenter.swift rename to iOS/Layover/Layover/Scenes/SignUpScene/SignUpPresenter.swift