Skip to content

Commit

Permalink
Merge pull request #154 from boostcampwm-2024/feature/#151-participanโ€ฆ
Browse files Browse the repository at this point in the history
โ€ฆts-layout-sync

[FEAT/#151] ์ฐธ๊ฐ€์ž๋“ค์˜ ํ™”๋ฉด ์ˆœ์„œ๋ฅผ ๋™๊ธฐํ™” ํ•ฉ๋‹ˆ๋‹ค.
  • Loading branch information
youn9k authored Dec 2, 2024
2 parents bf9d57a + b8a7f82 commit 31cb0f8
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ public final class ConnectionRepositoryImpl: ConnectionRepository {

public var clients: [ConnectionClient]

private let didEnterNewUserSubject = PassthroughSubject<(UserInfo, UIView), Never>()
public var didEnterNewUserPublisher: AnyPublisher<(UserInfo, UIView), Never> {
didEnterNewUserSubject.eraseToAnyPublisher()
}
private let _localVideoView = CapturableVideoView()
private var localUserInfo: UserInfo?
public private(set) var localUserInfo: UserInfo?

public var localVideoView: UIView { _localVideoView }
public var capturedLocalVideo: UIImage? { _localVideoView.capturedImage }
Expand Down Expand Up @@ -225,7 +229,10 @@ extension ConnectionRepositoryImpl {
}, receiveValue: { [weak self] entity in
guard let self else { return }
let newUser = entity.newUser
let emptyClient = clients.first(where: { $0.remoteUserInfo == nil })
guard let emptyClient = clients.first(where: { $0.remoteUserInfo == nil }) else {
PTGDataLogger.log("๋ฐฉ์ด ๊ฐ€๋“ ์ฐผ๋Š”๋ฐ ๋ˆ„๊ตฐ๊ฐ€ ์ž…์žฅํ–ˆ์–ด์š”!")
return
}

guard let viewPosition = UserInfo.ViewPosition(rawValue: newUser.initialPosition),
let roomID = self.localUserInfo?.roomID
Expand All @@ -238,8 +245,9 @@ extension ConnectionRepositoryImpl {
viewPosition: viewPosition,
roomID: roomID
)

emptyClient?.setRemoteUserInfo(newUserInfoEntity)

emptyClient.setRemoteUserInfo(newUserInfoEntity)
didEnterNewUserSubject.send((newUserInfoEntity, emptyClient.remoteVideoView))
PTGDataLogger.log("newUser Entered: \(newUserInfoEntity)")
})
.store(in: &cancellables)
Expand Down Expand Up @@ -274,6 +282,7 @@ extension ConnectionRepositoryImpl {
private func setLocalUserInfo(entity: RoomOwnerEntity) -> RoomOwnerEntity {
guard let localUserInfo = localUserInfo(for: entity) else { return entity }
self.localUserInfo = localUserInfo
self.didEnterNewUserSubject.send((localUserInfo, localVideoView))
return entity
}

Expand Down Expand Up @@ -305,7 +314,7 @@ extension ConnectionRepositoryImpl {
private func localUserInfo(for entity: RoomOwnerEntity) -> UserInfo? {
return UserInfo(
id: entity.hostID,
nickname: "๋‚ด๊ฐ€ ํ˜ธ์ŠคํŠธ๋‹ค",
nickname: String(entity.hostID.suffix(4)), // TODO: ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ๋‹‰๋„ค์ž„์œผ๋กœ ๋ณ€๊ฒฝ ์˜ˆ์ •
isHost: true,
viewPosition: .topLeading,
roomID: entity.roomID
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import UIKit
import Combine
import PhotoGetherDomainInterface

public final class DidEnterNewUserPublisherUseCaseImpl: DidEnterNewUserPublisherUseCase {
public func publisher() -> AnyPublisher<(UserInfo, UIView), Never> {
return connectionRepository.didEnterNewUserPublisher
}
private let connectionRepository: ConnectionRepository

public init(connectionRepository: ConnectionRepository) {
self.connectionRepository = connectionRepository
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import UIKit
import PhotoGetherDomainInterface

public final class GetLocalVideoUseCaseImpl: GetLocalVideoUseCase {
public func execute() -> UIView {
// TODO: ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ํ•˜๋‚˜์˜ localVideoView๋งŒ ๋“ค๊ณ  ์žˆ๋„๋ก ๋ณ€๊ฒฝ ์˜ˆ์ •
connectionRepository.localVideoView
public func execute() -> (UserInfo?, UIView) {
return (connectionRepository.localUserInfo, connectionRepository.localVideoView)
}

private let connectionRepository: ConnectionRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@ import UIKit
import PhotoGetherDomainInterface

public final class GetRemoteVideoUseCaseImpl: GetRemoteVideoUseCase {
public func execute() -> [UIView] {
let sortedClients = connectionRepository.clients
.sorted { lhs, rhs in
let lhsPosition = lhs.remoteUserInfo?.viewPosition.rawValue ?? Int.max
let rhsPosition = rhs.remoteUserInfo?.viewPosition.rawValue ?? Int.max
return lhsPosition < rhsPosition
}
.map { $0.remoteVideoView }

return sortedClients
public func execute() -> [(UserInfo?, UIView)] {
return connectionRepository.clients.map { ($0.remoteUserInfo, $0.remoteVideoView) }
}

private let connectionRepository: ConnectionRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public struct UserInfo: Identifiable {

public enum ViewPosition: Int {
case topLeading
case bottomTrailing
case topTrailing
case bottomLeading
case bottomTrailing
}

public init(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import UIKit
import Combine

public protocol ConnectionRepository {
var didEnterNewUserPublisher: AnyPublisher<(UserInfo, UIView), Never> { get }

var localUserInfo: UserInfo? { get }

var clients: [ConnectionClient] { get }
var localVideoView: UIView { get }
var capturedLocalVideo: UIImage? { get }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import UIKit
import Combine

public protocol DidEnterNewUserPublisherUseCase {
func publisher() -> AnyPublisher<(UserInfo, UIView), Never>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import Foundation
import UIKit

public protocol GetLocalVideoUseCase {
func execute() -> UIView
func execute() -> (UserInfo?, UIView)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import Foundation
import UIKit

public protocol GetRemoteVideoUseCase {
func execute() -> [UIView]
func execute() -> [(UserInfo?, UIView)]
}
7 changes: 6 additions & 1 deletion PhotoGether/PhotoGether/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
connectionRepository: connectionRepository
)

let didEnterNewUserPublisherUseCase: DidEnterNewUserPublisherUseCase = DidEnterNewUserPublisherUseCaseImpl(
connectionRepository: connectionRepository
)

let photoRoomViewModel: PhotoRoomViewModel = PhotoRoomViewModel(
captureVideosUseCase: captureVideosUseCase
)
Expand All @@ -97,7 +101,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
sendOfferUseCase: sendOfferUseCase,
getLocalVideoUseCase: getLocalVideoUseCase,
getRemoteVideoUseCase: getRemoteVideoUseCase,
createRoomUseCase: createRoomUseCase
createRoomUseCase: createRoomUseCase,
didEnterNewUserPublisherUseCase: didEnterNewUserPublisherUseCase
)

let waitingRoomViewController: WaitingRoomViewController = WaitingRoomViewController(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ import UIKit
import DesignSystem

public extension UIViewController {
private struct ToastState {
static var presentedToast: UIView?
}

func showToast(message: String, duration: TimeInterval = 2.0) {
// ์ด๋ฏธ ํ† ์ŠคํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ œ๊ฑฐ
if let existingToast = ToastState.presentedToast {
existingToast.removeFromSuperview()
ToastState.presentedToast = nil
}

let padding = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 20)
let toastLabel: PTGPaddingLabel = {
let lbl = PTGPaddingLabel(padding: padding)
Expand All @@ -23,6 +33,7 @@ public extension UIViewController {
}()

view.addSubview(toastLabel)
ToastState.presentedToast = toastLabel

let maxWidth: CGFloat = view.frame.width > 0 ? view.frame.width * 0.7 : 300

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import UIKit
import SnapKit

public enum ParticipantPosition {
public enum ParticipantPosition: Int {
case topLeading
case bottomTrailing
case topTrailing
case bottomLeading
case bottomTrailing

public init?(rawValue: Int) {
switch rawValue {
case 0: self = .topLeading
case 1: self = .bottomTrailing
case 2: self = .topTrailing
case 3: self = .bottomLeading
default: return nil
}
}
}

public final class PTGParticipantsGridView: UIView {
Expand Down Expand Up @@ -105,6 +115,3 @@ extension PTGParticipantsGridView {
static let itemSpacing: CGFloat = 11
}
}



Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ private extension WaitingRoomView {

func configureUI() {
self.backgroundColor = PTGColor.gray90.color

startButton.setTitle(to: StartButtonTitle.one.rawValue)
startButton.setTitle(to: "์ดฌ์˜์‹œ์ž‘")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public final class EnterLoadingViewController: BaseViewController, ViewControlle
label.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.top.equalTo(activityIndicator.snp.bottom).offset(10)
$0.horizontalEdges.equalToSuperview().inset(20)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,33 +65,25 @@ public final class WaitingRoomViewController: BaseViewController {
private func bindOutput() {
let output = viewModel.transform(input: input.eraseToAnyPublisher())

output.sink { [weak self] in
output
.receive(on: RunLoop.main)
.sink { [weak self] in
guard let self else { return }
switch $0 {
// MARK: ๋„ค๋น„๊ฒŒ์ด์…˜ ์ฒ˜๋ฆฌ
case .navigateToPhotoRoom:
self.navigateToPhotoRoom()

// MARK: ๋‚ด ๋น„๋””์˜ค ํ™”๋ฉด ์—…๋ฐ์ดํŠธ
case .localVideo(let localVideoView):
print(localVideoView)
updateParticipantView(view: localVideoView, position: .topLeading)
updateParticipantNickname(nickname: "๋‚˜๋Š” ํ˜ธ์ŠคํŠธ์•ผ", position: .topLeading)

// MARK: ์ƒ๋Œ€๋ฐฉ ๋น„๋””์˜ค ํ™”๋ฉด ์—…๋ฐ์ดํŠธ
case .remoteVideos(let remoteVideoViews):
let guestVideoView1 = remoteVideoViews[safe: 0] ?? UIView()
let guestVideoView2 = remoteVideoViews[safe: 1] ?? UIView()
let guestVideoView3 = remoteVideoViews[safe: 2] ?? UIView()

updateParticipantView(view: guestVideoView1, position: .bottomTrailing)
updateParticipantView(view: guestVideoView2, position: .topTrailing)
updateParticipantView(view: guestVideoView3, position: .bottomLeading)

updateParticipantNickname(nickname: "๋‚˜๋Š” ๊ฒŒ์ŠคํŠธ1", position: .bottomTrailing)
updateParticipantNickname(nickname: "๋‚˜๋Š” ๊ฒŒ์ŠคํŠธ2", position: .topTrailing)
updateParticipantNickname(nickname: "๋‚˜๋Š” ๊ฒŒ์ŠคํŠธ3", position: .bottomLeading)

// MARK: ํ™”๋ฉด ์—…๋ฐ์ดํŠธ
case let .shouldUpdateVideoView(videoView, viewPosition):
guard let participantPosition = ParticipantPosition(rawValue: viewPosition) else { return }
updateParticipantView(view: videoView, position: participantPosition)

// MARK: ๋‹‰๋„ค์ž„ ์—…๋ฐ์ดํŠธ
case let .shouldUpdateNickname(nickname, viewPosition):
guard let participantPosition = ParticipantPosition(rawValue: viewPosition) else { return }
updateParticipantNickname(nickname: nickname, position: participantPosition)

// MARK: ๋งˆ์ดํฌ ์Œ์†Œ๊ฑฐ UI ์—…๋ฐ์ดํŠธ
case .micMuteState:
return
Expand Down
Loading

0 comments on commit 31cb0f8

Please sign in to comment.