mirror of
https://github.com/lux-tel/session-ios.git
synced 2026-10-30 20:38:32 +00:00
232 lines
7.4 KiB
Swift
232 lines
7.4 KiB
Swift
// Copyright © 2025 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import UIKit
|
|
import SwiftUI
|
|
import UniformTypeIdentifiers
|
|
import SessionUIKit
|
|
import SessionMessagingKit
|
|
import SessionUtilitiesKit
|
|
|
|
// MARK: - ImageDataManager.DataSource Convenience
|
|
|
|
public extension ImageDataManager.DataSource {
|
|
static func from(
|
|
attachment: Attachment,
|
|
using dependencies: Dependencies
|
|
) -> ImageDataManager.DataSource? {
|
|
guard
|
|
attachment.isVisualMedia,
|
|
let path: String = try? dependencies[singleton: .attachmentManager]
|
|
.path(for: attachment.downloadUrl)
|
|
else { return nil }
|
|
|
|
if attachment.isVideo {
|
|
/// Videos need special handling so handle those specially
|
|
return .videoUrl(
|
|
URL(fileURLWithPath: path),
|
|
(UTType(sessionMimeType: attachment.contentType) ?? .invalid),
|
|
attachment.sourceFilename,
|
|
dependencies[singleton: .attachmentManager]
|
|
)
|
|
}
|
|
|
|
return .url(URL(fileURLWithPath: path))
|
|
}
|
|
|
|
static func thumbnailFrom(
|
|
attachment: Attachment,
|
|
size: ImageDataManager.ThumbnailSize,
|
|
using dependencies: Dependencies
|
|
) -> ImageDataManager.DataSource? {
|
|
guard let path: String = try? dependencies[singleton: .attachmentManager].path(for: attachment.downloadUrl) else {
|
|
return nil
|
|
}
|
|
|
|
return thumbnailFrom(
|
|
utType: (UTType(sessionMimeType: attachment.contentType) ?? .invalid),
|
|
path: path,
|
|
sourceFilename: attachment.sourceFilename,
|
|
size: size,
|
|
using: dependencies
|
|
)
|
|
}
|
|
|
|
static func thumbnailFrom(
|
|
quoteViewModel: QuoteViewModel,
|
|
using dependencies: Dependencies
|
|
) -> ImageDataManager.DataSource? {
|
|
guard
|
|
let info: QuoteViewModel.AttachmentInfo = quoteViewModel.quotedAttachmentInfo,
|
|
let path: String = try? dependencies[singleton: .attachmentManager]
|
|
.path(for: info.downloadUrl)
|
|
else { return nil }
|
|
|
|
return .thumbnailFrom(
|
|
utType: info.utType,
|
|
path: path,
|
|
sourceFilename: info.sourceFilename,
|
|
size: .small,
|
|
using: dependencies
|
|
)
|
|
}
|
|
|
|
static func thumbnailFrom(
|
|
utType: UTType,
|
|
path: String,
|
|
sourceFilename: String? = nil,
|
|
size: ImageDataManager.ThumbnailSize,
|
|
using dependencies: Dependencies
|
|
) -> ImageDataManager.DataSource? {
|
|
guard utType != .invalid else { return nil }
|
|
|
|
/// Can't thumbnail animated images so just load the full file in this case
|
|
if utType.isAnimated {
|
|
return .url(URL(fileURLWithPath: path))
|
|
}
|
|
|
|
/// Videos have a custom method for generating their thumbnails so use that instead
|
|
if utType.isVideo {
|
|
return .videoUrl(
|
|
URL(fileURLWithPath: path),
|
|
utType,
|
|
sourceFilename,
|
|
dependencies[singleton: .attachmentManager]
|
|
)
|
|
}
|
|
|
|
return .urlThumbnail(
|
|
URL(fileURLWithPath: path),
|
|
size,
|
|
dependencies[singleton: .attachmentManager]
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - ImageDataManagerType Convenience
|
|
|
|
public extension ImageDataManagerType {
|
|
@MainActor
|
|
func loadImage(
|
|
attachment: Attachment,
|
|
using dependencies: Dependencies,
|
|
onComplete: @MainActor @escaping (ImageDataManager.FrameBuffer?) -> Void = { _ in }
|
|
) {
|
|
guard let source: ImageDataManager.DataSource = ImageDataManager.DataSource.from(
|
|
attachment: attachment,
|
|
using: dependencies
|
|
) else { return onComplete(nil) }
|
|
|
|
load(source, onComplete: onComplete)
|
|
}
|
|
|
|
@MainActor
|
|
func loadThumbnail(
|
|
size: ImageDataManager.ThumbnailSize,
|
|
attachment: Attachment,
|
|
using dependencies: Dependencies,
|
|
onComplete: @MainActor @escaping (ImageDataManager.FrameBuffer?) -> Void = { _ in }
|
|
) {
|
|
guard let source: ImageDataManager.DataSource = ImageDataManager.DataSource.thumbnailFrom(
|
|
attachment: attachment,
|
|
size: size,
|
|
using: dependencies
|
|
) else { return onComplete(nil) }
|
|
|
|
load(source, onComplete: onComplete)
|
|
}
|
|
}
|
|
|
|
// MARK: - SessionImageView Convenience
|
|
|
|
public extension SessionImageView {
|
|
@MainActor
|
|
func loadImage(from path: String, onComplete: (@MainActor (ImageDataManager.FrameBuffer?) -> Void)? = nil) {
|
|
loadImage(.url(URL(fileURLWithPath: path)), onComplete: onComplete)
|
|
}
|
|
|
|
@MainActor
|
|
func loadImage(
|
|
attachment: Attachment,
|
|
using dependencies: Dependencies,
|
|
onComplete: (@MainActor (ImageDataManager.FrameBuffer?) -> Void)? = nil
|
|
) {
|
|
guard let source: ImageDataManager.DataSource = ImageDataManager.DataSource.from(
|
|
attachment: attachment,
|
|
using: dependencies
|
|
) else {
|
|
onComplete?(nil)
|
|
return
|
|
}
|
|
|
|
loadImage(source, onComplete: onComplete)
|
|
}
|
|
|
|
@MainActor
|
|
func loadThumbnail(
|
|
size: ImageDataManager.ThumbnailSize,
|
|
attachment: Attachment,
|
|
using dependencies: Dependencies,
|
|
onComplete: (@MainActor (ImageDataManager.FrameBuffer?) -> Void)? = nil
|
|
) {
|
|
guard let source: ImageDataManager.DataSource = ImageDataManager.DataSource.thumbnailFrom(
|
|
attachment: attachment,
|
|
size: size,
|
|
using: dependencies
|
|
) else {
|
|
onComplete?(nil)
|
|
return
|
|
}
|
|
|
|
loadImage(source, onComplete: onComplete)
|
|
}
|
|
|
|
@MainActor
|
|
func loadPlaceholder(seed: String, text: String, size: CGFloat, onComplete: (@MainActor (ImageDataManager.FrameBuffer?) -> Void)? = nil) {
|
|
loadImage(.placeholderIcon(seed: seed, text: text, size: size), onComplete: onComplete)
|
|
}
|
|
}
|
|
|
|
// MARK: - SessionAsyncImage Convenience
|
|
|
|
public extension SessionAsyncImage {
|
|
init(
|
|
attachment: Attachment,
|
|
thumbnailSize: ImageDataManager.ThumbnailSize,
|
|
using dependencies: Dependencies,
|
|
@ViewBuilder content: @escaping (Image) -> Content,
|
|
@ViewBuilder placeholder: @escaping () -> Placeholder
|
|
) {
|
|
let source: ImageDataManager.DataSource? = ImageDataManager.DataSource.thumbnailFrom(
|
|
attachment: attachment,
|
|
size: thumbnailSize,
|
|
using: dependencies
|
|
)
|
|
|
|
/// Fallback in case we don't have a valid source
|
|
self.init(
|
|
source: (source ?? .image("", nil)),
|
|
dataManager: dependencies[singleton: .imageDataManager],
|
|
content: content,
|
|
placeholder: placeholder
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - Attachment Convenience
|
|
|
|
public extension Attachment {
|
|
func quoteAttachmentInfo(using dependencies: Dependencies) -> QuoteViewModel.AttachmentInfo? {
|
|
guard let utType: UTType = UTType(sessionMimeType: contentType) else { return nil }
|
|
|
|
return QuoteViewModel.AttachmentInfo(
|
|
id: id,
|
|
utType: utType,
|
|
isVoiceMessage: (variant == .voiceMessage),
|
|
downloadUrl: downloadUrl,
|
|
sourceFilename: sourceFilename,
|
|
thumbnailSource: .thumbnailFrom(attachment: self, size: .small, using: dependencies)
|
|
)
|
|
}
|
|
}
|
|
|