Signal-iOS/SignalServiceKit/Messages/Attachments/V2/AttachmentReference/TSResource/TSResourceReference.swift

78 lines
3.0 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
/// A reference to an attachment.
/// In the legacy world...this is just the attachment itself in disguise.
/// In the v2 world, this is an AttachmentReference, from the join table between Attachments and their owners.
/// We begin the v1->v2 migration by establishing that all callers must get a reference first and then get
/// the full attachment.
public protocol TSResourceReference {
var resourceId: TSResourceId { get }
var concreteType: ConcreteTSResourceReference { get }
/// Filename from the sender, used for rendering as a file attachment.
/// NOT the same as the file name on disk.
var sourceFilename: String? { get }
/// Media size (in pixels) from the sender, used for display size before downloading.
/// Not necessarily the same as the actual media size (if spoofed by the sender).
var sourceMediaSizePixels: CGSize? { get }
/// Hint from the sender telling us how to render the attachment.
var renderingFlag: AttachmentReference.RenderingFlag { get }
/// Caption for story message media attachments
var storyMediaCaption: StyleOnlyMessageBody? { get }
/// Caption for message body attachments.
/// Unused in the modern app but may be set for old messages.
var legacyMessageCaption: String? { get }
// NOTE: mimeType and contentType are deliberately excluded from
// this protocol; they have wildly different meanings in v1 and v2
// and are safe to use in entirely different circumstances.
// To check these values, fetch the full resource.
func hasSameOwner(as other: TSResourceReference) -> Bool
// MARK: Message owner getters
func fetchOwningMessage(tx: SDSAnyReadTransaction) -> TSMessage?
func orderInOwningMessage(_ message: TSMessage) -> UInt32?
}
// MARK: - Convenience fetchers
extension TSResourceReference {
/// Note: this takes an SDS transaction because its a convenience
/// method that accesses globals. If you want a testable variant
/// that lets you override the return value, use TSResourceStore.
public func fetch(tx: SDSAnyReadTransaction) -> TSResource? {
// Always re-fetch. Legacy TSAttachmentReferences already have the attachment object,
// but its better to have the API expectation be that the object you get back from this
// fetch method is always fresh.
return DependenciesBridge.shared.tsResourceStore.fetch(self.resourceId, tx: tx.asV2Read)
}
}
extension Array where Element == TSResourceReference {
/// Ordering of the return values is not guaranteed.
///
/// Note: this takes an SDS transaction because its a convenience
/// method that accesses globals. If you want a testable variant
/// that lets you override the return value, use TSResourceStore.
public func fetchAll(tx: SDSAnyReadTransaction) -> [TSResource] {
return DependenciesBridge.shared.tsResourceStore.fetch(self.map(\.resourceId), tx: tx.asV2Read)
}
}