From 9c02b29ead565acf976be901c67e0e2e70b1dab3 Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 21:24:41 +0900 Subject: [PATCH 01/13] =?UTF-8?q?feat=20:=20=EC=A2=8C=EC=9A=B0=20=EC=8A=A4?= =?UTF-8?q?=EC=99=80=EC=9D=B4=ED=94=84=20=EA=B0=80=EC=9D=B4=EB=93=9C=20?= =?UTF-8?q?=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 앱 실행마다 가이드 애니메이션이 첫 한번만 보이도록 UserDefault 에 저장 --- Particle/Particle/Entry/AppDelegate.swift | 2 ++ .../SelectSentenceViewController.swift | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Particle/Particle/Entry/AppDelegate.swift b/Particle/Particle/Entry/AppDelegate.swift index 4580a79..c4d4e96 100644 --- a/Particle/Particle/Entry/AppDelegate.swift +++ b/Particle/Particle/Entry/AppDelegate.swift @@ -38,6 +38,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return } } + + UserDefaults.standard.set(false, forKey: "ShowSwipeGuide") return true } diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift index f480b6f..5156607 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift @@ -107,6 +107,15 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen setupInitialView() } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + guard let alreadyShow = UserDefaults.standard.object(forKey: "ShowSwipeGuide") as? Bool, + alreadyShow == false else { + return + } + showSwipeGuide() + } + private func setupInitialView() { view.backgroundColor = .black addSubviews() @@ -146,15 +155,21 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen return } let imageRequestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:]) + private func showSwipeGuide() { let request = VNRecognizeTextRequest { [weak self] (request, error) in guard error == nil else { Console.error(error?.localizedDescription ?? "VNRecognizeTextRequestError") return } + UIView.animate(withDuration: 0.8, delay: 0.0, options: [.curveEaseOut]) { [weak self] in + self?.selectedPhotoCollectionView.contentOffset.x = 70 + } completion: { _ in guard let observations = request.results as? [VNRecognizedTextObservation] else { return + UIView.animate(withDuration: 0.2, delay: 0.0, options: [.curveEaseInOut]) { [weak self] in + self?.selectedPhotoCollectionView.contentOffset.x = 1 } for observation in observations { @@ -182,6 +197,7 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen } catch let error { Console.error(error.localizedDescription) } + UserDefaults.standard.set(true, forKey: "ShowSwipeGuide") } // MARK: - SelectSentenceViewControllable From 8cbc85466ee41312545c15f473139999f4f09f5c Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 21:29:48 +0900 Subject: [PATCH 02/13] =?UTF-8?q?fix=20:=20PhotoPicker=20RIB=20=EC=97=90?= =?UTF-8?q?=20=EC=82=AC=EC=A7=84=20=EC=84=A0=ED=83=9D=20=EB=84=98=EB=B2=84?= =?UTF-8?q?=EB=A7=81=20=EB=82=B4=EB=B6=80=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 선태된 순서를 기반으로 중간에 선택한 사진을 해제할 경우 나머지 사진들이 선택된 순서에 따라 넘버링을 동적으로 업데이트 --- .../PhotoPickerViewController.swift | 70 ++++++++++++++----- .../PhotoPicker/View/PhotoCell.swift | 20 +++--- 2 files changed, 63 insertions(+), 27 deletions(-) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/PhotoPickerViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/PhotoPickerViewController.swift index 77de943..92be6ed 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/PhotoPickerViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/PhotoPickerViewController.swift @@ -16,7 +16,9 @@ protocol PhotoPickerPresentableListener: AnyObject { func nextButtonTapped(with images: [PHAsset]) } -final class PhotoPickerViewController: UIViewController, PhotoPickerPresentable, PhotoPickerViewControllable { +final class PhotoPickerViewController: UIViewController, + PhotoPickerPresentable, + PhotoPickerViewControllable { enum Metric { enum NavigationBar { @@ -31,7 +33,7 @@ final class PhotoPickerViewController: UIViewController, PhotoPickerPresentable, weak var listener: PhotoPickerPresentableListener? private var disposeBag: DisposeBag = .init() - private var selectedItems: [PHAsset] = [] + private var selectedIndexPaths: [IndexPath] = [] private let navigationBar: UIView = { let view = UIView() @@ -74,6 +76,7 @@ final class PhotoPickerViewController: UIViewController, PhotoPickerPresentable, return collectionView }() + // MARK: - Initializers init() { super.init(nibName: nil, bundle: nil) modalPresentationStyle = .fullScreen @@ -83,6 +86,7 @@ final class PhotoPickerViewController: UIViewController, PhotoPickerPresentable, fatalError("init(coder:) has not been implemented") } + // MARK: - View LifeCycles override func viewDidLoad() { super.viewDidLoad() setupInitialView() @@ -120,12 +124,18 @@ final class PhotoPickerViewController: UIViewController, PhotoPickerPresentable, nextButton.rx.tap .bind { [weak self] in - self?.listener?.nextButtonTapped(with: self?.selectedItems ?? []) + guard let self = self else { return } + self.listener?.nextButtonTapped(with: self.getSelectedPhotoes()) } .disposed(by: disposeBag) } private func bind() { + bindCollectionViewCell() + bindItemSelected() + } + + private func bindCollectionViewCell() { Observable.of(Array(0...(photoCount - 1))) .bind(to: photoCollectionView.rx.items( cellIdentifier: PhotoCell.defaultReuseIdentifier, @@ -133,36 +143,62 @@ final class PhotoPickerViewController: UIViewController, PhotoPickerPresentable, ) { index, item, cell in guard let allPhotos = allPhotos else { - Console.error("allPhotos 값이 존재하지 않습니다.") + Console.error("\(#function) allPhotos 값이 존재하지 않습니다.") return } cell.setImage(with: allPhotos.object(at: item)) } .disposed(by: disposeBag) - + } + + private func bindItemSelected() { photoCollectionView .rx .itemSelected .subscribe { [weak self] indexPath in - guard let self = self else { return } + guard let self = self, + let indexPath = indexPath.element else { return } - guard let allPhotos = allPhotos else { - Console.error("allPhotos 값이 존재하지 않습니다.") - return - } - let selectedPhoto = allPhotos.object(at: indexPath.element?.row ?? 0) - if self.selectedItems.contains(selectedPhoto) { - self.selectedItems.remove(at: self.selectedItems.firstIndex(of: selectedPhoto) ?? .zero) + if self.selectedIndexPaths.contains(indexPath) { + self.selectedIndexPaths.remove( + at: self.selectedIndexPaths.firstIndex(of: indexPath) ?? .zero + ) + guard let cell = self.getCell(at: indexPath) else { return } + cell.uncheck() } else { - self.selectedItems.append(selectedPhoto) + self.selectedIndexPaths.append(indexPath) } - guard let cell = self.photoCollectionView.cellForItem(at: indexPath.element ?? .init(item: 0, section: 0)) as? PhotoCell else { - return + + for (order, indexPath) in self.selectedIndexPaths.enumerated() { + guard let cell = self.getCell(at: indexPath) else { return } + cell.check(number: order + 1) } - cell.check(number: self.selectedItems.count) } .disposed(by: disposeBag) } + + private func getSelectedPhotoes() -> [PHAsset] { + guard let allPhotos = allPhotos else { + Console.error("\(#function) allPhotos 값이 존재하지 않습니다.") + return [] + } + let selectedPhotoes = selectedIndexPaths.map { + allPhotos.object(at: $0.row) + } + + return selectedPhotoes + } + + private func getCell(at indexPath: IndexPath?) -> PhotoCell? { + guard let indexPath = indexPath else { + Console.error("\(#function) indexPath가 존재하지 않습니다.") + return nil + } + guard let cell = self.photoCollectionView.cellForItem(at: indexPath) as? PhotoCell else { + return nil + } + return cell + } } // MARK: - Layout Settting diff --git a/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/View/PhotoCell.swift b/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/View/PhotoCell.swift index e99f8ae..dbf7a3a 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/View/PhotoCell.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/PhotoPicker/View/PhotoCell.swift @@ -70,16 +70,16 @@ final class PhotoCell: UICollectionViewCell { } func check(number: Int) { - if checkBox_checked.alpha == 0 { - dimmingView.alpha = 0.3 - checkBox_checked.alpha = 1 - numberLabel.alpha = 1 - numberLabel.text = "\(number)" - } else { - dimmingView.alpha = 0 - checkBox_checked.alpha = 0 - numberLabel.alpha = 0 - } + dimmingView.alpha = 0.3 + checkBox_checked.alpha = 1 + numberLabel.alpha = 1 + numberLabel.text = "\(number)" + } + + func uncheck() { + dimmingView.alpha = 0 + checkBox_checked.alpha = 0 + numberLabel.alpha = 0 } } From 14320e328cfe0150238b2117274192be446d64b6 Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 22:14:55 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat=20:=20=EC=84=A0=ED=83=9D=EB=90=9C=20?= =?UTF-8?q?=EC=82=AC=EC=A7=84=EB=93=A4=EC=9D=84=20=EC=A2=8C=EC=9A=B0=20?= =?UTF-8?q?=EC=8A=A4=EC=99=80=EC=9D=B4=ED=94=84=EA=B0=80=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=9C=20CollectionView=20=EB=A1=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SelectedPhotoCell 생성 - 스와이프 페이지 인덱싱 적용 - 네비게이션바에 "다음" 버튼 추가 --- .../SelectSentenceViewController.swift | 84 ++++++++++- .../View/SelectedPhotoCell.swift | 136 ++++++++++++++++++ 2 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/View/SelectedPhotoCell.swift diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift index 5156607..24a3c59 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift @@ -17,6 +17,7 @@ protocol SelectSentencePresentableListener: AnyObject { func showEditSentenceModal(with text: String) func backButtonTapped() + func nextButtonTapped() } final class SelectSentenceViewController: UIViewController, SelectSentencePresentable, SelectSentenceViewControllable { @@ -31,6 +32,9 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen static let height = 44 static let backButtonLeftMargin = 8 static let nextButtonRightMargin = 8 + enum CollectionViewCell { + static let width = DeviceSize.width + static let height = DeviceSize.height - Metric.NavigationBar.height - InfoBox.height - 100 } } @@ -49,6 +53,14 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen return button }() + private let nextButton: UIButton = { + let button = UIButton() + button.setTitle("다음", for: .normal) + button.setTitleColor(.systemGray, for: .disabled) + button.setTitleColor(.particleColor.main, for: .normal) + return button + }() + private let navigationTitle: UILabel = { let label = UILabel() label.text = "문장 선택 1/7" @@ -74,6 +86,21 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen let imageView = UIImageView() imageView.contentMode = .scaleAspectFit return imageView + private let selectedPhotoCollectionView: UICollectionView = { + let layout = UICollectionViewFlowLayout() + layout.itemSize = CGSize( + width: Metric.CollectionViewCell.width, + height: Metric.CollectionViewCell.height + ) + layout.minimumLineSpacing = 0 + layout.minimumInteritemSpacing = 0 + layout.scrollDirection = .horizontal + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.isPagingEnabled = true + collectionView.showsHorizontalScrollIndicator = false + collectionView.register(SelectedPhotoCell.self) + collectionView.backgroundColor = .init(hex: 0x1f1f1f) + return collectionView }() private let textView: UITextView = { @@ -122,6 +149,7 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen setConstraints() setupNavigationBar() configureTextView() + bind() } private func setupNavigationBar() { @@ -131,16 +159,39 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen self?.listener?.backButtonTapped() } .disposed(by: disposeBag) + + nextButton.rx.tap + .bind { [weak self] in + self?.listener?.nextButtonTapped() + } + .disposed(by: disposeBag) + + // TODO: 각 사진에서 문장추출이 모두 완료되었을 때 nextButton 활성화 +// nextButton.isEnabled = false } private func configureTextView() { textView.delegate = self + private func bind() { + + bindCollectionViewCell() + bindPageIndex() } private func addCustomMenuItem() { let menuItem1 = UIMenuItem(title: "문장뽑기", action: #selector(textSelected(_:))) UIMenuController.shared.menuItems = nil UIMenuController.shared.menuItems = [menuItem1] + private func bindCollectionViewCell() { + Observable.of(selectedImages) + .bind(to: selectedPhotoCollectionView.rx.items( + cellIdentifier: SelectedPhotoCell.defaultReuseIdentifier, + cellType: SelectedPhotoCell.self) + ) { [weak self] index, item, cell in + cell.setImage(with: item) + cell.listener = self + } + .disposed(by: disposeBag) } @objc private func textSelected(_ sender: UIMenuController) { @@ -148,6 +199,28 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen let selectedText = textView.text(in: selectedRange) ?? "선택된 문장이 없습니다." listener?.showEditSentenceModal(with: selectedText) } + private func bindPageIndex() { + selectedPhotoCollectionView + .rx + .contentOffset + .subscribe { [weak self] point in + guard let self = self, let positionX = point.element?.x else { return } + switch positionX { + case (0.. Date: Tue, 8 Aug 2023 22:21:14 +0900 Subject: [PATCH 04/13] =?UTF-8?q?fix=20:=20OrganizingSentenceRepository=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AddArticleComponent 에 OrganizingSentenceRepositoryImp 생성 - 잘못된 위치에서 생성된 OrganizingSentenceRepository 코드 제거 - AddArticle 하위 RIB 들이 이를 공유하도록 설정 --- Particle/Particle/LoggedIn/LoggedInBuilder.swift | 12 +++--------- .../OrganizingSentenceRepository.swift | 5 ++--- .../HomeTab/AddArticle/AddArticleBuilder.swift | 3 ++- .../SelectSentence/SelectSentenceBuilder.swift | 16 ++++++---------- .../SelectSentenceInteractor.swift | 16 ++++++++++++---- Particle/Particle/Main/MainBuilder.swift | 10 ++-------- .../Particle/Root/RootComponent+LoggedIn.swift | 6 +----- 7 files changed, 28 insertions(+), 40 deletions(-) diff --git a/Particle/Particle/LoggedIn/LoggedInBuilder.swift b/Particle/Particle/LoggedIn/LoggedInBuilder.swift index 6e02543..0ae1ff6 100644 --- a/Particle/Particle/LoggedIn/LoggedInBuilder.swift +++ b/Particle/Particle/LoggedIn/LoggedInBuilder.swift @@ -8,19 +8,13 @@ import RIBs protocol LoggedInDependency: Dependency { - // TODO: Make sure to convert the variable into lower-camelcase. - var LoggedInViewController: LoggedInViewControllable { get } - var organizingSentenceRepository: OrganizingSentenceRepository { get } + var loggedInViewController: LoggedInViewControllable { get } } final class LoggedInComponent: Component, MainDependency { - // TODO: Make sure to convert the variable into lower-camelcase. - fileprivate var LoggedInViewController: LoggedInViewControllable { - return dependency.LoggedInViewController - } - var organizingSentenceRepository: OrganizingSentenceRepository { - return dependency.organizingSentenceRepository + fileprivate var loggedInViewController: LoggedInViewControllable { + return dependency.loggedInViewController } } diff --git a/Particle/Particle/Main/HomeTab/AddArticle/AddAriticleRepository/OrganizingSentenceRepository.swift b/Particle/Particle/Main/HomeTab/AddArticle/AddAriticleRepository/OrganizingSentenceRepository.swift index 953161b..ecca19e 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/AddAriticleRepository/OrganizingSentenceRepository.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/AddAriticleRepository/OrganizingSentenceRepository.swift @@ -14,9 +14,8 @@ public protocol OrganizingSentenceRepository { } public final class OrganizingSentenceRepositoryImp: OrganizingSentenceRepository { - public var sentenceFile: RxSwift.BehaviorSubject<[String]> { - sentenceSubject - } + + public var sentenceFile: BehaviorSubject<[String]> = .init(value: []) private let sentenceSubject = BehaviorSubject<[String]>(value: [ "그렇게 쓴 글은 매일 사회관계망서비스(SNS)에 남기기도 하고, 모아서 책으로 내기도 한다.", diff --git a/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift b/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift index 88a28b8..25c1eb7 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift @@ -16,6 +16,7 @@ protocol AddArticleDependency: Dependency { final class AddArticleComponent: Component { + var repository = OrganizingSentenceRepositoryImp() // TODO: Make sure to convert the variable into lower-camelcase. fileprivate var addArticleViewController: ViewControllable { return dependency.addArticleViewController @@ -63,6 +64,6 @@ extension AddArticleComponent: PhotoPickerDependency, SetAdditionalInformationDependency { var organizingSentenceRepository: OrganizingSentenceRepository { - return OrganizingSentenceRepositoryImp() //FIXME: ?? + return repository } } diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceBuilder.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceBuilder.swift index bf3afb9..2dc59d6 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceBuilder.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceBuilder.swift @@ -9,13 +9,13 @@ import RIBs import Photos protocol SelectSentenceDependency: Dependency { - // TODO: Declare the set of dependencies required by this RIB, but cannot be - // created by this RIB. + var organizingSentenceRepository: OrganizingSentenceRepository { get } } final class SelectSentenceComponent: Component { - - // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. + fileprivate var organizingSentenceRepository: OrganizingSentenceRepository { + return dependency.organizingSentenceRepository + } } // MARK: - Builder @@ -33,7 +33,7 @@ final class SelectSentenceBuilder: Builder, SelectSent func build(withListener listener: SelectSentenceListener, images: [PHAsset]) -> SelectSentenceRouting { let component = SelectSentenceComponent(dependency: dependency) let viewController = SelectSentenceViewController(selectedImages: images) - let interactor = SelectSentenceInteractor(presenter: viewController) + let interactor = SelectSentenceInteractor(presenter: viewController, repository: component.organizingSentenceRepository) interactor.listener = listener let editSentenceBuilder = EditSentenceBuilder(dependency: component) @@ -46,8 +46,4 @@ final class SelectSentenceBuilder: Builder, SelectSent } } -extension SelectSentenceComponent: EditSentenceDependency, OrganizingSentenceDependency { - var organizingSentenceRepository: OrganizingSentenceRepository { - OrganizingSentenceRepositoryImp() - } -} +extension SelectSentenceComponent: EditSentenceDependency { } diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift index 90adc82..a0dff4d 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift @@ -28,13 +28,16 @@ protocol SelectSentenceListener: AnyObject { final class SelectSentenceInteractor: PresentableInteractor, SelectSentenceInteractable, SelectSentencePresentableListener { - + weak var router: SelectSentenceRouting? weak var listener: SelectSentenceListener? + private var organizingSentenceRepository: OrganizingSentenceRepository + // TODO: Add additional dependencies to constructor. Do not perform any logic // in constructor. - override init(presenter: SelectSentencePresentable) { + init(presenter: SelectSentencePresentable, repository: OrganizingSentenceRepository) { + self.organizingSentenceRepository = repository super.init(presenter: presenter) presenter.listener = self } @@ -56,9 +59,14 @@ final class SelectSentenceInteractor: PresentableInteractor, OrganizingSentenceDependency, SetAdditionalInformationDependency { - var organizingSentenceRepository: OrganizingSentenceRepository { - dependency.organizingSentenceRepository - } -} +final class MainComponent: Component { } // MARK: - Builder diff --git a/Particle/Particle/Root/RootComponent+LoggedIn.swift b/Particle/Particle/Root/RootComponent+LoggedIn.swift index da0143b..e5ef2d6 100644 --- a/Particle/Particle/Root/RootComponent+LoggedIn.swift +++ b/Particle/Particle/Root/RootComponent+LoggedIn.swift @@ -13,11 +13,7 @@ protocol RootDependencyLoggedIn: Dependency { extension RootComponent: LoggedInDependency { - var LoggedInViewController: LoggedInViewControllable { + var loggedInViewController: LoggedInViewControllable { return rootViewController } - - var organizingSentenceRepository: OrganizingSentenceRepository { - return OrganizingSentenceRepositoryImp() - } } From e899afa18dfdf85bbca3dd26eb8adf5e52b53ce8 Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 22:22:45 +0900 Subject: [PATCH 05/13] =?UTF-8?q?feat=20:=20Extension=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UIImageView 에 fetchImage 메서드 completion 파라미터 추가 - UIView 에서 각 코너에 Radius 값을 설정할 수 있는 addRoundedCorner 메서드 추가 --- .../Particle/Extension/UIImageView+.swift | 11 +++++---- Particle/Particle/Extension/UIView+.swift | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 Particle/Particle/Extension/UIView+.swift diff --git a/Particle/Particle/Extension/UIImageView+.swift b/Particle/Particle/Extension/UIImageView+.swift index 0264d02..50867e9 100644 --- a/Particle/Particle/Extension/UIImageView+.swift +++ b/Particle/Particle/Extension/UIImageView+.swift @@ -10,7 +10,7 @@ import Photos extension UIImageView { - func fetchImage(asset: PHAsset, contentMode: PHImageContentMode, targetSize: CGSize) { + func fetchImage(asset: PHAsset, contentMode: PHImageContentMode, targetSize: CGSize, _ completion: ((CGFloat) -> Void)? = nil) { let options = PHImageRequestOptions() options.version = .original options.deliveryMode = .opportunistic @@ -21,11 +21,12 @@ extension UIImageView { targetSize: targetSize, contentMode: contentMode, options: options) { image, info in - if image == nil { - Console.error(#function) - print(info ?? #function) - } else { + + if let image = image { self.image = image + completion?(image.size.height / image.size.width) + } else { + Console.error("\(#function) image 가 존재하지 않습니다.") } } } diff --git a/Particle/Particle/Extension/UIView+.swift b/Particle/Particle/Extension/UIView+.swift new file mode 100644 index 0000000..78c85c5 --- /dev/null +++ b/Particle/Particle/Extension/UIView+.swift @@ -0,0 +1,23 @@ +// +// UIView+.swift +// Particle +// +// Created by 이원빈 on 2023/08/08. +// + +import UIKit + +extension UIView { + + func addRoundedCorner(corners: UIRectCorner, radius: CGFloat) { + let maskPath = UIBezierPath( + roundedRect: bounds, + byRoundingCorners: corners, + cornerRadii: CGSize(width: radius, height: radius) + ) + + let maskLayer = CAShapeLayer() + maskLayer.path = maskPath.cgPath + layer.mask = maskLayer + } +} From 4b243c0e7258af90061b3b9b7bfc8d6f2c6251c8 Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 22:25:32 +0900 Subject: [PATCH 06/13] =?UTF-8?q?style=20:=20=EC=BB=A8=EB=B2=A4=EC=85=98?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 변수명 소문자 카멜케이스 적용 - 매직리터럴, 매직넘버 enum Metric 으로 분리 - 불필요한 주석 제거, 마크주석 적용 - 개행 컨벤션 적용 --- .../Particle/LoggedIn/LoggedInBuilder.swift | 2 +- .../AddArticle/AddArticleBuilder.swift | 10 +++---- .../AddArticle/AddArticleInteractor.swift | 11 ++------ .../EditSentence/EditSentenceBuilder.swift | 12 +++------ .../EditSentenceViewController.swift | 8 +++--- .../SelectSentenceViewController.swift | 27 ++++++++++++++----- Particle/Particle/Root/RootRouter.swift | 1 - 7 files changed, 35 insertions(+), 36 deletions(-) diff --git a/Particle/Particle/LoggedIn/LoggedInBuilder.swift b/Particle/Particle/LoggedIn/LoggedInBuilder.swift index 0ae1ff6..7750af1 100644 --- a/Particle/Particle/LoggedIn/LoggedInBuilder.swift +++ b/Particle/Particle/LoggedIn/LoggedInBuilder.swift @@ -37,7 +37,7 @@ final class LoggedInBuilder: Builder, LoggedInBuildable { let mainBuilder = MainBuilder(dependency: component) return LoggedInRouter( interactor: interactor, - viewController: component.LoggedInViewController, + viewController: component.loggedInViewController, mainBuilder: mainBuilder ) } diff --git a/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift b/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift index 25c1eb7..6f6bffd 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/AddArticleBuilder.swift @@ -8,21 +8,15 @@ import RIBs protocol AddArticleDependency: Dependency { - // TODO: Make sure to convert the variable into lower-camelcase. var addArticleViewController: ViewControllable { get } - // TODO: Declare the set of dependencies required by this RIB, but won't be - // created by this RIB. } final class AddArticleComponent: Component { - var repository = OrganizingSentenceRepositoryImp() - // TODO: Make sure to convert the variable into lower-camelcase. + fileprivate var addArticleViewController: ViewControllable { return dependency.addArticleViewController } - - // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. } // MARK: - Builder @@ -32,6 +26,7 @@ protocol AddArticleBuildable: Buildable { } final class AddArticleBuilder: Builder, AddArticleBuildable { + override init(dependency: AddArticleDependency) { super.init(dependency: dependency) @@ -39,6 +34,7 @@ final class AddArticleBuilder: Builder, AddArticleBuildabl func build(withListener listener: AddArticleListener) -> AddArticleRouting { let component = AddArticleComponent(dependency: dependency) + let interactor = AddArticleInteractor() interactor.listener = listener diff --git a/Particle/Particle/Main/HomeTab/AddArticle/AddArticleInteractor.swift b/Particle/Particle/Main/HomeTab/AddArticle/AddArticleInteractor.swift index f5d85f2..67b73c0 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/AddArticleInteractor.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/AddArticleInteractor.swift @@ -25,19 +25,14 @@ protocol AddArticleRouting: Routing { func detachSetAdditionalInformation() } -protocol AddArticleListener: AnyObject { - // TODO: Declare methods the interactor can invoke to communicate with other RIBs. -} +protocol AddArticleListener: AnyObject { } final class AddArticleInteractor: Interactor, AddArticleInteractable { weak var router: AddArticleRouting? weak var listener: AddArticleListener? - // TODO: Add additional dependencies to constructor. Do not perform any logic - // in constructor. - override init() { - } + override init() { } override func didBecomeActive() { super.didBecomeActive() @@ -48,7 +43,6 @@ final class AddArticleInteractor: Interactor, AddArticleInteractable { super.willResignActive() router?.cleanupViews() - // TODO: Pause any business logic. } // MARK: - PhotoPickerListener @@ -71,7 +65,6 @@ final class AddArticleInteractor: Interactor, AddArticleInteractable { router?.attachOrganizingSentence() } - // MARK: - OrganizingSentenceListener func organizingSentenceNextButtonTapped() { diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceBuilder.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceBuilder.swift index 06eb845..ad0caed 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceBuilder.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceBuilder.swift @@ -7,15 +7,9 @@ import RIBs -protocol EditSentenceDependency: Dependency { - // TODO: Declare the set of dependencies required by this RIB, but cannot be - // created by this RIB. -} - -final class EditSentenceComponent: Component { +protocol EditSentenceDependency: Dependency { } - // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. -} +final class EditSentenceComponent: Component { } // MARK: - Builder @@ -31,7 +25,7 @@ final class EditSentenceBuilder: Builder, EditSentenceBu func build(withListener listener: EditSentenceListener, text: String) -> EditSentenceRouting { _ = EditSentenceComponent(dependency: dependency) - let viewController = EditSentenceViewController(with: text) // FIXME: text 데이터 전달과정 리뷰요청. component 활용방법 연구 + let viewController = EditSentenceViewController(with: text) let interactor = EditSentenceInteractor(presenter: viewController) interactor.listener = listener return EditSentenceRouter(interactor: interactor, viewController: viewController) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift index 0ad96e2..bfd83c4 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift @@ -90,9 +90,7 @@ final class EditSentenceViewController: UIViewController, EditSentencePresentabl height: 50 ) ) - uiview.layer.borderWidth = 1 - uiview.layer.borderColor = UIColor.systemGray6.cgColor - uiview.layer.backgroundColor = UIColor.systemBackground.cgColor + uiview.layer.backgroundColor = UIColor.darkGray.cgColor return uiview }() @@ -105,6 +103,8 @@ final class EditSentenceViewController: UIViewController, EditSentencePresentabl return button }() + // MARK: - Initializers + init(with text: String) { self.originalText = text super.init(nibName: nil, bundle: nil) @@ -116,6 +116,8 @@ final class EditSentenceViewController: UIViewController, EditSentencePresentabl fatalError("init(coder:) has not been implemented") } + // MARK: - View LifeCycles + override func viewDidLoad() { super.viewDidLoad() setupKeyboardNotification() diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift index 24a3c59..a169063 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift @@ -20,7 +20,9 @@ protocol SelectSentencePresentableListener: AnyObject { func nextButtonTapped() } -final class SelectSentenceViewController: UIViewController, SelectSentencePresentable, SelectSentenceViewControllable { +final class SelectSentenceViewController: UIViewController, + SelectSentencePresentable, + SelectSentenceViewControllable { enum Metric { enum Title { @@ -29,15 +31,21 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen } enum NavigationBar { - static let height = 44 - static let backButtonLeftMargin = 8 - static let nextButtonRightMargin = 8 + static let height: CGFloat = 44 + static let backButtonLeftMargin: CGFloat = 8 + static let nextButtonRightMargin: CGFloat = 8 + } + + enum InfoBox { + static let height: CGFloat = 53 + } + enum CollectionViewCell { static let width = DeviceSize.width static let height = DeviceSize.height - Metric.NavigationBar.height - InfoBox.height - 100 } } - + weak var listener: SelectSentencePresentableListener? private var disposeBag: DisposeBag = .init() @@ -114,6 +122,8 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen return textView }() + // MARK: - Initializers + init(selectedImages: [PHAsset]) { super.init(nibName: nil, bundle: nil) @@ -129,6 +139,8 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen fatalError("init(coder:) has not been implemented") } + // MARK: - View LifeCycles + override func viewDidLoad() { super.viewDidLoad() setupInitialView() @@ -154,6 +166,7 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen private func setupNavigationBar() { navigationController?.isNavigationBarHidden = true + backButton.rx.tap .bind { [weak self] in self?.listener?.backButtonTapped() @@ -274,6 +287,7 @@ final class SelectSentenceViewController: UIViewController, SelectSentencePresen } // MARK: - SelectSentenceViewControllable + func present(viewController: ViewControllable) { present(viewController.uiviewController, animated: true) } @@ -339,7 +353,7 @@ private extension SelectSentenceViewController { infoBox.snp.makeConstraints { $0.top.equalTo(navigationBar.snp.bottom) $0.leading.trailing.equalTo(view.safeAreaLayoutGuide) - $0.height.equalTo(53) + $0.height.equalTo(Metric.InfoBox.height) } infoLabel.snp.makeConstraints { @@ -361,6 +375,7 @@ import SwiftUI @available(iOS 13.0, *) struct SelectSentenceViewController_Preview: PreviewProvider { + static var previews: some View { SelectSentenceViewController(selectedImages: []).showPreview() } diff --git a/Particle/Particle/Root/RootRouter.swift b/Particle/Particle/Root/RootRouter.swift index 7be03b8..a6cfe5b 100644 --- a/Particle/Particle/Root/RootRouter.swift +++ b/Particle/Particle/Root/RootRouter.swift @@ -58,7 +58,6 @@ final class RootRouter: LaunchRouter, Ro private let loggedInBuilder: LoggedInBuildable private var loggedOut: ViewableRouting? -// private var loggedIn: Routing? private func routeToLoggedOut() { let loggedOut = loggedOutBuilder.build(withListener: interactor) From b07c41ad873f0665beee7754b97629d832398c8b Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 22:29:08 +0900 Subject: [PATCH 07/13] =?UTF-8?q?fix=20:=20EditSentence=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - nextButton -> saveButton 으로 네이밍 수정 - 버튼 탭시 데이터 전달 --- .../EditSentence/EditSentenceInteractor.swift | 6 +++--- .../EditSentence/EditSentenceViewController.swift | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift index 8fb9fee..9b1256a 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift @@ -19,7 +19,7 @@ protocol EditSentencePresentable: Presentable { protocol EditSentenceListener: AnyObject { // TODO: Declare methods the interactor can invoke to communicate with other RIBs. - func dismissEditSentence() + func dismissEditSentence(with text: String) } final class EditSentenceInteractor: PresentableInteractor, @@ -48,7 +48,7 @@ final class EditSentenceInteractor: PresentableInteractor Date: Tue, 8 Aug 2023 22:30:58 +0900 Subject: [PATCH 08/13] =?UTF-8?q?refactor=20:=20=EA=B8=B0=EC=A1=B4?= =?UTF-8?q?=EC=9D=98=20OCR=20=EC=BD=94=EB=93=9C=20=EB=B0=8F=20TextView=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SelectSentenceViewController.swift | 93 ------------------- 1 file changed, 93 deletions(-) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift index a169063..c976361 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift @@ -90,10 +90,6 @@ final class SelectSentenceViewController: UIViewController, return label }() - private let textImage: UIImageView = { - let imageView = UIImageView() - imageView.contentMode = .scaleAspectFit - return imageView private let selectedPhotoCollectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize( @@ -111,28 +107,11 @@ final class SelectSentenceViewController: UIViewController, return collectionView }() - private let textView: UITextView = { - let textView = CustomTextView() - textView.isEditable = false - textView.font = .preferredFont(forTextStyle: .title3) - textView.textColor = .init(UIColor(hex: 0xededed)) - textView.backgroundColor = .black - textView.tintColor = .particleColor.main - textView.text = "default Text" - return textView - }() // MARK: - Initializers init(selectedImages: [PHAsset]) { super.init(nibName: nil, bundle: nil) - - selectedImages.forEach { - $0.toImage(contentMode: .default, targetSize: textImage.frame.size) { [weak self] image in - guard let image = image else { return } - self?.recognizeTextImage(image) - } - } } required init?(coder aDecoder: NSCoder) { @@ -160,7 +139,6 @@ final class SelectSentenceViewController: UIViewController, addSubviews() setConstraints() setupNavigationBar() - configureTextView() bind() } @@ -183,18 +161,12 @@ final class SelectSentenceViewController: UIViewController, // nextButton.isEnabled = false } - private func configureTextView() { - textView.delegate = self private func bind() { bindCollectionViewCell() bindPageIndex() } - private func addCustomMenuItem() { - let menuItem1 = UIMenuItem(title: "문장뽑기", action: #selector(textSelected(_:))) - UIMenuController.shared.menuItems = nil - UIMenuController.shared.menuItems = [menuItem1] private func bindCollectionViewCell() { Observable.of(selectedImages) .bind(to: selectedPhotoCollectionView.rx.items( @@ -207,11 +179,6 @@ final class SelectSentenceViewController: UIViewController, .disposed(by: disposeBag) } - @objc private func textSelected(_ sender: UIMenuController) { - if let selectedRange = textView.selectedTextRange { - let selectedText = textView.text(in: selectedRange) ?? "선택된 문장이 없습니다." - listener?.showEditSentenceModal(with: selectedText) - } private func bindPageIndex() { selectedPhotoCollectionView .rx @@ -236,52 +203,15 @@ final class SelectSentenceViewController: UIViewController, .disposed(by: disposeBag) } - func recognizeTextImage(_ image: UIImage?) { - guard let image = image, let ciImage = CIImage(image: image) else { - return - } - let imageRequestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:]) private func showSwipeGuide() { - let request = VNRecognizeTextRequest { [weak self] (request, error) in - guard error == nil else { - Console.error(error?.localizedDescription ?? "VNRecognizeTextRequestError") - return - } UIView.animate(withDuration: 0.8, delay: 0.0, options: [.curveEaseOut]) { [weak self] in self?.selectedPhotoCollectionView.contentOffset.x = 70 } completion: { _ in - guard let observations = request.results as? [VNRecognizedTextObservation] else { - return UIView.animate(withDuration: 0.2, delay: 0.0, options: [.curveEaseInOut]) { [weak self] in self?.selectedPhotoCollectionView.contentOffset.x = 1 } - for observation in observations { - - guard let topCandidate = observation.topCandidates(1).first else { - continue - } - - let recognizedText = topCandidate.string - - DispatchQueue.main.async { [weak self] in - self?.textView.text += recognizedText - } - } - - DispatchQueue.main.async { [weak self] in - self?.textView.text += "\n\n\n" - } - } - request.recognitionLevel = .accurate - request.recognitionLanguages = ["ko-KR"] - request.usesLanguageCorrection = true - - do { - try imageRequestHandler.perform([request]) - } catch let error { - Console.error(error.localizedDescription) } UserDefaults.standard.set(true, forKey: "ShowSwipeGuide") } @@ -299,18 +229,8 @@ final class SelectSentenceViewController: UIViewController, } } -// MARK: - UITextViewDelegate -extension SelectSentenceViewController: UITextViewDelegate { extension SelectSentenceViewController: SelectedPhotoCellListener { - func textViewDidChangeSelection(_ textView: UITextView) { - let selectedRange = textView.selectedRange - - if selectedRange.length > 0 { - addCustomMenuItem() - } else { - UIMenuController.shared.menuItems = nil - } } } @@ -361,7 +281,6 @@ private extension SelectSentenceViewController { $0.leading.equalToSuperview().offset(20) } - textView.snp.makeConstraints { selectedPhotoCollectionView.snp.makeConstraints { $0.top.equalTo(infoBox.snp.bottom) $0.leading.trailing.bottom.equalTo(view.safeAreaLayoutGuide) @@ -381,15 +300,3 @@ struct SelectSentenceViewController_Preview: PreviewProvider { } } #endif - - -final class CustomTextView: UITextView { - override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { - return false - } - - override func buildMenu(with builder: UIMenuBuilder) { - builder.remove(menu: .lookup) - super.buildMenu(with: builder) - } -} From 32e57b0474683dc39333f9d5c4fb5a327d22405d Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 22:34:16 +0900 Subject: [PATCH 09/13] =?UTF-8?q?feat=20:=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=93=9C=EB=9E=98=EA=B7=B8=20=ED=9B=84=20copy=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=ED=83=AD=EC=8B=9C=20EditSentence=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=EB=B7=B0=20=EC=84=A4=EC=A0=95=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 텍스트 드래그 시 나타나는 시스템 메뉴 수정 불가 - copy notification을 구독하여 copy 를 탭했을 때 EditSentence 모달을 띄우도록 설정 --- .../SelectSentence/SelectSentenceViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift index c976361..9bd4fb5 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceViewController.swift @@ -231,6 +231,8 @@ final class SelectSentenceViewController: UIViewController, extension SelectSentenceViewController: SelectedPhotoCellListener { + func copyButtonTapped(with text: String) { + listener?.showEditSentenceModal(with: text) } } From 29d41593a651f43658f96a7668f7c9c034d51320 Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 8 Aug 2023 22:35:23 +0900 Subject: [PATCH 10/13] =?UTF-8?q?feat=20:=20SelectSentence=20=EB=84=A4?= =?UTF-8?q?=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=EB=B0=94=20"=EB=8B=A4?= =?UTF-8?q?=EC=9D=8C"=20=EB=B2=84=ED=8A=BC=20=ED=83=AD=20=EC=95=A1?= =?UTF-8?q?=EC=85=98=20=EA=B5=AC=ED=98=84=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AddArticle/SelectSentence/SelectSentenceInteractor.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift index a0dff4d..b6b2584 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceInteractor.swift @@ -72,4 +72,8 @@ final class SelectSentenceInteractor: PresentableInteractor Date: Tue, 8 Aug 2023 22:37:28 +0900 Subject: [PATCH 11/13] =?UTF-8?q?refactor=20:=20=EA=B8=B0=ED=83=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EditSentence 모달이 띄워졌을 때 백그라운드 탭 임시 비활성화 - EditSentence 모달 Corner Radius 적용 - attachEditSentence() 중복요청 에러 방지용 조건문 추가 --- .../EditSentence/EditSentenceViewController.swift | 6 +++++- .../ModalStyle/EditSentencePresentationController.swift | 2 +- .../AddArticle/SelectSentence/SelectSentenceRouter.swift | 3 +++ .../SelectSentence/SelectSentenceViewController.swift | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift index f59f375..384e1b2 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceViewController.swift @@ -138,6 +138,7 @@ final class EditSentenceViewController: UIViewController, EditSentencePresentabl private func setupInitialView() { view.backgroundColor = .init(hex: 0x1F1F1F) + view.addRoundedCorner(corners: [.topLeft, .topRight], radius: 24) addSubviews() setConstraints() } @@ -256,7 +257,10 @@ import SwiftUI @available(iOS 13.0, *) struct EditSentenceViewController_Preview: PreviewProvider { static var previews: some View { - EditSentenceViewController(with: "테스트 문구").showPreview() + EditSentenceViewController( + with: "테스트 문구" + ) + .showPreview() } } #endif diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/ModalStyle/EditSentencePresentationController.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/ModalStyle/EditSentencePresentationController.swift index 9d9ed70..13c8c35 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/ModalStyle/EditSentencePresentationController.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/ModalStyle/EditSentencePresentationController.swift @@ -49,7 +49,7 @@ final class EditSentencePresentationController: UIPresentationController { guard let superview = presentingViewController.view else { return } superview.addSubview(dimmingView) setupDimmingViewLayout(in: superview) - adoptTapGestureRecognizer() +// adoptTapGestureRecognizer() // FIXME: dimmingView 탭시, 모달 dismiss 기능을 막아둠 dimmingView.alpha = 0 presentingViewController.transitionCoordinator?.animate( diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceRouter.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceRouter.swift index ff890d2..37bb389 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceRouter.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/SelectSentenceRouter.swift @@ -34,6 +34,9 @@ final class SelectSentenceRouter: ViewableRouter Date: Tue, 8 Aug 2023 22:37:44 +0900 Subject: [PATCH 12/13] =?UTF-8?q?refactor=20:=20project.pbxproj=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Particle/Particle.xcodeproj/project.pbxproj | 35 +++++++++++++-------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Particle/Particle.xcodeproj/project.pbxproj b/Particle/Particle.xcodeproj/project.pbxproj index a7f1a2d..b4a3741 100644 --- a/Particle/Particle.xcodeproj/project.pbxproj +++ b/Particle/Particle.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 55; + objectVersion = 56; objects = { /* Begin PBXBuildFile section */ @@ -38,6 +38,7 @@ 3520EF442A74DDA700A53B34 /* YdestreetB.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3520EF422A74DDA700A53B34 /* YdestreetB.otf */; }; 3520EF452A74DDA700A53B34 /* YdestreetL.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3520EF432A74DDA700A53B34 /* YdestreetL.otf */; }; 3520EF472A74DFBD00A53B34 /* UIFont+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3520EF462A74DFBD00A53B34 /* UIFont+.swift */; }; + AF0D09DB2A823001003EE03D /* UIView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0D09DA2A823001003EE03D /* UIView+.swift */; }; AF0D71C52A5BE6A200157758 /* AppComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0D71C42A5BE6A200157758 /* AppComponent.swift */; }; AF0D71CB2A5BE9B600157758 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0D71C72A5BE9B600157758 /* RootRouter.swift */; }; AF0D71CC2A5BE9B600157758 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0D71C82A5BE9B600157758 /* RootViewController.swift */; }; @@ -65,6 +66,7 @@ AF1D32B02A680CC700980F14 /* PhotoPickerInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1D32AC2A680CC700980F14 /* PhotoPickerInteractor.swift */; }; AF4A19112A6A1E4B00932372 /* PhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4A19102A6A1E4B00932372 /* PhotoCell.swift */; }; AF4A19132A6A59BB00932372 /* UIImageView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4A19122A6A59BA00932372 /* UIImageView+.swift */; }; + AF6059F92A75FEA600FE1565 /* SelectedPhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF6059F82A75FEA600FE1565 /* SelectedPhotoCell.swift */; }; AFB4BDC52A4093DC008BA9E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFB4BDC42A4093DC008BA9E0 /* AppDelegate.swift */; }; AFB4BDC72A4093DC008BA9E0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFB4BDC62A4093DC008BA9E0 /* SceneDelegate.swift */; }; AFB4BDCE2A4093DD008BA9E0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFB4BDCD2A4093DD008BA9E0 /* Assets.xcassets */; }; @@ -137,6 +139,7 @@ 3520EF422A74DDA700A53B34 /* YdestreetB.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = YdestreetB.otf; sourceTree = ""; }; 3520EF432A74DDA700A53B34 /* YdestreetL.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = YdestreetL.otf; sourceTree = ""; }; 3520EF462A74DFBD00A53B34 /* UIFont+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+.swift"; sourceTree = ""; }; + AF0D09DA2A823001003EE03D /* UIView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+.swift"; sourceTree = ""; }; AF0D71C42A5BE6A200157758 /* AppComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppComponent.swift; sourceTree = ""; }; AF0D71C72A5BE9B600157758 /* RootRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = ""; }; AF0D71C82A5BE9B600157758 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; @@ -164,6 +167,7 @@ AF1D32AC2A680CC700980F14 /* PhotoPickerInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerInteractor.swift; sourceTree = ""; }; AF4A19102A6A1E4B00932372 /* PhotoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoCell.swift; sourceTree = ""; }; AF4A19122A6A59BA00932372 /* UIImageView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+.swift"; sourceTree = ""; }; + AF6059F82A75FEA600FE1565 /* SelectedPhotoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedPhotoCell.swift; sourceTree = ""; }; AFB4BDC12A4093DC008BA9E0 /* Particle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Particle.app; sourceTree = BUILT_PRODUCTS_DIR; }; AFB4BDC42A4093DC008BA9E0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; AFB4BDC62A4093DC008BA9E0 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -278,13 +282,6 @@ path = Utils; sourceTree = ""; }; - 3520EF242A5FB7E400A53B34 /* AddArticleNavigation */ = { - isa = PBXGroup; - children = ( - ); - path = AddArticleNavigation; - sourceTree = ""; - }; 3520EF272A74DADE00A53B34 /* Fonts */ = { isa = PBXGroup; children = ( @@ -423,6 +420,14 @@ path = View; sourceTree = ""; }; + AF6059F72A75FE9100FE1565 /* View */ = { + isa = PBXGroup; + children = ( + AF6059F82A75FEA600FE1565 /* SelectedPhotoCell.swift */, + ); + path = View; + sourceTree = ""; + }; AF86D82C2A4E6030009F1E9D /* Entry */ = { isa = PBXGroup; children = ( @@ -526,6 +531,7 @@ AFBB5F6E2A66B60D002416DA /* SelectSentence */ = { isa = PBXGroup; children = ( + AF6059F72A75FE9100FE1565 /* View */, AFBB5F702A66B65D002416DA /* SelectSentenceRouter.swift */, AFBB5F712A66B65D002416DA /* SelectSentenceViewController.swift */, AFBB5F722A66B65D002416DA /* SelectSentenceBuilder.swift */, @@ -555,6 +561,7 @@ 3520EF462A74DFBD00A53B34 /* UIFont+.swift */, AFBB5F6C2A66B5C1002416DA /* UIViewController+.swift */, AF4A19122A6A59BA00932372 /* UIImageView+.swift */, + AF0D09DA2A823001003EE03D /* UIView+.swift */, ); path = Extension; sourceTree = ""; @@ -597,7 +604,7 @@ }; }; buildConfigurationList = AFB4BDBC2A4093DC008BA9E0 /* Build configuration list for PBXProject "Particle" */; - compatibilityVersion = "Xcode 13.0"; + compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -714,6 +721,7 @@ AFBB5F772A66B65D002416DA /* SelectSentenceInteractor.swift in Sources */, 3520EF192A5E91A900A53B34 /* SetAdditionalInformationInteractor.swift in Sources */, AF1945172A5C407500B9FFA1 /* Constant.swift in Sources */, + AF6059F92A75FEA600FE1565 /* SelectedPhotoCell.swift in Sources */, AF4A19112A6A1E4B00932372 /* PhotoCell.swift in Sources */, AF0D71DA2A5BEEAD00157758 /* RootComponent+LoggedOut.swift in Sources */, AFBB5F752A66B65D002416DA /* SelectSentenceViewController.swift in Sources */, @@ -743,6 +751,7 @@ 3520EF082A5E8F3400A53B34 /* UIImage+ParticleImage.swift in Sources */, AFBD9BC52A715FBC0076A404 /* UIColor+ParticleColor.swift in Sources */, AFB4BDC52A4093DC008BA9E0 /* AppDelegate.swift in Sources */, + AF0D09DB2A823001003EE03D /* UIView+.swift in Sources */, 3520EF042A5E6F9C00A53B34 /* OrganizingSentenceRepository.swift in Sources */, AF0D71CE2A5BE9B600157758 /* RootInteractor.swift in Sources */, 3520EEF52A5CD3C000A53B34 /* OrganizingSentenceInteractor.swift in Sources */, @@ -831,7 +840,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -885,7 +894,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -911,7 +920,7 @@ INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleLightContent; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -941,7 +950,7 @@ INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleLightContent; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", From 06c1c3fa0c1dac1769e15b282fdb421706ed3113 Mon Sep 17 00:00:00 2001 From: wongbingg Date: Tue, 22 Aug 2023 20:40:34 +0900 Subject: [PATCH 13/13] =?UTF-8?q?fix=20:=20=EB=AC=B8=EC=9E=A5=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C=20=ED=9B=84=20=EC=A0=80=EC=9E=A5=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=ED=83=AD=EC=8B=9C=20=EB=8B=A4=EC=9D=8C=20=EC=82=AC=EC=A7=84?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9E=90=EB=8F=99=20=EC=8A=A4=EC=99=80?= =?UTF-8?q?=EC=9D=B4=ED=94=84=20#7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 마지막 사진에서 문장 추출 후 저장버튼 탭시, 다음 버튼 활성화 --- .../EditSentence/EditSentenceInteractor.swift | 3 ++- .../SelectSentenceInteractor.swift | 19 ++++++++++++++----- .../SelectSentenceViewController.swift | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift index 9b1256a..a43fe6a 100644 --- a/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift +++ b/Particle/Particle/Main/HomeTab/AddArticle/SelectSentence/EditSentence/EditSentenceInteractor.swift @@ -18,8 +18,8 @@ protocol EditSentencePresentable: Presentable { } protocol EditSentenceListener: AnyObject { - // TODO: Declare methods the interactor can invoke to communicate with other RIBs. func dismissEditSentence(with text: String) + func swipeToNextPhoto() } final class EditSentenceInteractor: PresentableInteractor, @@ -50,5 +50,6 @@ final class EditSentenceInteractor: PresentableInteractor