Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 동영상 선택, 편집 기능 #152

Merged
merged 19 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
81c83d9
✨ EditVideo 기본 vip 파일 구성
anyukyung Nov 29, 2023
4d31423
💄 EditVideo 기본 레이아웃 구성
anyukyung Nov 29, 2023
f87e647
✨ 동영상 수정 뷰 반복 재생, 소리 조절 기능
anyukyung Nov 29, 2023
72c8198
🐛 LoopingPlayerView 레이아웃 버그
anyukyung Nov 29, 2023
f5623a9
♻️ load duration 로직 interactor로 분리, 영상 길이 체크
anyukyung Nov 29, 2023
c072726
✨ PHPicker로 영상 선택, 다음 화면으로 영상 패싱
anyukyung Nov 29, 2023
1022887
✨ VideoFileWorker 분리
anyukyung Nov 29, 2023
f0523e3
✨ UIVideoEditor 영상 편집 기능
anyukyung Nov 30, 2023
dfcd442
♻️ temporary directory에 임시 파일 copy
anyukyung Nov 30, 2023
7512a1f
🔧 코드 리뷰 반영
anyukyung Nov 30, 2023
166ab1b
♻️ 코드 리뷰 반영, 테스트를 위한 개선 및 순환 참조 가능성 제거
anyukyung Nov 30, 2023
4638a59
Merge branch 'iOS/dev' into iOS/feat#115
anyukyung Nov 30, 2023
68faf3d
🔧 Edit 데이터 패싱 에러 고치는 중..
anyukyung Nov 30, 2023
b6cf138
🔧 임시 fix
anyukyung Nov 30, 2023
e28bff0
🔧 변수 리네이밍, phpicker 업로드 완료 후 dimiss
anyukyung Nov 30, 2023
3c966bb
🐛 파일 path 못찾는 에러 수정
anyukyung Nov 30, 2023
0efcf23
🐛 기본 directory tmp로 변경 및 mockUserWorker 헤더 삭제
anyukyung Nov 30, 2023
ac6dc43
🔧 영상 load중 error 발생할 경우 toast
anyukyung Nov 30, 2023
38e30b0
🐛 showToast 메인스레드에서 실행
anyukyung Nov 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions iOS/Layover/Layover.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@
FC2511AD2B04EACD004717BC /* MapInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511AC2B04EACD004717BC /* MapInteractor.swift */; };
FC2511AF2B04EAD9004717BC /* MapPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511AE2B04EAD9004717BC /* MapPresenter.swift */; };
FC2511B12B04EAEC004717BC /* MapModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511B02B04EAEC004717BC /* MapModels.swift */; };
FC3752302B170A620000D439 /* EditVideoPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC37522A2B170A620000D439 /* EditVideoPresenter.swift */; };
FC3752312B170A620000D439 /* EditVideoWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC37522B2B170A620000D439 /* EditVideoWorker.swift */; };
FC3752322B170A620000D439 /* EditVideoRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC37522C2B170A620000D439 /* EditVideoRouter.swift */; };
FC3752332B170A620000D439 /* EditVideoModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC37522D2B170A620000D439 /* EditVideoModels.swift */; };
FC3752342B170A620000D439 /* EditVideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC37522E2B170A620000D439 /* EditVideoViewController.swift */; };
FC3752352B170A620000D439 /* EditVideoInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC37522F2B170A620000D439 /* EditVideoInteractor.swift */; };
FC3752372B170B230000D439 /* EditVideoConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC3752362B170B230000D439 /* EditVideoConfigurator.swift */; };
FC3F3BD82B069EB30080E3A6 /* MapCarouselCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC3F3BD72B069EB30080E3A6 /* MapCarouselCollectionViewCell.swift */; };
FC42E4142B17AB69005D4956 /* VideoFileWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC42E4132B17AB69005D4956 /* VideoFileWorker.swift */; };
FC49758F2B03432800D8627F /* Pretendard-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC4975862B03432700D8627F /* Pretendard-SemiBold.ttf */; };
FC4975932B03432800D8627F /* Pretendard-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC49758A2B03432800D8627F /* Pretendard-Bold.ttf */; };
FC4975942B03432800D8627F /* Pretendard-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC49758B2B03432800D8627F /* Pretendard-Regular.ttf */; };
Expand Down Expand Up @@ -196,7 +204,15 @@
FC2511AC2B04EACD004717BC /* MapInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapInteractor.swift; sourceTree = "<group>"; };
FC2511AE2B04EAD9004717BC /* MapPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapPresenter.swift; sourceTree = "<group>"; };
FC2511B02B04EAEC004717BC /* MapModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapModels.swift; sourceTree = "<group>"; };
FC37522A2B170A620000D439 /* EditVideoPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoPresenter.swift; sourceTree = "<group>"; };
FC37522B2B170A620000D439 /* EditVideoWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoWorker.swift; sourceTree = "<group>"; };
FC37522C2B170A620000D439 /* EditVideoRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoRouter.swift; sourceTree = "<group>"; };
FC37522D2B170A620000D439 /* EditVideoModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoModels.swift; sourceTree = "<group>"; };
FC37522E2B170A620000D439 /* EditVideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoViewController.swift; sourceTree = "<group>"; };
FC37522F2B170A620000D439 /* EditVideoInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoInteractor.swift; sourceTree = "<group>"; };
FC3752362B170B230000D439 /* EditVideoConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditVideoConfigurator.swift; sourceTree = "<group>"; };
FC3F3BD72B069EB30080E3A6 /* MapCarouselCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapCarouselCollectionViewCell.swift; sourceTree = "<group>"; };
FC42E4132B17AB69005D4956 /* VideoFileWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoFileWorker.swift; sourceTree = "<group>"; };
FC4975862B03432700D8627F /* Pretendard-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-SemiBold.ttf"; sourceTree = "<group>"; };
FC49758A2B03432800D8627F /* Pretendard-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Bold.ttf"; sourceTree = "<group>"; };
FC49758B2B03432800D8627F /* Pretendard-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.ttf"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -431,6 +447,20 @@
path = Map;
sourceTree = "<group>";
};
FC3752292B170A050000D439 /* EditVideo */ = {
isa = PBXGroup;
children = (
FC37522E2B170A620000D439 /* EditVideoViewController.swift */,
FC37522F2B170A620000D439 /* EditVideoInteractor.swift */,
FC37522A2B170A620000D439 /* EditVideoPresenter.swift */,
FC37522D2B170A620000D439 /* EditVideoModels.swift */,
FC37522B2B170A620000D439 /* EditVideoWorker.swift */,
FC37522C2B170A620000D439 /* EditVideoRouter.swift */,
FC3752362B170B230000D439 /* EditVideoConfigurator.swift */,
);
path = EditVideo;
sourceTree = "<group>";
};
FC4975852B0342CE00D8627F /* Fonts */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -564,6 +594,7 @@
835783C22B14A41600E7D304 /* MockLoginWorker.swift */,
834B7BD42B14F888002BD176 /* MockSignUpWorker.swift */,
193686732B15C489008902CD /* UserWorker.swift */,
FC42E4132B17AB69005D4956 /* VideoFileWorker.swift */,
);
path = Workers;
sourceTree = "<group>";
Expand All @@ -581,6 +612,7 @@
1945521A2B0478A100299768 /* Home */,
FC930E6E2B0CD73B00AA48E3 /* Profile */,
FC5BE1152B148B540036366D /* EditProfile */,
FC3752292B170A050000D439 /* EditVideo */,
194552272B0479B600299768 /* BaseViewController.swift */,
);
path = Scenes;
Expand Down Expand Up @@ -782,6 +814,7 @@
83C35E1E2B10923C00D8DD5C /* PlaybackCell.swift in Sources */,
FC2511A42B045D6C004717BC /* SignUpModels.swift in Sources */,
FC767F932B1220CC0088CF9B /* NicknameDTO.swift in Sources */,
FC3752312B170A620000D439 /* EditVideoWorker.swift in Sources */,
FC68E2A12B023326001AABFF /* EndPoint.swift in Sources */,
1972CCDF2B14C9B000C3C762 /* Notification.Name+.swift in Sources */,
FC2511AF2B04EAD9004717BC /* MapPresenter.swift in Sources */,
Expand All @@ -791,6 +824,7 @@
FC5BE11C2B148D160036366D /* EditProfilePresenter.swift in Sources */,
FC68E2A32B0233BC001AABFF /* NetworkError.swift in Sources */,
FC3F3BD82B069EB30080E3A6 /* MapCarouselCollectionViewCell.swift in Sources */,
FC3752342B170A620000D439 /* EditVideoViewController.swift in Sources */,
194552252B0478B400299768 /* HomeViewController.swift in Sources */,
194552222B0478B400299768 /* HomeWorker.swift in Sources */,
FC5BE1202B148D170036366D /* EditProfileViewController.swift in Sources */,
Expand All @@ -803,6 +837,10 @@
FC5BE11D2B148D160036366D /* EditProfileWorker.swift in Sources */,
194551F62B037F2D00299768 /* LoginViewController.swift in Sources */,
FC767FA52B125F430088CF9B /* UIViewController+.swift in Sources */,
FC3752332B170A620000D439 /* EditVideoModels.swift in Sources */,
FC3752322B170A620000D439 /* EditVideoRouter.swift in Sources */,
FC3752352B170A620000D439 /* EditVideoInteractor.swift in Sources */,
FC3752302B170A620000D439 /* EditVideoPresenter.swift in Sources */,
FCEE0FF22B036B6000195BBE /* LOButton.swift in Sources */,
FC5BE1212B148D170036366D /* EditProfileInteractor.swift in Sources */,
FC930E7C2B0CD80800AA48E3 /* ProfileConfigurator.swift in Sources */,
Expand All @@ -820,11 +858,13 @@
194551F42B037F2D00299768 /* LoginRouter.swift in Sources */,
FC4975992B03439000D8627F /* UIFont+.swift in Sources */,
FC5BE11E2B148D160036366D /* EditProfileRouter.swift in Sources */,
FC42E4142B17AB69005D4956 /* VideoFileWorker.swift in Sources */,
FC767F952B1222350088CF9B /* ProfileImageDTO.swift in Sources */,
194551F52B037F2D00299768 /* LoginModels.swift in Sources */,
834B7BD52B14F888002BD176 /* MockSignUpWorker.swift in Sources */,
835A619E2B068115002F22A5 /* PlaybackWorker.swift in Sources */,
1972CCD22B125ED700C3C762 /* UserDefaultStored.swift in Sources */,
FC3752372B170B230000D439 /* EditVideoConfigurator.swift in Sources */,
FC2511AD2B04EACD004717BC /* MapInteractor.swift in Sources */,
19C7AFD62B02584D003B35F2 /* KeychainStored.swift in Sources */,
FC930E802B0CFB0B00AA48E3 /* ProfileHeaderView.swift in Sources */,
Expand Down
35 changes: 35 additions & 0 deletions iOS/Layover/Layover/Scenes/EditVideo/EditVideoConfigurator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// EditVideoConfigurator.swift
// Layover
//
// Created by kong on 2023/11/29.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import Foundation

