Files
GIFCollector/GIFCollector MessagesExtension/Views/AddGIFViewController.swift
Joshua Higgins 4ef60608cd init, finished
2025-06-02 17:49:33 -04:00

187 lines
6.2 KiB
Swift

import UIKit
class AddGIFViewController: UIViewController {
private let titleLabel: UILabel = {
let label = UILabel()
label.text = "Add New GIF"
label.font = .systemFont(ofSize: 18, weight: .bold)
label.textAlignment = .center
return label
}()
private let urlTextField: UITextField = {
let textField = UITextField()
textField.placeholder = "Enter GIF URL"
textField.borderStyle = .roundedRect
textField.autocorrectionType = .no
textField.autocapitalizationType = .none
textField.keyboardType = .URL
textField.returnKeyType = .next
textField.clearButtonMode = .whileEditing
return textField
}()
private let previewGIFPlayer: GIFPlayerView = {
let player = GIFPlayerView()
player.clipsToBounds = true
player.layer.cornerRadius = 8
player.backgroundColor = .systemGray6
return player
}()
private let loadingIndicator: UIActivityIndicatorView = {
let indicator = UIActivityIndicatorView(style: .medium)
indicator.hidesWhenStopped = true
return indicator
}()
private let saveButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Save", for: .normal)
button.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
button.backgroundColor = .systemBlue
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 8
button.isEnabled = false
return button
}()
private let cancelButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Cancel", for: .normal)
button.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
return button
}()
private var currentTask: URLSessionDataTask?
var onSaveGIF: ((GIF) -> Void)?
var onCancel: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
setupActions()
}
private func setupUI() {
view.backgroundColor = .systemBackground
view.addSubview(titleLabel)
view.addSubview(urlTextField)
view.addSubview(previewGIFPlayer)
view.addSubview(loadingIndicator)
view.addSubview(saveButton)
view.addSubview(cancelButton)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
urlTextField.translatesAutoresizingMaskIntoConstraints = false
previewGIFPlayer.translatesAutoresizingMaskIntoConstraints = false
loadingIndicator.translatesAutoresizingMaskIntoConstraints = false
saveButton.translatesAutoresizingMaskIntoConstraints = false
cancelButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
urlTextField.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 16),
urlTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
urlTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
previewGIFPlayer.topAnchor.constraint(equalTo: urlTextField.bottomAnchor, constant: 16),
previewGIFPlayer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
previewGIFPlayer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
previewGIFPlayer.heightAnchor.constraint(equalToConstant: 150),
loadingIndicator.centerXAnchor.constraint(equalTo: previewGIFPlayer.centerXAnchor),
loadingIndicator.centerYAnchor.constraint(equalTo: previewGIFPlayer.centerYAnchor),
saveButton.topAnchor.constraint(equalTo: previewGIFPlayer.bottomAnchor, constant: 24),
saveButton.leadingAnchor.constraint(equalTo: view.centerXAnchor, constant: 8),
saveButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
saveButton.heightAnchor.constraint(equalToConstant: 44),
cancelButton.topAnchor.constraint(equalTo: previewGIFPlayer.bottomAnchor, constant: 24),
cancelButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
cancelButton.trailingAnchor.constraint(equalTo: view.centerXAnchor, constant: -8),
cancelButton.heightAnchor.constraint(equalToConstant: 44),
])
}
private func setupActions() {
urlTextField.delegate = self
urlTextField.addTarget(self, action: #selector(urlTextDidChange), for: .editingChanged)
saveButton.addTarget(self, action: #selector(saveButtonTapped), for: .touchUpInside)
cancelButton.addTarget(self, action: #selector(cancelButtonTapped), for: .touchUpInside)
}
@objc private func urlTextDidChange() {
guard let urlString = urlTextField.text, !urlString.isEmpty else {
previewGIFPlayer.stopAnimating()
saveButton.isEnabled = false
return
}
loadGIFPreview(from: urlString)
}
private func loadGIFPreview(from urlString: String) {
// Cancel any existing task
currentTask?.cancel()
guard let url = URL(string: urlString) else {
saveButton.isEnabled = false
return
}
loadingIndicator.startAnimating()
previewGIFPlayer.stopAnimating()
currentTask = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
DispatchQueue.main.async {
guard let self = self else { return }
self.loadingIndicator.stopAnimating()
if let data = data, error == nil {
self.previewGIFPlayer.loadGIF(from: data)
self.previewGIFPlayer.startAnimating()
self.saveButton.isEnabled = true
} else {
self.previewGIFPlayer.stopAnimating()
self.saveButton.isEnabled = false
}
}
}
currentTask?.resume()
}
@objc private func saveButtonTapped() {
guard let urlString = urlTextField.text, !urlString.isEmpty else { return }
let gif = GIF(urlString: urlString)
onSaveGIF?(gif)
dismiss(animated: true)
}
@objc private func cancelButtonTapped() {
onCancel?()
dismiss(animated: true)
}
}
extension AddGIFViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}