forked from LoopKit/LoopKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEmojiInputController.swift
More file actions
153 lines (112 loc) · 5.16 KB
/
EmojiInputController.swift
File metadata and controls
153 lines (112 loc) · 5.16 KB
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
149
150
151
152
153
//
// EmojiInputController.swift
// LoopKit
//
// Copyright © 2017 LoopKit Authors. All rights reserved.
//
import UIKit
public class EmojiInputController: UIInputViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, IdentifiableClass {
@IBOutlet private weak var collectionView: UICollectionView!
@IBOutlet private weak var sectionIndex: UIStackView!
public weak var delegate: EmojiInputControllerDelegate?
var emojis: EmojiDataSource!
static func instance(withEmojis emojis: EmojiDataSource) -> EmojiInputController {
let bundle = Bundle(for: self)
let storyboard = UIStoryboard(name: className, bundle: bundle)
let controller = storyboard.instantiateInitialViewController() as! EmojiInputController
controller.emojis = emojis
return controller
}
public override func viewDidLoad() {
super.viewDidLoad()
inputView = view as? UIInputView
inputView?.allowsSelfSizing = true
view.translatesAutoresizingMaskIntoConstraints = false
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.sectionHeadersPinToVisibleBounds = true
layout.sectionFootersPinToVisibleBounds = true
}
setupSectionIndex()
// Scroll to medium absorption
DispatchQueue.main.async {
self.collectionView.scrollToItem(at: IndexPath(row: 0, section: 1), at: .left, animated: false)
}
}
private func setupSectionIndex() {
sectionIndex.removeAllArrangedSubviews()
for section in emojis.sections {
let label = UILabel(frame: .zero)
label.text = section.indexSymbol
sectionIndex.addArrangedSubview(label)
}
}
@IBOutlet weak var deleteButton: UIButton! {
didSet {
let image = UIImage(systemName: "delete.left", compatibleWith: traitCollection)
deleteButton.setImage(image, for: .normal)
}
}
// MARK: - Actions
@IBAction func switchKeyboard(_ sender: Any) {
delegate?.emojiInputControllerDidAdvanceToStandardInputMode(self)
}
@IBAction func deleteBackward(_ sender: Any) {
inputView?.playInputClick()
textDocumentProxy.deleteBackward()
}
@IBAction func indexTouched(_ sender: UIGestureRecognizer) {
let xLocation = max(0, sender.location(in: sectionIndex).x / sectionIndex.frame.width)
let items = sectionIndex.arrangedSubviews.count
let section = min(items - 1, Int(xLocation * CGFloat(items)))
collectionView.scrollToItem(at: IndexPath(item: 0, section: section), at: .left, animated: false)
}
// MARK: - UICollectionViewDataSource
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return emojis.sections.count
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return emojis.sections[section].items.count
}
public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: kind == UICollectionView.elementKindSectionHeader ? EmojiInputHeaderView.className : "Footer", for: indexPath)
if let cell = cell as? EmojiInputHeaderView {
cell.titleLabel.text = emojis.sections[indexPath.section].title.localizedUppercase
}
return cell
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: EmojiInputCell.className, for: indexPath) as! EmojiInputCell
cell.label.text = emojis.sections[indexPath.section].items[indexPath.row]
return cell
}
// MARK: - UICollectionViewDelegateFlowLayout
// MARK: - UICollectionViewDelegate
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
inputView?.playInputClick()
textDocumentProxy.insertText(emojis.sections[indexPath.section].items[indexPath.row])
delegate?.emojiInputControllerDidSelectItemInSection(indexPath.section)
}
}
public protocol EmojiInputControllerDelegate: AnyObject {
func emojiInputControllerDidAdvanceToStandardInputMode(_ controller: EmojiInputController)
func emojiInputControllerDidSelectItemInSection(_ section: Int)
}
// MARK: - Default Implementations
extension EmojiInputControllerDelegate {
public func emojiInputControllerDidSelectItemInSection(_ section: Int) { }
}
extension UIInputView: UIInputViewAudioFeedback {
public var enableInputClicksWhenVisible: Bool { return true }
func playInputClick() {
let device = UIDevice.current
device.playInputClick()
}
}
private extension UIStackView {
func removeAllArrangedSubviews() {
for view in arrangedSubviews {
view.removeFromSuperview()
}
}
}