diff --git a/WSSiOS/WSSiOS.xcodeproj/project.pbxproj b/WSSiOS/WSSiOS.xcodeproj/project.pbxproj index 33c6f2ea5..5e4867f29 100644 --- a/WSSiOS/WSSiOS.xcodeproj/project.pbxproj +++ b/WSSiOS/WSSiOS.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ 2C9A196D2C5692370043044A /* MyPageSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9A196C2C5692360043044A /* MyPageSettingView.swift */; }; 2C9A196F2C56923B0043044A /* MyPageSettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9A196E2C56923B0043044A /* MyPageSettingViewController.swift */; }; 2C9A19712C56925F0043044A /* MyPageInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9A19702C56925F0043044A /* MyPageInfoViewModel.swift */; }; + 2C9BDDA42CA79BCA0026D038 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 2C9BDDA32CA79BCA0026D038 /* Then */; }; 2C9CBDB12C5BB4340084481F /* BlocksService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9CBDB02C5BB4340084481F /* BlocksService.swift */; }; 2CA2F6522B527B590045B4C2 /* MyPageModalAvatarFeatureLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA2F6512B527B590045B4C2 /* MyPageModalAvatarFeatureLabelView.swift */; }; 2CA2F65B2B53041E0045B4C2 /* LibraryBaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA2F65A2B53041E0045B4C2 /* LibraryBaseViewController.swift */; }; @@ -62,7 +63,9 @@ 2CA2F6622B530BBF0045B4C2 /* LibraryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA2F6612B530BBF0045B4C2 /* LibraryCollectionViewCell.swift */; }; 2CB613F32B575E4500FC3F89 /* MyPageInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CB613F22B575E4500FC3F89 /* MyPageInfoViewController.swift */; }; 2CB613F52B575E6A00FC3F89 /* MyPageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CB613F42B575E6A00FC3F89 /* MyPageInfoView.swift */; }; - 2CC4CCCB2C9AF8B000FB863B /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 2CC4CCCA2C9AF8B000FB863B /* Then */; }; + 2CC4CCD82C9B340900FB863B /* MyPageProfileVisibilityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC4CCD72C9B340800FB863B /* MyPageProfileVisibilityView.swift */; }; + 2CC4CCDA2C9B341300FB863B /* MyPageProfileVisibilityViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC4CCD92C9B341200FB863B /* MyPageProfileVisibilityViewModel.swift */; }; + 2CC4CCDC2C9B341900FB863B /* MyPageProfileVisibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC4CCDB2C9B341900FB863B /* MyPageProfileVisibilityViewController.swift */; }; 2CCBF9EE2B4C1FC500D787C2 /* MyPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCBF9ED2B4C1FC500D787C2 /* MyPageViewController.swift */; }; 2CCBF9F02B4C1FD800D787C2 /* MyPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCBF9EF2B4C1FD800D787C2 /* MyPageView.swift */; }; 2CCBF9F22B4D347B00D787C2 /* WSSMainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCBF9F12B4D347B00D787C2 /* WSSMainButton.swift */; }; @@ -384,6 +387,9 @@ 2CA2F6612B530BBF0045B4C2 /* LibraryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryCollectionViewCell.swift; sourceTree = ""; }; 2CB613F22B575E4500FC3F89 /* MyPageInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageInfoViewController.swift; sourceTree = ""; }; 2CB613F42B575E6A00FC3F89 /* MyPageInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageInfoView.swift; sourceTree = ""; }; + 2CC4CCD72C9B340800FB863B /* MyPageProfileVisibilityView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyPageProfileVisibilityView.swift; sourceTree = ""; }; + 2CC4CCD92C9B341200FB863B /* MyPageProfileVisibilityViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyPageProfileVisibilityViewModel.swift; sourceTree = ""; }; + 2CC4CCDB2C9B341900FB863B /* MyPageProfileVisibilityViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyPageProfileVisibilityViewController.swift; sourceTree = ""; }; 2CCBF9ED2B4C1FC500D787C2 /* MyPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageViewController.swift; sourceTree = ""; }; 2CCBF9EF2B4C1FD800D787C2 /* MyPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageView.swift; sourceTree = ""; }; 2CCBF9F12B4D347B00D787C2 /* WSSMainButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WSSMainButton.swift; sourceTree = ""; }; @@ -649,7 +655,7 @@ files = ( 3999BFEE2B4E6CA000984832 /* UIImageViewAlignedSwift in Frameworks */, CD3E5A852B54254F00C0A659 /* RxKeyboard in Frameworks */, - 2CC4CCCB2C9AF8B000FB863B /* Then in Frameworks */, + 2C9BDDA42CA79BCA0026D038 /* Then in Frameworks */, 2CD229442B42E7A2005400BE /* RxRelay in Frameworks */, 2CD229392B42E77F005400BE /* Kingfisher in Frameworks */, 2CD229342B42E771005400BE /* SnapKit in Frameworks */, @@ -813,6 +819,7 @@ 2CCBF9EA2B4C1E3700D787C2 /* MyPageViewController */ = { isa = PBXGroup; children = ( + 2CC4CCDB2C9B341900FB863B /* MyPageProfileVisibilityViewController.swift */, 2CCBF9ED2B4C1FC500D787C2 /* MyPageViewController.swift */, 2C5D0F5E2B50523B00C76D3C /* MyPageChangeNicknameViewController.swift */, 2C9A196E2C56923B0043044A /* MyPageSettingViewController.swift */, @@ -827,6 +834,7 @@ 2CCBF9EB2B4C1E4600D787C2 /* MyPageView */ = { isa = PBXGroup; children = ( + 2CC4CCD72C9B340800FB863B /* MyPageProfileVisibilityView.swift */, 2CCBF9EF2B4C1FD800D787C2 /* MyPageView.swift */, 2C5D0F602B50525700C76D3C /* MyPageChangeNicknameView.swift */, 2CB613F42B575E6A00FC3F89 /* MyPageInfoView.swift */, @@ -843,6 +851,7 @@ 2CCBF9FD2B4DBF4200D787C2 /* MyPageViewModel */ = { isa = PBXGroup; children = ( + 2CC4CCD92C9B341200FB863B /* MyPageProfileVisibilityViewModel.swift */, 2C9A19702C56925F0043044A /* MyPageInfoViewModel.swift */, 2CCBF9FF2B4DBFD200D787C2 /* MyPageChangeNickNameViewModel.swift */, 2C9A19682C567D6B0043044A /* MyPageViewModel.swift */, @@ -2120,7 +2129,7 @@ 39EF97AB2B53E43800D2148B /* Lottie */, CD3E5A842B54254F00C0A659 /* RxKeyboard */, 3916EC852B89B42C007835B5 /* RxGesture */, - 2CC4CCCA2C9AF8B000FB863B /* Then */, + 2C9BDDA32CA79BCA0026D038 /* Then */, ); productName = WSSiOS; productReference = 2CD229182B42E685005400BE /* WSSiOS.app */; @@ -2158,7 +2167,7 @@ 3999BFEC2B4E6CA000984832 /* XCRemoteSwiftPackageReference "UIImageViewAlignedSwift" */, CD3E5A832B54254F00C0A659 /* XCRemoteSwiftPackageReference "RxKeyboard" */, 3916EC842B89B42C007835B5 /* XCRemoteSwiftPackageReference "RxGesture" */, - 2CC4CCC92C9AF8B000FB863B /* XCRemoteSwiftPackageReference "Then" */, + 2C9BDDA22CA79BCA0026D038 /* XCRemoteSwiftPackageReference "Then" */, ); productRefGroup = 2CD229192B42E685005400BE /* Products */; projectDirPath = ""; @@ -2228,6 +2237,7 @@ CD3E5A822B54253E00C0A659 /* MemoEditViewController.swift in Sources */, B9AC1BD22BF0B485006EDE92 /* HomeNoticeView.swift in Sources */, C9063A972BD3F868006AD8F9 /* HomeRealtimePopularView.swift in Sources */, + 2CC4CCDC2C9B341900FB863B /* MyPageProfileVisibilityViewController.swift in Sources */, A1708F182B4D8E2F00E35E50 /* HomeView.swift in Sources */, 2C19A4FD2BBA90E700D4D151 /* WSSDropDownTableView.swift in Sources */, 2C9A19672C567CC20043044A /* MyPageProfileHeaderView.swift in Sources */, @@ -2276,6 +2286,7 @@ CD6F49552C705B22005AD392 /* FeedNovelConnectCollectionViewCell.swift in Sources */, 2C9A19692C567D6B0043044A /* MyPageViewModel.swift in Sources */, C9AF1AE22BCC234300208BC9 /* HomeTodayPopularView.swift in Sources */, + 2CC4CCD82C9B340900FB863B /* MyPageProfileVisibilityView.swift in Sources */, 2CD9115E2C0D8A28006B8D72 /* FeedGenreViewController.swift in Sources */, 39F687002C6F60400065999F /* ReadStatus.swift in Sources */, 39CC16902B529AB6003F56AE /* RegisterNormalReadStatusView.swift in Sources */, @@ -2375,6 +2386,7 @@ CD39F2DA2B50DDBF00B73A5C /* TrashNovelDetailInfoGenreView.swift in Sources */, 39F686FE2C6F5D5C0065999F /* NovelDetailInfoReviewGraphStackView.swift in Sources */, 2CD9114A2C0D8948006B8D72 /* FeedContentView.swift in Sources */, + 2CC4CCDA2C9B341300FB863B /* MyPageProfileVisibilityViewModel.swift in Sources */, B9A0FD6E2BFCF16F0004252E /* HomeRealtimePopularContentTableViewCell.swift in Sources */, C99DDFDF2C8613C900EDC0C4 /* SearchViewController.swift in Sources */, 2CD9114A2C0D8948006B8D72 /* FeedContentView.swift in Sources */, @@ -2716,7 +2728,7 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 2CC4CCC92C9AF8B000FB863B /* XCRemoteSwiftPackageReference "Then" */ = { + 2C9BDDA22CA79BCA0026D038 /* XCRemoteSwiftPackageReference "Then" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/devxoul/Then"; requirement = { @@ -2783,9 +2795,9 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 2CC4CCCA2C9AF8B000FB863B /* Then */ = { + 2C9BDDA32CA79BCA0026D038 /* Then */ = { isa = XCSwiftPackageProductDependency; - package = 2CC4CCC92C9AF8B000FB863B /* XCRemoteSwiftPackageReference "Then" */; + package = 2C9BDDA22CA79BCA0026D038 /* XCRemoteSwiftPackageReference "Then" */; productName = Then; }; 2CD229332B42E771005400BE /* SnapKit */ = { diff --git a/WSSiOS/WSSiOS/App/SceneDelegate.swift b/WSSiOS/WSSiOS/App/SceneDelegate.swift index c7d23e0f3..78563f774 100644 --- a/WSSiOS/WSSiOS/App/SceneDelegate.swift +++ b/WSSiOS/WSSiOS/App/SceneDelegate.swift @@ -14,7 +14,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } - let navigationController = UINavigationController(rootViewController: WSSTabBarController()) + let navigationController = UINavigationController(rootViewController: MyPageSettingViewController()) navigationController.isNavigationBarHidden = true self.window = UIWindow(windowScene: windowScene) diff --git a/WSSiOS/WSSiOS/Network/User/UserService.swift b/WSSiOS/WSSiOS/Network/User/UserService.swift index 3dce12c8a..2d1bae2f0 100644 --- a/WSSiOS/WSSiOS/Network/User/UserService.swift +++ b/WSSiOS/WSSiOS/Network/User/UserService.swift @@ -13,11 +13,19 @@ protocol UserService { func getUserData() -> Single func patchUserName(userNickName: String) -> Single func getUserCharacterData() -> Single + func getUserProfileVisibility() -> Single + func patchUserProfileVisibility(isProfilePublic: Bool) -> Single } final class DefaultUserService: NSObject, Networking { private let userNickNameQueryItems: [URLQueryItem] = [URLQueryItem(name: "userNickname", value: String(describing: 10))] + + func makeUserProfileVisibilityQueryItems(isProfilePublic: Bool) -> [URLQueryItem] { + return [ URLQueryItem(name: "isProfilePublic", + value: String(isProfilePublic))] + } + private var urlSession: URLSession = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil) @@ -84,6 +92,46 @@ extension DefaultUserService: UserService { return Single.error(error) } } + + func getUserProfileVisibility() -> RxSwift.Single { + do { + let request = try makeHTTPRequest(method: .get, + path: URLs.MyPage.ProfileVisibility.isProfileVisibility, + headers: APIConstants.testTokenHeader, + body: nil) + NetworkLogger.log(request: request) + + return urlSession.rx.data(request: request) + .map { + try self.decode(data: $0, + to: UserProfileVisibility.self) + } + .asSingle() + } catch { + return Single.error(error) + } + } + + func patchUserProfileVisibility(isProfilePublic: Bool) -> RxSwift.Single { + guard let userProfileVisibility = try? JSONEncoder().encode(UserProfileVisibility(isProfilePublic: isProfilePublic)) else { + return .error(NetworkServiceError.invalidRequestError) + } + + do { + let request = try makeHTTPRequest(method: .patch, + path: URLs.MyPage.ProfileVisibility.isProfileVisibility, + queryItems: makeUserProfileVisibilityQueryItems(isProfilePublic: isProfilePublic), + headers: APIConstants.testTokenHeader, + body: nil) + NetworkLogger.log(request: request) + + return urlSession.rx.data(request: request) + .map { _ in } + .asSingle() + } catch { + return Single.error(error) + } + } } diff --git a/WSSiOS/WSSiOS/Resource/Assets.xcassets/icon/NovelDetail/icCacelModal.imageset/Contents.json b/WSSiOS/WSSiOS/Resource/Assets.xcassets/icon/NovelDetail/icCacelModal.imageset/Contents.json deleted file mode 100644 index 780bd4742..000000000 --- a/WSSiOS/WSSiOS/Resource/Assets.xcassets/icon/NovelDetail/icCacelModal.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "icCacelModal.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/WSSiOS/WSSiOS/Resource/Assets.xcassets/icon/NovelDetail/icCacelModal.imageset/icCacelModal.svg b/WSSiOS/WSSiOS/Resource/Assets.xcassets/icon/NovelDetail/icCacelModal.imageset/icCacelModal.svg deleted file mode 100644 index 16ba4f4ef..000000000 --- a/WSSiOS/WSSiOS/Resource/Assets.xcassets/icon/NovelDetail/icCacelModal.imageset/icCacelModal.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/WSSiOS/WSSiOS/Resource/Constants/Strings/StringLiterals.swift b/WSSiOS/WSSiOS/Resource/Constants/Strings/StringLiterals.swift index 306b191bf..398b22ae4 100644 --- a/WSSiOS/WSSiOS/Resource/Constants/Strings/StringLiterals.swift +++ b/WSSiOS/WSSiOS/Resource/Constants/Strings/StringLiterals.swift @@ -37,6 +37,7 @@ enum StringLiterals { static let myPageSetting = "설정" static let myPageInfo = "계정설정" static let myPageBlockUser = "차단유저 목록" + static let isVisibleProfile = "프로필 공개 설정" } } @@ -209,6 +210,11 @@ enum StringLiterals { case second = "리뷰, 피드 게시글, 댓글은 탈퇴 시 자동으로 삭제되지 않아요. 탈퇴 전 개별적으로 삭제해 주세요." case third = "계정 정보는 탈퇴 즉시 삭제되어 바로 재가입 가능하지만, 회원가입부터 작품 평가를 다시 해야 해요." } + + enum isVisiableProfile { + static let completeTitle = "완료" + static let isPrivateProfile = "비공개" + } } enum Library { diff --git a/WSSiOS/WSSiOS/Resource/Constants/URLs/URLs.swift b/WSSiOS/WSSiOS/Resource/Constants/URLs/URLs.swift index 085fbc930..f904f8437 100644 --- a/WSSiOS/WSSiOS/Resource/Constants/URLs/URLs.swift +++ b/WSSiOS/WSSiOS/Resource/Constants/URLs/URLs.swift @@ -73,6 +73,9 @@ enum URLs { return "/blocks/\(blockID)" } } + enum ProfileVisibility { + static let isProfileVisibility = "/users/profile-status" + } } enum Recommend { diff --git a/WSSiOS/WSSiOS/Resource/Extensions/UIViewController+.swift b/WSSiOS/WSSiOS/Resource/Extensions/UIViewController+.swift index 341619f97..10c49aee9 100644 --- a/WSSiOS/WSSiOS/Resource/Extensions/UIViewController+.swift +++ b/WSSiOS/WSSiOS/Resource/Extensions/UIViewController+.swift @@ -253,6 +253,19 @@ extension UIViewController { self.dismiss(animated: true) } + + func pushToMyPageProfileVisibilityViewController() { + let viewController = MyPageProfileVisibilityViewController( + viewModel: MyPageProfileVisibilityViewModel( + userRepository: DefaultUserRepository( + userService: DefaultUserService(), + blocksService: DefaultBlocksService() + ) + ) + ) + + self.navigationController?.pushViewController(viewController, animated: true) + } } extension UIViewController: UIGestureRecognizerDelegate { diff --git a/WSSiOS/WSSiOS/Source/Data/DTO/MyProfileResult.swift b/WSSiOS/WSSiOS/Source/Data/DTO/MyProfileResult.swift index e3ddd24c4..b8e2df4e6 100644 --- a/WSSiOS/WSSiOS/Source/Data/DTO/MyProfileResult.swift +++ b/WSSiOS/WSSiOS/Source/Data/DTO/MyProfileResult.swift @@ -41,3 +41,7 @@ struct UserAvatar: Codable { struct UserNickNameResult: Codable { let userNickname: String } + +struct UserProfileVisibility: Codable { + let isProfilePublic: Bool +} diff --git a/WSSiOS/WSSiOS/Source/Data/Repository/UserRepository.swift b/WSSiOS/WSSiOS/Source/Data/Repository/UserRepository.swift index 6189b6bbd..c91fbbaca 100644 --- a/WSSiOS/WSSiOS/Source/Data/Repository/UserRepository.swift +++ b/WSSiOS/WSSiOS/Source/Data/Repository/UserRepository.swift @@ -16,6 +16,8 @@ protocol UserRepository { func getUserCharacter() -> Observable func getBlocksList() -> Observable func deleteBlockUser(blockID: Int) -> Observable + func getUserProfileVisibility() -> Observable + func patchUserProfileVisibility(isProfilePublic: Bool) -> Observable } struct DefaultUserRepository: UserRepository { @@ -63,4 +65,14 @@ struct DefaultUserRepository: UserRepository { return blocksService.deleteBlockUser(blockID: blockID) .asObservable() } + + func getUserProfileVisibility() -> Observable { + return userService.getUserProfileVisibility() + .asObservable() + } + + func patchUserProfileVisibility(isProfilePublic: Bool) -> Observable { + return userService.patchUserProfileVisibility(isProfilePublic: isProfilePublic) + .asObservable() + } } diff --git a/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageView/MyPageProfileVisibilityView.swift b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageView/MyPageProfileVisibilityView.swift new file mode 100644 index 000000000..6461dd6ce --- /dev/null +++ b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageView/MyPageProfileVisibilityView.swift @@ -0,0 +1,118 @@ +// +// MyPageProfileVisibilityView.swift +// WSSiOS +// +// Created by 신지원 on 9/18/24. +// + +import UIKit + +import SnapKit +import Then + +final class MyPageProfileVisibilityView: UIView { + + //MARK: - Components + + private let profilePrivateView = UIView() + private let profilePrivateLabel = UILabel() + let profilePrivateToggleButton = UIButton() + + //In VC + let backButton = UIButton() + let completeButton = UIButton() + + // MARK: - Life Cycle + + override init(frame: CGRect) { + super.init(frame: frame) + + setUI() + setHierarchy() + setLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //MARK: - UI + + private func setUI() { + self.do { + $0.backgroundColor = .wssWhite + } + + profilePrivateView.do { + $0.backgroundColor = .wssWhite + } + + profilePrivateLabel.do { + $0.textColor = .wssBlack + $0.applyWSSFont(.body1, with: StringLiterals.MyPage.isVisiableProfile.isPrivateProfile) + } + + profilePrivateToggleButton.do { + $0.setImage(.checkDefault, for: .normal) + } + + backButton.do { + $0.setImage(.icNavigateLeft.withRenderingMode(.alwaysOriginal), for: .normal) + } + + completeButton.do { + $0.setTitle(StringLiterals.MyPage.isVisiableProfile.completeTitle, for: .normal) + $0.setTitleColor(.wssGray200, for: .normal) + $0.titleLabel?.applyWSSFont(.title2, with: StringLiterals.MyPage.isVisiableProfile.completeTitle) + } + } + + private func setHierarchy() { + self.addSubview(profilePrivateView) + profilePrivateView.addSubviews(profilePrivateLabel, + profilePrivateToggleButton) + } + + private func setLayout() { + profilePrivateView.snp.makeConstraints { + $0.top.equalTo(safeAreaLayoutGuide.snp.top) + $0.width.equalToSuperview() + $0.height.equalTo(63) + } + + profilePrivateLabel.snp.makeConstraints { + $0.leading.equalToSuperview().inset(30) + $0.centerY.equalToSuperview() + } + + profilePrivateToggleButton.snp.makeConstraints { + $0.size.equalTo(44) + $0.centerY.equalToSuperview() + $0.trailing.equalToSuperview().inset(20) + } + + backButton.snp.makeConstraints { + $0.size.equalTo(24) + } + + completeButton.snp.makeConstraints { + $0.width.equalTo(48) + $0.height.equalTo(42) + } + } + + //MARK: - Data + + func bindData(isPrivate: Bool) { + profilePrivateToggleButton.setImage(isPrivate ? .checkSelected : .checkDefault, + for: .normal) + } + + func changeCompleteButton(change: Bool) { + completeButton.do { + $0.setTitleColor(change ? .wssPrimary100: .wssGray200, + for: .normal) + } + } +} + diff --git a/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageProfileVisibilityViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageProfileVisibilityViewController.swift new file mode 100644 index 000000000..afc75213f --- /dev/null +++ b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageProfileVisibilityViewController.swift @@ -0,0 +1,92 @@ +// +// MyPageProfileVisibilityViewController.swift +// WSSiOS +// +// Created by 신지원 on 9/18/24. +// + +import UIKit + +import RxSwift + +final class MyPageProfileVisibilityViewController: UIViewController { + + //MARK: - Properties + + private let viewModel: MyPageProfileVisibilityViewModel + private let disposeBag = DisposeBag() + + //MARK: - Components + + private let rootView = MyPageProfileVisibilityView() + + // MARK: - Life Cycle + + init(viewModel: MyPageProfileVisibilityViewModel) { + + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + self.view = rootView + } + + override func viewDidLoad() { + super.viewDidLoad() + + bindViewModel() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + setNavigation() + hideTabBar() + swipeBackGesture() + } + + //MARK: - Bind + + private func bindViewModel() { + let input = MyPageProfileVisibilityViewModel.Input( + isVisibilityToggleButtonDidTap: rootView.profilePrivateToggleButton.rx.tap, + backButtonDidTap: rootView.backButton.rx.tap, + completeButtonDidTap: rootView.completeButton.rx.tap) + + let output = viewModel.transform(from: input, disposeBag: self.disposeBag) + + output.changePrivateToggleButton + .subscribe(with: self, onNext: { owner, isPublic in + owner.rootView.bindData(isPrivate: !isPublic) + }) + .disposed(by: disposeBag) + + output.changeCompleteButton + .subscribe(with: self, onNext: { owner, change in + owner.rootView.changeCompleteButton(change: change) + }) + .disposed(by: disposeBag) + + output.popViewControllerAction + .bind(with: self, onNext: { owner, _ in + owner.popToLastViewController() + }) + .disposed(by: disposeBag) + } + +} + +//MARK: - UI + +extension MyPageProfileVisibilityViewController { + private func setNavigation() { + preparationSetNavigationBar(title: StringLiterals.Navigation.Title.isVisibleProfile, + left: self.rootView.backButton, + right: self.rootView.completeButton) + } +} diff --git a/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageSettingViewController.swift b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageSettingViewController.swift index 1d189e7b7..c80875ef7 100644 --- a/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageSettingViewController.swift +++ b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewController/MyPageSettingViewController.swift @@ -77,7 +77,7 @@ final class MyPageSettingViewController: UIViewController { owner.pushToMyPageInfoViewController() case 1: print("프로필 공개 여부 설정") - //pushVC + owner.pushToMyPageProfileVisibilityViewController() case 2: print("웹소소 공식 계정") if let url = URL(string: StringLiterals.MyPage.SettingURL.instaURL) { diff --git a/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewModel/MyPageProfileVisibilityViewModel.swift b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewModel/MyPageProfileVisibilityViewModel.swift new file mode 100644 index 000000000..356cd3d78 --- /dev/null +++ b/WSSiOS/WSSiOS/Source/Presentation/MyPage/MyPageViewModel/MyPageProfileVisibilityViewModel.swift @@ -0,0 +1,101 @@ +// +// MyPageProfileVisibilityViewModel.swift +// WSSiOS +// +// Created by 신지원 on 9/18/24. +// + +import UIKit + +import RxSwift +import RxCocoa + +final class MyPageProfileVisibilityViewModel: ViewModelType { + + //MARK: - Properties + + private let userRepository: UserRepository + private let disposeBag = DisposeBag() + + //초기값 부여 + private var initStatus: Bool = true + private var isPublic: Bool = true + + //MARK: - Life Cycle + + init(userRepository: UserRepository) { + self.userRepository = userRepository + + self.getUserProfileVisibility() + .map { $0.isProfilePublic } + .subscribe(with: self, onNext: { owner, isPublic in + owner.initStatus = isPublic + }) + .disposed(by: disposeBag) + + self.isPublic = self.initStatus + print(self.isPublic, "💖") + } + + struct Input { + let isVisibilityToggleButtonDidTap: ControlEvent + let backButtonDidTap: ControlEvent + let completeButtonDidTap: ControlEvent + } + + struct Output { + let changePrivateToggleButton = PublishRelay() + let changeCompleteButton = PublishRelay() + let popViewControllerAction = PublishRelay() + } + + func transform(from input: Input, disposeBag: DisposeBag) -> Output { + let output = Output() + + input.isVisibilityToggleButtonDidTap + .subscribe(with: self, onNext: { owner, _ in + owner.isPublic.toggle() + output.changePrivateToggleButton.accept(owner.isPublic) + output.changeCompleteButton.accept(owner.initStatus != owner.isPublic) + }) + .disposed(by: disposeBag) + + input.completeButtonDidTap + .subscribe(with: self, onNext: { owner, _ in + guard owner.initStatus != owner.isPublic else { return } + + owner.patchUserProfileVisibility(isProfilePublic: owner.isPublic) + .subscribe(onNext: { + output.popViewControllerAction.accept(true) + //TODO: - toastMessage + }, onError: { error in + print(error) + }) + .disposed(by: owner.disposeBag) + }) + .disposed(by: disposeBag) + + input.backButtonDidTap + .subscribe(with: self, onNext: { owner, _ in + output.popViewControllerAction.accept(true) + }) + .disposed(by: disposeBag) + + return output + } + + //MARK: - Custom Method + + //MARK: - API + + private func getUserProfileVisibility() -> Observable { + return userRepository.getUserProfileVisibility() + } + + private func patchUserProfileVisibility(isProfilePublic: Bool) -> Observable { + return userRepository.patchUserProfileVisibility(isProfilePublic: isProfilePublic) + } +} + + +