mirror of
https://github.com/Finb/Bark.git
synced 2025-12-08 21:36:01 +00:00
Compare commits
3 Commits
cea0020f31
...
c1d9dfe7f6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1d9dfe7f6 | ||
|
|
fb252f20c9 | ||
|
|
30a9f51236 |
@ -186,10 +186,8 @@ extension SoundsViewController: UIDocumentPickerDelegate {
|
||||
/// 选择 caf 文件
|
||||
func pickerSoundFile() {
|
||||
if #available(iOS 14.0, *) {
|
||||
let types = UTType.types(tag: "caf",
|
||||
tagClass: UTTagClass.filenameExtension,
|
||||
conformingTo: nil)
|
||||
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: types)
|
||||
/// 直接修改文件扩展为 .audio iOS 支持的音频格式
|
||||
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.audio])
|
||||
documentPicker.delegate = self
|
||||
documentPicker.allowsMultipleSelection = false
|
||||
documentPicker.modalPresentationStyle = .pageSheet
|
||||
@ -208,8 +206,58 @@ extension SoundsViewController: UIDocumentPickerDelegate {
|
||||
let fileCoordinator = NSFileCoordinator()
|
||||
let err = NSErrorPointer(nilLiteral: ())
|
||||
fileCoordinator.coordinate(readingItemAt: url, error: err) { url in
|
||||
self.importSoundActionRelay.accept(url)
|
||||
// 检查文件扩展名是否为 caf
|
||||
if url.pathExtension.lowercased() == "caf" {
|
||||
// 如果是 caf 文件,直接导入
|
||||
self.importSoundActionRelay.accept(url)
|
||||
} else {
|
||||
// 如果不是 caf 文件,先转换为 caf 格式
|
||||
convertAudioToCAF(inputURL: url) { url in
|
||||
if let url {
|
||||
// 转换成功后导入
|
||||
self.importSoundActionRelay.accept(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
url.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
|
||||
/// 将音频文件转换为 CAF 格式
|
||||
/// - Parameters:
|
||||
/// - inputURL: 输入音频文件的 URL
|
||||
/// - completion: 转换完成后的回调,返回转换后的 CAF 文件 URL,如果转换失败则返回 nil
|
||||
func convertAudioToCAF(inputURL: URL, completion: @escaping (URL?) -> Void) {
|
||||
let fileName = inputURL.deletingPathExtension().lastPathComponent
|
||||
let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent("\(fileName).caf")
|
||||
|
||||
do {
|
||||
if FileManager.default.fileExists(atPath: outputURL.path) {
|
||||
try FileManager.default.removeItem(at: outputURL)
|
||||
}
|
||||
|
||||
let asset = AVAsset(url: inputURL)
|
||||
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else {
|
||||
completion(nil)
|
||||
return
|
||||
}
|
||||
|
||||
let maxDuration = CMTime(seconds: 29.9, preferredTimescale: 600)
|
||||
if asset.duration > maxDuration {
|
||||
exportSession.timeRange = CMTimeRange(start: .zero, duration: maxDuration)
|
||||
}
|
||||
|
||||
exportSession.outputFileType = .caf
|
||||
exportSession.outputURL = outputURL
|
||||
|
||||
exportSession.exportAsynchronously {
|
||||
DispatchQueue.main.async {
|
||||
completion(exportSession.status == .completed ? outputURL : nil)
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
completion(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class MessageItemView: UIView {
|
||||
|
||||
let imageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
imageView.layer.cornerRadius = 4
|
||||
imageView.clipsToBounds = true
|
||||
return imageView
|
||||
@ -168,10 +168,16 @@ extension MessageItemView {
|
||||
self.dateLabel.text = message.dateText
|
||||
if let image = message.image {
|
||||
imageView.isHidden = false
|
||||
// 图片未缓存时,使用的默认尺寸
|
||||
remakeImageViewConstraints(width: 200, height: 100)
|
||||
// 移除图片查看器
|
||||
imageView.removeImageViewer()
|
||||
|
||||
// loadDiskFileSynchronously
|
||||
imageView.kf.setImage(with: URL(string: image), options: [.targetCache(imageCache), .keepCurrentImageWhileLoading, .loadDiskFileSynchronously]) { [weak self] result in
|
||||
guard let self else { return }
|
||||
guard let image = try? result.get().image else {
|
||||
self.imageView.image = nil
|
||||
return
|
||||
}
|
||||
|
||||
@ -179,12 +185,13 @@ extension MessageItemView {
|
||||
let isDarkMode = UIScreen.main.traitCollection.userInterfaceStyle == .dark
|
||||
var options: [ImageViewerOption] = [
|
||||
.closeIcon(UIImage(named: "back")!),
|
||||
.theme(isDarkMode ? .dark : .light)
|
||||
.theme(isDarkMode ? .dark : .light),
|
||||
.contentMode(.scaleAspectFit)
|
||||
]
|
||||
if #available(iOS 14.0, *) {
|
||||
options.append(.rightNavItemTitle(NSLocalizedString("save"), onTap: { _ in
|
||||
options.append(.rightNavItemTitle(NSLocalizedString("save"), onTap: { [weak self] _ in
|
||||
// 保存 image 到相册
|
||||
self.saveImageToAlbum(image)
|
||||
self?.saveImageToAlbum(image)
|
||||
}))
|
||||
}
|
||||
self.imageView.setupImageViewer(options: options)
|
||||
@ -193,6 +200,7 @@ extension MessageItemView {
|
||||
}
|
||||
} else {
|
||||
imageView.isHidden = true
|
||||
remakeImageViewConstraints(width: 0, height: 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,6 +215,10 @@ extension MessageItemView {
|
||||
height = 400
|
||||
}
|
||||
|
||||
remakeImageViewConstraints(width: width, height: height)
|
||||
}
|
||||
|
||||
func remakeImageViewConstraints(width: CGFloat, height: CGFloat) {
|
||||
imageView.snp.remakeConstraints { make in
|
||||
make.width.equalTo(width)
|
||||
make.height.equalTo(height)
|
||||
@ -238,3 +250,18 @@ extension MessageItemView {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UIImageView {
|
||||
func removeImageViewer() {
|
||||
var _tapRecognizer: UIGestureRecognizer?
|
||||
gestureRecognizers?.forEach {
|
||||
// 手势类名是 TapWithDataRecognizer
|
||||
if "\(type(of: $0))" == "TapWithDataRecognizer" {
|
||||
_tapRecognizer = $0
|
||||
}
|
||||
}
|
||||
if let _tapRecognizer {
|
||||
self.removeGestureRecognizer(_tapRecognizer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user