diff --git a/iOS/Layover/Layover/DesignSystem/LODescriptionView.swift b/iOS/Layover/Layover/DesignSystem/LODescriptionView.swift index c7f8a23..450fed3 100644 --- a/iOS/Layover/Layover/DesignSystem/LODescriptionView.swift +++ b/iOS/Layover/Layover/DesignSystem/LODescriptionView.swift @@ -8,7 +8,7 @@ import UIKit final class LODescriptionView: UIView { - static let descriptionWidth: CGFloat = 170 + static let descriptionWidth: CGFloat = 210 static let descriptionHeight: CGFloat = 63 // MARK: - View isTouched State diff --git a/iOS/Layover/Layover/Network/DTOs/ReportDTO.swift b/iOS/Layover/Layover/Network/DTOs/ReportDTO.swift index 8588bd8..69ae128 100644 --- a/iOS/Layover/Layover/Network/DTOs/ReportDTO.swift +++ b/iOS/Layover/Layover/Network/DTOs/ReportDTO.swift @@ -9,7 +9,13 @@ import Foundation struct ReportDTO: Codable { - let memberId: Int? + let memberID: Int? let boardID: Int let reportType: String + + enum CodingKeys: String, CodingKey { + case memberID = "memberId" + case boardID = "boardId" + case reportType + } } diff --git a/iOS/Layover/Layover/Network/EndPoint/Factories/DefaultPostManagerEndPointFactory.swift b/iOS/Layover/Layover/Network/EndPoint/Factories/DefaultPostManagerEndPointFactory.swift index 061f5de..61e2048 100644 --- a/iOS/Layover/Layover/Network/EndPoint/Factories/DefaultPostManagerEndPointFactory.swift +++ b/iOS/Layover/Layover/Network/EndPoint/Factories/DefaultPostManagerEndPointFactory.swift @@ -16,7 +16,7 @@ protocol PostManagerEndPointFactory { struct DefaultPostManagerEndPointFactory: PostManagerEndPointFactory { func reportPlaybackVideoEndpoint(boardID: Int, reportType: String) -> EndPoint> { let bodyParmeters: ReportDTO = ReportDTO( - memberId: nil, + memberID: nil, boardID: boardID, reportType: reportType) diff --git a/iOS/Layover/Layover/Scenes/Playback/Cell/PlaybackCell.swift b/iOS/Layover/Layover/Scenes/Playback/Cell/PlaybackCell.swift index c61c01e..cc783f8 100644 --- a/iOS/Layover/Layover/Scenes/Playback/Cell/PlaybackCell.swift +++ b/iOS/Layover/Layover/Scenes/Playback/Cell/PlaybackCell.swift @@ -39,16 +39,20 @@ final class PlaybackCell: UICollectionViewCell { playbackView.descriptionView.titleLabel.text = post.board.title playbackView.descriptionView.setText(post.board.description ?? "") playbackView.setDescriptionViewUI() + playbackView.profileButton.setImage(UIImage.profile, for: .normal) playbackView.profileLabel.text = post.member.username setTagButtons(with: post.tags) - playbackView.setProfileButton(member: post.member) - playbackView.setLocationText(location: post.board.location ?? "이름 모를 곳") memberID = nil memberID = post.member.memberID playbackView.profileButton.removeTarget(nil, action: nil, for: .allEvents) playbackView.profileButton.addTarget(self, action: #selector(profileButtonDidTap), for: .touchUpInside) } + func setProfileImageAndLocation(imageData: Data?, location: String) { + playbackView.setLocationText(location: location) + playbackView.setProfileButton(imageData: imageData) + } + func addAVPlayer(url: URL) { playbackView.resetPlayer() playbackView.addAVPlayer(url: url) diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift index 6b6d518..4ebe050 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift @@ -31,6 +31,8 @@ protocol PlaybackBusinessLogic { func moveToTagPlay(with request: PlaybackModels.MoveToRelativeView.Request) @discardableResult func fetchPosts() -> Task + @discardableResult + func loadProfileImageAndLocation(with request: PlaybackModels.LoadProfileImageAndLocation.Request) -> Task } protocol PlaybackDataStore: AnyObject { @@ -84,7 +86,7 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { posts = worker.makeInfiniteScroll(posts: posts) self.posts = posts } - let videos: [Models.PlaybackVideo] = await transPostToVideo(posts) + let videos: [Models.PlaybackVideo] = transPostToVideo(posts) let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) await MainActor.run { presenter?.presentVideoList(with: response) @@ -251,25 +253,23 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { previousCell.playbackView.playPlayer() } - private func transPostToVideo(_ posts: [Post]) async -> [Models.PlaybackVideo] { - return await posts.asyncCompactMap { post in + private func transPostToVideo(_ posts: [Post]) -> [Models.PlaybackVideo] { + return posts.compactMap { post in guard let videoURL: URL = post.board.videoURL else { return nil } - async let profileImageData = self.worker?.fetchImageData(with: post.member.profileImageURL) - async let thumbnailImageData = self.worker?.fetchImageData(with: post.board.thumbnailImageURL) - async let location = self.worker?.transLocation(latitude: post.board.latitude, longitude: post.board.longitude) - return Models.PlaybackVideo(displayPost: Models.DisplayedPost( - member: Models.Member( - memberID: post.member.identifier, - username: post.member.username, - profileImageData: await profileImageData), - board: Models.Board( - boardID: post.board.identifier, - title: post.board.title, - description: post.board.description, - thumbnailImageData: await thumbnailImageData, - videoURL: videoURL, - location: await location), - tags: post.tag)) + return Models.PlaybackVideo( + displayedPost: Models.DisplayedPost( + member: Models.Member( + memberID: post.member.identifier, + username: post.member.username, + profileImageURL: post.member.profileImageURL), + board: Models.Board( + boardID: post.board.identifier, + title: post.board.title, + description: post.board.description, + videoURL: videoURL, + latitude: post.board.latitude, + longitude: post.board.longitude), + tags: post.tag)) } } @@ -314,7 +314,7 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { } guard let newPosts else { return false } self.posts?.append(contentsOf: newPosts) - let videos: [Models.PlaybackVideo] = await transPostToVideo(newPosts) + let videos: [Models.PlaybackVideo] = transPostToVideo(newPosts) let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) await MainActor.run { presenter?.presentLoadFetchVideos(with: response) @@ -325,4 +325,17 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { return false } } + + func loadProfileImageAndLocation(with request: PlaybackModels.LoadProfileImageAndLocation.Request) -> Task { + Task { + async let profileImageData = self.worker?.fetchImageData(with: request.profileImageURL) + async let location: String? = self.worker?.transLocation(latitude: request.latitude, longitude: request.longitude) + let response: Models.LoadProfileImageAndLocation.Response = Models.LoadProfileImageAndLocation.Response(curCell: request.curCell, profileImageData: await profileImageData, location: await location) + await MainActor.run { + presenter?.presentLoadProfileImageAndLocation(with: response) + return true + } + return false + } + } } diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackModels.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackModels.swift index f53b77d..905d63b 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackModels.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackModels.swift @@ -12,7 +12,7 @@ enum PlaybackModels { // MARK: - Properties Type struct PlaybackVideo: Hashable { var id: UUID = UUID() - let displayPost: DisplayedPost + let displayedPost: DisplayedPost } enum ParentView { @@ -32,16 +32,16 @@ enum PlaybackModels { struct Member: Hashable { let memberID: Int let username: String - let profileImageData: Data? + let profileImageURL: URL? } struct Board: Hashable { let boardID: Int let title: String let description: String? - let thumbnailImageData: Data? let videoURL: URL - let location: String? + let latitude: Double + let longitude: Double } // MARK: - UseCase Load Video List @@ -235,4 +235,27 @@ enum PlaybackModels { } } + + // MARK: - UseCase Load ProfileImage & Location + + enum LoadProfileImageAndLocation { + struct Request { + let curCell: PlaybackCell + let profileImageURL: URL? + let latitude: Double + let longitude: Double + } + + struct Response { + let curCell: PlaybackCell + let profileImageData: Data? + let location: String? + } + + struct ViewModel { + let curCell: PlaybackCell + let profileImageData: Data? + let location: String + } + } } diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift index 75ff4ba..5bfafa8 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift @@ -26,6 +26,7 @@ protocol PlaybackPresentationLogic { func presentDeleteVideo(with response: PlaybackModels.DeletePlaybackVideo.Response) func presentProfile() func presentTagPlay() + func presentLoadProfileImageAndLocation(with response: PlaybackModels.LoadProfileImageAndLocation.Response) } final class PlaybackPresenter: PlaybackPresentationLogic { @@ -128,4 +129,9 @@ final class PlaybackPresenter: PlaybackPresentationLogic { func presentTagPlay() { viewController?.routeToTagPlay() } + + func presentLoadProfileImageAndLocation(with response: PlaybackModels.LoadProfileImageAndLocation.Response) { + let viewModel: Models.LoadProfileImageAndLocation.ViewModel = Models.LoadProfileImageAndLocation.ViewModel(curCell: response.curCell, profileImageData: response.profileImageData, location: response.location ?? "이름 모를 곳") + viewController?.setProfileImageAndLocation(viewModel: viewModel) + } } diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackView.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackView.swift index 90b2f64..0b7248e 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackView.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackView.swift @@ -48,9 +48,10 @@ final class PlaybackView: UIView { let button: UIButton = UIButton() button.layer.cornerRadius = 19 button.layer.borderWidth = 1 - button.layer.borderColor = UIColor.layoverWhite.cgColor + button.layer.borderColor = UIColor.grey400.cgColor button.backgroundColor = .layoverWhite button.clipsToBounds = true + button.imageView?.contentMode = .scaleAspectFill return button }() @@ -65,6 +66,7 @@ final class PlaybackView: UIView { private let locationLabel: UILabel = { let label: UILabel = UILabel() label.font = .loFont(type: .body2) + label.text = "이름 모를 곳에서" label.textColor = UIColor.layoverWhite return label }() @@ -201,8 +203,8 @@ final class PlaybackView: UIView { } } - func setProfileButton(member: PlaybackModels.Member) { - if let imageData: Data = member.profileImageData { + func setProfileButton(imageData: Data?) { + if let imageData { profileButton.setImage(UIImage(data: imageData), for: .normal) } else { profileButton.setImage(UIImage.profile, for: .normal) diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift index 6416113..86598ff 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift @@ -33,6 +33,7 @@ protocol PlaybackDisplayLogic: AnyObject { func deleteVideo(viewModel: PlaybackModels.DeletePlaybackVideo.ViewModel) func routeToProfile() func routeToTagPlay() + func setProfileImageAndLocation(viewModel: PlaybackModels.LoadProfileImageAndLocation.ViewModel) } final class PlaybackViewController: BaseViewController { @@ -244,14 +245,20 @@ extension PlaybackViewController: PlaybackDisplayLogic { playbackCollectionView.register(PlaybackCell.self, forCellWithReuseIdentifier: PlaybackCell.identifier) dataSource = UICollectionViewDiffableDataSource(collectionView: playbackCollectionView) { (collectionView, indexPath, playbackVideo) -> UICollectionViewCell? in guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PlaybackCell.identifier, for: indexPath) as? PlaybackCell else { return PlaybackCell() } - cell.setPlaybackContents(post: playbackVideo.displayPost) + cell.setPlaybackContents(post: playbackVideo.displayedPost) if let teleportIndex = viewModel.teleportIndex { if indexPath.row == 0 || indexPath.row == teleportIndex { + cell.playbackView.resetPlayer() return cell } } + cell.addAVPlayer(url: playbackVideo.displayedPost.board.videoURL) + self.interactor?.loadProfileImageAndLocation(with: Models.LoadProfileImageAndLocation.Request( + curCell: cell, + profileImageURL: playbackVideo.displayedPost.member.profileImageURL, + latitude: playbackVideo.displayedPost.board.latitude, + longitude: playbackVideo.displayedPost.board.longitude)) cell.delegate = self - cell.addAVPlayer(url: playbackVideo.displayPost.board.videoURL) return cell } } @@ -298,6 +305,10 @@ extension PlaybackViewController: PlaybackDisplayLogic { func routeToTagPlay() { router?.routeToTagPlay() } + + func setProfileImageAndLocation(viewModel: PlaybackModels.LoadProfileImageAndLocation.ViewModel) { + viewModel.curCell.setProfileImageAndLocation(imageData: viewModel.profileImageData, location: viewModel.location) + } } extension PlaybackViewController: UICollectionViewDelegateFlowLayout { diff --git a/iOS/Layover/Layover/Scenes/Profile/ProfileInteractor.swift b/iOS/Layover/Layover/Scenes/Profile/ProfileInteractor.swift index 1789ddb..4ea5cc2 100644 --- a/iOS/Layover/Layover/Scenes/Profile/ProfileInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Profile/ProfileInteractor.swift @@ -60,7 +60,7 @@ final class ProfileInteractor: ProfileBusinessLogic, ProfileDataStore { guard let userProfile = await userWorker?.fetchProfile(by: profileId) else { return false } - + posts = [] nickname = userProfile.username introduce = userProfile.introduce diff --git a/iOS/Layover/Layover/Scenes/Report/ReportConfigurator.swift b/iOS/Layover/Layover/Scenes/Report/ReportConfigurator.swift index 7de9c41..289187d 100644 --- a/iOS/Layover/Layover/Scenes/Report/ReportConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Report/ReportConfigurator.swift @@ -17,8 +17,8 @@ final class ReportConfigurator: Configurator { let viewController: ReportViewController = viewController let interactor: ReportInteractor = ReportInteractor() let presenter: ReportPresenter = ReportPresenter() -// let worker: ReportWorker = ReportWorker() - let worker: ReportWorkerProtocol = MockReportWorker() + let worker: ReportWorker = ReportWorker() +// let worker: ReportWorkerProtocol = MockReportWorker() let router: ReportRouter = ReportRouter() router.viewController = viewController diff --git a/iOS/Layover/Layover/Workers/Mocks/MockReportWorker.swift b/iOS/Layover/Layover/Workers/Mocks/MockReportWorker.swift index 9182dec..6a28cd0 100644 --- a/iOS/Layover/Layover/Workers/Mocks/MockReportWorker.swift +++ b/iOS/Layover/Layover/Workers/Mocks/MockReportWorker.swift @@ -35,8 +35,8 @@ final class MockReportWorker: ReportWorkerProtocol { do { let bodyParameters = ReportDTO( - memberId: nil, - boardID: 1, + memberID: nil, + boardID: 1, reportType: "청소년에게 유해한 내용입니다.") let endPoint = EndPoint>(path: "/report", method: .POST,