Skip to content

Commit d33d9f1

Browse files
committed
previewing and trimming recordings that have been saved to the Replays folder works (really any Documents relative path can be passed
1 parent b04182e commit d33d9f1

File tree

7 files changed

+144
-12
lines changed

7 files changed

+144
-12
lines changed

ios/RNReactNativeReplaykit.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
#import <ReplayKit/ReplayKit.h>
99
#import "RNReactNativeReplaykit-Swift.h"
10-
//#import "RNReactNativeReplaykit-Swift.h"
11-
//@class ReplayFileUtil;
1210

1311

1412
@interface RNReactNativeReplaykit : NSObject <RCTBridgeModule>

ios/RNReactNativeReplaykit.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ - (dispatch_queue_t)methodQueue
5555
[self.screenRecordCoordinator stopRecording];
5656
}
5757

58+
RCT_EXPORT_METHOD(previewRecording:(NSString *)path)
59+
{
60+
[self.screenRecordCoordinator previewRecordingWithFileName:path];
61+
}
62+
63+
64+
5865
RCT_EXPORT_MODULE()
5966

6067
@end

ios/ScreenRecord/FileUtil.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
//
55
// Created by Giridhar on 20/06/17.
66
// Copyright © 2017 Giridhar. All rights reserved.
7-
//
7+
// Modified By: [
8+
// Matt Thompson 9/2018
9+
//]
810

911

1012
import Foundation
@@ -32,6 +34,26 @@ import Foundation
3234
}
3335
}
3436
}
37+
38+
class func replaceItem(at dstURL: URL, with srcURL: URL) {
39+
do {
40+
try FileManager.default.removeItem(at: dstURL)
41+
self.copyItem(at: srcURL, to: dstURL)
42+
} catch let error as NSError {
43+
print(error.localizedDescription)
44+
}
45+
}
46+
47+
class func copyItem(at srcURL: URL, to dstURL: URL) {
48+
do {
49+
try FileManager.default.copyItem(at: srcURL, to: dstURL)
50+
} catch let error as NSError {
51+
if error.code == NSFileWriteFileExistsError {
52+
print("File exists. Trying to replace")
53+
self.replaceItem(at: dstURL, with: srcURL)
54+
}
55+
}
56+
}
3557

3658
class func filePath(_ fileName: String) -> String
3759
{
@@ -49,7 +71,7 @@ import Foundation
4971
let directoryContents = try! FileManager.default.contentsOfDirectory(at: replayPath!, includingPropertiesForKeys: nil, options: [])
5072
let urls = directoryContents.map({
5173
(url: URL) -> String in
52-
return url.absoluteString
74+
return url.relativePath
5375
})
5476
return urls
5577
}

ios/ScreenRecord/ScreenRecordCoordinator.swift

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
//
55
// Created by Giridhar on 21/06/17.
66
// Copyright © 2017 Giridhar. All rights reserved.
7-
//
7+
// Modified By: [
8+
// Matt Thompson 9/2018
9+
//]
810

911
import Foundation
12+
import AVKit
1013

1114
@objc class ScreenRecordCoordinator: NSObject
1215
{
1316
let viewOverlay = WindowUtil()
1417
let screenRecorder = ScreenRecorder()
1518
var recordCompleted:((Error?) ->Void)?
19+
let previewDelegateView = PreviewDelegateView()
1620

1721
override init()
1822
{
@@ -41,6 +45,19 @@ import Foundation
4145
self.recordCompleted?(error)
4246
}
4347
}
48+
49+
func previewRecording (withFileName fileURL: String) {
50+
if UIVideoEditorController.canEditVideo(atPath: fileURL) {
51+
previewDelegateView.setCoordinator(coordinator: self)
52+
let rootView = UIApplication.getTopMostViewController()
53+
let editController = UIVideoEditorController()
54+
editController.videoPath = fileURL
55+
editController.delegate = previewDelegateView
56+
rootView?.present(editController, animated: true, completion: nil)
57+
} else {
58+
// handle error with onPreviewError config or something that is one of the init config options
59+
}
60+
}
4461

