From 2ffa3a7f43a7818ace46cec01277557ddd85f29a Mon Sep 17 00:00:00 2001 From: chaemin2001 Date: Fri, 25 Oct 2024 11:34:24 +0900 Subject: [PATCH 1/6] Add Social Provider --- SNUTT-2022/SNUTT.xcodeproj/project.pbxproj | 4 +++ .../SNUTT/AppState/States/UserState.swift | 1 + SNUTT-2022/SNUTT/Models/SocialProvider.swift | 26 +++++++++++++++++++ .../SNUTT/Repositories/Dto/UserDto.swift | 8 ++++++ 4 files changed, 39 insertions(+) create mode 100644 SNUTT-2022/SNUTT/Models/SocialProvider.swift diff --git a/SNUTT-2022/SNUTT.xcodeproj/project.pbxproj b/SNUTT-2022/SNUTT.xcodeproj/project.pbxproj index 7bd11b68..6ee88ee1 100644 --- a/SNUTT-2022/SNUTT.xcodeproj/project.pbxproj +++ b/SNUTT-2022/SNUTT.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 738407102B6060F800007E62 /* ThemeState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 738406F82B57154400007E62 /* ThemeState.swift */; }; 73AB84D22C35128B0075DE83 /* IntegrateAccountScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73AB84D12C35128B0075DE83 /* IntegrateAccountScene.swift */; }; 73AB84D42C3514080075DE83 /* IntegrateAccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73AB84D32C3514080075DE83 /* IntegrateAccountViewModel.swift */; }; + 73B6E0882CCB34B2006DD4F0 /* SocialProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73B6E0862CCB34AA006DD4F0 /* SocialProvider.swift */; }; B800A38B2B76132C008E8D84 /* SearchTimeMaskDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B800A38A2B76132C008E8D84 /* SearchTimeMaskDto.swift */; }; B800A38C2B77BD78008E8D84 /* SearchTimeMaskDto.swift in Sources */ = {isa = PBXBuildFile; fileRef = B800A38A2B76132C008E8D84 /* SearchTimeMaskDto.swift */; }; B82EA54C2B62C8490029FDF3 /* LectureMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82EA54B2B62C8490029FDF3 /* LectureMapView.swift */; }; @@ -377,6 +378,7 @@ 738407042B577E9000007E62 /* ThemeDetailScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeDetailScene.swift; sourceTree = ""; }; 73AB84D12C35128B0075DE83 /* IntegrateAccountScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrateAccountScene.swift; sourceTree = ""; }; 73AB84D32C3514080075DE83 /* IntegrateAccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrateAccountViewModel.swift; sourceTree = ""; }; + 73B6E0862CCB34AA006DD4F0 /* SocialProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialProvider.swift; sourceTree = ""; }; B800A38A2B76132C008E8D84 /* SearchTimeMaskDto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTimeMaskDto.swift; sourceTree = ""; }; B82EA54B2B62C8490029FDF3 /* LectureMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LectureMapView.swift; sourceTree = ""; }; B82EA54D2B6393190029FDF3 /* KakaoMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoMapView.swift; sourceTree = ""; }; @@ -1040,6 +1042,7 @@ 731D9FFC297BC5060027BA25 /* Bookmark.swift */, 738406ED2B57107C00007E62 /* Theme.swift */, B84A4EA02B6035EE00C1E1A0 /* Building.swift */, + 73B6E0862CCB34AA006DD4F0 /* SocialProvider.swift */, ); path = Models; sourceTree = ""; @@ -1601,6 +1604,7 @@ BE9413BF28C2157600171060 /* NotificationDto.swift in Sources */, DCD41A7527E5CEA500CF380E /* AppState.swift in Sources */, CE4777F32A6ADCAC00E03253 /* VacancyRepository.swift in Sources */, + 73B6E0882CCB34B2006DD4F0 /* SocialProvider.swift in Sources */, DC1E0ED4287738F2005632A3 /* TimetableRouter.swift in Sources */, DC29159F28660F7800FE5F9A /* ReviewScene.swift in Sources */, CE3384BA2A86704100437CC5 /* FriendsService.swift in Sources */, diff --git a/SNUTT-2022/SNUTT/AppState/States/UserState.swift b/SNUTT-2022/SNUTT/AppState/States/UserState.swift index f1d16c81..f3d6a8a9 100644 --- a/SNUTT-2022/SNUTT/AppState/States/UserState.swift +++ b/SNUTT-2022/SNUTT/AppState/States/UserState.swift @@ -10,6 +10,7 @@ import SwiftUI class UserState { @Published var accessToken: String? @Published var current: User? + @Published var socialProvider: SocialProvider? /// Primary key of User. Required to logout. This is not `localId`. var userId: String? diff --git a/SNUTT-2022/SNUTT/Models/SocialProvider.swift b/SNUTT-2022/SNUTT/Models/SocialProvider.swift new file mode 100644 index 00000000..8473eed0 --- /dev/null +++ b/SNUTT-2022/SNUTT/Models/SocialProvider.swift @@ -0,0 +1,26 @@ +// +// SocialProvider.swift +// SNUTT +// +// Created by 이채민 on 10/25/24. +// + +import Foundation + +struct SocialProvider { + var local: Bool + var facebook: Bool + var google: Bool + var kakao: Bool + var apple: Bool +} + +extension SocialProvider { + init(from dto: SocialProviderDto) { + local = dto.local + facebook = dto.facebook + google = dto.google + kakao = dto.kakao + apple = dto.apple + } +} diff --git a/SNUTT-2022/SNUTT/Repositories/Dto/UserDto.swift b/SNUTT-2022/SNUTT/Repositories/Dto/UserDto.swift index 8a81c8dc..85d15abe 100644 --- a/SNUTT-2022/SNUTT/Repositories/Dto/UserDto.swift +++ b/SNUTT-2022/SNUTT/Repositories/Dto/UserDto.swift @@ -52,3 +52,11 @@ struct SendVerificationCodeDto: Decodable { struct EmailVerifiedDto: Decodable { let is_email_verified: Bool } + +struct SocialProviderDto: Codable { + let local: Bool + let facebook: Bool + let google: Bool + let kakao: Bool + let apple: Bool +} From 1f1444dee80e54ba78034b82eb220d98ae9a0580 Mon Sep 17 00:00:00 2001 From: chaemin2001 Date: Fri, 25 Oct 2024 11:34:45 +0900 Subject: [PATCH 2/6] Add API --- .../Repositories/Router/UserRouter.swift | 39 +++++++++++++-- .../SNUTT/Repositories/UserRepository.swift | 48 +++++++++++++++++-- SNUTT-2022/SNUTT/Services/UserService.swift | 43 +++++++++++++++-- 3 files changed, 119 insertions(+), 11 deletions(-) diff --git a/SNUTT-2022/SNUTT/Repositories/Router/UserRouter.swift b/SNUTT-2022/SNUTT/Repositories/Router/UserRouter.swift index 420c12e7..d225123f 100644 --- a/SNUTT-2022/SNUTT/Repositories/Router/UserRouter.swift +++ b/SNUTT-2022/SNUTT/Repositories/Router/UserRouter.swift @@ -11,7 +11,7 @@ import Foundation enum UserRouter: Router { var baseURL: URL { switch self { - case .getUser, .changeNickname: + case .getUser, .getSocialProvider, .changeNickname: return URL(string: NetworkConfiguration.serverV1BaseURL + "/users")! default: return URL(string: NetworkConfiguration.serverV1BaseURL + "/user")! @@ -21,10 +21,15 @@ enum UserRouter: Router { static let shouldAddToken: Bool = true case getUser + case getSocialProvider case changeNickname(nickname: String) case changePassword(oldPassword: String, newPassword: String) case addLocalId(localId: String, localPassword: String) - case connectFacebook(fbId: String, fbToken: String) + case connectKakao(kakaoToken: String) + case disconnectKakao + case connectGoogle(googleToken: String) + case disconnectGoogle + case connectFacebook(facebookId: String, facebookToken: String) case disconnectFacebook case getFB case addDevice(fcmToken: String) @@ -37,12 +42,22 @@ enum UserRouter: Router { switch self { case .getUser: return .get + case .getSocialProvider: + return .get case .changeNickname: return .patch case .changePassword: return .put case .addLocalId: return .post + case .connectKakao: + return .post + case .disconnectKakao: + return .delete + case .connectGoogle: + return .post + case .disconnectGoogle: + return .delete case .connectFacebook: return .post case .disconnectFacebook: @@ -66,8 +81,14 @@ enum UserRouter: Router { switch self { case .getUser, .changeNickname: return "/me" + case .getSocialProvider: + return "/me/social_providers" case .changePassword, .addLocalId: return "/password" + case .connectKakao, .disconnectKakao: + return "/kakao" + case .connectGoogle, .disconnectGoogle: + return "/google" case .connectFacebook, .disconnectFacebook, .getFB: return "/facebook" case let .addDevice(fcmToken): @@ -87,14 +108,24 @@ enum UserRouter: Router { switch self { case .getUser: return nil + case .getSocialProvider: + return nil case let .changeNickname(nickname): return ["nickname": nickname] case let .changePassword(oldPassword, newPassword): return ["old_password": oldPassword, "new_password": newPassword] case let .addLocalId(localId, localPasword): return ["id": localId, "password": localPasword] - case let .connectFacebook(fbId, fbToken): - return ["fb_id": fbId, "fb_token": fbToken] + case let .connectKakao(kakaoToken): + return ["token": kakaoToken] + case .disconnectKakao: + return nil + case let .connectGoogle(googleToken): + return ["token": googleToken] + case .disconnectGoogle: + return nil + case let .connectFacebook(facebookId, facebookToken): + return ["fb_id": facebookId, "fb_token": facebookToken] case .disconnectFacebook: return nil case .getFB: diff --git a/SNUTT-2022/SNUTT/Repositories/UserRepository.swift b/SNUTT-2022/SNUTT/Repositories/UserRepository.swift index ed28250c..f4bc49dc 100644 --- a/SNUTT-2022/SNUTT/Repositories/UserRepository.swift +++ b/SNUTT-2022/SNUTT/Repositories/UserRepository.swift @@ -10,8 +10,13 @@ import Foundation protocol UserRepositoryProtocol { func fetchUser() async throws -> UserDto + func fetchSocialProvider() async throws -> SocialProviderDto func changeNickname(to nickname: String) async throws -> UserDto - func connectFacebook(fbId: String, fbToken: String) async throws -> TokenResponseDto + func connectKakao(kakaoToken: String) async throws -> TokenResponseDto + func disconnectKakao() async throws -> TokenResponseDto + func connectGoogle(googleToken: String) async throws -> TokenResponseDto + func disconnectGoogle() async throws -> TokenResponseDto + func connectFacebook(facebookId: String, facebookToken: String) async throws -> TokenResponseDto func disconnectFacebook() async throws -> TokenResponseDto func changePassword(from oldPassword: String, to newPassword: String) async throws -> TokenResponseDto func addLocalId(localId: String, localPassword: String) async throws -> TokenResponseDto @@ -35,6 +40,13 @@ class UserRepository: UserRepositoryProtocol { .serializingDecodable(UserDto.self) .handlingError() } + + func fetchSocialProvider() async throws -> SocialProviderDto { + return try await session + .request(UserRouter.getSocialProvider) + .serializingDecodable(SocialProviderDto.self) + .handlingError() + } func changeNickname(to nickname: String) async throws -> UserDto { return try await session @@ -42,10 +54,40 @@ class UserRepository: UserRepositoryProtocol { .serializingDecodable(UserDto.self) .handlingError() } + + func connectKakao(kakaoToken: String) async throws -> + TokenResponseDto { + return try await session + .request(UserRouter.connectKakao(kakaoToken: kakaoToken)) + .serializingDecodable(TokenResponseDto.self) + .handlingError() + } + + func disconnectKakao() async throws -> TokenResponseDto { + return try await session + .request(UserRouter.disconnectKakao) + .serializingDecodable(TokenResponseDto.self) + .handlingError() + } + + func connectGoogle(googleToken: String) async throws -> + TokenResponseDto { + return try await session + .request(UserRouter.connectGoogle(googleToken: googleToken)) + .serializingDecodable(TokenResponseDto.self) + .handlingError() + } + + func disconnectGoogle() async throws -> TokenResponseDto { + return try await session + .request(UserRouter.disconnectKakao) + .serializingDecodable(TokenResponseDto.self) + .handlingError() + } - func connectFacebook(fbId: String, fbToken: String) async throws -> TokenResponseDto { + func connectFacebook(facebookId: String, facebookToken: String) async throws -> TokenResponseDto { return try await session - .request(UserRouter.connectFacebook(fbId: fbId, fbToken: fbToken)) + .request(UserRouter.connectFacebook(facebookId: facebookId, facebookToken: facebookToken)) .serializingDecodable(TokenResponseDto.self) .handlingError() } diff --git a/SNUTT-2022/SNUTT/Services/UserService.swift b/SNUTT-2022/SNUTT/Services/UserService.swift index 24220cea..060416cc 100644 --- a/SNUTT-2022/SNUTT/Services/UserService.swift +++ b/SNUTT-2022/SNUTT/Services/UserService.swift @@ -10,12 +10,17 @@ import Foundation @MainActor protocol UserServiceProtocol: Sendable { func fetchUser() async throws + func fetchSocialProvider() async throws func changeNickname(to nickname: String) async throws func deleteUser() async throws func addLocalId(localId: String, localPassword: String) async throws func changePassword(from oldPassword: String, to newPassword: String) async throws + func connectKakao(kakaoToken: String) async throws + func disconnectKakao() async throws + func connectGoogle(googleToken: String) async throws + func disconnectGoogle() async throws + func connectFacebook(facebookId: String, facebookToken: String) async throws func disconnectFacebook() async throws - func connectFacebook(fbId: String, fbToken: String) async throws func addDevice(fcmToken: String) async throws func deleteDevice(fcmToken: String) async throws func sendVerificationCode(email: String) async throws @@ -35,6 +40,11 @@ struct UserService: UserServiceProtocol, UserAuthHandler { var userDefaultsRepository: UserDefaultsRepositoryProtocol { localRepositories.userDefaultsRepository } + + func fetchSocialProvider() async throws { + let dto = try await userRepository.fetchSocialProvider() + appState.user.socialProvider = SocialProvider(from: dto) + } func fetchUser() async throws { let dto = try await userRepository.fetchUser() @@ -55,9 +65,29 @@ struct UserService: UserServiceProtocol, UserAuthHandler { let dto = try await userRepository.addLocalId(localId: localId, localPassword: localPassword) try await updateToken(from: dto) } + + func connectKakao(kakaoToken: String) async throws { + let dto = try await userRepository.connectKakao(kakaoToken: kakaoToken) + try await updateToken(from: dto) + } + + func disconnectKakao() async throws { + let dto = try await userRepository.disconnectKakao() + try await updateToken(from: dto) + } + + func connectGoogle(googleToken: String) async throws { + let dto = try await userRepository.connectGoogle(googleToken: googleToken) + try await updateToken(from: dto) + } + + func disconnectGoogle() async throws { + let dto = try await userRepository.disconnectGoogle() + try await updateToken(from: dto) + } - func connectFacebook(fbId: String, fbToken: String) async throws { - let dto = try await userRepository.connectFacebook(fbId: fbId, fbToken: fbToken) + func connectFacebook(facebookId: String, facebookToken: String) async throws { + let dto = try await userRepository.connectFacebook(facebookId: facebookId, facebookToken: facebookToken) try await updateToken(from: dto) } @@ -114,12 +144,17 @@ struct UserService: UserServiceProtocol, UserAuthHandler { class FakeUserService: UserServiceProtocol { func fetchUser() {} + func fetchSocialProvider() {} func changeNickname(to _: String) async throws {} func deleteUser() async throws {} func addLocalId(localId _: String, localPassword _: String) async throws {} func changePassword(from _: String, to _: String) async throws {} + func connectKakao(kakaoToken _: String) async throws {} + func disconnectKakao() async throws {} + func connectGoogle(googleToken _: String) async throws {} + func disconnectGoogle() async throws {} + func connectFacebook(facebookId _: String, facebookToken _: String) async throws {} func disconnectFacebook() async throws {} - func connectFacebook(fbId _: String, fbToken _: String) async throws {} func addDevice(fcmToken _: String) async throws {} func deleteDevice(fcmToken _: String) async throws {} func sendVerificationCode(email _: String) async throws {} From 25ba3dd15a2c02d8e56f9b00f0628312f67b9f06 Mon Sep 17 00:00:00 2001 From: chaemin2001 Date: Fri, 25 Oct 2024 11:35:04 +0900 Subject: [PATCH 3/6] Add connection for google, kakao --- .../SNUTT/Extensions/FacebookLogin.swift | 4 +- .../IntegrateAccountViewModel.swift | 46 +++++++++++-- .../SNUTT/ViewModels/OnboardViewModel.swift | 4 +- .../SNUTT/ViewModels/SettingViewModel.swift | 8 +++ .../Settings/IntegrateAccountScene.swift | 67 +++++++++++++++++-- .../Views/Scenes/Settings/SettingScene.swift | 1 + 6 files changed, 114 insertions(+), 16 deletions(-) diff --git a/SNUTT-2022/SNUTT/Extensions/FacebookLogin.swift b/SNUTT-2022/SNUTT/Extensions/FacebookLogin.swift index b6c46e21..11db4ee8 100644 --- a/SNUTT-2022/SNUTT/Extensions/FacebookLogin.swift +++ b/SNUTT-2022/SNUTT/Extensions/FacebookLogin.swift @@ -9,7 +9,7 @@ import FacebookLogin protocol FacebookLoginProtocol: BaseViewModelProtocol { func performFacebookSignIn() - func handleFacebookToken(fbId: String, fbToken: String) async + func handleFacebookToken(facebookId: String, facebookToken: String) async } extension FacebookLoginProtocol { @@ -44,7 +44,7 @@ extension FacebookLoginProtocol { } Task { @MainActor in - await self.handleFacebookToken(fbId: fbUserId, fbToken: fbToken) + await self.handleFacebookToken(facebookId: fbUserId, facebookToken: fbToken) } } } diff --git a/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift b/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift index 83d16b83..e64774fb 100644 --- a/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift +++ b/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift @@ -10,14 +10,30 @@ import SwiftUI extension IntegrateAccountScene { class ViewModel: BaseViewModel, ObservableObject { - @Published var currentUser: User? + @Published var currentSocialProvider: SocialProvider? override init(container: DIContainer) { super.init(container: container) - appState.user.$current.assign(to: &$currentUser) + appState.user.$socialProvider.assign(to: &$currentSocialProvider) } - + + func detachKakao() async { + do { + try await services.userService.disconnectKakao() + } catch { + services.globalUIService.presentErrorAlert(error: error) + } + } + + func detachGoogle() async { + do { + try await services.userService.disconnectGoogle() + } catch { + services.globalUIService.presentErrorAlert(error: error) + } + } + func detachFacebook() async { do { try await services.userService.disconnectFacebook() @@ -28,10 +44,30 @@ extension IntegrateAccountScene { } } +extension IntegrateAccountScene.ViewModel: KakaoLoginProtocol { + func handleKakaoToken(kakaoToken: String) async { + do { + try await services.userService.connectKakao(kakaoToken: kakaoToken) + } catch { + services.globalUIService.presentErrorAlert(error: error) + } + } +} + +extension IntegrateAccountScene.ViewModel: GoogleLoginProtocol { + func handleGoogleToken(googleToken: String) async { + do { + try await services.userService.connectGoogle(googleToken: googleToken) + } catch { + services.globalUIService.presentErrorAlert(error: error) + } + } +} + extension IntegrateAccountScene.ViewModel: FacebookLoginProtocol { - func handleFacebookToken(fbId: String, fbToken: String) async { + func handleFacebookToken(facebookId: String, facebookToken: String) async { do { - try await services.userService.connectFacebook(fbId: fbId, fbToken: fbToken) + try await services.userService.connectFacebook(facebookId: facebookId, facebookToken: facebookToken) } catch { services.globalUIService.presentErrorAlert(error: error) } diff --git a/SNUTT-2022/SNUTT/ViewModels/OnboardViewModel.swift b/SNUTT-2022/SNUTT/ViewModels/OnboardViewModel.swift index 938f2406..7803742b 100644 --- a/SNUTT-2022/SNUTT/ViewModels/OnboardViewModel.swift +++ b/SNUTT-2022/SNUTT/ViewModels/OnboardViewModel.swift @@ -78,9 +78,9 @@ extension OnboardScene { } extension OnboardScene.ViewModel: FacebookLoginProtocol { - func handleFacebookToken(fbId _: String, fbToken: String) async { + func handleFacebookToken(facebookId _: String, facebookToken: String) async { do { - try await services.authService.loginWithFacebook(facebookToken: fbToken) + try await services.authService.loginWithFacebook(facebookToken: facebookToken) } catch { handleSocialLoginError(error) } diff --git a/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift b/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift index fefd31b5..bd57f062 100644 --- a/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift +++ b/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift @@ -77,6 +77,14 @@ class SettingViewModel: BaseViewModel, ObservableObject { services.globalUIService.presentErrorAlert(error: error) } } + + func fetchSocialProvider() async { + do { + try await services.userService.fetchSocialProvider() + } catch { + services.globalUIService.presentErrorAlert(error: error) + } + } var versionString: String { let appVersion = AppMetadata.appVersion.value diff --git a/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift b/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift index 8c67f026..f1c5a925 100644 --- a/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift +++ b/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift @@ -9,31 +9,84 @@ import SwiftUI struct IntegrateAccountScene: View { @ObservedObject var viewModel: ViewModel - @State private var isDisconnectFBAlertPresented: Bool = false + @State private var isDisconnectKakaoAlertPresented: Bool = false + @State private var isDisconnectGoogleAlertPresented: Bool = false + @State private var isDisconnectAppleAlertPresented: Bool = false + @State private var isDisconnectFacebookAlertPresented: Bool = false var body: some View { List { - if let facebookName = viewModel.currentUser?.fbName { - SettingsTextItem(title: "페이스북 이름", detail: facebookName) + if (viewModel.currentSocialProvider?.kakao == true) { + SettingsButtonItem(title: "카카오 계정 연동 해제", role: .destructive) { + isDisconnectKakaoAlertPresented = true + } + } else { + SettingsButtonItem(title: "카카오 계정 연동") { + viewModel.performKakaoSignIn() + } + } + if (viewModel.currentSocialProvider?.google == true) { + SettingsButtonItem(title: "구글 계정 연동 해제", role: .destructive) { + isDisconnectGoogleAlertPresented = true + } + } else { + SettingsButtonItem(title: "구글 계정 연동") { + viewModel.performGoogleSignIn() + } + } + if (viewModel.currentSocialProvider?.apple == true) { + SettingsButtonItem(title: "애플 계정 연동 해제", role: .destructive) { + isDisconnectAppleAlertPresented = true + } + } else { + SettingsButtonItem(title: "애플 계정 연동") { + // 애플 + } + } + if (viewModel.currentSocialProvider?.facebook == true) { SettingsButtonItem(title: "페이스북 계정 연동 해제", role: .destructive) { - isDisconnectFBAlertPresented = true + isDisconnectFacebookAlertPresented = true } } else { SettingsButtonItem(title: "페이스북 계정 연동") { viewModel.performFacebookSignIn() } } + + } + .alert("카카오 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectKakaoAlertPresented) { + Button("취소", role: .cancel, action: {}) + Button("해제", role: .destructive, action: { + Task { + await viewModel.detachKakao() + } + }) + } + .alert("구글 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectGoogleAlertPresented) { + Button("취소", role: .cancel, action: {}) + Button("해제", role: .destructive, action: { + Task { + await viewModel.detachGoogle() + } + }) + } + .alert("애플 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectAppleAlertPresented) { + Button("취소", role: .cancel, action: {}) + Button("해제", role: .destructive, action: { + Task { + // 애플 + } + }) } - .alert("페이스북 계정 연동 해제", isPresented: $isDisconnectFBAlertPresented) { + .alert("페이스북 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectFacebookAlertPresented) { Button("취소", role: .cancel, action: {}) Button("해제", role: .destructive, action: { Task { await viewModel.detachFacebook() } }) - } message: { - Text("페이스북 연동을 해제하시겠습니까?") } + .navigationTitle("SNS 계정 연동 및 해제") } } diff --git a/SNUTT-2022/SNUTT/Views/Scenes/Settings/SettingScene.swift b/SNUTT-2022/SNUTT/Views/Scenes/Settings/SettingScene.swift index 924cd77e..246d3fa3 100644 --- a/SNUTT-2022/SNUTT/Views/Scenes/Settings/SettingScene.swift +++ b/SNUTT-2022/SNUTT/Views/Scenes/Settings/SettingScene.swift @@ -108,6 +108,7 @@ struct SettingScene: View { .navigationBarTitleDisplayMode(.inline) .task { await viewModel.fetchUser() + await viewModel.fetchSocialProvider() await viewModel.getThemeList() } From 2efc6398c695aec6802af282bfc6684cd75ea702 Mon Sep 17 00:00:00 2001 From: chaemin2001 Date: Fri, 25 Oct 2024 11:39:18 +0900 Subject: [PATCH 4/6] Update refresh --- SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift b/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift index e64774fb..2465bee5 100644 --- a/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift +++ b/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift @@ -21,6 +21,7 @@ extension IntegrateAccountScene { func detachKakao() async { do { try await services.userService.disconnectKakao() + try await services.userService.fetchSocialProvider() } catch { services.globalUIService.presentErrorAlert(error: error) } @@ -29,6 +30,7 @@ extension IntegrateAccountScene { func detachGoogle() async { do { try await services.userService.disconnectGoogle() + try await services.userService.fetchSocialProvider() } catch { services.globalUIService.presentErrorAlert(error: error) } @@ -37,6 +39,7 @@ extension IntegrateAccountScene { func detachFacebook() async { do { try await services.userService.disconnectFacebook() + try await services.userService.fetchSocialProvider() } catch { services.globalUIService.presentErrorAlert(error: error) } @@ -48,6 +51,7 @@ extension IntegrateAccountScene.ViewModel: KakaoLoginProtocol { func handleKakaoToken(kakaoToken: String) async { do { try await services.userService.connectKakao(kakaoToken: kakaoToken) + try await services.userService.fetchSocialProvider() } catch { services.globalUIService.presentErrorAlert(error: error) } @@ -58,6 +62,7 @@ extension IntegrateAccountScene.ViewModel: GoogleLoginProtocol { func handleGoogleToken(googleToken: String) async { do { try await services.userService.connectGoogle(googleToken: googleToken) + try await services.userService.fetchSocialProvider() } catch { services.globalUIService.presentErrorAlert(error: error) } @@ -68,6 +73,7 @@ extension IntegrateAccountScene.ViewModel: FacebookLoginProtocol { func handleFacebookToken(facebookId: String, facebookToken: String) async { do { try await services.userService.connectFacebook(facebookId: facebookId, facebookToken: facebookToken) + try await services.userService.fetchSocialProvider() } catch { services.globalUIService.presentErrorAlert(error: error) } From 08e7eb38ab535237fff069b8cd139ffb30b2948d Mon Sep 17 00:00:00 2001 From: chaemin2001 Date: Wed, 30 Oct 2024 22:53:29 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EC=95=A0=ED=94=8C=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20Comment=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Settings/IntegrateAccountScene.swift | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift b/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift index f1c5a925..49dada9f 100644 --- a/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift +++ b/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift @@ -34,15 +34,15 @@ struct IntegrateAccountScene: View { viewModel.performGoogleSignIn() } } - if (viewModel.currentSocialProvider?.apple == true) { - SettingsButtonItem(title: "애플 계정 연동 해제", role: .destructive) { - isDisconnectAppleAlertPresented = true - } - } else { - SettingsButtonItem(title: "애플 계정 연동") { - // 애플 - } - } +// if (viewModel.currentSocialProvider?.apple == true) { +// SettingsButtonItem(title: "애플 계정 연동 해제", role: .destructive) { +// isDisconnectAppleAlertPresented = true +// } +// } else { +// SettingsButtonItem(title: "애플 계정 연동") { +// +// } +// } if (viewModel.currentSocialProvider?.facebook == true) { SettingsButtonItem(title: "페이스북 계정 연동 해제", role: .destructive) { isDisconnectFacebookAlertPresented = true @@ -70,14 +70,14 @@ struct IntegrateAccountScene: View { } }) } - .alert("애플 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectAppleAlertPresented) { - Button("취소", role: .cancel, action: {}) - Button("해제", role: .destructive, action: { - Task { - // 애플 - } - }) - } +// .alert("애플 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectAppleAlertPresented) { +// Button("취소", role: .cancel, action: {}) +// Button("해제", role: .destructive, action: { +// Task { +// +// } +// }) +// } .alert("페이스북 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectFacebookAlertPresented) { Button("취소", role: .cancel, action: {}) Button("해제", role: .destructive, action: { From 4bf1ff2d4f8df1f49a91dd6dd9fcb58874bbfe68 Mon Sep 17 00:00:00 2001 From: chaemin2001 Date: Wed, 30 Oct 2024 13:55:38 +0000 Subject: [PATCH 6/6] Apply SwiftFormat changes --- .../SNUTT/Repositories/UserRepository.swift | 16 +++++++++------- SNUTT-2022/SNUTT/Services/UserService.swift | 10 +++++----- .../ViewModels/IntegrateAccountViewModel.swift | 6 +++--- .../SNUTT/ViewModels/SettingViewModel.swift | 2 +- .../Scenes/Settings/IntegrateAccountScene.swift | 7 +++---- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/SNUTT-2022/SNUTT/Repositories/UserRepository.swift b/SNUTT-2022/SNUTT/Repositories/UserRepository.swift index f4bc49dc..a661d083 100644 --- a/SNUTT-2022/SNUTT/Repositories/UserRepository.swift +++ b/SNUTT-2022/SNUTT/Repositories/UserRepository.swift @@ -40,7 +40,7 @@ class UserRepository: UserRepositoryProtocol { .serializingDecodable(UserDto.self) .handlingError() } - + func fetchSocialProvider() async throws -> SocialProviderDto { return try await session .request(UserRouter.getSocialProvider) @@ -54,30 +54,32 @@ class UserRepository: UserRepositoryProtocol { .serializingDecodable(UserDto.self) .handlingError() } - + func connectKakao(kakaoToken: String) async throws -> - TokenResponseDto { + TokenResponseDto + { return try await session .request(UserRouter.connectKakao(kakaoToken: kakaoToken)) .serializingDecodable(TokenResponseDto.self) .handlingError() } - + func disconnectKakao() async throws -> TokenResponseDto { return try await session .request(UserRouter.disconnectKakao) .serializingDecodable(TokenResponseDto.self) .handlingError() } - + func connectGoogle(googleToken: String) async throws -> - TokenResponseDto { + TokenResponseDto + { return try await session .request(UserRouter.connectGoogle(googleToken: googleToken)) .serializingDecodable(TokenResponseDto.self) .handlingError() } - + func disconnectGoogle() async throws -> TokenResponseDto { return try await session .request(UserRouter.disconnectKakao) diff --git a/SNUTT-2022/SNUTT/Services/UserService.swift b/SNUTT-2022/SNUTT/Services/UserService.swift index 060416cc..6abde581 100644 --- a/SNUTT-2022/SNUTT/Services/UserService.swift +++ b/SNUTT-2022/SNUTT/Services/UserService.swift @@ -40,7 +40,7 @@ struct UserService: UserServiceProtocol, UserAuthHandler { var userDefaultsRepository: UserDefaultsRepositoryProtocol { localRepositories.userDefaultsRepository } - + func fetchSocialProvider() async throws { let dto = try await userRepository.fetchSocialProvider() appState.user.socialProvider = SocialProvider(from: dto) @@ -65,22 +65,22 @@ struct UserService: UserServiceProtocol, UserAuthHandler { let dto = try await userRepository.addLocalId(localId: localId, localPassword: localPassword) try await updateToken(from: dto) } - + func connectKakao(kakaoToken: String) async throws { let dto = try await userRepository.connectKakao(kakaoToken: kakaoToken) try await updateToken(from: dto) } - + func disconnectKakao() async throws { let dto = try await userRepository.disconnectKakao() try await updateToken(from: dto) } - + func connectGoogle(googleToken: String) async throws { let dto = try await userRepository.connectGoogle(googleToken: googleToken) try await updateToken(from: dto) } - + func disconnectGoogle() async throws { let dto = try await userRepository.disconnectGoogle() try await updateToken(from: dto) diff --git a/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift b/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift index 2465bee5..714969ac 100644 --- a/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift +++ b/SNUTT-2022/SNUTT/ViewModels/IntegrateAccountViewModel.swift @@ -17,7 +17,7 @@ extension IntegrateAccountScene { appState.user.$socialProvider.assign(to: &$currentSocialProvider) } - + func detachKakao() async { do { try await services.userService.disconnectKakao() @@ -26,7 +26,7 @@ extension IntegrateAccountScene { services.globalUIService.presentErrorAlert(error: error) } } - + func detachGoogle() async { do { try await services.userService.disconnectGoogle() @@ -35,7 +35,7 @@ extension IntegrateAccountScene { services.globalUIService.presentErrorAlert(error: error) } } - + func detachFacebook() async { do { try await services.userService.disconnectFacebook() diff --git a/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift b/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift index bd57f062..6d0108e0 100644 --- a/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift +++ b/SNUTT-2022/SNUTT/ViewModels/SettingViewModel.swift @@ -77,7 +77,7 @@ class SettingViewModel: BaseViewModel, ObservableObject { services.globalUIService.presentErrorAlert(error: error) } } - + func fetchSocialProvider() async { do { try await services.userService.fetchSocialProvider() diff --git a/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift b/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift index 49dada9f..ea026e60 100644 --- a/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift +++ b/SNUTT-2022/SNUTT/Views/Scenes/Settings/IntegrateAccountScene.swift @@ -16,7 +16,7 @@ struct IntegrateAccountScene: View { var body: some View { List { - if (viewModel.currentSocialProvider?.kakao == true) { + if viewModel.currentSocialProvider?.kakao == true { SettingsButtonItem(title: "카카오 계정 연동 해제", role: .destructive) { isDisconnectKakaoAlertPresented = true } @@ -25,7 +25,7 @@ struct IntegrateAccountScene: View { viewModel.performKakaoSignIn() } } - if (viewModel.currentSocialProvider?.google == true) { + if viewModel.currentSocialProvider?.google == true { SettingsButtonItem(title: "구글 계정 연동 해제", role: .destructive) { isDisconnectGoogleAlertPresented = true } @@ -43,7 +43,7 @@ struct IntegrateAccountScene: View { // // } // } - if (viewModel.currentSocialProvider?.facebook == true) { + if viewModel.currentSocialProvider?.facebook == true { SettingsButtonItem(title: "페이스북 계정 연동 해제", role: .destructive) { isDisconnectFacebookAlertPresented = true } @@ -52,7 +52,6 @@ struct IntegrateAccountScene: View { viewModel.performFacebookSignIn() } } - } .alert("카카오 계정 연동을 해제하시겠습니까?", isPresented: $isDisconnectKakaoAlertPresented) { Button("취소", role: .cancel, action: {})