From 460873a770e0168d90b6ad74e68fd755ee88f7fc Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:46:54 +0900 Subject: [PATCH 1/6] =?UTF-8?q?:sparkles:=20=ED=98=84=EC=9E=AC=20=EC=98=81?= =?UTF-8?q?=EC=83=81=20=EC=A3=BC=EC=86=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UploadPost/UploadPostInteractor.swift | 50 +++++++++++++++---- .../Scenes/UploadPost/UploadPostModels.swift | 15 ++++-- .../UploadPost/UploadPostPresenter.swift | 9 ++-- .../UploadPost/UploadPostViewController.swift | 2 +- .../Scenes/UploadPost/UploadPostWorker.swift | 23 +++++++++ .../Location/CurrentLocationManager.swift | 6 +++ 6 files changed, 87 insertions(+), 18 deletions(-) diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift index 72650eb..9c65e74 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift @@ -17,9 +17,11 @@ protocol UploadPostBusinessLogic { func fetchTags() func editTags(with request: UploadPostModels.EditTags.Request) func fetchThumbnailImage() async - func fetchCurrentAddress() async + func fetchCurrentAddress() async -> UploadPostModels.AddressInfo? func canUploadPost(request: UploadPostModels.CanUploadPost.Request) func uploadPost(request: UploadPostModels.UploadPost.Request) + func fetchVideoAddress() async -> UploadPostModels.AddressInfo? + func fetchAddresses() async } protocol UploadPostDataStore { @@ -80,8 +82,8 @@ final class UploadPostInteractor: NSObject, UploadPostBusinessLogic, UploadPostD } } - func fetchCurrentAddress() async { - guard let location = locationManager.getCurrentLocation() else { return } + func fetchCurrentAddress() async -> UploadPostModels.AddressInfo? { + guard let location = locationManager.getCurrentLocation() else { return nil } let localeIdentifier = Locale.preferredLanguages.first != nil ? Locale.preferredLanguages[0] : Locale.current.identifier let locale = Locale(identifier: localeIdentifier) do { @@ -89,14 +91,35 @@ final class UploadPostInteractor: NSObject, UploadPostBusinessLogic, UploadPostD let administrativeArea = address?.administrativeArea let locality = address?.locality let subLocality = address?.subLocality - let response = Models.FetchCurrentAddress.Response(administrativeArea: administrativeArea, - locality: locality, - subLocality: subLocality) - await MainActor.run { - presenter?.presentCurrentAddress(with: response) - } + return Models.AddressInfo( + administrativeArea: administrativeArea, + locality: locality, + subLocality: subLocality) } catch { os_log(.error, log: .data, "Failed to fetch Current Address with error: %@", error.localizedDescription) + return nil + } + } + + func fetchVideoAddress() async -> UploadPostModels.AddressInfo? { + guard let videoURL, + let videoLocation = await worker?.loadVideoLocation(videoURL: videoURL), + let location = locationManager.getVideoLocation(latitude: videoLocation.latitude, longitude: videoLocation.longitude) + else { return nil } + let localeIdentifier = Locale.preferredLanguages.first != nil ? Locale.preferredLanguages[0] : Locale.current.identifier + let locale = Locale(identifier: localeIdentifier) + do { + let address = try await CLGeocoder().reverseGeocodeLocation(location, preferredLocale: locale).last + let administrativeArea = address?.administrativeArea + let locality = address?.locality + let subLocality = address?.subLocality + return Models.AddressInfo( + administrativeArea: administrativeArea, + locality: locality, + subLocality: subLocality) + } catch { + os_log(.error, log: .data, "Failed to fetch Video Address with error: %@", error.localizedDescription) + return nil } } @@ -127,6 +150,15 @@ final class UploadPostInteractor: NSObject, UploadPostBusinessLogic, UploadPostD } } + func fetchAddresses() async { + async let currentAddress = fetchCurrentAddress() + async let videoAddress = fetchVideoAddress() + let response: Models.FetchCurrentAddress.Response = Models.FetchCurrentAddress.Response(addressInfo: [await videoAddress, await currentAddress].compactMap { $0 }) + await MainActor.run { + presenter?.presentCurrentAddress(with: response) + } + } + private func exportVideoWithoutAudio(at url: URL) async { let composition = AVMutableComposition() let sourceAsset = AVURLAsset(url: url) diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift index 74f2560..d956ef2 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift @@ -13,6 +13,17 @@ enum UploadPostModels { static let titleMaxLength: Int = 15 static let contentMaxLength: Int = 50 + struct VideoAddress { + let latitude: Double + let longitude: Double + } + + struct AddressInfo { + let administrativeArea: String? + let locality: String? + let subLocality: String? + } + enum CanUploadPost { struct Request { let title: String? @@ -61,9 +72,7 @@ enum UploadPostModels { } struct Response { - let administrativeArea: String? - let locality: String? - let subLocality: String? + let addressInfo: [AddressInfo] } struct ViewModel { let fullAddress: String diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift index d8c249f..56a1d3c 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift @@ -34,11 +34,11 @@ final class UploadPostPresenter: UploadPostPresentationLogic { func presentCurrentAddress(with response: UploadPostModels.FetchCurrentAddress.Response) { let addresses: [String] = [ - response.administrativeArea, - response.locality, - response.subLocality] + response.addressInfo.first?.administrativeArea, + response.addressInfo.first?.locality, + response.addressInfo.first?.subLocality] .compactMap { $0 } - + var fullAddress: [String] = [] for address in addresses { @@ -46,7 +46,6 @@ final class UploadPostPresenter: UploadPostPresentationLogic { fullAddress.append(address) } } - let viewModel = Models.FetchCurrentAddress.ViewModel(fullAddress: fullAddress.joined(separator: " ")) viewController?.displayCurrentAddress(viewModel: viewModel) } diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift index 3836130..be27b59 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift @@ -176,7 +176,7 @@ final class UploadPostViewController: BaseViewController { private func fetchPostInfo() { Task { - await interactor?.fetchCurrentAddress() + await interactor?.fetchAddresses() await interactor?.fetchThumbnailImage() } } diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostWorker.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostWorker.swift index 02535f0..dfc2f23 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostWorker.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostWorker.swift @@ -7,12 +7,14 @@ // import UIKit +import AVFoundation import OSLog protocol UploadPostWorkerProtocol { func uploadPost(with request: UploadPost) async -> UploadPostDTO? func uploadVideo(with request: UploadVideoRequestDTO, videoURL: URL) async -> Bool + func loadVideoLocation(videoURL: URL) async -> UploadPostModels.VideoAddress? } final class UploadPostWorker: NSObject, UploadPostWorkerProtocol { @@ -64,6 +66,27 @@ final class UploadPostWorker: NSObject, UploadPostWorkerProtocol { } } + func loadVideoLocation(videoURL: URL) async -> UploadPostModels.VideoAddress? { + let asset = AVAsset(url: videoURL) + let metadata = try? await asset.load(.metadata) + guard let metadata else { return nil } + for meta in metadata { + if meta.commonKey == AVMetadataKey.commonKeyLocation { + let location = try? await meta.load(.stringValue)?.split(separator: "+") + if location?.count ?? 0 < 2 { + return nil + } + guard let latitudeString = location?[0], + let longitudeString = location?[1], + let latitude = Double(latitudeString), + let longitude = Double(longitudeString) + else { return nil } + return Models.VideoAddress(latitude: latitude, longitude: longitude) + } + } + return nil + } + } extension UploadPostWorker: URLSessionTaskDelegate { diff --git a/iOS/Layover/Layover/Services/Location/CurrentLocationManager.swift b/iOS/Layover/Layover/Services/Location/CurrentLocationManager.swift index c2e77cc..e6ba6bf 100644 --- a/iOS/Layover/Layover/Services/Location/CurrentLocationManager.swift +++ b/iOS/Layover/Layover/Services/Location/CurrentLocationManager.swift @@ -28,6 +28,12 @@ final class CurrentLocationManager: NSObject { return CLLocation(latitude: space.latitude, longitude: space.longitude) } + func getVideoLocation(latitude: Double?, longitude: Double?) -> CLLocation? { + guard let latitude, + let longitude else { return nil } + return CLLocation(latitude: latitude, longitude: longitude) + } + func getAuthorizationStatus() -> CLAuthorizationStatus { return locationFetcher.authorizationStatus } From 089edc7b36d7c7cc2fdb778c8ca2e137e99b86ed Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:01:55 +0900 Subject: [PATCH 2/6] =?UTF-8?q?:recycle:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../LayoverTests/Mocks/Workers/MockUploadPostWorker.swift | 4 ++++ .../Scenes/UploadPost/UploadPostInteractorTests.swift | 8 ++++---- .../Scenes/UploadPost/UploadPostPresenterTests.swift | 7 ++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockUploadPostWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockUploadPostWorker.swift index d74df6c..c2fa7ed 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/MockUploadPostWorker.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockUploadPostWorker.swift @@ -53,4 +53,8 @@ final class MockUploadPostWorker: UploadPostWorkerProtocol { return true } + func loadVideoLocation(videoURL: URL) async -> Layover.UploadPostModels.VideoAddress? { + nil + } + } diff --git a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift index f334d86..d206dc2 100644 --- a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift @@ -107,10 +107,10 @@ class UploadPostInteractorTests: XCTestCase { sut.presenter = spy // when - await sut.fetchCurrentAddress() + await sut.fetchAddresses() // then - XCTAssertTrue(spy.presentCurrentAddressCalled, "fetchCurrentAddress 함수가 presentCurrentAddress을 호출하지 못함") + XCTAssertTrue(spy.presentCurrentAddressCalled, "fetchAddress 함수가 presentCurrentAddress을 호출하지 못함") } func test_fetchCurrentAddress를_호출하면_presenter에게_위치데이터를_전달한다() async throws { @@ -119,10 +119,10 @@ class UploadPostInteractorTests: XCTestCase { sut.presenter = spy // when - await sut.fetchCurrentAddress() + await sut.fetchAddresses() // then - XCTAssertNotNil(spy.presentCurrentAddressResponse, "fetchCurrentAddress 함수가 presenter에게 위치데이터를 전달하지 못함") + XCTAssertNotNil(spy.presentCurrentAddressResponse, "fetchAddress 함수가 presenter에게 위치데이터를 전달하지 못함") } func test_fetchThumbnailImage를_호출하면_presenter의_presentThumbnailImage가_호출된다() async { diff --git a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift index f137e30..6f84934 100644 --- a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift +++ b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift @@ -108,9 +108,10 @@ class UploadPostPresenterTests: XCTestCase { // given let spy = UploadPostDisplayLogicSpy() sut.viewController = spy - let response = Models.FetchCurrentAddress.Response(administrativeArea: nil, - locality: nil, - subLocality: nil) + let response = Models.FetchCurrentAddress.Response(addressInfo: [Models.AddressInfo( + administrativeArea: nil, + locality: nil, + subLocality: nil)]) // when sut.presentCurrentAddress(with: response) From a0027442854edbf7501f9cd25e11653ed8d13b01 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:37:21 +0900 Subject: [PATCH 3/6] =?UTF-8?q?:sparkles:=20action=20sheet=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UploadPost/UploadPostInteractor.swift | 33 ++++++++++++++++--- .../Scenes/UploadPost/UploadPostModels.swift | 32 +++++++++++++++++- .../UploadPost/UploadPostPresenter.swift | 12 +++++++ .../UploadPost/UploadPostViewController.swift | 28 ++++++++++++++++ 4 files changed, 100 insertions(+), 5 deletions(-) diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift index 9c65e74..e28cb82 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostInteractor.swift @@ -22,6 +22,8 @@ protocol UploadPostBusinessLogic { func uploadPost(request: UploadPostModels.UploadPost.Request) func fetchVideoAddress() async -> UploadPostModels.AddressInfo? func fetchAddresses() async + func showActionSheet() + func selectAddress(with request: UploadPostModels.SelectAddress.Request) } protocol UploadPostDataStore { @@ -47,6 +49,8 @@ final class UploadPostInteractor: NSObject, UploadPostBusinessLogic, UploadPostD var videoURL: URL? var isMuted: Bool? var tags: [String]? = [] + var videoAddress: Models.AddressInfo? + var currentAddress: Models.AddressInfo? // MARK: - Object LifeCycle @@ -151,14 +155,36 @@ final class UploadPostInteractor: NSObject, UploadPostBusinessLogic, UploadPostD } func fetchAddresses() async { - async let currentAddress = fetchCurrentAddress() - async let videoAddress = fetchVideoAddress() - let response: Models.FetchCurrentAddress.Response = Models.FetchCurrentAddress.Response(addressInfo: [await videoAddress, await currentAddress].compactMap { $0 }) + async let currentAddressInfo = fetchCurrentAddress() + async let videoAddressInfo = fetchVideoAddress() + + videoAddress = await videoAddressInfo + currentAddress = await currentAddressInfo + + let response: Models.FetchCurrentAddress.Response = Models.FetchCurrentAddress.Response(addressInfo: [ videoAddress, currentAddress].compactMap { $0 }) await MainActor.run { presenter?.presentCurrentAddress(with: response) } } + func selectAddress(with request: UploadPostModels.SelectAddress.Request) { + var response: Models.FetchCurrentAddress.Response + switch request.addressType { + case .video: + guard let videoAddress else { return } + response = Models.FetchCurrentAddress.Response(addressInfo: [videoAddress]) + case .current: + guard let currentAddress else { return } + response = Models.FetchCurrentAddress.Response(addressInfo: [currentAddress]) + } + presenter?.presentCurrentAddress(with: response) + } + + func showActionSheet() { + let response: Models.ShowActionSheet.Response = Models.ShowActionSheet.Response(videoAddress: videoAddress, currentAddress: currentAddress) + presenter?.presentShowActionSheet(with: response) + } + private func exportVideoWithoutAudio(at url: URL) async { let composition = AVMutableComposition() let sourceAsset = AVURLAsset(url: url) @@ -190,5 +216,4 @@ final class UploadPostInteractor: NSObject, UploadPostBusinessLogic, UploadPostD os_log(.error, log: .data, "Failed to extract Video Without Audio with error: %@", error.localizedDescription) } } - } diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift index d956ef2..8c93182 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostModels.swift @@ -24,6 +24,11 @@ enum UploadPostModels { let subLocality: String? } + enum AddressType { + case video + case current + } + enum CanUploadPost { struct Request { let title: String? @@ -88,7 +93,32 @@ enum UploadPostModels { struct Response { } - struct VideModel { + struct ViewModel { + + } + } + + enum ShowActionSheet { + struct Request { + + } + struct Response { + let videoAddress: AddressInfo? + let currentAddress: AddressInfo? + } + struct ViewModel { + let addressTypes: [AddressType] + } + } + + enum SelectAddress { + struct Request { + let addressType: AddressType + } + struct Response { + + } + struct ViewModel { } } diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift index 56a1d3c..9c83199 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostPresenter.swift @@ -14,6 +14,7 @@ protocol UploadPostPresentationLogic { func presentCurrentAddress(with response: UploadPostModels.FetchCurrentAddress.Response) func presentUploadButton(with response: UploadPostModels.CanUploadPost.Response) func presentUnsupportedFormatAlert() + func presentShowActionSheet(with response: UploadPostModels.ShowActionSheet.Response) } final class UploadPostPresenter: UploadPostPresentationLogic { @@ -58,4 +59,15 @@ final class UploadPostPresenter: UploadPostPresentationLogic { func presentUnsupportedFormatAlert() { viewController?.displayUnsupportedFormatAlert() } + + func presentShowActionSheet(with response: UploadPostModels.ShowActionSheet.Response) { + var addressTypes: [Models.AddressType] = [] + if response.videoAddress != nil { + addressTypes.append(.video) + } + if response.currentAddress != nil { + addressTypes.append(.current) + } + viewController?.displayActionSheet(viewModel: Models.ShowActionSheet.ViewModel(addressTypes: addressTypes)) + } } diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift index be27b59..14f13e1 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift @@ -14,6 +14,7 @@ protocol UploadPostDisplayLogic: AnyObject { func displayCurrentAddress(viewModel: UploadPostModels.FetchCurrentAddress.ViewModel) func displayUploadButton(viewModel: UploadPostModels.CanUploadPost.ViewModel) func displayUnsupportedFormatAlert() + func displayActionSheet(viewModel: UploadPostModels.ShowActionSheet.ViewModel) } final class UploadPostViewController: BaseViewController { @@ -142,6 +143,7 @@ final class UploadPostViewController: BaseViewController { setConstraints() setDelegation() addTarget() + addLocationTarget() fetchPostInfo() } @@ -247,6 +249,11 @@ final class UploadPostViewController: BaseViewController { scrollView.addGestureRecognizer(singleTapGestureRecognizer) } + private func addLocationTarget() { + let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(locationDidTap)) + locationImageLabel.addGestureRecognizer(singleTapGestureRecognizer) + } + @objc private func titleTextChanged() { interactor?.canUploadPost(request: Models.CanUploadPost.Request(title: titleTextField.text)) } @@ -270,6 +277,10 @@ final class UploadPostViewController: BaseViewController { router?.routeToBack() } + @objc private func locationDidTap() { + interactor?.showActionSheet() + } + } extension UploadPostViewController: UITextFieldDelegate { @@ -321,4 +332,21 @@ extension UploadPostViewController: UploadPostDisplayLogic { Toast.shared.showToast(message: "지원하지 않는 파일 형식이에요 😢") } + func displayActionSheet(viewModel: UploadPostModels.ShowActionSheet.ViewModel) { + let actionSheet = UIAlertController(title: "주소 선택", message: "원하는 위치의 주소를 선택하세요.", preferredStyle: .actionSheet) + for type in viewModel.addressTypes { + switch type { + case .video: + actionSheet.addAction(UIAlertAction(title: "영상 위치", style: .default, handler: { _ in + self.interactor?.selectAddress(with: Models.SelectAddress.Request(addressType: type)) + })) + case .current: + actionSheet.addAction(UIAlertAction(title: "현재 위치", style: .default, handler: { _ in + self.interactor?.selectAddress(with: Models.SelectAddress.Request(addressType: type)) + })) + } + } + actionSheet.addAction(UIAlertAction(title: "취소", style: .cancel, handler: nil)) + present(actionSheet, animated: true, completion: nil) + } } From 2629f19378427f99b396e1b4f7d05ea269687d1a Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:41:00 +0900 Subject: [PATCH 4/6] =?UTF-8?q?:wrench:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=98=A4=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 --- .../Scenes/UploadPost/UploadPostPresenterTests.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift index 6f84934..4e44de1 100644 --- a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift +++ b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostPresenterTests.swift @@ -73,6 +73,11 @@ class UploadPostPresenterTests: XCTestCase { } + func displayActionSheet(viewModel: Layover.UploadPostModels.ShowActionSheet.ViewModel) { + // + } + + } // MARK: - Tests From ce182f65809b1a2e9a5dfce230c65424ab850ce2 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:41:32 +0900 Subject: [PATCH 5/6] =?UTF-8?q?:wrench:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../Scenes/UploadPost/UploadPostInteractorTests.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift index d206dc2..20d3282 100644 --- a/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Scenes/UploadPost/UploadPostInteractorTests.swift @@ -73,6 +73,10 @@ class UploadPostInteractorTests: XCTestCase { } + func presentShowActionSheet(with response: Layover.UploadPostModels.ShowActionSheet.Response) { + // + } + } // MARK: - Tests From 4d10bded7a87c73c32797098b6d4e2a0a5e00905 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Fri, 26 Jan 2024 00:12:10 +0900 Subject: [PATCH 6/6] =?UTF-8?q?:recycle:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 4 ++ .../Layover/DesignSystem/LOTextLabel.swift | 39 +++++++++++++++++++ .../UploadPost/UploadPostViewController.swift | 7 ++-- 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 iOS/Layover/Layover/DesignSystem/LOTextLabel.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index 8fb0922..cbe146d 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -157,6 +157,7 @@ 836C338B2B15D22C00ECAFB0 /* PlaybackConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */; }; 836C33912B17629400ECAFB0 /* MapRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33902B17629400ECAFB0 /* MapRouter.swift */; }; 83957AA62B20F94C00B3BA8A /* MockPlaybackWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83957AA52B20F94C00B3BA8A /* MockPlaybackWorker.swift */; }; + 839F1DF82B62AEDA0071C622 /* LOTextLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839F1DF72B62AEDA0071C622 /* LOTextLabel.swift */; }; 83C35E1B2B108C3500D8DD5C /* PlaybackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C35E1A2B108C3500D8DD5C /* PlaybackView.swift */; }; 83C35E1E2B10923C00D8DD5C /* PlaybackCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C35E1D2B10923C00D8DD5C /* PlaybackCell.swift */; }; FC0E80242B1A0BBB00EF56D6 /* UploadPostPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC0E801E2B1A0BBB00EF56D6 /* UploadPostPresenter.swift */; }; @@ -422,6 +423,7 @@ 836C33902B17629400ECAFB0 /* MapRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapRouter.swift; sourceTree = ""; }; 836C33972B1843BE00ECAFB0 /* SettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewController.swift; sourceTree = ""; }; 83957AA52B20F94C00B3BA8A /* MockPlaybackWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPlaybackWorker.swift; sourceTree = ""; }; + 839F1DF72B62AEDA0071C622 /* LOTextLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOTextLabel.swift; sourceTree = ""; }; 83C35E1A2B108C3500D8DD5C /* PlaybackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackView.swift; sourceTree = ""; }; 83C35E1D2B10923C00D8DD5C /* PlaybackCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackCell.swift; sourceTree = ""; }; FC0E801E2B1A0BBB00EF56D6 /* UploadPostPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadPostPresenter.swift; sourceTree = ""; }; @@ -1191,6 +1193,7 @@ 8321A2F62B1E14A1000A12AF /* LOPopUpView.swift */, 8321A2F82B1E15F3000A12AF /* LOReportStackView.swift */, 8321A2FA2B1E1739000A12AF /* LOReportContentView.swift */, + 839F1DF72B62AEDA0071C622 /* LOTextLabel.swift */, ); path = DesignSystem; sourceTree = ""; @@ -1561,6 +1564,7 @@ 198167A42B20583D0032F563 /* SettingInteractor.swift in Sources */, FC4E0C1D2B28977000152596 /* CurrentLocationManager.swift in Sources */, 83C35E1B2B108C3500D8DD5C /* PlaybackView.swift in Sources */, + 839F1DF82B62AEDA0071C622 /* LOTextLabel.swift in Sources */, FC4E0C192B28955400152596 /* LocationFetcher.swift in Sources */, 835A61A02B068115002F22A5 /* PlaybackModels.swift in Sources */, FC0E80292B1A0BBB00EF56D6 /* UploadPostInteractor.swift in Sources */, diff --git a/iOS/Layover/Layover/DesignSystem/LOTextLabel.swift b/iOS/Layover/Layover/DesignSystem/LOTextLabel.swift new file mode 100644 index 0000000..132a1e3 --- /dev/null +++ b/iOS/Layover/Layover/DesignSystem/LOTextLabel.swift @@ -0,0 +1,39 @@ +// +// LOTextLabel.swift +// Layover +// +// Created by 황지웅 on 1/25/24. +// Copyright © 2024 CodeBomber. All rights reserved. +// + +import UIKit + +final class LOTextLabel: UILabel { + + private var padding = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0) + + convenience init(padding: UIEdgeInsets) { + self.init() + self.padding = padding + setUI() + } + + override func drawText(in rect: CGRect) { + super.drawText(in: rect.inset(by: padding)) + } + + override var intrinsicContentSize: CGSize { + var contentSize = super.intrinsicContentSize + contentSize.height += padding.top + padding.bottom + contentSize.width += padding.left + padding.right + + return contentSize + } + + private func setUI() { + layer.cornerRadius = 8 + layer.borderWidth = 1 + layer.borderColor = UIColor.grey500.cgColor + backgroundColor = UIColor.clear + } +} diff --git a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift index 14f13e1..623d0d3 100644 --- a/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift +++ b/iOS/Layover/Layover/Scenes/UploadPost/UploadPostViewController.swift @@ -76,11 +76,12 @@ final class UploadPostViewController: BaseViewController { return imageLabel }() - private let currentAddressLabel: UILabel = { - let label = UILabel() + private let currentAddressLabel: LOTextLabel = { + let label = LOTextLabel(padding: UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)) label.font = .loFont(type: .body2) label.numberOfLines = 1 label.adjustsFontSizeToFitWidth = true + label.isUserInteractionEnabled = true return label }() @@ -251,7 +252,7 @@ final class UploadPostViewController: BaseViewController { private func addLocationTarget() { let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(locationDidTap)) - locationImageLabel.addGestureRecognizer(singleTapGestureRecognizer) + currentAddressLabel.addGestureRecognizer(singleTapGestureRecognizer) } @objc private func titleTextChanged() {