diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index f65a48dd..57fbf9d6 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 70113E7129C1D01800CBA08B /* VideoEditorModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70113E7029C1D01800CBA08B /* VideoEditorModule.swift */; }; 8A32EED0258CB5430098F852 /* bundleEffects in Resources */ = {isa = PBXBuildFile; fileRef = 8A32EECF258CB5430098F852 /* bundleEffects */; }; 8A32EEDF258CB70C0098F852 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A32EEDE258CB70C0098F852 /* Assets.xcassets */; }; + DBD546942C5CC7D7003157BA /* SummaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD546932C5CC7D7003157BA /* SummaryViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -41,6 +42,7 @@ 8AFC95CF269DC12D00B4114B /* BNBLicenseUtils.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = BNBLicenseUtils.xcframework; sourceTree = ""; }; 8D879ADE024EEEC9574AAB2D /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; A24378930003F0F910117502 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DBD546932C5CC7D7003157BA /* SummaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SummaryViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -102,6 +104,7 @@ 70113E7029C1D01800CBA08B /* VideoEditorModule.swift */, 636C55232B0DF24100678849 /* PhotoEditorModule.swift */, 639DA00F254700290011C153 /* ViewController.swift */, + DBD546932C5CC7D7003157BA /* SummaryViewController.swift */, 63F7115F29D1F21A00045A06 /* short_music_20.wav */, 634FAC06255C351900FB0DBC /* Localizable.strings */, 639DA011254700290011C153 /* Main.storyboard */, @@ -252,6 +255,7 @@ 636C55242B0DF24100678849 /* PhotoEditorModule.swift in Sources */, 70113E7129C1D01800CBA08B /* VideoEditorModule.swift in Sources */, 639DA00C254700290011C153 /* AppDelegate.swift in Sources */, + DBD546942C5CC7D7003157BA /* SummaryViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/Example/Assets.xcassets/nav_back_arrow.imageset/Contents.json b/Example/Example/Assets.xcassets/nav_back_arrow.imageset/Contents.json new file mode 100644 index 00000000..6543f7ca --- /dev/null +++ b/Example/Example/Assets.xcassets/nav_back_arrow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon-chevron-left-l.pdf", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example/Example/Assets.xcassets/nav_back_arrow.imageset/icon-chevron-left-l.pdf b/Example/Example/Assets.xcassets/nav_back_arrow.imageset/icon-chevron-left-l.pdf new file mode 100644 index 00000000..11ee31e5 Binary files /dev/null and b/Example/Example/Assets.xcassets/nav_back_arrow.imageset/icon-chevron-left-l.pdf differ diff --git a/Example/Example/SummaryViewController.swift b/Example/Example/SummaryViewController.swift new file mode 100644 index 00000000..e6f2b9de --- /dev/null +++ b/Example/Example/SummaryViewController.swift @@ -0,0 +1,77 @@ +// +// SummaryViewController.swift +// Example +// +// Created by Andrey Sak on 2.08.24. +// + +import UIKit + +class SummaryViewController: UIViewController { + + var editCoverHandler: (() -> Void)? + + var coverImage: UIImage? + + private let coverImageView: UIImageView = { + let imageView = UIImageView() + imageView.clipsToBounds = true + imageView.contentMode = .scaleAspectFill + return imageView + }() + + private let backButton: UIButton = { + let button = UIButton() + button.setImage(UIImage(resource: .navBackArrow), for: .normal) + return button + }() + + private let editCoverButton: UIButton = { + let button = UIButton() + button.layer.borderColor = UIColor.white.cgColor + button.layer.borderWidth = 2.0 + button.setTitle("Edit cover", for: .normal) + return button + }() + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = UIColor.gray + + view.addSubview(coverImageView) + coverImageView.image = coverImage + coverImageView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + coverImageView.widthAnchor.constraint(equalToConstant: 180), + coverImageView.heightAnchor.constraint(equalToConstant: 320), + coverImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + coverImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor) + ]) + + view.addSubview(backButton) + backButton.addTarget(self, action: #selector(editCoverAction), for: .touchUpInside) + backButton.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + backButton.widthAnchor.constraint(equalToConstant: 45), + backButton.heightAnchor.constraint(equalToConstant: 45), + backButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 10.0), + backButton.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 60.0) + ]) + + view.addSubview(editCoverButton) + editCoverButton.addTarget(self, action: #selector(editCoverAction), for: .touchUpInside) + editCoverButton.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + editCoverButton.widthAnchor.constraint(equalToConstant: 140), + editCoverButton.heightAnchor.constraint(equalToConstant: 45), + editCoverButton.centerXAnchor.constraint(equalTo: coverImageView.centerXAnchor), + editCoverButton.topAnchor.constraint(equalTo: coverImageView.bottomAnchor, constant: 10.0) + ]) + } + + @IBAction func editCoverAction(_ sender: Any) { + // 6. Back to editing cover + editCoverHandler?() + } +} diff --git a/Example/Example/VideoEditorModule.swift b/Example/Example/VideoEditorModule.swift index c9ce2a1c..c7325d21 100644 --- a/Example/Example/VideoEditorModule.swift +++ b/Example/Example/VideoEditorModule.swift @@ -27,6 +27,10 @@ class VideoEditorModule { configuration: config ) + var videoEditorArguments: [String: Any] = [:] + videoEditorArguments["ENABLE_NEW_UI"] = true + videoEditorSDK?.updateVideoEditorArgs(videoEditorArguments) + self.videoEditorSDK = videoEditorSDK } diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index aaa0d67b..3793822e 100644 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -34,9 +34,58 @@ class ViewController: UIViewController, BanubaVideoEditorDelegate, BanubaPhotoEd } func videoEditorDone(_ videoEditor: BanubaVideoEditor) { - videoEditor.dismissVideoEditor(animated: true) { [weak self] in - self?.exportVideo(videoEditor: videoEditor) + // 1. Export video + + guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let window = windowScene.windows.first, + let presentedViewController = window.rootViewController?.presentedViewController else { + return + } + + let progressViewController = videoEditorModule!.createProgressViewController() + progressViewController.cancelHandler = { videoEditor.stopExport() } + + presentedViewController.present(progressViewController, animated: true) + + let manager = FileManager.default + let exportedVideoFileName = "tmp.mov" + let videoURL = manager.temporaryDirectory.appendingPathComponent(exportedVideoFileName) + if manager.fileExists(atPath: videoURL.path) { + try? manager.removeItem(at: videoURL) } + + let exportConfiguration = videoEditorModule!.createExportConfiguration(destFile: videoURL) + + videoEditor.export( + using: exportConfiguration, + exportProgress: { [weak progressViewController] progress in + DispatchQueue.main.async { + progressViewController?.updateProgressView(with: Float(progress)) + } + }, + completion: { [weak presentedViewController, weak progressViewController] error, exportCoverImages in + DispatchQueue.main.async { + progressViewController?.dismiss(animated: true) { + guard error == nil else { + Logger.logError("error with exporting video \(error!)") + return + } + // 2. Open summary view controller + let summaryViewController = SummaryViewController() + // 3. Prepopulate summaryVC with cover image + summaryViewController.coverImage = exportCoverImages?.coverImage + + let navigationController = presentedViewController as? UINavigationController + summaryViewController.editCoverHandler = { [weak navigationController] in + // 5. Return to cover screen if needed + navigationController?.popViewController(animated: true) + } + + // 4. Show summary screen + navigationController?.pushViewController(summaryViewController, animated: true) + } + } + }) } // MARK: - Actions