final class EditVideoConfigurator: Configurator {

typealias ViewController = EditVideoViewController

static let shared = EditVideoConfigurator()

private init() { }

func configure(_ viewController: ViewController) {
let viewController = viewController
let videoFileWorker = VideoFileWorker()
let interactor = EditVideoInteractor()
let presenter = EditVideoPresenter()
let router = EditVideoRouter()

router.viewController = viewController
router.dataStore = interactor
viewController.interactor = interactor
viewController.router = router
interactor.presenter = presenter
interactor.videoFileWorker = videoFileWorker
presenter.viewController = viewController
}

}
54 changes: 54 additions & 0 deletions iOS/Layover/Layover/Scenes/EditVideo/EditVideoInteractor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// EditVideoInteractor.swift
// Layover
//
// Created by kong on 2023/11/29.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import AVFoundation
import UIKit

protocol EditVideoBusinessLogic {
func fetchVideo(request: EditVideoModels.FetchVideo.Request)
func deleteVideo()
}

protocol EditVideoDataStore {
var videoURL: URL? { get set }
}

final class EditVideoInteractor: EditVideoBusinessLogic, EditVideoDataStore {

// MARK: - Properties

typealias Models = EditVideoModels

var videoFileWorker: VideoFileWorker?
var presenter: EditVideoPresentationLogic?

var videoURL: URL?

func fetchVideo(request: EditVideoModels.FetchVideo.Request) {
let isEdited = request.editedVideoURL != nil
guard let videoURL = isEdited ? request.editedVideoURL : videoURL else { return }

Task {
let duration = try await AVAsset(url: videoURL).load(.duration)
let seconds = CMTimeGetSeconds(duration)
let response = Models.FetchVideo.Response(isEdited: isEdited,
videoURL: videoURL,
duration: seconds,
isWithinRange: 3.0...60.0 ~= seconds)
await MainActor.run {
presenter?.presentVideo(with: response)
}
}
}

func deleteVideo() {
guard let videoURL else { return }
videoFileWorker?.delete(at: videoURL)
}

}
31 changes: 31 additions & 0 deletions iOS/Layover/Layover/Scenes/EditVideo/EditVideoModels.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// EditVideoModels.swift
// Layover
//
// Created by kong on 2023/11/29.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

