TM-SGNL-iOS/Signal/ConversationView/LinkPreviewCallLink.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

155 lines
4.7 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
public import SignalRingRTC
public import SignalServiceKit
// MARK: -
public class LinkPreviewCallLink: LinkPreviewState {
public let conversationStyle: ConversationStyle?
public enum PreviewType {
case sent(OWSLinkPreview, ConversationStyle)
case draft(OWSLinkPreviewDraft)
}
private let previewType: PreviewType
private let callLink: CallLink
public init(previewType: PreviewType, callLink: CallLink) {
self.previewType = previewType
self.callLink = callLink
switch previewType {
case .sent(_, let conversationStyle):
self.conversationStyle = conversationStyle
case .draft:
self.conversationStyle = nil
}
}
public var isLoaded: Bool { true }
public var urlString: String? {
switch previewType {
case .sent(let linkPreview, _):
guard let urlString = linkPreview.urlString else {
owsFailDebug("Missing url")
return nil
}
return urlString
case .draft(let linkPreviewDraft):
return linkPreviewDraft.urlString
}
}
public var displayDomain: String? {
let displayDomain: String?
switch previewType {
case .sent(let linkPreview, _):
displayDomain = linkPreview.displayDomain
case .draft(let linkPreviewDraft):
displayDomain = linkPreviewDraft.displayDomain
}
guard let displayDomain else {
Logger.error("Missing display domain")
return nil
}
return displayDomain
}
public var title: String? {
let title: String?
switch previewType {
case .sent(let linkPreview, _):
title = linkPreview.title
case .draft(let linkPreviewDraft):
title = linkPreviewDraft.title
}
return title?.filterForDisplay.nilIfEmpty ?? CallStrings.signalCall
}
public var imageState: LinkPreviewImageState {
// Image is a local asset.
return .loaded
}
public func imageAsync(thumbnailQuality: AttachmentThumbnailQuality, completion: @escaping (UIImage) -> Void) {
if let image = CommonCallLinksUI.callLinkIcon(rootKey: callLink.rootKey) {
completion(image)
}
}
public func imageCacheKey(thumbnailQuality: AttachmentThumbnailQuality) -> LinkPreviewImageCacheKey? { return nil }
public var imagePixelSize: CGSize {
return CGSize(square: CommonCallLinksUI.Constants.circleViewDimension)
}
public var previewDescription: String? {
let description: String?
switch previewType {
case .sent(let linkPreview, _):
description = linkPreview.previewDescription
case .draft(let linkPreviewDraft):
description = linkPreviewDraft.previewDescription
}
return description?.filterForDisplay.nilIfEmpty ?? CallStrings.callLinkDescription
}
public var date: Date? {
switch previewType {
case .sent(let linkPreview, _):
linkPreview.date
case .draft(let linkPreviewDraft):
linkPreviewDraft.date
}
}
public let isGroupInviteLink = false
public var activityIndicatorStyle: UIActivityIndicatorView.Style {
LinkPreviewView.defaultActivityIndicatorStyle
}
}
public class CommonCallLinksUI {
public static func callLinkIcon(rootKey: CallLinkRootKey) -> UIImage? {
guard let image = UIImage(named: "video-compact") else { return nil }
let newSize = CGSize(square: Constants.circleViewDimension)
let theme = AvatarTheme.forData(rootKey.bytes.prefix(1))
let renderer = UIGraphicsImageRenderer(size: newSize)
let finalImage = renderer.image { context in
let rect = CGRect(origin: .zero, size: newSize)
let circlePath = UIBezierPath(ovalIn: rect)
theme.backgroundColor.setFill()
circlePath.fill()
context.cgContext.addPath(circlePath.cgPath)
context.cgContext.clip()
theme.foregroundColor.set()
let centerOffset = Constants.circleViewDimension/2 - Constants.iconDimension/2
let imageRect = CGRect(
x: centerOffset,
y: centerOffset,
width: Constants.iconDimension,
height: Constants.iconDimension
)
image.withRenderingMode(.alwaysTemplate).draw(in: imageRect)
}
return finalImage
}
public enum Constants {
public static let circleViewDimension: CGFloat = 64
fileprivate static let iconDimension: CGFloat = 36
}
}