From 11b5f1beaaac9ffbad4f9b22e092aba8179da7cc Mon Sep 17 00:00:00 2001 From: "In Ye, Kim" Date: Sat, 30 Nov 2024 00:37:34 +0900 Subject: [PATCH 1/8] =?UTF-8?q?chore=20#273=20=EC=B1=84=EB=84=90=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EC=8B=9C?= =?UTF-8?q?=EC=A0=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Splash/SplashViewController.swift | 9 +++------ .../AuthFeature/Sources/SignUpViewModel.swift | 18 ++++++++++++++++-- .../BroadcastCollectionViewModel.swift | 18 ++++++------------ 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/Projects/App/Sources/Splash/SplashViewController.swift b/Projects/App/Sources/Splash/SplashViewController.swift index 4ed4726e..7d93dd56 100644 --- a/Projects/App/Sources/Splash/SplashViewController.swift +++ b/Projects/App/Sources/Splash/SplashViewController.swift @@ -48,8 +48,6 @@ public final class SplashViewController: BaseViewController { extension SplashViewController { private func moveToMainView() { let fetchChannelListUsecase = DIContainer.shared.resolve(FetchChannelListUsecase.self) - let createChannelUsecase = DIContainer.shared.resolve(CreateChannelUsecase.self) - let deleteChannelUsecase = DIContainer.shared.resolve(DeleteChannelUsecase.self) let fetchChannelInfoUsecase = DIContainer.shared.resolve(FetchChannelInfoUsecase.self) let makeBroadcastUsecase = DIContainer.shared.resolve(MakeBroadcastUsecase.self) let fetchAllBroadcastUsecase = DIContainer.shared.resolve(FetchAllBroadcastUsecase.self) @@ -57,8 +55,6 @@ extension SplashViewController { let factory = DIContainer.shared.resolve(LiveStreamViewControllerFactory.self) let viewModel = BroadcastCollectionViewModel( fetchChannelListUsecase: fetchChannelListUsecase, - createChannelUsecase: createChannelUsecase, - deleteChannelUsecase: deleteChannelUsecase, fetchChannelInfoUsecase: fetchChannelInfoUsecase, makeBroadcastUsecase: makeBroadcastUsecase, fetchAllBroadcastUsecase: fetchAllBroadcastUsecase, @@ -66,10 +62,11 @@ extension SplashViewController { ) let viewController = BroadcastCollectionViewController(viewModel: viewModel, factory: factory) let navigationController = UINavigationController(rootViewController: viewController) - + let createChannelUsecase = DIContainer.shared.resolve(CreateChannelUsecase.self) + /// 유저의 이름이 저장되어 있지 않으면 유저 등록 뷰를 Navigation에 올림 if UserDefaults.standard.string(forKey: "USER_NAME") == nil { - let singUpViewModel = SignUpViewModel() + let singUpViewModel = SignUpViewModel(createChannelUsecase: createChannelUsecase) navigationController.viewControllers.append(SignUpViewController(viewModel: singUpViewModel)) } diff --git a/Projects/Features/AuthFeature/Sources/SignUpViewModel.swift b/Projects/Features/AuthFeature/Sources/SignUpViewModel.swift index 40a66db8..1097c5a3 100644 --- a/Projects/Features/AuthFeature/Sources/SignUpViewModel.swift +++ b/Projects/Features/AuthFeature/Sources/SignUpViewModel.swift @@ -2,6 +2,7 @@ import Combine import Foundation import BaseFeatureInterface +import LiveStationDomainInterface public class SignUpViewModel: ViewModel { public struct Input { @@ -16,6 +17,8 @@ public class SignUpViewModel: ViewModel { private let output = Output() private var cancellables = Set() + private let createChannelUsecase: any CreateChannelUsecase + public func transform(input: Input) -> Output { input.didWriteUserName .sink { [weak self] name in @@ -35,7 +38,9 @@ public class SignUpViewModel: ViewModel { return output } - public init() { } + public init(createChannelUsecase: CreateChannelUsecase) { + self.createChannelUsecase = createChannelUsecase + } private func validate(with name: String?) -> Bool { guard let name else { return false } @@ -47,6 +52,15 @@ public class SignUpViewModel: ViewModel { UserDefaults.standard.set(name, forKey: "USER_NAME") let savedName = UserDefaults.standard.string(forKey: "USER_NAME") - output.isSaved.send(savedName == name) + + createChannelUsecase.execute(name: "Guest") + .sink { _ in + } receiveValue: { [weak self] channelEntity in + UserDefaults.standard.set(channelEntity.id, forKey: "CHANNEL_ID") + let savedID = UserDefaults.standard.string(forKey: "CHANNEL_ID") + + self?.output.isSaved.send(savedName == name && savedID != nil) + } + .store(in: &cancellables) } } diff --git a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift index 9556f64a..33318058 100644 --- a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift +++ b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift @@ -43,8 +43,6 @@ public class BroadcastCollectionViewModel: ViewModel { private let output = Output() private let fetchChannelListUsecase: any FetchChannelListUsecase - private let createChannelUsecase: any CreateChannelUsecase - private let deleteChannelUsecase: any DeleteChannelUsecase private let fetchChannelInfoUsecase: any FetchChannelInfoUsecase private let makeBroadcastUsecase: any MakeBroadcastUsecase private let fetchAllBroadcastUsecase: any FetchAllBroadcastUsecase @@ -59,22 +57,18 @@ public class BroadcastCollectionViewModel: ViewModel { let extensionBundleID = "kr.codesquad.boostcamp9.Shook.BroadcastUploadExtension" private let userName = UserDefaults.standard.string(forKey: "USER_NAME") ?? "" - private var channelName: String = "" + private var broadcastName: String = "" private var channelDescription: String = "" - private var channel: ChannelEntity? + private var channelID = UserDefaults.standard.string(forKey: "CHANNEL_ID") public init( fetchChannelListUsecase: FetchChannelListUsecase, - createChannelUsecase: CreateChannelUsecase, - deleteChannelUsecase: DeleteChannelUsecase, fetchChannelInfoUsecase: FetchChannelInfoUsecase, makeBroadcastUsecase: MakeBroadcastUsecase, fetchAllBroadcastUsecase: FetchAllBroadcastUsecase, deleteBroadCastUsecase: DeleteBroadcastUsecase ) { self.fetchChannelListUsecase = fetchChannelListUsecase - self.createChannelUsecase = createChannelUsecase - self.deleteChannelUsecase = deleteChannelUsecase self.fetchChannelInfoUsecase = fetchChannelInfoUsecase self.makeBroadcastUsecase = makeBroadcastUsecase self.fetchAllBroadcastUsecase = fetchAllBroadcastUsecase @@ -95,7 +89,7 @@ public class BroadcastCollectionViewModel: ViewModel { self.output.streamingStartButtonIsActive.send(validness.isValid) self.output.errorMessage.send(validness.errorMessage) if validness.isValid { - channelName = name + broadcastName = name } } .store(in: &cancellables) @@ -114,9 +108,9 @@ public class BroadcastCollectionViewModel: ViewModel { input.didTapFinishStreamingButton .flatMap { [weak self] _ in - guard let self, let channel else { return Empty<(Void, Void), Error>().eraseToAnyPublisher() } - return deleteChannelUsecase.execute(channelID: channel.id) - .zip(deleteBroadCastUsecase.execute(id: channel.id)) + guard let self, + let channelID else { return Empty().eraseToAnyPublisher() } + return deleteBroadCastUsecase.execute(id: channelID) .eraseToAnyPublisher() } .sink { _ in From e827796e8641a58bbaa70e2dd2f5d10cf402d857 Mon Sep 17 00:00:00 2001 From: "In Ye, Kim" Date: Sat, 30 Nov 2024 00:38:08 +0900 Subject: [PATCH 2/8] style Edit UX Writing --- .../Features/AuthFeature/Sources/SignUpViewController.swift | 2 +- .../Sources/ViewControllers/SettingUIViewController.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Projects/Features/AuthFeature/Sources/SignUpViewController.swift b/Projects/Features/AuthFeature/Sources/SignUpViewController.swift index 629b40f7..e6f75559 100644 --- a/Projects/Features/AuthFeature/Sources/SignUpViewController.swift +++ b/Projects/Features/AuthFeature/Sources/SignUpViewController.swift @@ -25,7 +25,7 @@ public class SignUpViewController: BaseViewController { private let confettiAnimationView = LottieAnimationView(name: "confetti", bundle: Bundle(for: DesignSystemResources.self)) private let shookAnimationView = LottieAnimationView(name: "shook", bundle: Bundle(for: DesignSystemResources.self)) - private lazy var loadingView = SHLoadingView(message: "아이디 등록 중") + private lazy var loadingView = SHLoadingView(message: "닉네임 등록 중") public override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) diff --git a/Projects/Features/MainFeature/Sources/ViewControllers/SettingUIViewController.swift b/Projects/Features/MainFeature/Sources/ViewControllers/SettingUIViewController.swift index 325fd527..d0a7cc52 100644 --- a/Projects/Features/MainFeature/Sources/ViewControllers/SettingUIViewController.swift +++ b/Projects/Features/MainFeature/Sources/ViewControllers/SettingUIViewController.swift @@ -17,7 +17,7 @@ public final class SettingUIViewController: BaseViewController Date: Sat, 30 Nov 2024 00:38:33 +0900 Subject: [PATCH 3/8] =?UTF-8?q?chore=20#273=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=B1=84=EB=84=90=20=EC=83=9D=EC=84=B1=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModels/BroadcastCollectionViewModel.swift | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift index 33318058..8713a9e9 100644 --- a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift +++ b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift @@ -120,16 +120,12 @@ public class BroadcastCollectionViewModel: ViewModel { .store(in: &cancellables) input.didTapStartBroadcastButton - .flatMap { [weak self] _ in - guard let self else { return Empty().eraseToAnyPublisher() } - output.isReadyToStream.send(false) - return createChannelUsecase.execute(name: channelName) - } .flatMap { [weak self] in - guard let self else { return Empty().eraseToAnyPublisher() } - channel = $0 - return fetchChannelInfoUsecase.execute(channelID: $0.id) - .zip(makeBroadcastUsecase.execute(id: $0.id, title: $0.name, owner: userName, description: channelDescription)) + guard let self, + let channelID else { return Empty().eraseToAnyPublisher() } + output.isReadyToStream.send(false) + return fetchChannelInfoUsecase.execute(channelID: channelID) + .zip(makeBroadcastUsecase.execute(id: channelID, title: broadcastName, owner: userName, description: channelDescription)) .map { channelInfo, _ in channelInfo } .eraseToAnyPublisher() } From 37873846c6f5a20a0f212548a28b7f13a5f504d2 Mon Sep 17 00:00:00 2001 From: "In Ye, Kim" Date: Sat, 30 Nov 2024 00:38:47 +0900 Subject: [PATCH 4/8] =?UTF-8?q?chore=20#273=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModels/BroadcastCollectionViewModel.swift | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift index 8713a9e9..5c0bd5b3 100644 --- a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift +++ b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift @@ -181,15 +181,10 @@ public class BroadcastCollectionViewModel: ViewModel { /// - Parameter _: 방송 이름 /// - Returns: (Bool, String?) - 유효 여부와 에러 메시지 private func valid(_ value: String) -> (isValid: Bool, errorMessage: String?) { - let isLengthValid = 3...20 ~= value.count - let isCharactersValid = value.allSatisfy { $0.isLetter || $0.isNumber || $0 == "_" } + let trimmedValue = value.trimmingCharacters(in: .whitespaces) - if !isLengthValid && !isCharactersValid { - return (false, "3글자 이상,20글자 이하로 입력해 주세요. 특수문자는 언더바(_)만 가능합니다.") - } else if !isLengthValid { - return (false, "최소 3글자 이상, 최대 20글자 이하로 입력해 주세요.") - } else if !isCharactersValid { - return (false, "특수문자는 언더바(_)만 가능합니다.") + if trimmedValue.isEmpty { + return (false, "공백을 제외하고 최소 1글자 이상 입력해주세요.") } else { return (true, nil) } From 50d354bdad28d7d4bab1b3b472ecb2e9c8ef1ec0 Mon Sep 17 00:00:00 2001 From: "In Ye, Kim" Date: Sat, 30 Nov 2024 00:39:18 +0900 Subject: [PATCH 5/8] =?UTF-8?q?chore=20=EB=A9=94=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=EB=A0=88=EB=93=9C=EC=97=90=EC=84=9C=20=EB=B0=9B=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=81=B4=EB=A1=9C?= =?UTF-8?q?=EC=A0=80=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Features/AuthFeature/Sources/SignUpViewController.swift | 1 + .../Sources/ViewControllers/BroadcastUIViewController.swift | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Projects/Features/AuthFeature/Sources/SignUpViewController.swift b/Projects/Features/AuthFeature/Sources/SignUpViewController.swift index e6f75559..43e4ae17 100644 --- a/Projects/Features/AuthFeature/Sources/SignUpViewController.swift +++ b/Projects/Features/AuthFeature/Sources/SignUpViewController.swift @@ -62,6 +62,7 @@ public class SignUpViewController: BaseViewController { .store(in: &cancellables) output.isSaved + .receive(on: DispatchQueue.main) .sink { [weak self] isSaved in if isSaved { self?.textField.resignFirstResponder() diff --git a/Projects/Features/MainFeature/Sources/ViewControllers/BroadcastUIViewController.swift b/Projects/Features/MainFeature/Sources/ViewControllers/BroadcastUIViewController.swift index 6d661539..e68a5ef5 100644 --- a/Projects/Features/MainFeature/Sources/ViewControllers/BroadcastUIViewController.swift +++ b/Projects/Features/MainFeature/Sources/ViewControllers/BroadcastUIViewController.swift @@ -100,7 +100,8 @@ public final class BroadcastUIViewController: BaseViewController Date: Sat, 30 Nov 2024 01:01:40 +0900 Subject: [PATCH 6/8] =?UTF-8?q?chore=20#273=20=EB=B3=B4=EC=97=AC=EC=A7=80?= =?UTF-8?q?=EB=8A=94=20=ED=83=80=EC=9D=B4=ED=8B=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/ViewModels/BroadcastCollectionViewModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift index afa4f21d..e18451ab 100644 --- a/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift +++ b/Projects/Features/MainFeature/Sources/ViewModels/BroadcastCollectionViewModel.swift @@ -158,7 +158,7 @@ public class BroadcastCollectionViewModel: ViewModel { let broadcast = broadcastInfoEntities.first { $0.id == channelEntity.id } return Channel( id: channelEntity.id, - title: channelEntity.name, + title: broadcast?.title ?? "Unknown", thumbnailImageURLString: channelEntity.imageURLString, owner: broadcast?.owner ?? "Unknown", description: broadcast?.description ?? "" From f0beffa32823b194985355231b1b68217ede61fd Mon Sep 17 00:00:00 2001 From: "In Ye, Kim" Date: Sat, 30 Nov 2024 01:15:09 +0900 Subject: [PATCH 7/8] =?UTF-8?q?fix=20mainfeature=20=ED=8C=8C=EB=9D=BC?= =?UTF-8?q?=EB=AF=B8=ED=84=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Features/MainFeature/Demo/Sources/AppDelegate.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Projects/Features/MainFeature/Demo/Sources/AppDelegate.swift b/Projects/Features/MainFeature/Demo/Sources/AppDelegate.swift index 3c21585a..e2dab458 100644 --- a/Projects/Features/MainFeature/Demo/Sources/AppDelegate.swift +++ b/Projects/Features/MainFeature/Demo/Sources/AppDelegate.swift @@ -13,16 +13,12 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { ) -> Bool { window = UIWindow(frame: UIScreen.main.bounds) let mockFetchChannelListUsecase = MockFetchChannelListUsecaseImpl() - let mockCreateChannelUsecase = MockCreateChannelUsecaseImpl() - let mockDeleteChannelUsecase = MockDeleteChannelUsecaseImpl() let mockFetchChannelInfoUsecase = MockFetchChannelInfoUsecaseImpl() let mockmakeBroadcastUsecase = MockMakeBroadcastUsecaseImpl() let mockFetchAllBroadcastUsecase = MockFetchAllBroadcastUsecaseImpl() let mockDeleteBroadcastUsecase = MockDeleteBroadcastUsecaseImpl() let viewModel = BroadcastCollectionViewModel( fetchChannelListUsecase: mockFetchChannelListUsecase, - createChannelUsecase: mockCreateChannelUsecase, - deleteChannelUsecase: mockDeleteChannelUsecase, fetchChannelInfoUsecase: mockFetchChannelInfoUsecase, makeBroadcastUsecase: mockmakeBroadcastUsecase, fetchAllBroadcastUsecase: mockFetchAllBroadcastUsecase, @@ -37,5 +33,3 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { return true } } - - From b42c4046b8af468b146f66fa370635cdf8ed1f0a Mon Sep 17 00:00:00 2001 From: "In Ye, Kim" Date: Sat, 30 Nov 2024 01:45:02 +0900 Subject: [PATCH 8/8] =?UTF-8?q?fix=20auth=20feature=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthFeature/Demo/Sources/AppDelegate.swift | 3 ++- .../Demo/Sources/MockCreateChannelUsecaseImpl.swift | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Projects/Features/AuthFeature/Demo/Sources/MockCreateChannelUsecaseImpl.swift diff --git a/Projects/Features/AuthFeature/Demo/Sources/AppDelegate.swift b/Projects/Features/AuthFeature/Demo/Sources/AppDelegate.swift index a7d86acb..4e993edc 100644 --- a/Projects/Features/AuthFeature/Demo/Sources/AppDelegate.swift +++ b/Projects/Features/AuthFeature/Demo/Sources/AppDelegate.swift @@ -11,7 +11,8 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil ) -> Bool { window = UIWindow(frame: UIScreen.main.bounds) - let viewModel = SignUpViewModel() + let mockCreateChannelUsecase = MockCreateChannelUsecaseImpl() + let viewModel = SignUpViewModel(createChannelUsecase: mockCreateChannelUsecase) let viewController = SignUpViewController(viewModel: viewModel) window?.rootViewController = viewController window?.makeKeyAndVisible() diff --git a/Projects/Features/AuthFeature/Demo/Sources/MockCreateChannelUsecaseImpl.swift b/Projects/Features/AuthFeature/Demo/Sources/MockCreateChannelUsecaseImpl.swift new file mode 100644 index 00000000..398358b4 --- /dev/null +++ b/Projects/Features/AuthFeature/Demo/Sources/MockCreateChannelUsecaseImpl.swift @@ -0,0 +1,11 @@ +import Combine + +import LiveStationDomainInterface + +final class MockCreateChannelUsecaseImpl: CreateChannelUsecase { + func execute(name: String) -> AnyPublisher { + Future { promise in + promise(.success(ChannelEntity(id: "", name: name))) + }.eraseToAnyPublisher() + } +}