enum EditVideoModels {

enum FetchVideo {
struct Request {
let editedVideoURL: URL?
}
struct Response {
let isEdited: Bool
let videoURL: URL
let duration: Double
let isWithinRange: Bool
}
struct ViewModel {
let isEdited: Bool
let videoURL: URL
let duration: Double
let canNext: Bool
}
}

}
29 changes: 29 additions & 0 deletions iOS/Layover/Layover/Scenes/EditVideo/EditVideoPresenter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// EditVideoPresenter.swift
// Layover
//
// Created by kong on 2023/11/29.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

protocol EditVideoPresentationLogic {
func presentVideo(with response: EditVideoModels.FetchVideo.Response)
}

final class EditVideoPresenter: EditVideoPresentationLogic {

// MARK: - Properties

typealias Models = EditVideoModels
weak var viewController: EditVideoDisplayLogic?

func presentVideo(with response: EditVideoModels.FetchVideo.Response) {
let viewModel = Models.FetchVideo.ViewModel(isEdited: response.isEdited,
videoURL: response.videoURL,
duration: response.duration,
canNext: response.isWithinRange)
viewController?.displayVideo(viewModel: viewModel)
}
}
32 changes: 32 additions & 0 deletions iOS/Layover/Layover/Scenes/EditVideo/EditVideoRouter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// EditVideoRouter.swift
// Layover
//
// Created by kong on 2023/11/29.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

protocol EditVideoRoutingLogic {
func routeToNext()
}

protocol EditVideoDataPassing {
var dataStore: EditVideoDataStore? { get }
}

final class EditVideoRouter: NSObject, EditVideoRoutingLogic, EditVideoDataPassing {

// MARK: - Properties

weak var viewController: EditVideoViewController?
var dataStore: EditVideoDataStore?

// MARK: - Routing

func routeToNext() {

}

}
Loading