238 lines
6.6 KiB
Swift
238 lines
6.6 KiB
Swift
//
|
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
@objc
|
|
public protocol StickerKeyboardDelegate {
|
|
func didSelectSticker(stickerInfo: StickerInfo)
|
|
func presentManageStickersView()
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
@objc
|
|
public class StickerKeyboard: UIStackView {
|
|
|
|
// MARK: - Dependencies
|
|
|
|
private var databaseStorage: SDSDatabaseStorage {
|
|
return SDSDatabaseStorage.shared
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
@objc
|
|
public weak var delegate: StickerKeyboardDelegate?
|
|
|
|
private let headerView = UIStackView()
|
|
private let stickerCollectionView = StickerPackCollectionView()
|
|
|
|
private var stickerPacks = [StickerPack]()
|
|
|
|
private var stickerPack: StickerPack? {
|
|
didSet {
|
|
AssertIsOnMainThread()
|
|
|
|
// We use nil for the "recents" special-case.
|
|
if let stickerPack = stickerPack {
|
|
stickerCollectionView.showInstalledPack(stickerPack: stickerPack)
|
|
} else {
|
|
stickerCollectionView.showRecents()
|
|
}
|
|
}
|
|
}
|
|
|
|
@objc
|
|
public required init() {
|
|
super.init(frame: .zero)
|
|
|
|
createSubviews()
|
|
|
|
reloadStickers()
|
|
|
|
// By default, show the "recent" stickers.
|
|
assert(nil == stickerPack)
|
|
|
|
stickerCollectionView.showRecents()
|
|
|
|
NotificationCenter.default.addObserver(self,
|
|
selector: #selector(stickersOrPacksDidChange),
|
|
name: StickerManager.StickersOrPacksDidChange,
|
|
object: nil)
|
|
}
|
|
|
|
required public init(coder: NSCoder) {
|
|
notImplemented()
|
|
}
|
|
|
|
// TODO: Tune this value.
|
|
private let keyboardHeight: CGFloat = 300
|
|
|
|
@objc
|
|
public override var intrinsicContentSize: CGSize {
|
|
return CGSize(width: 0, height: keyboardHeight)
|
|
}
|
|
|
|
private func createSubviews() {
|
|
axis = .vertical
|
|
layoutMargins = .zero
|
|
autoresizingMask = .flexibleHeight
|
|
alignment = .fill
|
|
|
|
addBackgroundView(withBackgroundColor: Theme.offBackgroundColor)
|
|
|
|
addArrangedSubview(headerView)
|
|
headerView.setContentHuggingVerticalHigh()
|
|
headerView.setCompressionResistanceVerticalHigh()
|
|
|
|
stickerCollectionView.stickerDelegate = self
|
|
stickerCollectionView.backgroundColor = Theme.offBackgroundColor
|
|
addArrangedSubview(stickerCollectionView)
|
|
stickerCollectionView.setContentHuggingVerticalLow()
|
|
stickerCollectionView.setCompressionResistanceVerticalLow()
|
|
|
|
populateHeaderView()
|
|
}
|
|
|
|
@objc
|
|
public func wasPresented() {
|
|
// If there are no recents, default to showing the first sticker pack.
|
|
if stickerCollectionView.stickerCount < 1 {
|
|
stickerPack = stickerPacks.first
|
|
|
|
if stickerPack == nil {
|
|
// If the keyboard is presented and no stickers are
|
|
// installed, show the manage stickers view.
|
|
delegate?.presentManageStickersView()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func reloadStickers() {
|
|
databaseStorage.read { (transaction) in
|
|
self.stickerPacks = StickerManager.installedStickerPacks(transaction: transaction).sorted {
|
|
$0.dateCreated > $1.dateCreated
|
|
}
|
|
}
|
|
|
|
let packItems = stickerPacks.map { (stickerPack) in
|
|
StickerHorizontalListView.Item(stickerInfo: stickerPack.coverInfo) { [weak self] in
|
|
self?.stickerPack = stickerPack
|
|
}
|
|
}
|
|
packsCollectionView.items = packItems
|
|
|
|
guard stickerPacks.count > 0 else {
|
|
stickerPack = nil
|
|
return
|
|
}
|
|
}
|
|
|
|
private static let packCoverSize: CGFloat = 24
|
|
private static let packCoverSpacing: CGFloat = 12
|
|
private let packsCollectionView = StickerHorizontalListView(cellSize: StickerKeyboard.packCoverSize, spacing: StickerKeyboard.packCoverSpacing)
|
|
|
|
private func populateHeaderView() {
|
|
backgroundColor = Theme.offBackgroundColor
|
|
|
|
headerView.spacing = StickerKeyboard.packCoverSpacing
|
|
headerView.axis = .horizontal
|
|
headerView.alignment = .center
|
|
headerView.backgroundColor = Theme.offBackgroundColor
|
|
headerView.layoutMargins = UIEdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)
|
|
headerView.isLayoutMarginsRelativeArrangement = true
|
|
|
|
if FeatureFlags.stickerSearch {
|
|
let searchButton = buildHeaderButton("search-24") { [weak self] in
|
|
self?.searchButtonWasTapped()
|
|
}
|
|
headerView.addArrangedSubview(searchButton)
|
|
}
|
|
|
|
let recentsButton = buildHeaderButton("recent-outline-24") { [weak self] in
|
|
self?.recentsButtonWasTapped()
|
|
}
|
|
headerView.addArrangedSubview(recentsButton)
|
|
|
|
packsCollectionView.backgroundColor = Theme.offBackgroundColor
|
|
headerView.addArrangedSubview(packsCollectionView)
|
|
|
|
let manageButton = buildHeaderButton("plus-24") { [weak self] in
|
|
self?.manageButtonWasTapped()
|
|
}
|
|
headerView.addArrangedSubview(manageButton)
|
|
|
|
updateHeaderView()
|
|
}
|
|
|
|
private func buildHeaderButton(_ imageName: String, block: @escaping () -> Void) -> UIView {
|
|
let button = OWSButton(imageName: imageName, tintColor: Theme.secondaryColor, block: block)
|
|
button.setContentHuggingHigh()
|
|
button.setCompressionResistanceHigh()
|
|
return button
|
|
}
|
|
|
|
private func updateHeaderView() {
|
|
}
|
|
|
|
// MARK: Events
|
|
|
|
@objc func stickersOrPacksDidChange() {
|
|
AssertIsOnMainThread()
|
|
|
|
Logger.verbose("")
|
|
|
|
reloadStickers()
|
|
updateHeaderView()
|
|
}
|
|
|
|
private func searchButtonWasTapped() {
|
|
AssertIsOnMainThread()
|
|
|
|
Logger.verbose("")
|
|
|
|
// TODO:
|
|
}
|
|
|
|
private func recentsButtonWasTapped() {
|
|
AssertIsOnMainThread()
|
|
|
|
Logger.verbose("")
|
|
|
|
// nil is used for the recents special-case.
|
|
stickerPack = nil
|
|
}
|
|
|
|
private func manageButtonWasTapped() {
|
|
AssertIsOnMainThread()
|
|
|
|
Logger.verbose("")
|
|
|
|
delegate?.presentManageStickersView()
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
extension StickerKeyboard: StickerPackCollectionViewDelegate {
|
|
public func didTapSticker(stickerInfo: StickerInfo) {
|
|
AssertIsOnMainThread()
|
|
|
|
Logger.verbose("")
|
|
|
|
delegate?.didSelectSticker(stickerInfo: stickerInfo)
|
|
}
|
|
|
|
public func stickerPreviewHostView() -> UIView? {
|
|
AssertIsOnMainThread()
|
|
|
|
return self
|
|
}
|
|
|
|
public func stickerPreviewHasOverlay() -> Bool {
|
|
return false
|
|
}
|
|
}
|