From e838a1c7a012995b3fbe0820d6b158c924912566 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Sun, 28 May 2023 22:12:40 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[Fix]=20#155=20-=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseStorage/VC/CourseStorageVC.swift | 59 ++++++++++++------- .../PrivateCourseListView.swift | 16 +++-- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift index 18781140..de412c4d 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift @@ -35,7 +35,6 @@ final class CourseStorageVC: UIViewController { .addPagedView(pagedView: [privateCourseListView, scrapCourseListView]) private var deleteCourseButton = CustomButton(title: "삭제하기").then { - $0.isHidden = true $0.isEnabled = false } @@ -49,6 +48,7 @@ final class CourseStorageVC: UIViewController { self.setDelegate() self.setDeleteButton() } + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) guard UserManager.shared.userType != .visitor else { return } @@ -63,7 +63,6 @@ extension CourseStorageVC { private func setPrivateCourseData(courseList: [PrivateCourse]) { self.privateCourseList = courseList self.privateCourseListView.setData(courseList: courseList) - self.deleteCourseButton.isHidden = true self.hideTabBar(wantsToHide: false) } @@ -111,27 +110,37 @@ extension CourseStorageVC { privateCourseListView.delegate = self } - private func showHiddenViews(withDuration: TimeInterval = 0) { + private func hideTabBarWithAnimation() { if let frame = tabBarController?.tabBar.frame { - let factor: CGFloat = -1 + let factor: CGFloat = 1 let y = frame.origin.y + (frame.size.height * factor) UIView.animate(withDuration: 0.7, animations: { self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: frame.height) }) } - UIView.animate(withDuration: withDuration) { - self.deleteCourseButton.transform = CGAffineTransform(translationX: 0, y: 34) - } } - private func hideHiddenViews(withDuration: TimeInterval = 0) { + private func showTabBarWithAnimation() { if let frame = tabBarController?.tabBar.frame { - let factor: CGFloat = 1 + let factor: CGFloat = -1 let y = frame.origin.y + (frame.size.height * factor) UIView.animate(withDuration: 0.7, animations: { self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: frame.height) }) } + } + + private func finishEditMode(withDuration: TimeInterval = 0) { + showTabBarWithAnimation() + + UIView.animate(withDuration: withDuration) { + self.deleteCourseButton.transform = CGAffineTransform(translationX: 0, y: 34) + } + } + + private func startEditMode(withDuration: TimeInterval = 0) { + hideTabBarWithAnimation() + view.bringSubviewToFront(deleteCourseButton) UIView.animate(withDuration: withDuration) { self.deleteCourseButton.transform = CGAffineTransform(translationX: 0, y: -34) @@ -143,18 +152,24 @@ extension CourseStorageVC { extension CourseStorageVC { @objc func deleteCourseButtonDidTap(_sender: UIButton) { - guard let selectedList = privateCourseListView.courseListCollectionView.indexPathsForSelectedItems else { return } + guard let selectedList = privateCourseListView.courseListCollectionView.indexPathsForSelectedItems else { + return + } + var deleteToCourseId = [Int]() + for indexPath in selectedList { - let publicCourse = privateCourseList[indexPath.item] - deleteToCourseId.append(publicCourse.id) + let privateCourse = privateCourseList[indexPath.item] + deleteToCourseId.append(privateCourse.id) } + let deleteAlertVC = RNAlertVC(description: "삭제하시겠습니까?") deleteAlertVC.modalPresentationStyle = .overFullScreen deleteAlertVC.rightButtonTapAction = { deleteAlertVC.dismiss(animated: false) self.deleteCourse(courseIdList: deleteToCourseId) } + self.present(deleteAlertVC, animated: false) } } @@ -165,6 +180,7 @@ extension CourseStorageVC { private func setUI() { view.backgroundColor = .w1 } + private func setLayout() { view.addSubviews(naviBar) @@ -184,8 +200,9 @@ extension CourseStorageVC { make.top.equalTo(naviBar.snp.bottom) make.leading.bottom.trailing.equalTo(view.safeAreaLayoutGuide) } + deleteCourseButton.snp.makeConstraints { make in - make.bottom.equalToSuperview().inset(34) + make.top.equalTo(view.safeAreaLayoutGuide.snp.bottom) make.leading.trailing.equalToSuperview().inset(16) make.height.equalTo(44) } @@ -205,18 +222,16 @@ extension CourseStorageVC: ScrapCourseListViewDelegate { extension CourseStorageVC: PrivateCourseListViewDelegate { func courseListEditButtonTapped() { - if privateCourseListView.isEditMode == false { - self.deleteCourseButton.isHidden = false - self.deleteCourseButton.isEnabled = false + if privateCourseListView.isEditMode == true { self.deleteCourseButton.setTitle(title: "삭제하기") - hideHiddenViews(withDuration: 0.7) + startEditMode(withDuration: 0.7) } - if privateCourseListView.isEditMode == true { - self.hideTabBar(wantsToHide: false) - self.deleteCourseButton.isHidden = false - showHiddenViews(withDuration: 0.7) + + if privateCourseListView.isEditMode == false { + finishEditMode(withDuration: 0.7) } } + func selectCellDidTapped() { guard let selectedCells = privateCourseListView.courseListCollectionView.indexPathsForSelectedItems else { return } let countSelectCells = selectedCells.count @@ -326,7 +341,7 @@ extension CourseStorageVC { if 200..<300 ~= status { print("삭제 성공") self.getPrivateCourseList() - self.showHiddenViews(withDuration: 0.7) + self.finishEditMode(withDuration: 0.7) } if status >= 400 { diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift index 739ecfd3..53e0cd6b 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift @@ -114,19 +114,17 @@ extension PrivateCourseListView { extension PrivateCourseListView { @objc func editButtonDidTap() { + isEditMode.toggle() + if isEditMode { - self.totalNumOfRecordlabel.text = "총 코스 \(self.courseList.count)개" - self.editButton.setTitle("편집", for: .normal) - self.delegate?.courseListEditButtonTapped() - self.courseListCollectionView.reloadData() - isEditMode = false - } else { self.totalNumOfRecordlabel.text = "코스 선택" - self.delegate?.courseListEditButtonTapped() self.editButton.setTitle("취소", for: .normal) - self.courseListCollectionView.reloadData() - isEditMode = true + } else { + self.totalNumOfRecordlabel.text = "총 코스 \(self.courseList.count)개" + self.editButton.setTitle("편집", for: .normal) } + + self.delegate?.courseListEditButtonTapped() } } // MARK: - UI & Layout From c488f4428f5a9a3bee1d5e8c47446baf32d78b3a Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Sun, 28 May 2023 22:38:47 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[Fix]=20#155=20-=20=ED=8E=B8=EC=A7=91=20?= =?UTF-8?q?=EC=8B=9C=EC=9E=91=20=EB=B0=8F=20=EC=B7=A8=EC=86=8C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseStorage/VC/CourseStorageVC.swift | 26 +++------- .../PrivateCourseListView.swift | 52 +++++++++++-------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift index de412c4d..5f2e7e26 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift @@ -132,6 +132,8 @@ extension CourseStorageVC { private func finishEditMode(withDuration: TimeInterval = 0) { showTabBarWithAnimation() + self.deleteCourseButton.setEnabled(false) + self.deleteCourseButton.setTitle(title: "삭제하기") UIView.animate(withDuration: withDuration) { self.deleteCourseButton.transform = CGAffineTransform(translationX: 0, y: 34) @@ -222,31 +224,19 @@ extension CourseStorageVC: ScrapCourseListViewDelegate { extension CourseStorageVC: PrivateCourseListViewDelegate { func courseListEditButtonTapped() { - if privateCourseListView.isEditMode == true { - self.deleteCourseButton.setTitle(title: "삭제하기") - startEditMode(withDuration: 0.7) - } - - if privateCourseListView.isEditMode == false { - finishEditMode(withDuration: 0.7) - } + privateCourseListView.isEditMode ? startEditMode(withDuration: 0.7) : finishEditMode(withDuration: 0.7) } func selectCellDidTapped() { guard let selectedCells = privateCourseListView.courseListCollectionView.indexPathsForSelectedItems else { return } + let countSelectCells = selectedCells.count + if privateCourseListView.isEditMode == true { - if privateCourseListView.isEditMode == false { - self.deleteCourseButton.isEnabled = false - self.deleteCourseButton.setTitle(title: "삭제하기") - } self.deleteCourseButton.setTitle(title: "삭제하기(\(countSelectCells))") - self.deleteCourseButton.isEnabled = false - self.deleteCourseButton.setEnabled(true) - } - if selectedCells.count == 0 { - self.deleteCourseButton.isEnabled = false } + + self.deleteCourseButton.setEnabled(countSelectCells != 0) } } // MARK: - Network @@ -334,6 +324,7 @@ extension CourseStorageVC { courseProvider.request(.deleteCourse(courseIdList: courseIdList)) { [weak self] response in LoadingIndicator.hideLoading() guard let self = self else { return } + self.privateCourseListView.isEditMode = false switch response { case .success(let result): print("리절트", result) @@ -342,7 +333,6 @@ extension CourseStorageVC { print("삭제 성공") self.getPrivateCourseList() self.finishEditMode(withDuration: 0.7) - } if status >= 400 { print("400 error") diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift index 53e0cd6b..1e91cc37 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift @@ -27,7 +27,11 @@ final class PrivateCourseListView: UIView { weak var courseStorageVC: UIViewController? - var isEditMode: Bool = false + var isEditMode: Bool = false { + didSet { + isEditMode ? startEditMode() : finishEditMode() + } + } final let collectionViewInset = UIEdgeInsets(top: 28, left: 16, bottom: 28, right: 16) final let itemSpacing: CGFloat = 10 @@ -116,17 +120,26 @@ extension PrivateCourseListView { @objc func editButtonDidTap() { isEditMode.toggle() - if isEditMode { - self.totalNumOfRecordlabel.text = "코스 선택" - self.editButton.setTitle("취소", for: .normal) - } else { - self.totalNumOfRecordlabel.text = "총 코스 \(self.courseList.count)개" - self.editButton.setTitle("편집", for: .normal) - } - self.delegate?.courseListEditButtonTapped() } + + private func startEditMode() { + self.totalNumOfRecordlabel.text = "코스 선택" + self.editButton.setTitle("취소", for: .normal) + } + + private func finishEditMode() { + self.totalNumOfRecordlabel.text = "총 코스 \(self.courseList.count)개" + self.editButton.setTitle("편집", for: .normal) + self.deselectAllItems() + } + + private func deselectAllItems() { + guard let selectedItems = courseListCollectionView.indexPathsForSelectedItems else { return } + for indexPath in selectedItems { courseListCollectionView.deselectItem(at: indexPath, animated: false) } + } } + // MARK: - UI & Layout extension PrivateCourseListView { @@ -187,16 +200,14 @@ extension PrivateCourseListView: UICollectionViewDelegate, UICollectionViewDataS } else { cell.selectCell(didSelect: false) } - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CourseListCVC.className, for: indexPath) - as? CourseListCVC else { return UICollectionViewCell() } - cell.setCellType(type: .title) + let model = courseList[indexPath.item] let cellTitle = "\(model.departure.region) \(model.departure.city)" cell.setData(imageURL: model.image, title: cellTitle, location: nil, didLike: nil) return cell } + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard collectionView.cellForItem(at: indexPath) is CourseListCVC else { return } guard let cell = collectionView.cellForItem(at: indexPath) as? CourseListCVC else { return } if isEditMode { cell.selectCell(didSelect: true) @@ -204,22 +215,21 @@ extension PrivateCourseListView: UICollectionViewDelegate, UICollectionViewDataS } else { collectionView.deselectItem(at: indexPath, animated: true) cellDidTapped.send(indexPath.item) - delegate?.selectCellDidTapped() } } + func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { - guard collectionView.cellForItem(at: indexPath) is CourseListCVC else { return } guard let selectedCells = collectionView.indexPathsForSelectedItems else { - return } + return + } + guard let cell = collectionView.cellForItem(at: indexPath) as? CourseListCVC else { return } + if isEditMode { - let countSelectCells = selectedCells.count - delegate?.selectCellDidTapped() cell.selectCell(didSelect: false) - } else { - collectionView.deselectItem(at: indexPath, animated: true) - delegate?.selectCellDidTapped() } + + delegate?.selectCellDidTapped() } } // MARK: - UICollectionViewDelegateFlowLayout From 3b5a7eaca77e8bc21b89c0e5b0456f6c86f11c11 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Sun, 28 May 2023 23:01:53 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[Fix]=20#155=20-=20=EB=B3=B4=EA=B4=80?= =?UTF-8?q?=ED=95=A8=20=EB=B7=B0=EC=97=90=EC=84=9C=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EB=B7=B0=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20=EC=8B=9C=20=ED=83=AD?= =?UTF-8?q?=EB=B0=94=20UI=EC=9C=84=EC=B9=98=EA=B0=80=20=EC=83=81=EC=8A=B9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseStorage/VC/CourseStorageVC.swift | 32 +++++++++++++++---- .../PrivateCourseListView.swift | 1 + 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift index 5f2e7e26..d7d44348 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift @@ -55,6 +55,14 @@ final class CourseStorageVC: UIViewController { self.getPrivateCourseList() self.getScrapCourseList() } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + if privateCourseListView.isEditMode { + self.finishEditMode(withDuration: 0) + } + } } // MARK: - Methods @@ -76,6 +84,12 @@ extension CourseStorageVC { } private func bindUI() { + viewPager.$selectedTabIndex.sink { [weak self] selectedTabIndex in + guard let self = self else { return } + print(selectedTabIndex) + self.deleteCourseButton.isHidden = (selectedTabIndex != 0) + }.store(in: cancelBag) + privateCourseListView.courseDrawButtonTapped.sink { [weak self] in guard let self = self else { return } self.tabBarController?.selectedIndex = 0 @@ -110,28 +124,30 @@ extension CourseStorageVC { privateCourseListView.delegate = self } - private func hideTabBarWithAnimation() { + private func hideTabBarWithAnimation(duration: TimeInterval = 0.7) { if let frame = tabBarController?.tabBar.frame { let factor: CGFloat = 1 let y = frame.origin.y + (frame.size.height * factor) - UIView.animate(withDuration: 0.7, animations: { + UIView.animate(withDuration: duration, animations: { self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: frame.height) }) } } - private func showTabBarWithAnimation() { + private func showTabBarWithAnimation(duration: TimeInterval = 0.7) { if let frame = tabBarController?.tabBar.frame { let factor: CGFloat = -1 let y = frame.origin.y + (frame.size.height * factor) - UIView.animate(withDuration: 0.7, animations: { + UIView.animate(withDuration: duration, animations: { self.tabBarController?.tabBar.frame = CGRect(x: frame.origin.x, y: y, width: frame.width, height: frame.height) }) } } private func finishEditMode(withDuration: TimeInterval = 0) { - showTabBarWithAnimation() + self.privateCourseListView.isEditMode = false + + showTabBarWithAnimation(duration: withDuration) self.deleteCourseButton.setEnabled(false) self.deleteCourseButton.setTitle(title: "삭제하기") @@ -141,7 +157,9 @@ extension CourseStorageVC { } private func startEditMode(withDuration: TimeInterval = 0) { - hideTabBarWithAnimation() + self.privateCourseListView.isEditMode = true + + hideTabBarWithAnimation(duration: withDuration) view.bringSubviewToFront(deleteCourseButton) UIView.animate(withDuration: withDuration) { @@ -239,7 +257,9 @@ extension CourseStorageVC: PrivateCourseListViewDelegate { self.deleteCourseButton.setEnabled(countSelectCells != 0) } } + // MARK: - Network + extension CourseStorageVC { private func getPrivateCourseList() { LoadingIndicator.showLoading() diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift index 1e91cc37..28bc7694 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CourseListView/PrivateCourseListView.swift @@ -232,6 +232,7 @@ extension PrivateCourseListView: UICollectionViewDelegate, UICollectionViewDataS delegate?.selectCellDidTapped() } } + // MARK: - UICollectionViewDelegateFlowLayout extension PrivateCourseListView: UICollectionViewDelegateFlowLayout {