add video import duration limit
This commit is contained in:
1 parent
38c6d06a0e
commit
2148a348da
4 files changed
+61
-38
No files matched your search
@@ -8,44 +8,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ZIPFoundation
|
import ZIPFoundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import CoreTransferable
|
|
||||||
|
|
||||||
struct Movie: Transferable {
|
|
||||||
let url: URL
|
|
||||||
|
|
||||||
static var transferRepresentation: some TransferRepresentation {
|
|
||||||
FileRepresentation(contentType: .movie) { movie in
|
|
||||||
SentTransferredFile(movie.url)
|
|
||||||
} importing: { received in
|
|
||||||
let videoFolder = SymHandler.getDocumentsDirectory().appendingPathComponent("Videos", conformingTo: .directory)
|
|
||||||
if !FileManager.default.fileExists(atPath: videoFolder.path()) {
|
|
||||||
try? FileManager.default.createDirectory(at: videoFolder, withIntermediateDirectories: true)
|
|
||||||
}
|
|
||||||
let copy = videoFolder.appending(path: "\(UUID()).mp4")
|
|
||||||
|
|
||||||
if FileManager.default.fileExists(atPath: copy.path()) {
|
|
||||||
try FileManager.default.removeItem(at: copy)
|
|
||||||
}
|
|
||||||
|
|
||||||
try FileManager.default.copyItem(at: received.file, to: copy)
|
|
||||||
return Self.init(url: copy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LoadState {
|
|
||||||
case unknown, loading, loaded(Movie), failed
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LoadInfo: Identifiable, Equatable {
|
|
||||||
static func == (lhs: LoadInfo, rhs: LoadInfo) -> Bool {
|
|
||||||
lhs.id == rhs.id
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = UUID()
|
|
||||||
var autoReverses: Bool = false
|
|
||||||
var loadState: LoadState
|
|
||||||
}
|
|
||||||
|
|
||||||
class PosterBoardManager: ObservableObject {
|
class PosterBoardManager: ObservableObject {
|
||||||
static let ShortcutURL = "https://www.icloud.com/shortcuts/a28d2c02ca11453cb5b8f91c12cfa692"
|
static let ShortcutURL = "https://www.icloud.com/shortcuts/a28d2c02ca11453cb5b8f91c12cfa692"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import AVFoundation
|
import AVFoundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import CoreTransferable
|
||||||
|
|
||||||
extension CGImage {
|
extension CGImage {
|
||||||
var png: Data? {
|
var png: Data? {
|
||||||
@@ -23,7 +24,55 @@ extension CGImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Movie: Transferable {
|
||||||
|
let url: URL
|
||||||
|
|
||||||
|
static var transferRepresentation: some TransferRepresentation {
|
||||||
|
FileRepresentation(contentType: .movie) { movie in
|
||||||
|
SentTransferredFile(movie.url)
|
||||||
|
} importing: { received in
|
||||||
|
let videoFolder = SymHandler.getDocumentsDirectory().appendingPathComponent("Videos", conformingTo: .directory)
|
||||||
|
if !FileManager.default.fileExists(atPath: videoFolder.path()) {
|
||||||
|
try? FileManager.default.createDirectory(at: videoFolder, withIntermediateDirectories: true)
|
||||||
|
}
|
||||||
|
let copy = videoFolder.appending(path: "\(UUID()).mp4")
|
||||||
|
|
||||||
|
if FileManager.default.fileExists(atPath: copy.path()) {
|
||||||
|
try FileManager.default.removeItem(at: copy)
|
||||||
|
}
|
||||||
|
|
||||||
|
try FileManager.default.copyItem(at: received.file, to: copy)
|
||||||
|
return Self.init(url: copy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LoadState {
|
||||||
|
case unknown, loading, loaded(Movie), failed
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoadInfo: Identifiable, Equatable {
|
||||||
|
static func == (lhs: LoadInfo, rhs: LoadInfo) -> Bool {
|
||||||
|
lhs.id == rhs.id
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = UUID()
|
||||||
|
var autoReverses: Bool = false
|
||||||
|
var loadState: LoadState
|
||||||
|
}
|
||||||
|
|
||||||
class VideoHandler {
|
class VideoHandler {
|
||||||
|
static let MaxDurationSecs = 12.0
|
||||||
|
|
||||||
|
static func isVideoTooLong(at url: URL) -> Bool {
|
||||||
|
let asset = AVAsset(url: url)
|
||||||
|
|
||||||
|
let duration = asset.duration
|
||||||
|
let durationTime = CMTimeGetSeconds(duration)
|
||||||
|
|
||||||
|
return durationTime > MaxDurationSecs
|
||||||
|
}
|
||||||
|
|
||||||
static func createCaml(from url: URL, autoReverses: Bool) throws -> URL {
|
static func createCaml(from url: URL, autoReverses: Bool) throws -> URL {
|
||||||
// copy the resources
|
// copy the resources
|
||||||
let descrURL = SymHandler.getDocumentsDirectory().appendingPathComponent(UUID().uuidString, conformingTo: .directory)
|
let descrURL = SymHandler.getDocumentsDirectory().appendingPathComponent(UUID().uuidString, conformingTo: .directory)
|
||||||
|
|||||||
@@ -706,6 +706,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Failed to Import Video" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Fallback Shortcut Creator" : {
|
"Fallback Shortcut Creator" : {
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -1509,6 +1512,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"The video you imported is too long! Your video must be %@ seconds or less." : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"To apply, PosterBoard will need to open.\n\nYou can install an optional shortcut if the original method fails." : {
|
"To apply, PosterBoard will need to open.\n\nYou can install an optional shortcut if the original method fails." : {
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import AVKit
|
|||||||
|
|
||||||
struct VideoView: View {
|
struct VideoView: View {
|
||||||
@ObservedObject var pbManager = PosterBoardManager.shared
|
@ObservedObject var pbManager = PosterBoardManager.shared
|
||||||
|
@AppStorage("ignoreDurationLimit") var ignoreDurationLimit: Bool = false
|
||||||
|
|
||||||
@State var selectedVideo: PhotosPickerItem?
|
@State var selectedVideo: PhotosPickerItem?
|
||||||
|
|
||||||
@@ -103,8 +104,13 @@ struct VideoView: View {
|
|||||||
do {
|
do {
|
||||||
if let movie = try await selectedVideo?.loadTransferable(type: Movie.self) {
|
if let movie = try await selectedVideo?.loadTransferable(type: Movie.self) {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
if !ignoreDurationLimit && VideoHandler.isVideoTooLong(at: movie.url) {
|
||||||
|
pbManager.videos.remove(at: id)
|
||||||
|
UIApplication.shared.alert(title: NSLocalizedString("Failed to Import Video", comment: ""), body: String(format: NSLocalizedString("The video you imported is too long! Your video must be %@ seconds or less.", comment: ""), "\(Int(VideoHandler.MaxDurationSecs))"))
|
||||||
|
} else {
|
||||||
pbManager.videos[id].loadState = .loaded(movie)
|
pbManager.videos[id].loadState = .loaded(movie)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
pbManager.videos[id].loadState = .failed
|
pbManager.videos[id].loadState = .failed
|
||||||
|
|||||||
Reference in new issue
Block a user