ios/SpectrumKitSample/SpectrumKitSample-iOS/SpectrumView.swift (102 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. import UIKit final class SprectrumView: UIView, PickerButtonDelegate, UIGestureRecognizerDelegate { // MARK: - Public Properties var viewModel: SpectrumViewModel? { didSet { guard self.viewModel !== oldValue else { return } self.viewModel.flatMap(self.updateView(with:)) } } // MARK: - Private Properties // MARK: IBOutlet @IBOutlet private var scrollView: UIScrollView! @IBOutlet private var stackView: UIStackView! @IBOutlet private var sourceImageView: UIImageView! @IBOutlet private var sourceImageButton: UIButton! @IBOutlet private var inputTypeButton: UIButton! @IBOutlet private var outputTypeButton: UIButton! @IBOutlet private var outputFormatButton: UIButton! @IBOutlet private var outputFormatContainerView: UIView! @IBOutlet private var compressionModeButton: UIButton! @IBOutlet private var modeContainerView: UIView! @IBOutlet private var qualityContainerView: UIView! @IBOutlet private var qualityButton: PickerButton! @IBOutlet private var rotationButton: UIButton! @IBOutlet private var scalingButton: UIButton! @IBOutlet private var croppingButton: UIButton! @IBOutlet private var transcodeButton: UIButton! // MARK: - NSObject deinit { NotificationCenter.default.removeObserver(self) } override func awakeFromNib() { super.awakeFromNib() self.qualityButton.delegate = self self.qualityButton.pickerOptions = SpectrumViewModel.qualityPickerOptions self.transcodeButton.layer.cornerRadius = 5 NotificationCenter.default.addObserver(self, selector: #selector(self.didReceiveKeyboardNotification(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.didReceiveKeyboardNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } // MARK: - PickerButtonDelegate func pickerButton(_: UIButton, didPick option: Int) { self.viewModel!.quality = option } // MARK: - UIGestureRecognizerDelegate func gestureRecognizer(_: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer) -> Bool { return true } // MARK: - Public Methods func updateView(with viewModel: SpectrumViewModel) { self.sourceImageView.image = viewModel.source.image self.sourceImageButton.setTitle(viewModel.sourceImageDescription, for: .normal) self.inputTypeButton.setTitle(viewModel.inputType.title, for: .normal) self.outputTypeButton.setTitle(viewModel.outputType.title, for: .normal) self.outputFormatButton.setTitle(viewModel.outputFormat.title, for: .normal) self.compressionModeButton.setTitle(viewModel.compressionMode.title, for: .normal) self.qualityButton.currentOption = viewModel.quality self.rotationButton.setTitle(viewModel.rotation.title, for: .normal) self.scalingButton.setTitle(viewModel.scaling.title, for: .normal) self.croppingButton.setTitle(viewModel.cropping.title, for: .normal) self.transcodeButton.isEnabled = viewModel.isTranscodeButtonEnabled UIView.performWithoutAnimation { self.transcodeButton.setTitle(viewModel.actionButtonTitle, for: .normal) self.transcodeButton.layoutIfNeeded() } self.stackView.isUserInteractionEnabled = viewModel.isTranscoding == false if self.modeContainerView.isHidden == viewModel.showsEncodingMode { UIView.animate(withDuration: 0.4) { self.modeContainerView.isHidden = viewModel.showsEncodingMode == false } } if self.qualityContainerView.isHidden == viewModel.showsQuality { UIView.animate(withDuration: 0.4) { self.qualityContainerView.isHidden = viewModel.showsQuality == false } } if self.outputFormatContainerView.isHidden == viewModel.showsOutputFormat { UIView.animate(withDuration: 0.4) { self.outputFormatContainerView.isHidden = viewModel.showsOutputFormat == false } } } // MARK: - Private Methods @objc private func didReceiveKeyboardNotification(_ notification: Notification) { guard let keyboardFrame = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return } let intersection = self.convert(self.scrollView.frame, to: nil).intersection(keyboardFrame) self.scrollView.contentInset.bottom = intersection.height } // MARK: IBActions @IBAction private func didTapQualityButton(_ sender: UIButton) { sender.toggleFirstResponder() } @IBAction private func didTapBackgroundView(_ gestureRecognizer: UITapGestureRecognizer) { // We should only end editing if the tap isn't in the quality button's bounds // as its handler already toggles its first responder state. Guarding this handler // prevents from making any assumptions in regards to the order in which the gesture // and buttons handlers will be called. let locationInQualityButton = gestureRecognizer.location(in: self.qualityButton) guard self.qualityButton.bounds.contains(locationInQualityButton) == false else { return } self.endEditing(true) } @IBAction private func didTapTranscodeButton(_: UIButton) { self.viewModel!.transcode() } } private extension UIResponder { func toggleFirstResponder() { if self.isFirstResponder { self.resignFirstResponder() } else { self.becomeFirstResponder() } } }