session-ios/Session/Conversations/Message Cells/Content Views/LinkPreviewState.swift
Morgan Pretty eb0118ac10 Fixed a few more bugs and tweaked attachment download logic
Updated the code to only auto-start attachment downloads when a user opens a conversation (and only for the current page of messages)
Updated the GarbageCollectionJob to default to handling all cases (instead of requiring the cases to be defined) - this means we can add future cases without having to recreate the default job
Added logic to remove approved blinded contact records as part of the GarbageCollectionJob
Added code to better handle "invalid" attachments when migrating
Added a mechanism to retrieve the details for currently running jobs (ie. allows us to check for duplicate concurrent jobs)
Resolved the remaining TODOs in the GRDB migration code
Cleaned up DB update logic to update only the targeted columns
Fixed a bug due to a typo in a localised string
Fixed a bug where link previews without images or with custom copy weren't being processed as link previews
Fixed a bug where Open Groups could display with an empty name value
2022-07-01 12:52:41 +10:00

139 lines
4.2 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionMessagingKit
protocol LinkPreviewState {
var isLoaded: Bool { get }
var urlString: String? { get }
var title: String? { get }
var imageState: LinkPreview.ImageState { get }
var image: UIImage? { get }
}
public extension LinkPreview {
enum ImageState: Int {
case none
case loading
case loaded
case invalid
}
// MARK: LoadingState
struct LoadingState: LinkPreviewState {
var isLoaded: Bool { false }
var urlString: String? { nil }
var title: String? { nil }
var imageState: LinkPreview.ImageState { .none }
var image: UIImage? { nil }
}
// MARK: DraftState
struct DraftState: LinkPreviewState {
var isLoaded: Bool { true }
var urlString: String? { linkPreviewDraft.urlString }
var title: String? {
guard let value = linkPreviewDraft.title, value.count > 0 else { return nil }
return value
}
var imageState: LinkPreview.ImageState {
if linkPreviewDraft.jpegImageData != nil { return .loaded }
return .none
}
var image: UIImage? {
guard let jpegImageData = linkPreviewDraft.jpegImageData else { return nil }
guard let image = UIImage(data: jpegImageData) else {
owsFailDebug("Could not load image: \(jpegImageData.count)")
return nil
}
return image
}
// MARK: - Type Specific
private let linkPreviewDraft: LinkPreviewDraft
// MARK: - Initialization
init(linkPreviewDraft: LinkPreviewDraft) {
self.linkPreviewDraft = linkPreviewDraft
}
}
// MARK: SentState
struct SentState: LinkPreviewState {
var isLoaded: Bool { true }
var urlString: String? { linkPreview.url }
var title: String? {
guard let value = linkPreview.title, value.count > 0 else { return nil }
return value
}
var imageState: LinkPreview.ImageState {
guard linkPreview.attachmentId != nil else { return .none }
guard let imageAttachment: Attachment = imageAttachment else {
owsFailDebug("Missing imageAttachment.")
return .none
}
switch imageAttachment.state {
case .downloaded, .uploaded:
guard imageAttachment.isImage && imageAttachment.isValid else {
return .invalid
}
return .loaded
case .pendingDownload, .downloading, .uploading: return .loading
case .failedDownload, .failedUpload, .invalid: return .invalid
}
}
var image: UIImage? {
// Note: We don't check if the image is valid here because that can be confirmed
// in 'imageState' and it's a little inefficient
guard imageAttachment?.isImage == true else { return nil }
guard let imageData: Data = try? imageAttachment?.readDataFromFile() else {
return nil
}
guard let image = UIImage(data: imageData) else {
owsFailDebug("Could not load image: \(imageAttachment?.localRelativeFilePath ?? "unknown")")
return nil
}
return image
}
// MARK: - Type Specific
private let linkPreview: LinkPreview
private let imageAttachment: Attachment?
public var imageSize: CGSize {
guard let width: UInt = imageAttachment?.width, let height: UInt = imageAttachment?.height else {
return CGSize.zero
}
return CGSize(width: CGFloat(width), height: CGFloat(height))
}
// MARK: - Initialization
init(linkPreview: LinkPreview, imageAttachment: Attachment?) {
self.linkPreview = linkPreview
self.imageAttachment = imageAttachment
}
}
}