add video import duration limit

This commit is contained in:
leminlimez committed 2025-06-21 08:12:51 -04:00
1 parent 38c6d06a0e
commit 2148a348da
4 files changed
+62 -39

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)
+6
View File
@@ -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,7 +104,12 @@ 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 {
pbManager.videos[id].loadState = .loaded(movie) 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)
}
} }
} else { } else {
await MainActor.run { await MainActor.run {