diff --git a/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj b/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj index 38d3fda1..d2423c5c 100644 --- a/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj +++ b/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj @@ -71,7 +71,6 @@ 37DCA6572A47574300FF8F90 /* RandomTopicAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA6562A47574300FF8F90 /* RandomTopicAPI.swift */; }; 37DCA65A2A47598700FF8F90 /* RandomTopicService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA6592A47598700FF8F90 /* RandomTopicService.swift */; }; 37DCA65D2A475B5100FF8F90 /* RandomTopicResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA65C2A475B5100FF8F90 /* RandomTopicResponse.swift */; }; - 37DCA6602A48033400FF8F90 /* DetailDiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA65F2A48033400FF8F90 /* DetailDiaryViewController.swift */; }; 37DCA6652A48052200FF8F90 /* DetailDiaryResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA6642A48052200FF8F90 /* DetailDiaryResponse.swift */; }; 37DCA6672A480A7300FF8F90 /* DetailDiaryEndPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA6662A480A7300FF8F90 /* DetailDiaryEndPoint.swift */; }; 37DCA6692A480A8E00FF8F90 /* DetailDiaryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA6682A480A8E00FF8F90 /* DetailDiaryService.swift */; }; @@ -128,12 +127,7 @@ 4A9731DD2BAAC79800DEC0C8 /* SplashViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9731DC2BAAC79800DEC0C8 /* SplashViewModelTest.swift */; }; 4A9731DF2BAAC7F300DEC0C8 /* SplashServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9731DE2BAAC7F300DEC0C8 /* SplashServiceMock.swift */; }; 4A9E10E42A43468600295D07 /* BaseTargetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9E10E32A43468600295D07 /* BaseTargetType.swift */; }; - 4A9FAB452A4C3D1200C40D5A /* BadgeListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9FAB3E2A4C3D1200C40D5A /* BadgeListViewController.swift */; }; - 4A9FAB472A4C3D1200C40D5A /* BadgeListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9FAB422A4C3D1200C40D5A /* BadgeListTableViewCell.swift */; }; - 4A9FAB482A4C3D1200C40D5A /* BadgeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9FAB432A4C3D1200C40D5A /* BadgeHeaderView.swift */; }; - 4A9FAB492A4C3D1200C40D5A /* DetailBadgeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A9FAB442A4C3D1200C40D5A /* DetailBadgeCollectionViewCell.swift */; }; 4AA1EEEA2A5873A00017FF97 /* Urbanist-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4AA1EEE92A5870690017FF97 /* Urbanist-SemiBold.otf */; }; - 4AA5E4B42BF2355300F308C8 /* MySummaryViewModel2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AA5E4B32BF2355300F308C8 /* MySummaryViewModel2.swift */; }; 4AA6FEE92C3ABDB500E588E9 /* ResignSummaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AA6FEE82C3ABDB500E588E9 /* ResignSummaryViewController.swift */; }; 4AA942C22A2767D000A552A0 /* FSCalendar in Frameworks */ = {isa = PBXBuildFile; productRef = 4AA942C12A2767D000A552A0 /* FSCalendar */; }; 4AA942C52A2767D900A552A0 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4AA942C42A2767D900A552A0 /* SnapKit */; }; @@ -197,7 +191,6 @@ 4AC707BB2B74DE3E00B1D791 /* ServiceAcceptCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707BA2B74DE3E00B1D791 /* ServiceAcceptCollectionView.swift */; }; 4AC9489829ED800800489C2B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4AC9489729ED800800489C2B /* GoogleService-Info.plist */; }; 4AD04B3D2A190E9A004B7A58 /* UITextView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD04B3C2A190E9A004B7A58 /* UITextView+.swift */; }; - 4AD04B402A1921AE004B7A58 /* CorrectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD04B3F2A1921AE004B7A58 /* CorrectionViewController.swift */; }; 4ADA41772A556209001C0285 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ADA41762A556209001C0285 /* LoadingView.swift */; }; 4ADCA2D62A9272E9002904EB /* EditAlarmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ADCA2D52A9272E9002904EB /* EditAlarmViewController.swift */; }; 4AE35E9E2A7FE8CE00465FD5 /* UICollectionViewCell+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AE35E9D2A7FE8CE00465FD5 /* UICollectionViewCell+.swift */; }; @@ -295,7 +288,6 @@ 37DCA6562A47574300FF8F90 /* RandomTopicAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomTopicAPI.swift; sourceTree = ""; }; 37DCA6592A47598700FF8F90 /* RandomTopicService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomTopicService.swift; sourceTree = ""; }; 37DCA65C2A475B5100FF8F90 /* RandomTopicResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomTopicResponse.swift; sourceTree = ""; }; - 37DCA65F2A48033400FF8F90 /* DetailDiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailDiaryViewController.swift; sourceTree = ""; }; 37DCA6642A48052200FF8F90 /* DetailDiaryResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailDiaryResponse.swift; sourceTree = ""; }; 37DCA6662A480A7300FF8F90 /* DetailDiaryEndPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailDiaryEndPoint.swift; sourceTree = ""; }; 37DCA6682A480A8E00FF8F90 /* DetailDiaryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailDiaryService.swift; sourceTree = ""; }; @@ -359,12 +351,7 @@ 4A9731DC2BAAC79800DEC0C8 /* SplashViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashViewModelTest.swift; sourceTree = ""; }; 4A9731DE2BAAC7F300DEC0C8 /* SplashServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashServiceMock.swift; sourceTree = ""; }; 4A9E10E32A43468600295D07 /* BaseTargetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTargetType.swift; sourceTree = ""; }; - 4A9FAB3E2A4C3D1200C40D5A /* BadgeListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BadgeListViewController.swift; sourceTree = ""; }; - 4A9FAB422A4C3D1200C40D5A /* BadgeListTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BadgeListTableViewCell.swift; sourceTree = ""; }; - 4A9FAB432A4C3D1200C40D5A /* BadgeHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BadgeHeaderView.swift; sourceTree = ""; }; - 4A9FAB442A4C3D1200C40D5A /* DetailBadgeCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailBadgeCollectionViewCell.swift; sourceTree = ""; }; 4AA1EEE92A5870690017FF97 /* Urbanist-SemiBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Urbanist-SemiBold.otf"; sourceTree = ""; }; - 4AA5E4B32BF2355300F308C8 /* MySummaryViewModel2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySummaryViewModel2.swift; sourceTree = ""; }; 4AA6FEE82C3ABDB500E588E9 /* ResignSummaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResignSummaryViewController.swift; sourceTree = ""; }; 4AB349402CF203250047C484 /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; 4AB7C9182B75F9B500845733 /* GesturePublisher+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GesturePublisher+.swift"; sourceTree = ""; }; @@ -425,7 +412,6 @@ 4AC9489729ED800800489C2B /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 4AD04B382A190020004B7A58 /* UITextField+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+.swift"; sourceTree = ""; }; 4AD04B3C2A190E9A004B7A58 /* UITextView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+.swift"; sourceTree = ""; }; - 4AD04B3F2A1921AE004B7A58 /* CorrectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionViewController.swift; sourceTree = ""; }; 4AD923E62A0650B600FF5E27 /* SmeemStartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmeemStartViewController.swift; sourceTree = ""; }; 4ADA41762A556209001C0285 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; 4ADCA2D52A9272E9002904EB /* EditAlarmViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAlarmViewController.swift; sourceTree = ""; }; @@ -628,7 +614,6 @@ 4AF5076F2A10CBA2007C62B1 /* Onboarding */, 4AE4B5172A06BF4A00D45F87 /* AuthBottomSheet */, 6F62668A2A04E889000365CD /* Home */, - 4AD04B3E2A19217B004B7A58 /* Correction */, A3D7ECB82A26566F009857D6 /* EditUser */, 4AEB82962A4CB4F900C1114B /* BadgePopup */, ); @@ -773,7 +758,6 @@ 37DCA65E2A48030A00FF8F90 /* DetailDiary */ = { isa = PBXGroup; children = ( - 37DCA65F2A48033400FF8F90 /* DetailDiaryViewController.swift */, 37BCADF12BC3FFBF006EF960 /* DetailDiaryViewModel.swift */, 37B123B52CEEE58E00ED973A /* DetailDiaryCoachedView.swift */, ); @@ -1137,33 +1121,6 @@ path = VC; sourceTree = ""; }; - 4A9FAB3C2A4C3D1200C40D5A /* BadgeList */ = { - isa = PBXGroup; - children = ( - 4A9FAB3D2A4C3D1200C40D5A /* VC */, - 4A9FAB412A4C3D1200C40D5A /* View */, - ); - path = BadgeList; - sourceTree = ""; - }; - 4A9FAB3D2A4C3D1200C40D5A /* VC */ = { - isa = PBXGroup; - children = ( - 4A9FAB3E2A4C3D1200C40D5A /* BadgeListViewController.swift */, - ); - path = VC; - sourceTree = ""; - }; - 4A9FAB412A4C3D1200C40D5A /* View */ = { - isa = PBXGroup; - children = ( - 4A9FAB422A4C3D1200C40D5A /* BadgeListTableViewCell.swift */, - 4A9FAB432A4C3D1200C40D5A /* BadgeHeaderView.swift */, - 4A9FAB442A4C3D1200C40D5A /* DetailBadgeCollectionViewCell.swift */, - ); - path = View; - sourceTree = ""; - }; 4A9FAB4A2A4C3D3D00C40D5A /* EditNickname */ = { isa = PBXGroup; children = ( @@ -1335,7 +1292,6 @@ isa = PBXGroup; children = ( 4ABCBCCF2BDE9BA1003138A8 /* MySummaryViewModel.swift */, - 4AA5E4B32BF2355300F308C8 /* MySummaryViewModel2.swift */, ); path = ViewModel; sourceTree = ""; @@ -1577,14 +1533,6 @@ path = VC; sourceTree = ""; }; - 4AD04B3E2A19217B004B7A58 /* Correction */ = { - isa = PBXGroup; - children = ( - 4AD04B3F2A1921AE004B7A58 /* CorrectionViewController.swift */, - ); - path = Correction; - sourceTree = ""; - }; 4AD923E52A0650A000FF5E27 /* Splash */ = { isa = PBXGroup; children = ( @@ -1698,7 +1646,6 @@ children = ( 4A9FAB4A2A4C3D3D00C40D5A /* EditNickname */, 4ADCA2D42A9272D6002904EB /* EditAlarm */, - 4A9FAB3C2A4C3D1200C40D5A /* BadgeList */, ); path = EditUser; sourceTree = ""; @@ -1880,7 +1827,6 @@ 37DCA6742A484D5900FF8F90 /* PostDiaryAPI.swift in Sources */, 4ABCBCE72BE25E51003138A8 /* TrainingPlanResponse.swift in Sources */, 4AC705832BE8BA60003C5310 /* MyBadgeCollectionViewDatasource.swift in Sources */, - 4A9FAB472A4C3D1200C40D5A /* BadgeListTableViewCell.swift in Sources */, 4AC705AE2BECF0D4003C5310 /* EditPlanViewModel.swift in Sources */, 4AF7C22F2BFB797600E8C6CD /* LockBadgeCollectionViewCell.swift in Sources */, 6F294A3E2A26177B00856CC8 /* TrainingGoalViewController.swift in Sources */, @@ -1926,7 +1872,6 @@ 4ABCBCCC2BDE8E44003138A8 /* MySummaryService.swift in Sources */, 371107DA2AC99099007A4AC2 /* KeyboardFollowingLayoutHandler.swift in Sources */, 37B123B62CEEE58E00ED973A /* DetailDiaryCoachedView.swift in Sources */, - 4A9FAB452A4C3D1200C40D5A /* BadgeListViewController.swift in Sources */, 4ABCBCE52BE25D82003138A8 /* TrainingPlanViewController.swift in Sources */, 4AB7C9192B75F9B500845733 /* GesturePublisher+.swift in Sources */, 37A574CC29FF990E00312453 /* UIViewController+.swift in Sources */, @@ -1964,7 +1909,6 @@ 4A3373F52A45BF6600EFE6C4 /* OnboardingEndPoint.swift in Sources */, 4A6630362A51B0AD00D19CC9 /* EditDiaryViewController.swift in Sources */, 4A004D512B4ED783003C8936 /* TrainingWayResponse.swift in Sources */, - 37DCA6602A48033400FF8F90 /* DetailDiaryViewController.swift in Sources */, 4ABCBCC02BD7C521003138A8 /* MyPlanActiveCollectionViewCell.swift in Sources */, 4A0EA4572A01403E006CCE52 /* MoyaLoggingPlugin.swift in Sources */, 37035CF92AF2ADD2008EE521 /* DiaryViewModel.swift in Sources */, @@ -1985,14 +1929,12 @@ 4ADCA2D62A9272E9002904EB /* EditAlarmViewController.swift in Sources */, 4A004D592B4EE28D003C8936 /* PushTestAPI.swift in Sources */, 6F294A432A26179700856CC8 /* ServiceAcceptViewController.swift in Sources */, - 4AD04B402A1921AE004B7A58 /* CorrectionViewController.swift in Sources */, 4A1882FA2A8BBD0D0088F590 /* SmeemStartViewController.swift in Sources */, 4AC7058F2BEA1E40003C5310 /* NicknameContainerView.swift in Sources */, 4ABCBCDA2BE22733003138A8 /* MyPlanCollectionViewLayout.swift in Sources */, 3728B8D32A2CFED300EF4CF8 /* ForeignDiaryViewController.swift in Sources */, 373D29932CBFE17B00A559A3 /* View+.swift in Sources */, 4ABE3FD12A811F8400D1D22E /* SplashViewController.swift in Sources */, - 4A9FAB492A4C3D1200C40D5A /* DetailBadgeCollectionViewCell.swift in Sources */, 4ABCBCD02BDE9BA1003138A8 /* MySummaryViewModel.swift in Sources */, 4AC705812BE8B69E003C5310 /* MySummaryBadgeResponse.swift in Sources */, 4AFD7C292B600FED00FE7EFF /* NetworkManager.swift in Sources */, @@ -2007,7 +1949,6 @@ 37DCA66E2A484D3100FF8F90 /* PostDiaryResponse.swift in Sources */, 4A0EA4552A014027006CCE52 /* GeneralResponse.swift in Sources */, 378B20EE2BA0A01600604935 /* ForeignDiaryViewModel.swift in Sources */, - 4A9FAB482A4C3D1200C40D5A /* BadgeHeaderView.swift in Sources */, 4AC00ECC2AD1C143009230DA /* UICollectionView+.swift in Sources */, 4A9731D52BAAB6C900DEC0C8 /* SplashService.swift in Sources */, 4A8FFA5029C9E1FD00FB76C0 /* AppDelegate.swift in Sources */, @@ -2048,7 +1989,6 @@ 3797891C2AAE11D400C61EF4 /* NavigationBarConfigurationBuilder.swift in Sources */, 4A3373F82A461ABC00EFE6C4 /* OnboardingService.swift in Sources */, 4A9731D72BAAB6E100DEC0C8 /* SplashServiceProtocol.swift in Sources */, - 4AA5E4B42BF2355300F308C8 /* MySummaryViewModel2.swift in Sources */, 4ABCBCCA2BDD3E3D003138A8 /* MySummaryResponse.swift in Sources */, 4AC7059D2BEA2A8E003C5310 /* SettingEndPoint.swift in Sources */, 371107DD2ACAB571007A4AC2 /* BaseView.swift in Sources */, @@ -2277,7 +2217,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = "Team.Smeem-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2299,7 +2239,7 @@ CODE_SIGN_ENTITLEMENTS = "Smeem-iOS/Smeem-iOS.entitlements"; CODE_SIGN_IDENTITY = "Apple Distribution: YuJi Lee (K8LLWYQWXD)"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2024121202; + CURRENT_PROJECT_VERSION = 2024122400; DEVELOPMENT_TEAM = K8LLWYQWXD; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Smeem-iOS/Info.plist"; @@ -2315,7 +2255,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = "Team.Smeem-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = smeem_release; diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/Global/SmeemToastView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/Global/SmeemToastView.swift index 5b3d8d77..fecf385b 100644 --- a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/Global/SmeemToastView.swift +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/Global/SmeemToastView.swift @@ -54,6 +54,7 @@ enum SmeemError: Error { case clientError case serverError case unknwnError + case tokenError var displayText: String { switch self { @@ -65,6 +66,8 @@ enum SmeemError: Error { return "데이터를 불러올 수 없어요 :(" case .unknwnError: return "문제가 발생했어요. 다시 접속해 주세요. :(" + case .tokenError: + return "다시 로그인해 주세요. :(" } } } diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/NavigationBar/SmeemNavigationFactory.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/NavigationBar/SmeemNavigationFactory.swift index 5bbc67e3..1c46b92e 100644 --- a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/NavigationBar/SmeemNavigationFactory.swift +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SmeemComponent/NavigationBar/SmeemNavigationFactory.swift @@ -50,7 +50,6 @@ class NavigationBarFactory { .withLayout(type.layout) .build() navigationBar.applyConfiguraton(configuration) -// navigationBar.actionDelegate = DetailDiaryViewController() return navigationBar case .edit: let configuration = configurationBuilder diff --git a/Smeem-iOS/Smeem-iOS/Network/Base/NetworkManager.swift b/Smeem-iOS/Smeem-iOS/Network/Base/NetworkManager.swift index 24b22afd..37e03213 100644 --- a/Smeem-iOS/Smeem-iOS/Network/Base/NetworkManager.swift +++ b/Smeem-iOS/Smeem-iOS/Network/Base/NetworkManager.swift @@ -10,8 +10,10 @@ import Foundation final class NetworkManager { static func statusCodeErrorHandling(statusCode: Int) throws { switch statusCode { - case 400..<500: + case 400, 402..<500: throw SmeemError.clientError + case 401: + throw SmeemError.tokenError case 500...: throw SmeemError.serverError default: diff --git a/Smeem-iOS/Smeem-iOS/Presentation/Correction/CorrectionViewController.swift b/Smeem-iOS/Smeem-iOS/Presentation/Correction/CorrectionViewController.swift deleted file mode 100644 index 473ef2f3..00000000 --- a/Smeem-iOS/Smeem-iOS/Presentation/Correction/CorrectionViewController.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// CorrectionViewController.swift -// Smeem-iOS -// -// Created by 황찬미 on 2023/05/21. -// - -import UIKit - -final class CorrectionViewController: UIViewController { - - // MARK: - Property - - // MARK: - UI Property - - private let naviView = UIView() - - private let backButton: UIButton = { - let button = UIButton() - button.backgroundColor = .point - return button - }() - - private let editButton: UIButton = { - let button = UIButton() - button.backgroundColor = .point - return button - }() - - private let diaryScrollerView: DiaryScrollerView = { - let scrollerView = DiaryScrollerView() - scrollerView.viewType = .detailDiary - return scrollerView - }() - - // MARK: - Life Cycle - - override func viewDidLoad() { - super.viewDidLoad() - - setBackgroundColor() - setLayout() - } - - // MARK: - @objc - - // MARK: - Custom Method - - // MARK: - Layout - - private func setBackgroundColor() { - view.backgroundColor = .white - } - - private func setLayout() { - view.addSubviews(naviView, diaryScrollerView) - naviView.addSubviews(backButton, editButton) - - naviView.snp.makeConstraints { - $0.top.equalToSuperview().inset(44) - $0.leading.trailing.equalToSuperview() - $0.height.equalTo(66) - } - - backButton.snp.makeConstraints { - $0.leading.equalToSuperview().inset(12) - $0.centerY.equalToSuperview() - $0.height.width.equalTo(40) - } - - editButton.snp.makeConstraints { - $0.trailing.equalToSuperview().inset(18) - $0.centerY.equalToSuperview() - $0.height.width.equalTo(40) - } - - diaryScrollerView.snp.makeConstraints { - $0.top.equalTo(naviView.snp.bottom) - $0.leading.trailing.bottom.equalToSuperview() - } - } -} diff --git a/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift b/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift index 8e9c0b53..d2b52047 100644 --- a/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift +++ b/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift @@ -42,111 +42,122 @@ struct DetailDiaryCoachedView: View { // MARK: - Body var body: some View { - VStack(spacing: 0) { - SwiftUINavigationView(navigationViewModel: navigationViewModel, - selectedIndex: $selectedIndex, - navigationbarType: navigationbarType - ) - .onReceive(navigationViewModel.leftButtonTapped) { - dismiss() - } - .onReceive(navigationViewModel.rightButtonTapped) { - isShowingFloatingButtons = true - AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_edit(hasCorrections).event) - } - .confirmationDialog("", isPresented: $isShowingFloatingButtons) { - Button("수정하기", role: .none) { - if navigationbarType == .diaryDetails { - showEditConfirmation( - title: "수정 확인", - message: "수정시 모든 코칭 내용이 사라집니다. 그래도 수정하시겠습니까?", - firstActionTitle: "취소", - secondActionTitle: "확인", - firstActionHandler: { }, - secondActionHandler: { - navigateToEditDiary() - } - ) - } else { - navigateToEditDiary() + ZStack { + Color.white.ignoresSafeArea() + VStack(spacing: 0) { + SwiftUINavigationView(navigationViewModel: navigationViewModel, + selectedIndex: $selectedIndex, + navigationbarType: navigationbarType + ) + .onReceive(navigationViewModel.leftButtonTapped) { + dismiss() + } + .onReceive(navigationViewModel.rightButtonTapped) { + isShowingFloatingButtons = true + AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_edit(hasCorrections).event) + } + .confirmationDialog("", isPresented: $isShowingFloatingButtons) { + Button("수정하기", role: .none) { + if navigationbarType == .diaryDetails { + showEditConfirmation( + title: "수정 확인", + message: "수정시 모든 코칭 내용이 사라집니다. 그래도 수정하시겠습니까?", + firstActionTitle: "취소", + secondActionTitle: "확인", + firstActionHandler: { }, + secondActionHandler: { + navigateToEditDiary() + } + ) + } else { + navigateToEditDiary() + } + } + + Button("삭제하기", role: .destructive) { + deleteDiaryWithAPI(diaryID: diaryID ?? 0) + } + + Button("취소", role: .cancel) { + isShowingFloatingButtons = false } } - Button("삭제하기", role: .destructive) { - deleteDiaryWithAPI(diaryID: diaryID ?? 0) + if let topic = response?.topic { + if topic != "" { + RandomTopicViewSwiftUI(contentText: response?.topic) + } } - Button("취소", role: .cancel) { - isShowingFloatingButtons = false + if let response = response { + ScrollableDiaryView( + diaryText: response.content, + corrections: filteredCorrections, + currentIndex: currentIndex, + selectedIndex: selectedIndex, + dateText: response.createdAt, + authorText: response.username + ) + } else { + if isLoading { + SmemeEmptyView() + SmemeLoadingView() + } + } + + // "코칭 ON"일 때만 표시 + if selectedIndex == 1 { + Spacer() + CoachingContentView( + currentIndex: $currentIndex, + detailDiaryResponse: Binding( + get: { self.response ?? .empty }, + set: { _ in } + ), + corrections: $filteredCorrections + ) + } else { + Spacer() } } - - if let topic = response?.topic { - if topic != "" { - RandomTopicViewSwiftUI(contentText: response?.topic) + .onAppear { + AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_click(true).event) + Task { + await fetchCoachingData(diaryID: diaryID ?? 0) } } - - if let response = response { - ScrollableDiaryView( - diaryText: response.content, - corrections: filteredCorrections, - currentIndex: currentIndex, - selectedIndex: selectedIndex, - dateText: response.createdAt, - authorText: response.username + .onChange(of: selectedIndex) { newValue in + AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.toggle_click(convertSelectedIndexToString(newValue)).event ) - } else { + } + .overlay { if isLoading { SmemeEmptyView() SmemeLoadingView() } - } - - // "코칭 ON"일 때만 표시 - if selectedIndex == 1 { - Spacer() - CoachingContentView( - currentIndex: $currentIndex, - detailDiaryResponse: Binding( - get: { self.response ?? .empty }, - set: { _ in } - ), - corrections: $filteredCorrections - ) - } else { - Spacer() + + if onError { + ZStack { + Color.clear + VStack { + Spacer() + SmeemErrorToastView(type: $toastErrorMessage) + .padding(.bottom, 20.scaledByHeight()) + } } - } - .onAppear { - AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.mydiary_click(hasCorrections).event) - Task { - await fetchCoachingData(diaryID: diaryID ?? 0) - } - } - .onChange(of: selectedIndex) { newValue in - AmplitudeManager.shared.track(event: AmplitudeConstant.diaryDetail.toggle_click(convertSelectedIndexToString(newValue)).event - ) - } - .overlay { - if isLoading { - SmemeEmptyView() - SmemeLoadingView() - } - - if onError { - ZStack { - Color.clear - VStack { - Spacer() - SmeemErrorToastView(type: $toastErrorMessage) - .padding(.bottom, 20.scaledByHeight()) + .onDisappear { + onError = false } } - .onDisappear { - onError = false - } } + .gesture( + DragGesture() + .onEnded { value in + if value.translation.width > 50 { + dismiss() + } + } + ) } } } @@ -205,7 +216,6 @@ extension DetailDiaryCoachedView { self.changeRootViewControllerAndPresent(homeVC) case .failure(let error): toastErrorMessage = error - break } isLoading = false } diff --git a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/VC/BadgeListViewController.swift b/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/VC/BadgeListViewController.swift deleted file mode 100644 index 373170d8..00000000 --- a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/VC/BadgeListViewController.swift +++ /dev/null @@ -1,233 +0,0 @@ -// -// BadgeViewController.swift -// Smeem-iOS -// -// Created by JH on 2023/06/07. -// - -import UIKit - -import Kingfisher -import SnapKit - -class BadgeListViewController: UIViewController { - - // MARK: - Property - - private var badgeHeaderData = [(name: String(), imageURL: String())] - private var badgeListData = Array(repeating: Array(repeating: (name: String(), imageURL: String()), count: 0), count: 2) - private var totalBadgeData = Array(repeating: Array(repeating: (name: String(), imageURL: String()), count: 4), count: 2) - - // MARK: - UI Property - - private let headerContainerView = UIView() - - private lazy var cancelButton: UIButton = { - let button = UIButton() - button.setImage(Constant.Image.icnCancelBlack, for: .normal) - button.addTarget(self, action: #selector(cancelButtonDidtap), for: .touchUpInside) - return button - }() - - // TODO: addTarget 넣기 - - private lazy var badgeListTableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .grouped) - tableView.backgroundColor = .clear - tableView.separatorStyle = .none - tableView.showsVerticalScrollIndicator = false - let welcomeHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 196)) - setHeaderViewLayout(headerView: welcomeHeaderView) - tableView.tableHeaderView = welcomeHeaderView - return tableView - }() - - private let welcomeLabel: UILabel = { - let label = UILabel() - label.text = "웰컴 배지" - label.font = .s1 - label.textColor = .smeemBlack - return label - }() - - private let welcomeImage: UIImageView = { - let image = UIImageView() - image.image = Constant.Image.colorWelcomeBadge - return image - }() - - private let detailWelcomeLabel: UILabel = { - let label = UILabel() - label.font = .c3 - label.textColor = .smeemBlack - return label - }() - - // MARK: - Life Cycle - - override func viewDidLoad() { - super.viewDidLoad() - - setBackgroundColor() - setLayout() - setDelegate() - setRegister() - badgeListGetAPI() - } - - - // MARK: - @objc - - @objc func cancelButtonDidtap() { - self.navigationController?.popViewController(animated: true) - self.presentingViewController?.presentingViewController?.dismiss(animated: true) - } - - // MARK: - Custom Method - - private func setDelegate() { - badgeListTableView.delegate = self - badgeListTableView.dataSource = self - } - - private func setRegister() { - badgeListTableView.register(BadgeListTableViewCell.self, forCellReuseIdentifier: BadgeListTableViewCell.identifier) - badgeListTableView.register(BadgeHeaderView.self, forHeaderFooterViewReuseIdentifier: BadgeHeaderView.identifier) - } - - private func setHeaderViewData() { - let url = URL(string: badgeHeaderData[0].imageURL) ?? nil - welcomeImage.kf.setImage(with: url) - detailWelcomeLabel.text = badgeHeaderData[0].name - } - - - // MARK: - Layout - - private func setBackgroundColor() { - view.backgroundColor = .smeemWhite - } - - private func setLayout() { - view.addSubviews(headerContainerView, badgeListTableView) - headerContainerView.addSubview(cancelButton) - - headerContainerView.snp.makeConstraints{ - $0.top.leading.trailing.equalTo(view.safeAreaLayoutGuide) - $0.height.equalTo(convertByHeightRatio(66)) - } - - cancelButton.snp.makeConstraints { - $0.centerY.equalToSuperview() - $0.leading.equalToSuperview().offset(convertByHeightRatio(10)) - $0.width.height.equalTo(55) - } - - badgeListTableView.snp.makeConstraints { - $0.top.equalTo(headerContainerView.snp.bottom).offset(convertByHeightRatio(31)) - $0.leading.trailing.bottom.equalToSuperview() - } - } - - private func setHeaderViewLayout(headerView: UIView) { - headerView.addSubviews(welcomeLabel, welcomeImage, detailWelcomeLabel) - welcomeLabel.snp.makeConstraints { - $0.top.equalToSuperview().inset(convertByHeightRatio(4)) - $0.leading.equalToSuperview().inset(convertByHeightRatio(24)) - } - - welcomeImage.snp.makeConstraints { - $0.top.equalTo(welcomeLabel.snp.bottom).offset(convertByHeightRatio(6)) - $0.leading.equalToSuperview().inset(convertByHeightRatio(20)) - $0.width.height.equalTo(convertByHeightRatio(100)) - } - - detailWelcomeLabel.snp.makeConstraints { - $0.top.equalTo(welcomeImage.snp.bottom).offset(convertByHeightRatio(8)) - $0.leading.equalToSuperview().inset(convertByHeightRatio(44)) - } - } -} - -// MARK: - UICollectionViewDelegate - -extension BadgeListViewController: UITableViewDelegate { - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return convertByHeightRatio(30) - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - guard let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: BadgeHeaderView.identifier) as? BadgeHeaderView else { return UITableViewHeaderFooterView() } - switch section { - case 0: - headerView.labelType = .diaryCount - case 1: - headerView.labelType = .dailyDiary - /// ToDo: 없어도 되는지 확인 -// case 2: -// headerView.labelType = .otherBadge - default: - break - } - return headerView - } -} - -extension BadgeListViewController: UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { - return 2 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let cell = tableView.dequeueReusableCell(withIdentifier: BadgeListTableViewCell.identifier, for: indexPath) as? BadgeListTableViewCell else { return UITableViewCell() } - cell.badgeData = self.totalBadgeData[indexPath.section] - return cell - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return constraintByNotch(convertByHeightRatio(296), 286) - } -} - -// MARK: - Network - -extension BadgeListViewController { - private func badgeListGetAPI() { - MyPageAPI.shared.badgeListAPI() { result in - - switch result { - case .success(let response): - - for data in response { - if data.badgeType == "EVENT" { - data.badges.forEach { badge in - self.badgeHeaderData = [(badge.name, badge.imageUrl)] - } - } else if data.badgeType == "COUNTING" { - data.badges.forEach { badge in - self.badgeListData[0].append((name: badge.name, imageURL: badge.imageUrl)) - } - } else if data.badgeType == "COMBO" { - data.badges.forEach { badge in - self.badgeListData[1].append((name: badge.name, imageURL: badge.imageUrl)) - } - } else { - // self.badgeListData[2].append((name: badge.name, imageURL: badge.imageURL)) - } - } - - self.totalBadgeData = self.badgeListData - - self.setHeaderViewData() - self.badgeListTableView.reloadData() - - case .failure(let error): - self.showToast(toastType: .smeemErrorToast(message: error)) - } - } - } -} diff --git a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/BadgeHeaderView.swift b/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/BadgeHeaderView.swift deleted file mode 100644 index 7e18110b..00000000 --- a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/BadgeHeaderView.swift +++ /dev/null @@ -1,76 +0,0 @@ -// -// BadgeHeaderView.swift -// Smeem-iOS -// -// Created by JH on 2023/06/28. -// - -import UIKit - -import SnapKit - -enum HeaderLabelType { - case welcome - case diaryCount - case dailyDiary - case otherBadge -} - -final class BadgeHeaderView: UITableViewHeaderFooterView { - - static let identifier = "BadgeHeaderView" - - // MARK: - Property - - var labelType: HeaderLabelType = .welcome { - didSet { - setLabelText() - } - } - // MARK: - UI Property - - private let headerLabel: UILabel = { - let label = UILabel() - label.font = .s1 - label.textColor = .black - return label - }() - - // MARK: - Life Cycle - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - - setLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - @objc - // MARK: - Custom Method - - func setLabelText() { - switch labelType { - case .welcome: - headerLabel.text = "스페셜배지" - case .diaryCount: - headerLabel.text = "일기 누적 수" - case .dailyDiary: - headerLabel.text = "일기 연속 수" - case .otherBadge: - headerLabel.text = "부가 기능 활용" - } - } - - // MARK: - Layout - - func setLayout() { - addSubview(headerLabel) - - headerLabel.snp.makeConstraints { - $0.leading.equalToSuperview().inset(convertByHeightRatio(24)) - $0.centerY.equalToSuperview() - } - } -} diff --git a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/BadgeListTableViewCell.swift b/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/BadgeListTableViewCell.swift deleted file mode 100644 index 3d619f9f..00000000 --- a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/BadgeListTableViewCell.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// BadgeListCollectionViewCell.swift -// Smeem-iOS -// -// Created by JH on 2023/06/28. -// - -import UIKit - -final class BadgeListTableViewCell: UITableViewCell { - - // MARK: - Property - - static let identifier = "BadgeListTableViewCell" - - var badgeData = Array(repeating: (name: String(), imageURL: String()), count: 0) { - didSet { - detailBadgeCollectionView.reloadData() - } - } - - // MARK: - UI Property - - private lazy var detailBadgeCollectionView: UICollectionView = { - let layout = UICollectionViewFlowLayout() - let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) - collectionView.showsVerticalScrollIndicator = false - return collectionView - }() - - // MARK: - Life Cycle - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - setDelegate() - setRegister() - setLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - @objc - // MARK: - Custom Method - - private func setDelegate() { - detailBadgeCollectionView.delegate = self - detailBadgeCollectionView.dataSource = self - } - - private func setRegister() { - detailBadgeCollectionView.register(DetailBadgeCollectionViewCell.self, forCellWithReuseIdentifier: DetailBadgeCollectionViewCell.identifier) - } - - // MARK: - Layout - - private func setLayout() { - addSubviews(detailBadgeCollectionView) - - detailBadgeCollectionView.snp.makeConstraints { - $0.top.leading.trailing.bottom.equalToSuperview() - } - } - - // MARK: - UITableView Delegate -} - -extension BadgeListTableViewCell: UICollectionViewDelegate { - -} - -extension BadgeListTableViewCell: UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 4 - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: DetailBadgeCollectionViewCell.identifier, for: indexPath) as? DetailBadgeCollectionViewCell else { return UICollectionViewCell() } - cell.setBadgeData(data: (self.badgeData[indexPath.row].name, self.badgeData[indexPath.row].imageURL)) - return cell - } -} - -extension BadgeListTableViewCell: UICollectionViewDelegateFlowLayout { - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: convertByWidthRatio(100), height: convertByHeightRatio(128)) - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { - return 12 - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { - return constraintByNotch(14, 30) - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { - return UIEdgeInsets(top: 6, left: 20, bottom: 0, right: 31) - } -} diff --git a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/DetailBadgeCollectionViewCell.swift b/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/DetailBadgeCollectionViewCell.swift deleted file mode 100644 index c5ec618a..00000000 --- a/Smeem-iOS/Smeem-iOS/Presentation/EditUser/BadgeList/View/DetailBadgeCollectionViewCell.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// DetailBadgeCollectionVIewCell.swift -// Smeem-iOS -// -// Created by JH on 2023/06/28. -// - -import UIKit - -final class DetailBadgeCollectionViewCell: UICollectionViewCell { - - // MARK: - Property - - static let identifier = "DetailBadgeCollectionViewCell" - - // MARK: - UI Property - - private let badgeImage = UIImageView() - - private let badgeNameLabel: UILabel = { - let label = UILabel() - label.font = .c3 - label.textColor = .smeemBlack - return label - }() - - // MARK: - Life Cycle - - override init(frame: CGRect) { - super.init(frame: frame) - - setLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - Custom Method - - func setBadgeData(data: (name: String, image: String)) { - let url = URL(string: data.image) - badgeImage.kf.setImage(with: url) - badgeNameLabel.text = data.name - } - // MARK: - Layout - - private func setLayout() { - addSubviews(badgeImage, badgeNameLabel) - - badgeImage.snp.makeConstraints { - $0.top.leading.equalToSuperview() - $0.width.height.equalTo(66) - } - - badgeNameLabel.snp.makeConstraints { - $0.top.equalTo(badgeImage.snp.bottom).offset(convertByHeightRatio(4)) - $0.centerX.equalToSuperview() - } - } - - // MARK: - UITableView Delegate -} diff --git a/Smeem-iOS/Smeem-iOS/Presentation/MySummary/ViewModel/MySummaryViewModel2.swift b/Smeem-iOS/Smeem-iOS/Presentation/MySummary/ViewModel/MySummaryViewModel2.swift deleted file mode 100644 index bbe82729..00000000 --- a/Smeem-iOS/Smeem-iOS/Presentation/MySummary/ViewModel/MySummaryViewModel2.swift +++ /dev/null @@ -1,159 +0,0 @@ - -// -// MySummaryViewModel.swift -// Smeem-iOS -// -// Created by 황찬미 on 4/28/24. -// - -import Foundation -import Combine - -final class MySummaryViewMode2l: ViewModel { - - var provider: MySummaryServiceProtocol! - - private let mySmeemModel = ["방문일", "총 일기", "연속 일기", "배지"] - - struct Input { - let mySummarySubject: PassthroughSubject - let myPlanSubject: PassthroughSubject - let myBadgeSubject: PassthroughSubject - } - - struct Output { - let totalHasMyPlanResult: AnyPublisher - let totalHasNotPlanResult: AnyPublisher - let errorResult: AnyPublisher - let loadingViewResult: AnyPublisher - } - - private var cancelBag = Set() - private let errorSubject = PassthroughSubject() - private let nicknameDuplicateSubject = PassthroughSubject() - private let loadingViewSubject = PassthroughSubject() - private let planSettingSubject = PassthroughSubject() - - init(provider: MySummaryServiceProtocol) { - self.provider = provider - } - - func transform(input: Input) -> Output { - let mySummaryResult = input.mySummarySubject - .handleEvents(receiveSubscription: { _ in - self.loadingViewSubject.send(true) - }) - .flatMap { _ -> AnyPublisher in - return Future { promise in - self.provider.mySummaryGetAPI { result in - switch result { - case .success(let response): - promise(.success(response)) - case .failure(let error): - self.errorSubject.send(error) - } - } - } - .handleEvents(receiveCompletion: { _ in - self.loadingViewSubject.send(false) - }) - .eraseToAnyPublisher() - } - .eraseToAnyPublisher() - - let myPlanResult = input.myPlanSubject - .handleEvents(receiveSubscription: { _ in - self.loadingViewSubject.send(true) - }) - .flatMap { _ -> AnyPublisher in - return Future { promise in - self.provider.myPlanGetAPI { result in - switch result { - case .success(let response): - // 만약 데이터가 없다면 - guard let data = response.data else { -// self.planSettingSubject.send(()) - return - } - case .failure(let error): - self.errorSubject.send(error) - } - } - } - .handleEvents(receiveCompletion: { _ in - self.loadingViewSubject.send(false) - }) - .eraseToAnyPublisher() - } - .eraseToAnyPublisher() - - let myBadgeResult = input.myBadgeSubject - .handleEvents(receiveSubscription: { _ in - self.loadingViewSubject.send(true) - }) - .flatMap { _ -> AnyPublisher<[MySummaryBadgeResponse], Never> in - return Future<[MySummaryBadgeResponse], Never> { promise in - self.provider.myBadgeGetAPI { result in - switch result { - case .success(let response): - promise(.success(response)) - case .failure(let error): - self.errorSubject.send(error) - } - } - } - .handleEvents(receiveCompletion: { _ in - self.loadingViewSubject.send(false) - }) - .eraseToAnyPublisher() - } - .eraseToAnyPublisher() - - let planSettingResult = planSettingSubject.eraseToAnyPublisher() - - let totalHasMyPlanResult = Publishers.CombineLatest3(mySummaryResult, myPlanResult, myBadgeResult) - .map { result -> TotalMySummaryResponse in - var clearCountArray: [Int] = [] - (1...result.1.clearCount).forEach { number in - clearCountArray.append(number) - } - return TotalMySummaryResponse(mySumamryText: self.mySmeemModel.map{$0}, - mySummaryNumber: [result.0.visitDays, result.0.diaryCount, - result.0.diaryComboCount, result.0.badgeCount], - myPlan: MyPlanAppData(plan: result.1.plan, - goal: result.1.goal, - clearedCount: result.1.clearedCount, - clearCount: clearCountArray), - myBadge: result.2) - } - .eraseToAnyPublisher() - - let totalHasNotPlanResult = Publishers.CombineLatest3(mySummaryResult, planSettingResult, myBadgeResult) - .map { result -> TotalMySummaryResponse in - self.loadingViewSubject.send(false) - return TotalMySummaryResponse(mySumamryText: self.mySmeemModel.map{$0}, - mySummaryNumber: [result.0.visitDays, result.0.diaryCount, - result.0.diaryComboCount, result.0.badgeCount], - myPlan: nil, - myBadge: result.2) - } - .eraseToAnyPublisher() - -// let totalHasNotPlanResult = Publishers.CombineLatest3(mySummaryResult, mySummaryResult, mySummaryResult) -// .map { result -> TotalMySummaryResponse in -// self.loadingViewSubject.send(false) -// return TotalMySummaryResponse(mySumamryText: [""], mySummaryNumber: [123], myPlan: MyPlanAppData(plan: "", -// goal: "", clearedCount: 3, clearCount: [1]), myBadge: [MySummaryBadgeResponse(badgeId: 0, name: "", type: "", hasBadge: false, remainingNumber: 3, contentForNonBadgeOwner: "", contentForBadgeOwner: "", imageUrl: "", badgeAcquisitionRatio: 0.0)]) -// } -// .eraseToAnyPublisher() - - let errorResult = errorSubject.eraseToAnyPublisher() - let loadingViewResult = loadingViewSubject.eraseToAnyPublisher() - - - return Output(totalHasMyPlanResult: totalHasMyPlanResult, - totalHasNotPlanResult: totalHasNotPlanResult, - errorResult: errorResult, loadingViewResult: loadingViewResult) - } - -} diff --git a/Smeem-iOS/Smeem-iOS/Presentation/Splash/Splah/ViewModel/SplashViewModel.swift b/Smeem-iOS/Smeem-iOS/Presentation/Splash/Splah/ViewModel/SplashViewModel.swift index f1cc663e..fead7bfb 100644 --- a/Smeem-iOS/Smeem-iOS/Presentation/Splash/Splah/ViewModel/SplashViewModel.swift +++ b/Smeem-iOS/Smeem-iOS/Presentation/Splash/Splah/ViewModel/SplashViewModel.swift @@ -136,6 +136,24 @@ extension SplashViewModel { let clientVersion = client.split(separator: ".").map{$0} let forceVersion = force.split(separator: ".").map{$0} + // x 버전이 더 크면 강제 업데이트 + if forceVersion[0] > clientVersion[0] { + return true + // x 버전이 같고, y 버전이 더 크면 강제 업데이트 + } else if forceVersion[0] == clientVersion[0] && forceVersion[1] > clientVersion[1] { + return true + // x, y 버전이 같고, z버전이 더 크면 강제 업데이트 + } else if (forceVersion[0] == clientVersion[0] && forceVersion[1] == clientVersion[1]) && forceVersion[2] > clientVersion[2] { + return true + } + return false + } + + // 실수로 고려해야 하는 버전 + func checkVersion3(client: String, force: String) -> Bool { + let clientVersion = client.split(separator: ".").map{$0} + let forceVersion = force.split(separator: ".").map{$0} + // x 버전이 더 크면 강제 업데이트 if forceVersion[0] > clientVersion[0] { return true diff --git a/Smeem-iOS/Smeem-iOS/Supports/SceneDelegate.swift b/Smeem-iOS/Smeem-iOS/Supports/SceneDelegate.swift index fa0d502d..88f4199c 100644 --- a/Smeem-iOS/Smeem-iOS/Supports/SceneDelegate.swift +++ b/Smeem-iOS/Smeem-iOS/Supports/SceneDelegate.swift @@ -10,9 +10,9 @@ import UIKit import KakaoSDKAuth class SceneDelegate: UIResponder, UIWindowSceneDelegate { - + var window: UIWindow? - + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let scene = (scene as? UIWindowScene) else { return } self.window = UIWindow(windowScene: scene) @@ -29,35 +29,63 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } } - + func sceneDidDisconnect(_ scene: UIScene) { // Called as the scene is being released by the system. // This occurs shortly after the scene enters the background, or when its session is discarded. // Release any resources associated with this scene that can be re-created the next time the scene connects. // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). } - + func sceneDidBecomeActive(_ scene: UIScene) { // Called when the scene has moved from an inactive state to an active state. // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. } - + func sceneWillResignActive(_ scene: UIScene) { // Called when the scene will move from an active state to an inactive state. // This may occur due to temporary interruptions (ex. an incoming phone call). } - + func sceneWillEnterForeground(_ scene: UIScene) { // Called as the scene transitions from the background to the foreground. // Use this method to undo the changes made on entering the background. + + // MARK: Token Check + // 앱에 처음 진입한 온보딩을 거치는 유저라면, 해당 API를 호출할 필요가 없다. + if UserDefaultsManager.accessToken != "" { + AuthService.shared.reLoginAPI() { result in + switch result { + case .success(let response): + if let accessToken = response.data?.accessToken { + UserDefaultsManager.accessToken = accessToken + } + if let refreshToken = response.data?.refreshToken { + UserDefaultsManager.refreshToken = refreshToken + } + case .failure(let error): + // 1. 2주 후에 background 상태에서 진입한 유저일 경우 + // 2. 서버쪽에서 무언가 오류가 났을 경우 + // 401, 500 ... + // 유저 토큰 처리에 따라 분기할 수 있도록 Splash로 보낸다 + print("error 발생", error) +// if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, +// let delegate = scene.delegate as? SceneDelegate, +// let window = delegate.window { +// // 홈 화면으로 전환 +// let homeViewController = SplashViewController() // 실제 홈 VC로 변경 +// let navigationController = UINavigationController(rootViewController: homeViewController) +// window.rootViewController = navigationController +// window.makeKeyAndVisible() +// } + } + } + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - } - diff --git a/Smeem-iOS/Smeem-iOSTests/Onboarding/ViewModel/SplashViewModelTest.swift b/Smeem-iOS/Smeem-iOSTests/Onboarding/ViewModel/SplashViewModelTest.swift index 24f72215..87fcc1e4 100644 --- a/Smeem-iOS/Smeem-iOSTests/Onboarding/ViewModel/SplashViewModelTest.swift +++ b/Smeem-iOS/Smeem-iOSTests/Onboarding/ViewModel/SplashViewModelTest.swift @@ -14,17 +14,21 @@ final class SplashViewModelTest: XCTestCase { private var viewModel: SplashViewModel! private var mockService: SplashServiceMock! - private var appVersion: String! + private var beforeAppVersion: String! + private var afterAppVersion: String! + private var forceVersion: String! override func setUpWithError() throws { self.mockService = SplashServiceMock() self.viewModel = SplashViewModel(provider: mockService) - self.appVersion = viewModel.appVersion + self.beforeAppVersion = "3.0.1" + self.afterAppVersion = "3.1.0" + self.forceVersion = "3.1.0" } func test_강제업데이트안한유저_정확한데이터_return하는지() { // Given - let result = self.viewModel.checkVersion(client: "2.0.3", force: "3.0.0") + let result = self.viewModel.checkVersion(client: self.beforeAppVersion, force: self.forceVersion) // When let expectedResult = true @@ -35,7 +39,7 @@ final class SplashViewModelTest: XCTestCase { func test_강제업데이트로하고온유저_정확한데이터_return하는지() { // Given - let result = self.viewModel.checkVersion(client: self.appVersion, force: "3.0.0") + let result = self.viewModel.checkVersion(client: self.afterAppVersion, force: self.forceVersion) // When let expectedResult = false @@ -44,9 +48,20 @@ final class SplashViewModelTest: XCTestCase { XCTAssertEqual(result, expectedResult) } - func test_이전업데이트로직유저_강제업데이트팝업잘뜨는지() { + func test_첫업데이트로직유저_강제업데이트팝업잘뜨는지() { // Given - let result = self.viewModel.checkVersion2(client: "2.0.3", now: "2.0.4", force: "3.0.0") + let result = self.viewModel.checkVersion2(client: "2.0.3", now: "2.0.4", force: self.forceVersion) + + // When + let expectedResult = true + + // Then + XCTAssertEqual(result, expectedResult) + } + + func test_두번째업데이트로직유저_강제업데이트팝업잘뜨는지() { + // Given + let result = self.viewModel.checkVersion3(client: self.beforeAppVersion, force: self.forceVersion) // When let expectedResult = true