diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index 19e71b4c..b5111d68 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -1600,11 +1600,12 @@ CODE_SIGN_ENTITLEMENTS = "Runnect-iOS/Runnect-iOS.entitlements"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 23051501; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9K86FQHDLU; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Runnect-iOS/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = Runnect; INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "위치 정보 권한이 필요합니다."; INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "위치 정보 권한이 필요합니다."; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "위치 정보 권한이 필요합니다."; @@ -1637,11 +1638,12 @@ CODE_SIGN_ENTITLEMENTS = "Runnect-iOS/Runnect-iOS.entitlements"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 23051501; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9K86FQHDLU; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Runnect-iOS/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = Runnect; INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "위치 정보 권한이 필요합니다."; INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "위치 정보 권한이 필요합니다."; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "위치 정보 권한이 필요합니다."; diff --git a/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIViewController+.swift b/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIViewController+.swift index e1174385..a61a029b 100644 --- a/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIViewController+.swift +++ b/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIViewController+.swift @@ -29,4 +29,59 @@ extension UIViewController { func hideTabBar(wantsToHide: Bool) { self.tabBarController?.tabBar.isHidden = wantsToHide } + + /// 인증 과정을 다시 거치도록 SplashVC로 보내기 + func showSplashVC() { + let splashVC = SplashVC() + let navigationController = UINavigationController(rootViewController: splashVC) + guard let window = self.view.window else { return } + ViewControllerUtils.setRootViewController(window: window, viewController: navigationController, withAnimation: true) + } + + func presentSignInRequestAlertVC() { + let alertVC = CustomAlertVC() + .setTitle("가입 후 로그인 시 코스를 저장하고 달릴 수 있어요!") + .setLeftButtonTitle(NSAttributedString(string: "닫기", attributes: [.font: UIFont.h5, .foregroundColor: UIColor.m1])) + .setRightButtonTitle(NSAttributedString(string: "가입하기", attributes: [.font: UIFont.h5, .foregroundColor: UIColor.w1])) + alertVC.modalPresentationStyle = .overFullScreen + + alertVC.leftButtonTapAction = { + alertVC.dismiss(animated: false) + } + + alertVC.rightButtonTapAction = { + self.showSplashVC() + } + + self.present(alertVC, animated: false) + alertVC.setImage(ImageLiterals.imgSpaceship, size: CGSize(width: 229, height: 136)) + } + + func handleVisitor() -> Bool { + guard UserManager.shared.userType == .visitor else { return true } + self.presentSignInRequestAlertVC() + return false + } + + func showSignInRequestEmptyView() { + let emptyView = ListEmptyView(description: "러넥트에 가입하면 내가 그린 코스와\n 스크랩 코스를 관리할 수 있어요!", + buttonTitle: "가입하기") + emptyView.buttonTapAction = { + self.showSplashVC() + } + + emptyView.setImage(ImageLiterals.imgSpaceship, size: CGSize(width: 229, height: 136)) + + self.view.addSubview(emptyView) + + emptyView.snp.makeConstraints { make in + make.center.equalTo(view.safeAreaLayoutGuide) + make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(80) + } + } + + func showToastOnWindow(text: String) { + let window = self.view.window! + Toast.show(message: text, view: window, safeAreaBottomInset: self.safeAreaBottomInset()) + } } diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91.png b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91.png new file mode 100644 index 00000000..39f63fd3 Binary files /dev/null and b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91.png differ diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91@2x.png b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91@2x.png new file mode 100644 index 00000000..24eb62c5 Binary files /dev/null and b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91@2x.png differ diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91@3x.png b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91@3x.png new file mode 100644 index 00000000..dbaeacc5 Binary files /dev/null and b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Component 91@3x.png differ diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Contents.json b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Contents.json index e38bc455..b31bb323 100644 --- a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Contents.json +++ b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "Property 1=Component 77, Property 2=btn_heart2.png", + "filename" : "Component 91.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Property 1=Component 77, Property 2=btn_heart2@2x.png", + "filename" : "Component 91@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Property 1=Component 77, Property 2=btn_heart2@3x.png", + "filename" : "Component 91@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2.png b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2.png deleted file mode 100644 index b244240c..00000000 Binary files a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2.png and /dev/null differ diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2@2x.png b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2@2x.png deleted file mode 100644 index 1701a2fe..00000000 Binary files a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2@2x.png and /dev/null differ diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2@3x.png b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2@3x.png deleted file mode 100644 index 9107b153..00000000 Binary files a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/ic_heart.imageset/Property 1=Component 77, Property 2=btn_heart2@3x.png and /dev/null differ diff --git a/Runnect-iOS/Runnect-iOS/Global/Supports/SceneDelegate.swift b/Runnect-iOS/Runnect-iOS/Global/Supports/SceneDelegate.swift index f2baba80..5f92b293 100644 --- a/Runnect-iOS/Runnect-iOS/Global/Supports/SceneDelegate.swift +++ b/Runnect-iOS/Runnect-iOS/Global/Supports/SceneDelegate.swift @@ -6,6 +6,8 @@ // import UIKit +import KakaoSDKAuth +import KakaoSDKCommon class SceneDelegate: UIResponder, UIWindowSceneDelegate { @@ -21,6 +23,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { self.window = window window.makeKeyAndVisible() } + + func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { + if let url = URLContexts.first?.url { + if (AuthApi.isKakaoTalkLoginUrl(url)) { + _ = AuthController.handleOpenUrl(url: url) + } + } + } func sceneDidDisconnect(_ scene: UIScene) { // Called as the scene is being released by the system. diff --git a/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomAlertVC.swift b/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomAlertVC.swift index 96ff2f46..4fd70b1d 100644 --- a/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomAlertVC.swift +++ b/Runnect-iOS/Runnect-iOS/Global/UIComponents/CustomAlertVC.swift @@ -24,17 +24,23 @@ final class CustomAlertVC: UIViewController { .asDriver() } + var leftButtonTapAction: (() -> Void)? + var rightButtonTapAction: (() -> Void)? + + private var cancelBag = CancelBag() + // MARK: - UI Components private let alertView = UIView() private let alertImageView = UIImageView().then { $0.image = ImageLiterals.imgPaper } - private let contentsLabel = UILabel().then { - $0.text = "코스를 만들었어요!" + private let contentsLabel: UILabel = UILabel().then { + $0.text = "코스를 만들었어요!\n지정한 코스는 보관함에서 볼 수 있어요." $0.font = .h5 $0.textColor = .g2 $0.textAlignment = .center + $0.numberOfLines = 2 } private let leftButton = CustomButton(title: "보관함 가기") @@ -54,12 +60,22 @@ final class CustomAlertVC: UIViewController { super.viewDidLoad() self.setUI() self.setLayout() + self.bindViews() } } // MARK: - Methods extension CustomAlertVC { + /// 이미지 변경 + public func setImage(_ image: UIImage, size: CGSize) { + self.alertImageView.image = image + self.alertImageView.snp.updateConstraints { make in + make.width.equalTo(size.width) + make.height.equalTo(size.height) + } + } + /// conentsLabel의 텍스트 변경 @discardableResult public func setTitle(_ title: String) -> Self { @@ -80,6 +96,16 @@ extension CustomAlertVC { self.rightButton.changeTitle(attributedString: title) return self } + + private func bindViews() { + self.leftButtonTapped.sink { _ in + self.leftButtonTapAction?() + }.store(in: cancelBag) + + self.rightButtonTapped.sink { _ in + self.rightButtonTapAction?() + }.store(in: cancelBag) + } } // MARK: - UI & Layout @@ -109,6 +135,7 @@ extension CustomAlertVC { contentsLabel.snp.makeConstraints { make in make.top.equalTo(alertImageView.snp.bottom).offset(24) + make.leading.trailing.equalToSuperview().inset(10) make.centerX.equalToSuperview() } diff --git a/Runnect-iOS/Runnect-iOS/Global/UIComponents/ListEmptyView.swift b/Runnect-iOS/Runnect-iOS/Global/UIComponents/ListEmptyView.swift index d6a039d5..82347cad 100644 --- a/Runnect-iOS/Runnect-iOS/Global/UIComponents/ListEmptyView.swift +++ b/Runnect-iOS/Runnect-iOS/Global/UIComponents/ListEmptyView.swift @@ -17,6 +17,8 @@ final class ListEmptyView: UIView { weak var delegate: ListEmptyViewDelegate? + var buttonTapAction: (() -> Void)? + // MARK: - UI Components private let mainImageView = UIImageView().then { @@ -61,6 +63,14 @@ extension ListEmptyView { private func setAddTarget() { bottomButton.addTarget(self, action: #selector(bottomButtonDidTap), for: .touchUpInside) } + + public func setImage(_ image: UIImage, size: CGSize) { + self.mainImageView.image = image + self.mainImageView.snp.updateConstraints { make in + make.width.equalTo(size.width) + make.height.equalTo(size.height) + } + } } // MARK: - @objc Function @@ -68,6 +78,7 @@ extension ListEmptyView { extension ListEmptyView { @objc private func bottomButtonDidTap() { delegate?.emptyViewButtonTapped() + self.buttonTapAction?() } } diff --git a/Runnect-iOS/Runnect-iOS/Global/Utils/RNUtils/UserManager.swift b/Runnect-iOS/Runnect-iOS/Global/Utils/RNUtils/UserManager.swift index 604ce2c2..50305d6f 100644 --- a/Runnect-iOS/Runnect-iOS/Global/Utils/RNUtils/UserManager.swift +++ b/Runnect-iOS/Runnect-iOS/Global/Utils/RNUtils/UserManager.swift @@ -14,6 +14,11 @@ enum RNError: Error { case etc } +enum UserType { + case visitor + case registered +} + final class UserManager { static let shared = UserManager() @@ -23,6 +28,7 @@ final class UserManager { @UserDefaultWrapper(key: "refreshToken") public var refreshToken @UserDefaultWrapper(key: "isKakao") public var isKakao var hasAccessToken: Bool { return self.accessToken != nil } + var userType: UserType = .registered private init() {} @@ -45,6 +51,7 @@ final class UserManager { self.accessToken = data.accessToken self.refreshToken = data.refreshToken self.isKakao = provider == "KAKAO" ? true : false + UserManager.shared.userType = .registered completion(.success(data.type)) // 로그인인지 회원가입인지 전달 } catch { print(error.localizedDescription) diff --git a/Runnect-iOS/Runnect-iOS/Global/Utils/Toast.swift b/Runnect-iOS/Runnect-iOS/Global/Utils/Toast.swift index 1bed8bfa..d2b8dbc6 100644 --- a/Runnect-iOS/Runnect-iOS/Global/Utils/Toast.swift +++ b/Runnect-iOS/Runnect-iOS/Global/Utils/Toast.swift @@ -25,13 +25,14 @@ public class Toast { let toastContainer = UIView() let toastLabel = UILabel() - toastContainer.backgroundColor = .lightGray - toastContainer.alpha = 1 - toastContainer.layer.cornerRadius = 9 + toastContainer.backgroundColor = UIColor.g2.withAlphaComponent(0.7) + toastContainer.alpha = 1.0 + toastContainer.layer.cornerRadius = 15 toastContainer.clipsToBounds = true toastContainer.isUserInteractionEnabled = false - toastLabel.textColor = .white + toastLabel.textColor = .m4 + toastLabel.font = .b4 toastLabel.textAlignment = .center toastLabel.text = message toastLabel.clipsToBounds = true @@ -41,21 +42,23 @@ public class Toast { toastContainer.addSubview(toastLabel) view.addSubview(toastContainer) + let toastConatinerWidth = toastLabel.intrinsicContentSize.width + 40.0 + toastContainer.snp.makeConstraints { $0.centerX.equalToSuperview() - $0.bottom.equalToSuperview().inset(safeAreaBottomInset+80) - $0.width.equalTo(200) - $0.height.equalTo(44) + $0.bottom.equalToSuperview().inset(safeAreaBottomInset+160) + $0.width.equalTo(toastConatinerWidth) + $0.height.equalTo(31) } toastLabel.snp.makeConstraints { $0.center.equalToSuperview() } - UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveEaseIn, animations: { + UIView.animate(withDuration: 1.0, delay: 0.0, options: .curveEaseIn, animations: { toastContainer.alpha = 1.0 }, completion: { _ in - UIView.animate(withDuration: 0.4, delay: 1.0, options: .curveEaseOut, animations: { + UIView.animate(withDuration: 1.0, delay: 2.0, options: .curveEaseOut, animations: { toastContainer.alpha = 0.0 }, completion: {_ in toastContainer.removeFromSuperview() diff --git a/Runnect-iOS/Runnect-iOS/Network/Service/AuthInterceptor.swift b/Runnect-iOS/Runnect-iOS/Network/Service/AuthInterceptor.swift index 8470cc98..41be8ff1 100644 --- a/Runnect-iOS/Runnect-iOS/Network/Service/AuthInterceptor.swift +++ b/Runnect-iOS/Runnect-iOS/Network/Service/AuthInterceptor.swift @@ -18,6 +18,16 @@ final class AuthInterceptor: RequestInterceptor { private init() {} func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result) -> Void) { + var urlRequest = urlRequest + + // 방문자일 경우 + if UserManager.shared.userType == .visitor && urlRequest.url?.absoluteString.hasPrefix(Config.baseURL) == true { + urlRequest.setValue("visitor", forHTTPHeaderField: "accessToken") + urlRequest.setValue("null", forHTTPHeaderField: "refreshToken") + completion(.success(urlRequest)) + return + } + guard urlRequest.url?.absoluteString.hasPrefix(Config.baseURL) == true, let accessToken = UserManager.shared.accessToken, let refreshToken = UserManager.shared.refreshToken @@ -26,7 +36,6 @@ final class AuthInterceptor: RequestInterceptor { return } - var urlRequest = urlRequest urlRequest.setValue(accessToken, forHTTPHeaderField: "accessToken") urlRequest.setValue(refreshToken, forHTTPHeaderField: "refreshToken") print("adator 적용 \(urlRequest.headers)") @@ -38,6 +47,7 @@ final class AuthInterceptor: RequestInterceptor { guard let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401, let pathComponents = request.request?.url?.pathComponents, !pathComponents.contains("getNewToken") else { + dump(error) completion(.doNotRetryWithError(error)) return } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift index 7f582e02..616a3ecf 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift @@ -121,6 +121,11 @@ final class CourseDetailVC: UIViewController { extension CourseDetailVC { @objc func likeButtonDidTap(_ sender: UIButton) { + guard UserManager.shared.userType != .visitor else { + showToastOnWindow(text: "러넥트에 가입하면 코스를 스크랩할 수 있어요") + return + } + scrapCourse(scrapTF: !sender.isSelected) } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift index f4856ab5..eeac343b 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift @@ -100,7 +100,13 @@ extension CourseDiscoveryVC { let nextVC = CourseSearchVC() self.navigationController?.pushViewController(nextVC, animated: true) } + @objc private func pushToDiscoveryVC() { + guard UserManager.shared.userType != .visitor else { + self.showToastOnWindow(text: "러넥트에 가입하면 코스를 업로드할 수 있어요.") + return + } + let nextVC = MyCourseSelectVC() self.navigationController?.pushViewController(nextVC, animated: true) } @@ -242,6 +248,11 @@ extension CourseDiscoveryVC: UICollectionViewDelegateFlowLayout { extension CourseDiscoveryVC: CourseListCVCDeleagte { func likeButtonTapped(wantsTolike: Bool, index: Int) { + guard UserManager.shared.userType != .visitor else { + showToastOnWindow(text: "러넥트에 가입하면 코스를 스크랩할 수 있어요") + return + } + let publicCourseId = courseList[index].id scrapCourse(publicCourseId: publicCourseId, scrapTF: wantsTolike) } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift index 5d3d7fa4..1e5f66b9 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift @@ -204,6 +204,11 @@ extension CourseSearchVC: CustomNavigationBarDelegate { extension CourseSearchVC: CourseListCVCDeleagte { func likeButtonTapped(wantsTolike: Bool, index: Int) { + guard UserManager.shared.userType != .visitor else { + showToastOnWindow(text: "러넥트에 가입하면 코스를 스크랩할 수 있어요") + return + } + let pubilcCourseId = courseList[index].id scrapCourse(publicCourseId: pubilcCourseId, scrapTF: wantsTolike) } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift index a6e2456c..2f1d6cb9 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift @@ -38,7 +38,7 @@ final class CourseDrawingVC: UIViewController { $0.alpha = 0 } - private let guideView = GuideView(title: "지점과 지점을 연결해 코스를 완성하세요!") + private let guideView = GuideView(title: "지도를 눌러 코스를 그려주세요") private lazy var naviBarContainerStackView = UIStackView( arrangedSubviews: [notchCoverView, naviBar] @@ -200,6 +200,7 @@ extension CourseDrawingVC { } @objc private func completeButtonDidTap() { + guard handleVisitor() else { return } mapView.capturePathImage() } } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift index d7eb50bb..3a3bb9e6 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift @@ -46,6 +46,7 @@ final class CourseStorageVC: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + guard UserManager.shared.userType != .visitor else { return } self.getPrivateCourseList() self.getScrapCourseList() } @@ -106,13 +107,20 @@ extension CourseStorageVC { } private func setLayout() { - view.addSubviews(naviBar, viewPager) + view.addSubviews(naviBar) naviBar.snp.makeConstraints { make in make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide) make.height.equalTo(48) } + guard UserManager.shared.userType != .visitor else { + self.showSignInRequestEmptyView() + return + } + + view.addSubview(viewPager) + viewPager.snp.makeConstraints { make in make.top.equalTo(naviBar.snp.bottom) make.leading.bottom.trailing.equalTo(view.safeAreaLayoutGuide) diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift index 9bcf12c5..7ca1f921 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/Views/CVC/CourseListCVC.swift @@ -128,7 +128,9 @@ extension CourseListCVC { extension CourseListCVC { @objc func likeButtonDidTap(_ sender: UIButton) { guard let indexPath = self.indexPath else { return } - sender.isSelected.toggle() + if UserManager.shared.userType != .visitor { + sender.isSelected.toggle() + } delegate?.likeButtonTapped(wantsTolike: (sender.isSelected == true), index: indexPath) } } @@ -154,10 +156,10 @@ extension CourseListCVC { } likeButton.snp.makeConstraints { make in - make.top.equalTo(courseImageView.snp.bottom).offset(7) + make.top.equalTo(courseImageView.snp.bottom).offset(4) make.trailing.equalToSuperview() - make.width.equalTo(14) - make.height.equalTo(12) + make.width.equalTo(22) + make.height.equalTo(20) } labelStackView.snp.makeConstraints { make in diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift index ad3abeaa..34d75cf4 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift @@ -110,11 +110,11 @@ final class MyPageVC: UIViewController { setNavigationBar() setUI() setLayout() - getMyPageInfo() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + guard UserManager.shared.userType != .visitor else { return } self.getMyPageInfo() self.hideTabBar(wantsToHide: false) } @@ -268,6 +268,11 @@ extension MyPageVC { } private func setLayout() { + guard UserManager.shared.userType != .visitor else { + self.showSignInRequestEmptyView() + return + } + view.addSubviews(myProfileView, myRunningProgressView, firstDivideView, goalRewardInfoView, secondDivideView, activityRecordInfoView, thirdDivideView, uploadedCourseInfoView, fourthDivideView, settingView) diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift index 1510130a..9aaab093 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift @@ -137,13 +137,6 @@ extension PersonalInfoVC { self.logout() } - private func showSplashVC() { - let splashVC = SplashVC() - let navigationController = UINavigationController(rootViewController: splashVC) - guard let window = self.view.window else { return } - ViewControllerUtils.setRootViewController(window: window, viewController: navigationController, withAnimation: true) - } - private func requestAppleToken() { let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() diff --git a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunTrackingVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunTrackingVC.swift index 0a50d010..3c69b581 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunTrackingVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunTrackingVC.swift @@ -203,16 +203,7 @@ extension RunTrackingVC { @objc private func runningCompleteButtonDidTap() { stopwatch.isRunning.toggle() - let bottomSheetVC = CustomBottomSheetVC() - bottomSheetVC.modalPresentationStyle = .overFullScreen - - bottomSheetVC.completeButtonTapped.sink { [weak self] _ in - guard let self = self else { return } - self.pushToRunningRecordVC() - bottomSheetVC.dismiss(animated: true) - }.store(in: cancelBag) - - self.present(bottomSheetVC, animated: true) + self.pushToRunningRecordVC() } } diff --git a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift index 108df439..2cf56c18 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift @@ -305,6 +305,7 @@ extension RunningRecordVC { case .success(let result): let status = result.statusCode if 200..<300 ~= status { + self.showToastOnWindow(text: "저장한 러닝 기록은 마이페이지에서 볼 수 있어요.") self.navigationController?.popToRootViewController(animated: true) } if status >= 400 { diff --git a/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift index 5509f4c9..fa94ab0d 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift @@ -43,6 +43,12 @@ final class SignInSocialLoginVC: UIViewController { $0.setImage(ImageLiterals.imgKakaoLogin, for: .normal) } + private let visitorButton: UIButton = UIButton(type: .custom).then { + let attributedString = NSAttributedString(string: "회원가입 없이 둘러보기", attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue, .font: UIFont.b2, .foregroundColor: UIColor.white]) + + $0.setAttributedTitle(attributedString, for: .normal) + } + override func viewDidLoad() { super.viewDidLoad() setUI() @@ -55,7 +61,7 @@ final class SignInSocialLoginVC: UIViewController { // MARK: - @objc Function extension SignInSocialLoginVC { - @objc func touchUpAppleLoginButton() { + @objc func appleLoginButtonDidTap() { pushToAppleLogin() } @@ -112,14 +118,20 @@ extension SignInSocialLoginVC { } } } + + @objc private func visitorButtonDidTap() { + UserManager.shared.userType = .visitor + pushToTabBarController() + } } // MARK: - Methods extension SignInSocialLoginVC { private func setAddTarget() { - self.appleLoginButton.addTarget(self, action: #selector(touchUpAppleLoginButton), for: .touchUpInside) + self.appleLoginButton.addTarget(self, action: #selector(appleLoginButtonDidTap), for: .touchUpInside) self.kakaoLoginButton.addTarget(self, action: #selector(kakaoLoginButtonDidTap), for: .touchUpInside) + self.visitorButton.addTarget(self, action: #selector(visitorButtonDidTap), for: .touchUpInside) } private func pushToNickNameSetUpVC() { @@ -146,7 +158,7 @@ extension SignInSocialLoginVC { } private func setLayout() { - view.addSubviews(backgroundImageView, logoImageView, kakaoLoginButton, appleLoginButton) + view.addSubviews(backgroundImageView, logoImageView, kakaoLoginButton, appleLoginButton, visitorButton) backgroundImageView.snp.makeConstraints { make in make.edges.equalToSuperview() @@ -156,8 +168,15 @@ extension SignInSocialLoginVC { make.center.equalTo(view.safeAreaLayoutGuide) } + visitorButton.snp.makeConstraints { make in + make.bottom.equalTo(view.safeAreaLayoutGuide).inset(23) + make.height.equalTo(38) + make.width.equalTo(158) + make.centerX.equalToSuperview() + } + kakaoLoginButton.snp.makeConstraints { make in - make.bottom.equalToSuperview().inset(54) + make.bottom.equalTo(visitorButton.snp.top).offset(-10) make.height.equalTo(55) make.leading.trailing.equalToSuperview().inset(15) }