diff --git a/Segno/Segno.xcodeproj/project.pbxproj b/Segno/Segno.xcodeproj/project.pbxproj index ab0ca6c..d91f400 100644 --- a/Segno/Segno.xcodeproj/project.pbxproj +++ b/Segno/Segno.xcodeproj/project.pbxproj @@ -57,6 +57,8 @@ 7940FB2F292E063100276EFC /* DiaryDetailDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7940FB2E292E063100276EFC /* DiaryDetailDTO.swift */; }; 7940FB31292E065100276EFC /* DiaryDetailEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7940FB30292E065100276EFC /* DiaryDetailEndpoint.swift */; }; 7940FB33292E065F00276EFC /* DiaryDetailUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7940FB32292E065F00276EFC /* DiaryDetailUseCase.swift */; }; + 9825F41B29377875005F2163 /* ChangeUserNameUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9825F41A29377875005F2163 /* ChangeUserNameUseCase.swift */; }; + 9825F41D29377ACF005F2163 /* SettingsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9825F41C29377ACF005F2163 /* SettingsRepository.swift */; }; 982A2A472924AE74006F6ACD /* UserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */; }; 982A3699292C905300FDC6CF /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A3698292C905300FDC6CF /* DiaryDetailViewController.swift */; }; 982B3B7F292E68FB0077A44B /* DiaryDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982B3B7E292E68FB0077A44B /* DiaryDetailViewModel.swift */; }; @@ -70,6 +72,8 @@ 988414D72923304F007C9132 /* KeychainError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 988414D62923304F007C9132 /* KeychainError.swift */; }; 988414D929235345007C9132 /* DiaryCollectionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 988414D829235345007C9132 /* DiaryCollectionViewModel.swift */; }; 988414DB2923606B007C9132 /* DiaryListUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 988414DA2923606B007C9132 /* DiaryListUseCase.swift */; }; + 9894EAF529373385005F2B15 /* SettingsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9894EAF429373385005F2B15 /* SettingsUseCase.swift */; }; + 9894EAF829375281005F2B15 /* DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9894EAF729375281005F2B15 /* DarkMode.swift */; }; 98B5263E292CA46C00446413 /* TagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98B5263D292CA46C00446413 /* TagView.swift */; }; 98B52640292CB92900446413 /* MusicContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98B5263F292CB92900446413 /* MusicContentView.swift */; }; 98BEE36E2934907700B20143 /* LoginError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98BEE36D2934907700B20143 /* LoginError.swift */; }; @@ -128,6 +132,8 @@ 7940FB2E292E063100276EFC /* DiaryDetailDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailDTO.swift; sourceTree = ""; }; 7940FB30292E065100276EFC /* DiaryDetailEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailEndpoint.swift; sourceTree = ""; }; 7940FB32292E065F00276EFC /* DiaryDetailUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailUseCase.swift; sourceTree = ""; }; + 9825F41A29377875005F2163 /* ChangeUserNameUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeUserNameUseCase.swift; sourceTree = ""; }; + 9825F41C29377ACF005F2163 /* SettingsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRepository.swift; sourceTree = ""; }; 982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsKey.swift; sourceTree = ""; }; 982A3698292C905300FDC6CF /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; 982B3B7E292E68FB0077A44B /* DiaryDetailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewModel.swift; sourceTree = ""; }; @@ -141,6 +147,8 @@ 988414D62923304F007C9132 /* KeychainError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainError.swift; sourceTree = ""; }; 988414D829235345007C9132 /* DiaryCollectionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryCollectionViewModel.swift; sourceTree = ""; }; 988414DA2923606B007C9132 /* DiaryListUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryListUseCase.swift; sourceTree = ""; }; + 9894EAF429373385005F2B15 /* SettingsUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsUseCase.swift; sourceTree = ""; }; + 9894EAF729375281005F2B15 /* DarkMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkMode.swift; sourceTree = ""; }; 98B5263D292CA46C00446413 /* TagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagView.swift; sourceTree = ""; }; 98B5263F292CB92900446413 /* MusicContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicContentView.swift; sourceTree = ""; }; 98BEE36D2934907700B20143 /* LoginError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginError.swift; sourceTree = ""; }; @@ -225,6 +233,7 @@ 4F317792291BEB5E0019BDFC /* Presentation */ = { isa = PBXGroup; children = ( + 9894EAF629375272005F2B15 /* Utility */, 4F31779C291BEE900019BDFC /* Coordinator */, 4F31779B291BEE890019BDFC /* View */, 4F31779A291BEE810019BDFC /* ViewController */, @@ -281,6 +290,8 @@ 9841D6162925FACC00318EA9 /* LoginUseCase.swift */, 7940FB32292E065F00276EFC /* DiaryDetailUseCase.swift */, 988414DA2923606B007C9132 /* DiaryListUseCase.swift */, + 9894EAF429373385005F2B15 /* SettingsUseCase.swift */, + 9825F41A29377875005F2163 /* ChangeUserNameUseCase.swift */, ); path = UseCase; sourceTree = ""; @@ -358,6 +369,7 @@ 4FA32427292363AA00DB04D5 /* DiaryRepository.swift */, 982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */, 4F4E0D3D2924B925005ABA8F /* LoginRepository.swift */, + 9825F41C29377ACF005F2163 /* SettingsRepository.swift */, ); path = Repository; sourceTree = ""; @@ -418,6 +430,14 @@ path = Font; sourceTree = ""; }; + 9894EAF629375272005F2B15 /* Utility */ = { + isa = PBXGroup; + children = ( + 9894EAF729375281005F2B15 /* DarkMode.swift */, + ); + path = Utility; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -509,10 +529,12 @@ 4F4E0D3E2924B925005ABA8F /* LoginRepository.swift in Sources */, 4F9A00212922338E007D9057 /* AppDelegate.swift in Sources */, 983AE9D82935CEE2006547BD /* SettingsViewModel.swift in Sources */, + 9825F41D29377ACF005F2163 /* SettingsRepository.swift in Sources */, 66F0D7EE2925FF8B0074872E /* DiaryCell.swift in Sources */, 4F9A00202922337F007D9057 /* LoginViewController.swift in Sources */, 982A2A472924AE74006F6ACD /* UserDefaultsKey.swift in Sources */, 4F9A001B292227D7007D9057 /* NetworkManager.swift in Sources */, + 9894EAF529373385005F2B15 /* SettingsUseCase.swift in Sources */, 9841D6172925FACC00318EA9 /* LoginUseCase.swift in Sources */, 4FEBFAAD291CF62E00E78139 /* DiaryDetail.swift in Sources */, 4FEBFAB1291CFB5500E78139 /* SHMediaItem+.swift in Sources */, @@ -526,6 +548,7 @@ 666E6F81291CF49E00CECD4B /* LoginCoordinator.swift in Sources */, 7940FB31292E065100276EFC /* DiaryDetailEndpoint.swift in Sources */, 666E6F85291CF4AD00CECD4B /* MyPageCoordinator.swift in Sources */, + 9894EAF829375281005F2B15 /* DarkMode.swift in Sources */, 983AE9D22934F041006547BD /* NicknameCell.swift in Sources */, 983AE9D4293513AD006547BD /* SettingsCellModel.swift in Sources */, 4F4E0D79292522B7005ABA8F /* BaseURL.swift in Sources */, @@ -536,6 +559,7 @@ 4FCAC5C2292B5C9000BF9CDD /* LoginSession.swift in Sources */, 666E6F7D291CF45600CECD4B /* Coordinator.swift in Sources */, 982A3699292C905300FDC6CF /* DiaryDetailViewController.swift in Sources */, + 9825F41B29377875005F2163 /* ChangeUserNameUseCase.swift in Sources */, 666E6F8C291CFAC200CECD4B /* DiaryCollectionViewController.swift in Sources */, 666E6F8A291CF82700CECD4B /* TabBarPageCase.swift in Sources */, 79183800292225DC00BC6992 /* UIFont+.swift in Sources */, diff --git a/Segno/Segno/Data/Repository/SettingsRepository.swift b/Segno/Segno/Data/Repository/SettingsRepository.swift new file mode 100644 index 0000000..d432626 --- /dev/null +++ b/Segno/Segno/Data/Repository/SettingsRepository.swift @@ -0,0 +1,16 @@ +// +// SettingsRepository.swift +// Segno +// +// Created by YOONJONG on 2022/11/30. +// + +import RxSwift + +protocol SettingsRepository { + +} + +final class SettingsRepositoryImpl: SettingsRepository { + +} diff --git a/Segno/Segno/Domain/UseCase/ChangeUserNameUseCase.swift b/Segno/Segno/Domain/UseCase/ChangeUserNameUseCase.swift new file mode 100644 index 0000000..296a51e --- /dev/null +++ b/Segno/Segno/Domain/UseCase/ChangeUserNameUseCase.swift @@ -0,0 +1,27 @@ +// +// ChangeUserNameUseCase.swift +// Segno +// +// Created by YOONJONG on 2022/11/30. +// + +import RxSwift + +protocol ChangeUserNameUseCase { + func requestChangeNickname(to nickname: String) -> Bool +} + +final class ChangeUserNameUseCaseImpl: ChangeUserNameUseCase { + let repository: SettingsRepository + private let disposeBag = DisposeBag() + + init(repository: SettingsRepository = SettingsRepositoryImpl()) { + self.repository = repository + } + + func requestChangeNickname(to nickname: String) -> Bool { + // 임시 처리입니다. + debugPrint("SettingsUseCase - requestChangeNickname : \(nickname)으로 변경") + return true + } +} diff --git a/Segno/Segno/Domain/UseCase/SettingsUseCase.swift b/Segno/Segno/Domain/UseCase/SettingsUseCase.swift new file mode 100644 index 0000000..11e3f76 --- /dev/null +++ b/Segno/Segno/Domain/UseCase/SettingsUseCase.swift @@ -0,0 +1,56 @@ +// +// SettingsUseCase.swift +// Segno +// +// Created by YOONJONG on 2022/11/30. +// + +import RxSwift + +protocol SettingsUseCase { + func getAutoPlayMode() -> Bool + func changeAutoPlayMode(to mode: Bool) + func getDarkMode() -> Int + func changeDarkMode(to mode: Int) +} + +final class SettingsUseCaseImpl: SettingsUseCase { + let repository: LocalUtilityRepository + private let disposeBag = DisposeBag() + + init(repository: LocalUtilityRepository = LocalUtilityRepositoryImpl()) { + self.repository = repository + } + + func getAutoPlayMode() -> Bool { + if let isEnabled = repository.getUserDefaultsObject(forKey: .isAutoPlayEnabled) as? Bool { + debugPrint("SettingsUseCase - getAutoPlayMode : 키가 있습니다 - \(isEnabled)") + return isEnabled + } else { + repository.setUserDefaults(true, forKey: .isAutoPlayEnabled) + debugPrint("SettingsUseCase - getAutoPlayMode : 키가 없어 true 로 설정합니다.") + return true + } + } + + func changeAutoPlayMode(to mode: Bool) { + repository.setUserDefaults(mode, forKey: .isAutoPlayEnabled) + debugPrint("SettingsUseCase - changeAutoPlayMode : \(mode)로 설정") + } + + func getDarkMode() -> Int { + if let mode = repository.getUserDefaultsObject(forKey: .darkmode) as? Int { + debugPrint("SettingsUseCase - getDarkMode : 키가 있습니다 - \(mode)") + return mode + } else { + repository.setUserDefaults(DarkMode.system.rawValue, forKey: .darkmode) + debugPrint("SettingsUseCase - getDarkMode : 키가 없어 \(DarkMode.system.rawValue) 로 설정합니다.") + return DarkMode.system.rawValue + } + } + + func changeDarkMode(to mode: Int) { + repository.setUserDefaults(mode, forKey: .darkmode) + debugPrint("SettingsUseCase - changeDarkMode : \(mode)로 설정") + } +} diff --git a/Segno/Segno/Presentation/Utility/DarkMode.swift b/Segno/Segno/Presentation/Utility/DarkMode.swift new file mode 100644 index 0000000..2ad45c9 --- /dev/null +++ b/Segno/Segno/Presentation/Utility/DarkMode.swift @@ -0,0 +1,25 @@ +// +// DarkMode.swift +// Segno +// +// Created by YOONJONG on 2022/11/30. +// + +import Foundation + +enum DarkMode: Int, CaseIterable { + case system + case light + case dark + + var title: String { + switch self { + case .system: + return "시스템 설정" + case .light: + return "항상 밝게" + case .dark: + return "항상 어둡게" + } + } +} diff --git a/Segno/Segno/Presentation/View/SettingsCellModel.swift b/Segno/Segno/Presentation/View/SettingsCellModel.swift index 7403fbc..1da7940 100644 --- a/Segno/Segno/Presentation/View/SettingsCellModel.swift +++ b/Segno/Segno/Presentation/View/SettingsCellModel.swift @@ -8,5 +8,5 @@ enum SettingsCellModel { case nickname case settingsSwitch(title: String, isOn: Bool) - case settingsActionSheet(title: String) + case settingsActionSheet(title: String, mode: Int) } diff --git a/Segno/Segno/Presentation/ViewController/SettingsViewController.swift b/Segno/Segno/Presentation/ViewController/SettingsViewController.swift index e90686e..6eb369d 100644 --- a/Segno/Segno/Presentation/ViewController/SettingsViewController.swift +++ b/Segno/Segno/Presentation/ViewController/SettingsViewController.swift @@ -74,11 +74,10 @@ final class SettingsViewController: UIViewController { guard let newNickname = cell.nicknameTextField.text else { return Observable.empty() } - debugPrint("입력된 아이디 : ", newNickname) return self.viewModel.changeNickname(to: newNickname) } .subscribe(onNext: { result in - debugPrint("viewModel 메서드 실행 결과 : ", result) + debugPrint("여기에서 \(result)에 대한 피드백 Alert 띄웁니다.") }) .disposed(by: self.disposeBag) @@ -102,9 +101,10 @@ final class SettingsViewController: UIViewController { cell.configure(title: title, isOn: isOn, action: action) return cell - case .settingsActionSheet(let title): + case .settingsActionSheet(let title, let mode): guard let cell = tableView.dequeueReusableCell(withIdentifier: "SettingsActionSheetCell") as? SettingsActionSheetCell else { return UITableViewCell() } - cell.configure(left: title) + let darkModeTitle = DarkMode.allCases[mode].title + cell.configure(left: title, right: darkModeTitle) return cell } } @@ -116,15 +116,19 @@ final class SettingsViewController: UIViewController { guard let action = SettingsCellActions(rawValue: indexPath.row) else { return } switch action { case .darkmode: // 다크 모드 설정 + guard let cell = self?.tableView.cellForRow(at: indexPath) as? SettingsActionSheetCell else { return } let actionSheet = UIAlertController(title: "다크 모드 설정", message: nil, preferredStyle: .actionSheet) - actionSheet.addAction(UIAlertAction(title: "시스템 설정", style: .default, handler: { _ in - self?.viewModel.changeDarkMode(to: 0) + actionSheet.addAction(UIAlertAction(title: DarkMode.system.title, style: .default, handler: { _ in + self?.viewModel.changeDarkMode(to: DarkMode.system.rawValue) + cell.configure(right: DarkMode.system.title) })) - actionSheet.addAction(UIAlertAction(title: "항상 밝게", style: .default, handler: { _ in - self?.viewModel.changeDarkMode(to: 1) + actionSheet.addAction(UIAlertAction(title: DarkMode.light.title, style: .default, handler: { _ in + self?.viewModel.changeDarkMode(to: DarkMode.light.rawValue) + cell.configure(right: DarkMode.light.title) })) - actionSheet.addAction(UIAlertAction(title: "항상 어둡게", style: .default, handler: { _ in - self?.viewModel.changeDarkMode(to: 2) + actionSheet.addAction(UIAlertAction(title: DarkMode.dark.title, style: .default, handler: { _ in + self?.viewModel.changeDarkMode(to: DarkMode.dark.rawValue) + cell.configure(right: DarkMode.dark.title) })) self?.present(actionSheet, animated: true) default: diff --git a/Segno/Segno/Presentation/ViewModel/SettingsViewModel.swift b/Segno/Segno/Presentation/ViewModel/SettingsViewModel.swift index 037f506..d180bf7 100644 --- a/Segno/Segno/Presentation/ViewModel/SettingsViewModel.swift +++ b/Segno/Segno/Presentation/ViewModel/SettingsViewModel.swift @@ -10,49 +10,43 @@ import Foundation import RxSwift final class SettingsViewModel { - let dataSource = Observable<[SettingsCellModel]>.just([ + lazy var dataSource = Observable<[SettingsCellModel]>.just([ .nickname, - .settingsSwitch(title: "음악 자동 재생", isOn: true), // TODO: isOn은 로컬 디비로부터 불러와야 합니다. - .settingsActionSheet(title: "다크 모드") + .settingsSwitch(title: "음악 자동 재생", isOn: settingsUseCase.getAutoPlayMode()), + .settingsActionSheet(title: "다크 모드", mode: settingsUseCase.getDarkMode()) ]) - init() { - + private let settingsUseCase: SettingsUseCase + private let changeUserNameUseCase: ChangeUserNameUseCase + + init(settingsUseCase: SettingsUseCase = SettingsUseCaseImpl(), + changeUserNameUseCase: ChangeUserNameUseCase = ChangeUserNameUseCaseImpl() + ) { + self.settingsUseCase = settingsUseCase + self.changeUserNameUseCase = changeUserNameUseCase } - // TODO: 닉네임 변경 로직 func changeNickname(to nickname: String) -> Observable { -// return useCase.requestChangeNickname(to: nickname) - - // 임시 처리입니다. return Observable.create { emitter in - emitter.onNext(true) + let result = self.changeUserNameUseCase.requestChangeNickname(to: nickname) + emitter.onNext(result) return Disposables.create() } } - // TODO: 음악 자동 재생 여부 불러오기 / 클릭 시 반영하기 func getAutoPlayMode() -> Bool { - // return useCase.getAutoPlayMode() - - return true + return settingsUseCase.getAutoPlayMode() } func changeAutoPlayMode(to mode: Bool) { -// useCase.changeAutoPlayMode(to: mode) - - debugPrint("changeAutoPlayMode에서 \(mode)로 변경합니다") + settingsUseCase.changeAutoPlayMode(to: mode) } - // TODO: 다크모드 설정 불러오기 / 액션 시트 선택 시 반영하기 func getDarkMode() -> Int { - // return useCase.getDarkMode() - - return 0 + return settingsUseCase.getDarkMode() } func changeDarkMode(to mode: Int) { - // TODO: 액션 시트를 띄워야 합니다. - debugPrint("changeDarkMode에서 \(mode)로 변경합니다") + settingsUseCase.changeDarkMode(to: mode) } }