import PhotoEditorSDK
import UIKit
extension PhotoLinkSmartSticker {
@objc(PLinkSmartSticker) class LinkSmartSticker: SmartSticker {
private let cornerRadius = 10
private let fontSize = 17.0
private let padding: UIEdgeInsets = .init(top: 8, left: 16, bottom: 8, right: 16)
private let iconSize = CGSize(width: 24, height: 24)
private let previewText: String = "Link".uppercased()
let textColor: UIColor
let boxColor: UIColor
let iconColor: UIColor
override var prompt: SmartSticker.PromptViewController? {
LinkSmartStickerViewController(sticker: self)
}
var textAttributes: [NSAttributedString.Key: Any] {
[
.font: UIFont.boldSystemFont(ofSize: fontSize),
.foregroundColor: textColor
]
}
init(identifier: String, textColor: UIColor, boxColor: UIColor, iconColor: UIColor) {
self.textColor = textColor
self.boxColor = boxColor
self.iconColor = iconColor
super.init(identifier: identifier)
}
private func linkText(from metadata: [String: String]? = nil) -> String {
guard let metadata = metadata else { return previewText }
let url = URL(string: metadata["url"]!)!
return url.host?.lowercased() ?? previewText
}
override func size(for metadata: [String: String]? = nil) -> CGSize {
let text = linkText(from: metadata)
let textSize = text.imgly.bounds(textAttributes).size
let stickerWidth = iconSize.width + 8 + textSize.width
let stickerHeight = max(iconSize.height, textSize.height)
return CGRect(x: 0, y: 0, width: stickerWidth + padding.left + padding.right, height: stickerHeight + padding.top + padding.bottom).size
}
override func draw(with metadata: [String: String]?, context: CGContext, size: CGSize, scale: CGFloat) {
let rect = CGRect(origin: .zero, size: size)
let linkString = linkText(from: metadata)
let textSize = linkString.imgly.bounds(textAttributes).size
let stickerRect = CGRect(origin: .zero, size: self.size(for: metadata))
let iconRect = CGRect(origin: .zero, size: iconSize).offsetBy(dx: padding.left, dy: padding.top)
let dy = (iconRect.height - textSize.height) / 2 + padding.top
let textRect = CGRect(origin: .zero, size: textSize).offsetBy(dx: iconRect.maxX + 8, dy: dy)
let fittedRect = stickerRect.imgly.fitted(into: rect, with: .scaleAspectFit)
let fittedScale = fittedRect.width / stickerRect.width
context.translateBy(x: fittedRect.minX, y: fittedRect.minY)
context.scaleBy(x: fittedScale, y: fittedScale)
context.setFillColor(boxColor.cgColor)
context.imgly.addRoundedRect(of: stickerRect.size, cornerRadius: CGSize(width: cornerRadius, height: cornerRadius))
context.fillPath()
let image = UIImage(systemName: "link")?.withTintColor(iconColor)
image?.draw(in: iconRect)
linkString.imgly.draw(in: textRect, context: context, withAttributes: textAttributes)
}
}
@objc(PLinkSmartStickerViewController) class LinkSmartStickerViewController: SmartSticker.PromptViewController {
private let linkTextField: UITextField = {
let textField = UITextField()
textField.borderStyle = .none
textField.placeholder = "https://example.com"
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
private func createNavigationBar() -> UINavigationBar {
let navigationBar = UINavigationBar()
navigationBar.translatesAutoresizingMaskIntoConstraints = false
let navigationItem = UINavigationItem(title: "Add Link")
let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(addLinkTapped))
let cancelItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: nil, action: #selector(cancelTapped))
navigationItem.rightBarButtonItem = doneItem
navigationItem.leftBarButtonItem = cancelItem
navigationBar.setItems([navigationItem], animated: false)
return navigationBar
}
private func createURLLabel() -> UILabel {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 14)
label.textColor = UIColor.lightGray
label.text = "URL"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}
private func setupView() {
let navigationBar = createNavigationBar()
let urlLabel = createURLLabel()
view.addSubview(navigationBar)
view.addSubview(urlLabel)
view.addSubview(linkTextField)
NSLayoutConstraint.activate(
[
navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
navigationBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
navigationBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
urlLabel.topAnchor.constraint(equalTo: navigationBar.safeAreaLayoutGuide.bottomAnchor, constant: 16),
urlLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
linkTextField.topAnchor.constraint(equalTo: urlLabel.bottomAnchor, constant: 8),
linkTextField.leadingAnchor.constraint(equalTo: urlLabel.leadingAnchor)
]
)
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
setupView()
}
override func viewWillAppear(_ animated: Bool) {
linkTextField.becomeFirstResponder()
}
@objc func addLinkTapped() {
guard var text = linkTextField.text?.trimmingCharacters(in: .whitespaces) else { return }
if !text.starts(with: "http://"), !text.starts(with: "https://") {
text = "https://\(text)"
}
if URL(string: text) != nil {
done(metadata: ["url": text])
}
}
@objc func cancelTapped() {
cancel()
}
}
}
class PhotoLinkSmartSticker: Example, PhotoEditViewControllerDelegate {
override func invokeExample() {
let photo = Photo(url: Bundle.main.url(forResource: "LA", withExtension: "jpg")!)
let assetCatalog = AssetCatalog.defaultItems
let boxColors = [
UIColor(red: 246, green: 246, blue: 246).withAlphaComponent(0.55),
UIColor(red: 246, green: 246, blue: 246),
UIColor(red: 51, green: 51, blue: 55).withAlphaComponent(0.55),
UIColor(red: 51, green: 51, blue: 55)
]
let textColors = [
UIColor(red: 51, green: 51, blue: 55),
UIColor(red: 51, green: 51, blue: 55),
UIColor(red: 246, green: 246, blue: 246),
UIColor(red: 246, green: 246, blue: 246)
]
let iconColors = [
UIColor(red: 51, green: 51, blue: 55),
UIColor(red: 38, green: 119, blue: 253),
UIColor(red: 246, green: 246, blue: 246),
UIColor(red: 255, green: 92, blue: 0)
]
let multiLinkStickers = (0 ..< 4).map {
LinkSmartSticker(identifier: "imgly_link_smart_sticker_\($0 + 1)", textColor: textColors[$0], boxColor: boxColors[$0], iconColor: iconColors[$0])
}
let multiLinkSticker = MultiImageSticker(identifier: "imgly_link_smart_sticker", imageURL: nil, stickers: multiLinkStickers)
let stickerCategory = StickerCategory(identifier: "smart_stickers", title: "Smart Stickers", imageURL: Bundle.imgly.resourceBundle.url(forResource: "imgly_sticker_shapes_badge_28", withExtension: "png")!, stickers: [multiLinkSticker])
assetCatalog.stickers = [stickerCategory]
let configuration = Configuration { builder in
builder.assetCatalog = assetCatalog
}
let photoEditViewController = PhotoEditViewController(photoAsset: photo, configuration: configuration)
photoEditViewController.delegate = self
photoEditViewController.modalPresentationStyle = .fullScreen
presentingViewController?.present(photoEditViewController, animated: true, completion: nil)
}
func photoEditViewControllerShouldStart(_ photoEditViewController: PhotoEditViewController, task: PhotoEditorTask) -> Bool {
true
}
func photoEditViewControllerDidFinish(_ photoEditViewController: PhotoEditViewController, result: PhotoEditorResult) {
let stickerLinks = result.task.model.spriteModels.compactMap { ($0 as? StickerSpriteModel)?.metadata?["url"] }
print(stickerLinks)
presentingViewController?.dismiss(animated: true, completion: nil)
}
func photoEditViewControllerDidFail(_ photoEditViewController: PhotoEditViewController, error: PhotoEditorError) {
print(error.localizedDescription)
presentingViewController?.dismiss(animated: true, completion: nil)
}
func photoEditViewControllerDidCancel(_ photoEditViewController: PhotoEditViewController) {
presentingViewController?.dismiss(animated: true, completion: nil)
}
}
extension UIColor {
convenience init(red: Int, green: Int, blue: Int) {
self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1)
}
}