This repository has been archived by the owner on Apr 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 165
/
SpectrumView.swift
148 lines (119 loc) · 5.45 KB
/
SpectrumView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// 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()
}
}
}