SampleApp/RootViewController.swift (120 lines of code) (raw):
//
// Copyright (c) 2018. Uber Technologies
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Cyborg
import UIKit
class RootViewController: ViewController<ImportView> {
let theme: Theme
let resources: Resources
let preferences: Preferences
init(preferences: Preferences) {
self.preferences = preferences
theme = preferences.theme
resources = preferences.resources
super.init(viewCreator: ImportView.init)
title = "Import"
navigationItem.prompt = "Copy paste the VectorDrawable code into the text view"
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem
.setRightBarButton(UIBarButtonItem(title: "Theme",
style: .plain,
target: self,
action: #selector(editThemeTapped)),
animated: false)
specializedView
.importButton
.addTarget(self,
action: #selector(importButtonTapped),
for: .touchUpInside)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
specializedView.textView.becomeFirstResponder()
}
@objc
func importButtonTapped() {
if let data = (specializedView.textView.text ?? "").data(using: .utf8) {
switch VectorDrawable.create(from: data) {
case .ok(let drawable):
navigationController
.orAssert("This view controller requires a navigation controller to function correctly")?
.pushViewController(DisplayViewController(drawable: drawable,
theme: theme,
resources: resources),
animated: true)
case .error(let error):
showError(message: error)
}
} else {
showError(message: "Couldn't convert the text to UTF-8.")
}
}
@objc
func editThemeTapped() {
navigationController
.orAssert("This view controller requires a navigation controller to function correctly")?
.pushViewController(ThemeEditorViewController(preferences: preferences),
animated: true)
}
private func showError(message: String) {
let alert = UIAlertController(title: "Error",
message: message,
preferredStyle: .actionSheet)
alert.addAction(
UIAlertAction(title: "Ok", style: .default, handler: { (_) in
self.dismiss(animated: true, completion: nil)
})
)
present(alert, animated: true, completion: nil)
}
}
class ImportView: View {
let importButton: UIButton = {
let button = Button()
button.setTitle("Import", for: .normal)
return button
}()
let textView: UITextView = {
let textView = UITextView()
let bodyFont = UIFont.preferredFont(forTextStyle: .body)
textView.font = UIFont(name: "Menlo-Regular", size: bodyFont.pointSize) ?? bodyFont
return textView
}()
private var observer: AnyObject?
override init() {
super.init()
backgroundColor = .white
addSubview(textView)
addSubview(importButton)
textView.translatesAutoresizingMaskIntoConstraints = false
importButton.translatesAutoresizingMaskIntoConstraints = false
let padding: CGFloat = 10
let importButtonBottomConstraint = importButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: padding)
observer = importButtonBottomConstraint.moveWithKeyboard(in: self)
NSLayoutConstraint
.activate([
importButton.centerXAnchor.constraint(equalTo: centerXAnchor),
importButtonBottomConstraint,
textView.topAnchor.constraint(equalTo: readableContentGuide.topAnchor),
textView.bottomAnchor.constraint(equalTo: importButton.bottomAnchor, constant: padding),
textView.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor)
])
}
}
class Button: UIButton {
// TODO: add touch feedback, make this better resemble Apple's tinted buttons
init() {
super.init(frame: .zero)
setTitleColor(.white, for: .normal)
backgroundColor = tintColor
layer.cornerRadius = 5
}
@available(*, unavailable, message: "NSCoder and Interface Builder is not supported. Use Programmatic layout.")
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var intrinsicContentSize: CGSize {
var original = super.intrinsicContentSize
original.width += 20
return original
}
}