4562
func listAllReplays() -> Array<String>
4663
{
@@ -49,3 +66,68 @@ import Foundation
4966

5067

5168
}
69+
70+
class PreviewDelegateView: UIViewController, UINavigationControllerDelegate, UIVideoEditorControllerDelegate {
71+
72+
var coordinator: ScreenRecordCoordinator!
73+
var isSaved:Bool = false
74+
75+
func setCoordinator(coordinator: ScreenRecordCoordinator) -> Void {
76+
self.coordinator = coordinator
77+
}
78+
79+
func videoEditorController(_ editor: UIVideoEditorController, didSaveEditedVideoToPath editedVideoPath: String) {
80+
print("save called")
81+
if(!self.isSaved) {
82+
self.isSaved = true
83+
print("trimmed video saved!")
84+
editor.dismiss(animated: true, completion: {
85+
ReplayFileUtil.replaceItem(at: URL(fileURLWithPath: editor.videoPath), with: URL(fileURLWithPath: editedVideoPath))
86+
self.isSaved = false
87+
})
88+
}
89+
}
90+
}
91+
92+
extension UIApplication {
93+
class func getTopMostViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
94+
if let nav = base as? UINavigationController {
95+
return getTopMostViewController(base: nav.visibleViewController)
96+
}
97+
if let tab = base as? UITabBarController {
98+
if let selected = tab.selectedViewController {
99+
return getTopMostViewController(base: selected)
100+
}
101+
}
102+
if let presented = base?.presentedViewController {
103+
return getTopMostViewController(base: presented)
104+
}
105+
return base
106+
}
107+
}
108+
109+
110+
//extension FileManager {
111+
// func replaceWithCopyOfFile(at:URL, with:URL) {
112+
// do {
113+
// let url = try self.url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: with.deletingPathExtension(), create: true)
114+
// try self.copyItem(at: with, to: url.appendingPathComponent(with.lastPathComponent))
115+
//
116+
// let alert = NSAlert()
117+
// alert.messageText = "Replace \"\(at.lastPathComponent)\" in \"\(at.pathComponents[at.pathComponents.count - 2])\" with new file?"
118+
// alert.addButton(withTitle: "OK")
119+
// alert.addButton(withTitle: "Cancel")
120+
//
121+
// if alert.runModal() == NSAlertFirstButtonReturn {
122+
// _ = try FileManager.default.replaceItemAt(at, withItemAt: url.appendingPathComponent(with.lastPathComponent))
123+
// }
124+
//
125+
// // removes whole temporary directory as a clean up
126+
// try self.removeItem(at: url)
127+
// }
128+
// catch {
129+
// // error
130+
// print("unknown error")
131+
// }
132+
// }
133+
//}

ios/ScreenRecord/ScreenRecorder.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
//
55
// Created by Giridhar on 09/06/17.
66
// Copyright © 2017 Giridhar. All rights reserved.
7-
//
7+
// Modified By: [
8+
// Matt Thompson 9/2018
9+
//]
10+
811
import Foundation
912
import ReplayKit
1013
import AVKit
@@ -17,10 +20,6 @@ import AVKit
1720
var videoInput:AVAssetWriterInput!
1821

1922
let viewOverlay = WindowUtil()
20-
21-
public func pewpew () {
22-
23-
}
2423

2524
//MARK: Screen Recording
2625
public func startRecording(withFileName fileName: String, recordingHandler:@escaping (Error?)-> Void)
@@ -88,7 +87,7 @@ import AVKit
8887
{
8988
print(ReplayFileUtil.fetchAllReplays())
9089

91-
}
90+
}
9291
}
9392
} else {
9493
// Fallback on earlier versions

ios/ScreenRecord/WindowUtil.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
//
55
// Created by Giridhar on 21/06/17.
66
// Copyright © 2017 Giridhar. All rights reserved.
7-
//
7+
// Modified By: [
8+
// Matt Thompson 9/2018
9+
//]
810

911
import Foundation
1012
import UIKit
13+
import AVKit
1114

1215
protocol Overlayable
1316
{

licences/RNRK

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Matt Thompson
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)