diff --git a/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomain/UseCaseImpl/CaptureVideosUseCaseImpl.swift b/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomain/UseCaseImpl/CaptureVideosUseCaseImpl.swift index 8be35bff..1e845b80 100644 --- a/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomain/UseCaseImpl/CaptureVideosUseCaseImpl.swift +++ b/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomain/UseCaseImpl/CaptureVideosUseCaseImpl.swift @@ -1,19 +1,15 @@ import UIKit import PhotoGetherDomainInterface -import DesignSystem public final class CaptureVideosUseCaseImpl: CaptureVideosUseCase { public func execute() -> [UIImage] { - guard let localImage = connectionRepository.capturedLocalVideo - else { return [ - PTGImage.temp1.image, - PTGImage.temp2.image, - PTGImage.temp3.image, - PTGImage.temp4.image] - } - let remoteImages = connectionRepository.clients.map { $0.captureVideo() } + let localImage = connectionRepository.capturedLocalVideo ?? UIImage() + + let localUserImageInfo = [(connectionRepository.localUserInfo?.viewPosition, localImage)] + let remoteUserImagesInfo = connectionRepository.clients + .map { ($0.remoteUserInfo?.viewPosition, $0.captureVideo()) } - return [localImage] + remoteImages + return sortImages(localUserImageInfo + remoteUserImagesInfo) } private let connectionRepository: ConnectionRepository @@ -21,4 +17,37 @@ public final class CaptureVideosUseCaseImpl: CaptureVideosUseCase { public init(connectionRepository: ConnectionRepository) { self.connectionRepository = connectionRepository } + + private func sortImages(_ images: [(viewPosition: UserInfo.ViewPosition?, image: UIImage)]) -> [UIImage] { + let convertedArray = images.map { + (position: PositionOder(rawValue: $0.viewPosition?.rawValue ?? -1), + image: $0.image) + } + + // 배열의 2번 인덱스가 마지막 자리이기 때문에 nil일 경우 2로 설정했습니다 + let sortedByViewPosition = convertedArray.sorted { + let lhs = $0.position?.sequence ?? 2 + let rhs = $1.position?.sequence ?? 2 + return lhs < rhs + } + + return sortedByViewPosition.map { $0.image } + } +} + +/// case의 순서는 참가자의 참가 순서에 따른 화면 배치이고 sequence는 이미지 데이터 전달할 때의 배열 순서입니다 +private enum PositionOder: Int { + case topLeading + case bottomTrailing + case topTrailing + case bottomLeading + + var sequence: Int { + switch self { + case .topLeading: 0 + case .topTrailing: 1 + case .bottomLeading: 2 + case .bottomTrailing: 3 + } + } } diff --git a/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomainInterface/Entity/UserInfo.swift b/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomainInterface/Entity/UserInfo.swift index 09d63890..1b0ccb52 100644 --- a/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomainInterface/Entity/UserInfo.swift +++ b/PhotoGether/DomainLayer/PhotoGetherDomain/PhotoGetherDomainInterface/Entity/UserInfo.swift @@ -16,6 +16,15 @@ public struct UserInfo: Identifiable, Equatable, Codable { case bottomTrailing case topTrailing case bottomLeading + + public var color: UserColor { + switch self { + case .topLeading: return .orange + case .bottomTrailing: return .brown + case .topTrailing: return .blue + case .bottomLeading: return .gray + } + } } public init( @@ -31,4 +40,11 @@ public struct UserInfo: Identifiable, Equatable, Codable { self.viewPosition = viewPosition self.roomID = roomID } + + public enum UserColor: String, Codable { + case orange = "#FF7561" + case brown = "#E7C892" + case blue = "#82BBE6" + case gray = "#7D7C84" + } } diff --git a/PhotoGether/PresentationLayer/DesignSystem/DesignSystem/Source/UIColor+.swift b/PhotoGether/PresentationLayer/DesignSystem/DesignSystem/Source/UIColor+.swift new file mode 100644 index 00000000..0a33963c --- /dev/null +++ b/PhotoGether/PresentationLayer/DesignSystem/DesignSystem/Source/UIColor+.swift @@ -0,0 +1,26 @@ +import UIKit + +public extension UIColor { + convenience init(hex: String) { + let hexString = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int = UInt64() + Scanner(string: hexString).scanHexInt64(&int) + + let red, green, blue, alpha: UInt64 + switch hexString.count { + case 6: // 6자리 (RGB) + (red, green, blue, alpha) = ((int >> 16) & 0xFF, (int >> 8) & 0xFF, int & 0xFF, 0xFF) + case 8: // 8자리 (RGBA) + (red, green, blue, alpha) = ((int >> 24) & 0xFF, (int >> 16) & 0xFF, (int >> 8) & 0xFF, int & 0xFF) + default: + (red, green, blue, alpha) = (0, 0, 0, 0xFF) // 유효하지 않은 경우 기본값 + } + + self.init( + red: CGFloat(red) / 255.0, + green: CGFloat(green) / 255.0, + blue: CGFloat(blue) / 255.0, + alpha: CGFloat(alpha) / 255.0 + ) + } +} diff --git a/PhotoGether/PresentationLayer/EditPhotoRoomFeature/EditPhotoRoomFeature/Source/View/StickerView.swift b/PhotoGether/PresentationLayer/EditPhotoRoomFeature/EditPhotoRoomFeature/Source/View/StickerView.swift index 42853ffc..c6027dd2 100644 --- a/PhotoGether/PresentationLayer/EditPhotoRoomFeature/EditPhotoRoomFeature/Source/View/StickerView.swift +++ b/PhotoGether/PresentationLayer/EditPhotoRoomFeature/EditPhotoRoomFeature/Source/View/StickerView.swift @@ -206,8 +206,11 @@ final class StickerView: UIView { if owner == user { layerView.layer.borderColor = PTGColor.primaryGreen.color.cgColor + nicknameLabel.backgroundColor = PTGColor.primaryGreen.color } else { - layerView.layer.borderColor = PTGColor.gray70.color.cgColor + guard let hexColor = owner?.viewPosition.color.rawValue else { return } + layerView.layer.borderColor = UIColor(hex: hexColor).cgColor + nicknameLabel.backgroundColor = UIColor(hex: hexColor) } } diff --git a/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/View/PhotoRoomBottomView.swift b/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/View/PhotoRoomBottomView.swift index e5fa1632..cb897e65 100644 --- a/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/View/PhotoRoomBottomView.swift +++ b/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/View/PhotoRoomBottomView.swift @@ -59,6 +59,9 @@ final class PhotoRoomBottomView: UIView { filterButton.imageView?.tintColor = isHost ? .white : PTGColor.gray85.color switchCameraButton.setImage(PTGImage.switchIcon.image, for: .normal) + + switchCameraButton.isHidden = true + filterButton.isHidden = true } func setCameraButtonTimer(_ count: Int) { @@ -68,6 +71,10 @@ final class PhotoRoomBottomView: UIView { func stopCameraButtonTimer() { cameraButton.stopTimer() } + + func highlightCameraButton() { + cameraButton.layer.borderColor = PTGColor.primaryGreen.color.cgColor + } } extension PhotoRoomBottomView { diff --git a/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/ViewController/PhotoRoomViewController.swift b/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/ViewController/PhotoRoomViewController.swift index 44605167..646d3ace 100644 --- a/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/ViewController/PhotoRoomViewController.swift +++ b/PhotoGether/PresentationLayer/PhotoRoomFeature/PhotoRoomFeature/Source/ViewController/PhotoRoomViewController.swift @@ -137,6 +137,7 @@ public final class PhotoRoomViewController: BaseViewController, ViewControllerCo switch $0 { case .timer(let count): self.photoRoomBottomView.setCameraButtonTimer(count) + self.photoRoomBottomView.highlightCameraButton() case .timerCompleted(let images, let userInfo): self.photoRoomBottomView.stopCameraButtonTimer() diff --git a/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/View/WaitingRoomView.swift b/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/View/WaitingRoomView.swift index f2a63627..ebb91427 100644 --- a/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/View/WaitingRoomView.swift +++ b/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/View/WaitingRoomView.swift @@ -30,6 +30,11 @@ final class WaitingRoomView: UIView { guard let title = StartButtonTitle(from: count) else { return } startButton.setTitle(to: title.rawValue) } + + func enableStartButton() { + self.startButton.isEnabled = true + self.startButton.backgroundColor = PTGColor.primaryGreen.color + } } private extension WaitingRoomView { @@ -81,6 +86,8 @@ private extension WaitingRoomView { func configureUI() { self.backgroundColor = PTGColor.gray90.color startButton.setTitle(to: "촬영시작") + startButton.isEnabled = false + startButton.backgroundColor = .gray } } diff --git a/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewController/WaitingRoomViewController.swift b/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewController/WaitingRoomViewController.swift index be6eff36..fe68a011 100644 --- a/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewController/WaitingRoomViewController.swift +++ b/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewController/WaitingRoomViewController.swift @@ -112,6 +112,9 @@ public final class WaitingRoomViewController: BaseViewController { // MARK: 토스트 메시지 노출 case .shouldShowToast(let message): self.showToast(message: message, duration: 3.0) + + case .readyToStart: + self.waitingRoomView.enableStartButton() } }.store(in: &cancellables) } diff --git a/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewModel/WaitingRoomViewModel.swift b/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewModel/WaitingRoomViewModel.swift index 0c1061b4..505b746a 100644 --- a/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewModel/WaitingRoomViewModel.swift +++ b/PhotoGether/PresentationLayer/WaitingRoomFeature/WaitingRoomFeature/Source/ViewModel/WaitingRoomViewModel.swift @@ -18,6 +18,7 @@ public final class WaitingRoomViewModel { case shouldShowShareSheet(String) case navigateToPhotoRoom case shouldShowToast(String) + case readyToStart } private let sendOfferUseCase: SendOfferUseCase @@ -28,6 +29,7 @@ public final class WaitingRoomViewModel { private let toggleLocalMicStateUseCase: ToggleLocalMicStateUseCase private var isHost: Bool + private var inviteLinkMessage: String? private var cancellables = Set() private let output = PassthroughSubject() @@ -130,6 +132,10 @@ public final class WaitingRoomViewModel { } private func handleLinkButtonDidTap() { + if let inviteLinkMessage { + self.output.send(.shouldShowShareSheet(inviteLinkMessage)) + return + } createRoomUseCase.execute() .receive(on: RunLoop.main) .sink(receiveCompletion: { [weak self] completion in @@ -137,8 +143,10 @@ public final class WaitingRoomViewModel { debugPrint(error.localizedDescription) self?.output.send(.shouldShowToast("Failed to create room")) } - }, receiveValue: { [weak self] roomLink in - self?.output.send(.shouldShowShareSheet(roomLink)) + }, receiveValue: { [weak self] inviteLinkMessage in + self?.inviteLinkMessage = inviteLinkMessage + self?.output.send(.shouldShowShareSheet(inviteLinkMessage)) + self?.output.send(.readyToStart) }) .store(in: &cancellables) }