Make call links icon into UIImage using UIGraphics
This commit is contained in:
parent
1b28fd7ba0
commit
a84400a4fe
@ -407,8 +407,14 @@ private class _CreateCallLinkViewController: OWSTableViewController2 {
|
||||
// MARK: - CallLinkCardView
|
||||
|
||||
private class CallLinkCardView: UIView {
|
||||
private lazy var circleView: UIView = {
|
||||
return SignalUI.CallLinkComponentFactory.callLinkIconView()
|
||||
private lazy var iconView: UIImageView = {
|
||||
let image = CommonCallLinksUI.callLinkIcon()
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.autoSetDimensions(to: CGSize(
|
||||
width: Constants.circleViewDimension,
|
||||
height: Constants.circleViewDimension
|
||||
))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var textStack: UIStackView = {
|
||||
@ -506,7 +512,7 @@ private class CallLinkCardView: UIView {
|
||||
super.init(frame: .zero)
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.addArrangedSubviews([circleView, textStack, joinButton])
|
||||
stackView.addArrangedSubviews([iconView, textStack, joinButton])
|
||||
stackView.axis = .horizontal
|
||||
stackView.distribution = .fillProportionally
|
||||
stackView.alignment = .center
|
||||
@ -525,5 +531,45 @@ private class CallLinkCardView: UIView {
|
||||
static let spacingTextToButton: CGFloat = 16
|
||||
static let spacingIconToText: CGFloat = 12
|
||||
static let textStackSpacing: CGFloat = 2
|
||||
|
||||
static let circleViewDimension: CGFloat = CommonCallLinksUI.Constants.circleViewDimension
|
||||
}
|
||||
}
|
||||
|
||||
public class CommonCallLinksUI {
|
||||
public static func callLinkIcon() -> UIImage? {
|
||||
guard let image = UIImage(named: "video-compact") else { return nil }
|
||||
let newSize = CGSize(square: Constants.circleViewDimension)
|
||||
|
||||
let renderer = UIGraphicsImageRenderer(size: newSize)
|
||||
let finalImage = renderer.image { context in
|
||||
let rect = CGRect(origin: .zero, size: newSize)
|
||||
let circlePath = UIBezierPath(ovalIn: rect)
|
||||
|
||||
Constants.iconBackgroundColor.setFill()
|
||||
circlePath.fill()
|
||||
|
||||
context.cgContext.addPath(circlePath.cgPath)
|
||||
context.cgContext.clip()
|
||||
|
||||
Constants.iconTintColor.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
|
||||
}
|
||||
|
||||
enum Constants {
|
||||
static let circleViewDimension: CGFloat = 64
|
||||
fileprivate static let iconDimension: CGFloat = 36
|
||||
fileprivate static let iconBackgroundColor = UIColor(rgbHex: 0xE4E4FD)
|
||||
fileprivate static let iconTintColor = UIColor(rgbHex: 0x5151F6)
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,13 +48,16 @@ class LinkPreviewCallLink: LinkPreviewState {
|
||||
return .loaded
|
||||
}
|
||||
|
||||
public func imageAsync(thumbnailQuality: AttachmentThumbnailQuality, completion: @escaping (UIImage) -> Void) {}
|
||||
public func imageAsync(thumbnailQuality: AttachmentThumbnailQuality, completion: @escaping (UIImage) -> Void) {
|
||||
if let image = CommonCallLinksUI.callLinkIcon() {
|
||||
completion(image)
|
||||
}
|
||||
}
|
||||
|
||||
public func imageCacheKey(thumbnailQuality: AttachmentThumbnailQuality) -> LinkPreviewImageCacheKey? { return nil }
|
||||
|
||||
public var imagePixelSize: CGSize {
|
||||
// This value does not matter since the image is local for call links.
|
||||
return .zero
|
||||
return CGSize(square: CommonCallLinksUI.Constants.circleViewDimension)
|
||||
}
|
||||
|
||||
public var previewDescription: String? {
|
||||
|
||||
@ -336,7 +336,7 @@ public class LinkPreviewSent: LinkPreviewState {
|
||||
public var date: Date? { linkPreview.date }
|
||||
|
||||
public let isGroupInviteLink = false
|
||||
public var isCallLink = false
|
||||
public let isCallLink = false
|
||||
|
||||
public var activityIndicatorStyle: UIActivityIndicatorView.Style {
|
||||
LinkPreviewView.defaultActivityIndicatorStyle
|
||||
|
||||
@ -139,8 +139,6 @@ public class LinkPreviewView: ManualStackViewWithLayer {
|
||||
return LinkPreviewViewAdapterDraft(state: state)
|
||||
} else if state.isGroupInviteLink {
|
||||
return LinkPreviewViewAdapterGroupLink(state: state)
|
||||
} else if state.isCallLink {
|
||||
return LinkPreviewViewAdapterCallLink(state: state)
|
||||
} else {
|
||||
if state.hasLoadedImage {
|
||||
if Self.sentIsHero(state: state) {
|
||||
@ -914,143 +912,6 @@ private class LinkPreviewViewAdapterGroupLink: LinkPreviewViewAdapter {
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LinkPreviewViewAdapterCallLink: LinkPreviewViewAdapter {
|
||||
|
||||
let state: LinkPreviewState
|
||||
|
||||
init(state: LinkPreviewState) {
|
||||
self.state = state
|
||||
}
|
||||
|
||||
var rootStackConfig: ManualStackView.Config {
|
||||
ManualStackView.Config(
|
||||
axis: .horizontal,
|
||||
alignment: .fill,
|
||||
spacing: LinkPreviewView.sentNonHeroHSpacing,
|
||||
layoutMargins: LinkPreviewView.sentNonHeroLayoutMargins
|
||||
)
|
||||
}
|
||||
|
||||
var textStackConfig: ManualStackView.Config {
|
||||
return ManualStackView.Config(
|
||||
axis: .vertical,
|
||||
alignment: .leading,
|
||||
spacing: LinkPreviewView.sentVSpacing,
|
||||
layoutMargins: .zero
|
||||
)
|
||||
}
|
||||
|
||||
func configureForRendering(
|
||||
linkPreviewView: LinkPreviewView,
|
||||
hasAsymmetricalRounding: Bool,
|
||||
cellMeasurement: CVCellMeasurement
|
||||
) {
|
||||
|
||||
linkPreviewView.backgroundColor = Theme.secondaryBackgroundColor
|
||||
|
||||
var rootStackSubviews = [UIView]()
|
||||
|
||||
let iconView = CallLinkComponentFactory.callLinkIconView()
|
||||
iconView.contentMode = .scaleAspectFill
|
||||
iconView.clipsToBounds = true
|
||||
rootStackSubviews.append(iconView)
|
||||
|
||||
let textStack = linkPreviewView.textStack
|
||||
var textStackSubviews = [UIView]()
|
||||
if let titleLabel = sentTitleLabel(state: state) {
|
||||
textStackSubviews.append(titleLabel)
|
||||
}
|
||||
if let descriptionLabel = sentDescriptionLabel(state: state) {
|
||||
textStackSubviews.append(descriptionLabel)
|
||||
}
|
||||
textStack.configure(
|
||||
config: textStackConfig,
|
||||
cellMeasurement: cellMeasurement,
|
||||
measurementKey: Self.measurementKey_textStack,
|
||||
subviews: textStackSubviews
|
||||
)
|
||||
rootStackSubviews.append(textStack)
|
||||
|
||||
linkPreviewView.configure(
|
||||
config: rootStackConfig,
|
||||
cellMeasurement: cellMeasurement,
|
||||
measurementKey: Self.measurementKey_rootStack,
|
||||
subviews: rootStackSubviews
|
||||
)
|
||||
}
|
||||
|
||||
func measure(
|
||||
maxWidth: CGFloat,
|
||||
measurementBuilder: CVCellMeasurement.Builder,
|
||||
state: LinkPreviewState
|
||||
) -> CGSize {
|
||||
|
||||
var maxLabelWidth = (maxWidth - (
|
||||
textStackConfig.layoutMargins.totalWidth + rootStackConfig.layoutMargins.totalWidth
|
||||
))
|
||||
|
||||
var rootStackSubviewInfos = [ManualStackSubviewInfo]()
|
||||
|
||||
let imageSize = LinkPreviewView.sentNonHeroImageSize
|
||||
rootStackSubviewInfos.append(CGSize.square(imageSize).asManualSubviewInfo(hasFixedSize: true))
|
||||
maxLabelWidth -= imageSize + rootStackConfig.spacing
|
||||
|
||||
maxLabelWidth = max(0, maxLabelWidth)
|
||||
|
||||
var textStackSubviewInfos = [ManualStackSubviewInfo]()
|
||||
if let labelConfig = sentTitleLabelConfig(state: state) {
|
||||
let labelSize = CVText.measureLabel(config: labelConfig, maxWidth: maxLabelWidth)
|
||||
textStackSubviewInfos.append(labelSize.asManualSubviewInfo)
|
||||
}
|
||||
if let labelConfig = sentDescriptionLabelConfig(state: state) {
|
||||
let labelSize = CVText.measureLabel(config: labelConfig, maxWidth: maxLabelWidth)
|
||||
textStackSubviewInfos.append(labelSize.asManualSubviewInfo)
|
||||
}
|
||||
|
||||
let textStackMeasurement = ManualStackView.measure(
|
||||
config: textStackConfig,
|
||||
measurementBuilder: measurementBuilder,
|
||||
measurementKey: Self.measurementKey_textStack,
|
||||
subviewInfos: textStackSubviewInfos
|
||||
)
|
||||
rootStackSubviewInfos.append(textStackMeasurement.measuredSize.asManualSubviewInfo)
|
||||
|
||||
let rootStackMeasurement = ManualStackView.measure(
|
||||
config: rootStackConfig,
|
||||
measurementBuilder: measurementBuilder,
|
||||
measurementKey: Self.measurementKey_rootStack,
|
||||
subviewInfos: rootStackSubviewInfos,
|
||||
maxWidth: maxWidth
|
||||
)
|
||||
return rootStackMeasurement.measuredSize
|
||||
}
|
||||
}
|
||||
|
||||
public class CallLinkComponentFactory {
|
||||
public static func callLinkIconView() -> UIView {
|
||||
let circleView = CircleView()
|
||||
circleView.backgroundColor = UIColor(rgbHex: Constants.iconBackgroundColor)
|
||||
circleView.autoSetDimensions(to: CGSize(width: Constants.circleViewDimension, height: Constants.circleViewDimension))
|
||||
|
||||
let iconImageView = UIImageView(image: UIImage(named: "video-compact"))
|
||||
iconImageView.tintColor = UIColor(rgbHex: Constants.iconTintColor)
|
||||
iconImageView.autoSetDimensions(to: CGSize(width: Constants.iconDimension, height: Constants.iconDimension))
|
||||
circleView.addSubview(iconImageView)
|
||||
iconImageView.autoCenterInSuperview()
|
||||
|
||||
return circleView
|
||||
}
|
||||
|
||||
private enum Constants {
|
||||
static let circleViewDimension: CGFloat = 64
|
||||
static let iconDimension: CGFloat = 36
|
||||
static let iconBackgroundColor: UInt32 = 0xE4E4FD
|
||||
static let iconTintColor: UInt32 = 0x5151F6
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private class LinkPreviewViewAdapterSentHero: LinkPreviewViewAdapter {
|
||||
|
||||
let state: LinkPreviewState
|
||||
|
||||
Loading…
Reference in New Issue
Block a user