UX consistency and improvements #31
+114
-192
@@ -91,10 +91,8 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
let bottomBarView = UIView()
|
||||
let info = UILabel()
|
||||
|
||||
let pageTurnDropdownView = UIView()
|
||||
let pageTurnDropdownButton = UIButton()
|
||||
|
||||
let backgroundColorDropdownView = UIView()
|
||||
let backgroundColorDropdownButton = UIButton()
|
||||
|
||||
let homeButton = UIButton()
|
||||
@@ -347,12 +345,12 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
|
||||
func convertStringToColor(_ str: String) -> UIColor {
|
||||
let r: UIColor!
|
||||
switch str {
|
||||
case "White": r = .white
|
||||
case "Gray": r = .gray
|
||||
case "Black": r = .black
|
||||
case "Red": r = .red
|
||||
case "Blue": r = .blue
|
||||
switch str.lowercased() {
|
||||
case "white": r = .white
|
||||
case "gray": r = .gray
|
||||
case "black": r = .black
|
||||
case "red": r = .red
|
||||
case "blue": r = .blue
|
||||
default: r = .black
|
||||
}
|
||||
return r
|
||||
@@ -1072,7 +1070,7 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
self, action: #selector(goHome), for: .touchDown
|
||||
)
|
||||
NSLayoutConstraint.activate([
|
||||
homeButton.trailingAnchor.constraint(equalTo: topBarView.trailingAnchor, constant: -32),
|
||||
homeButton.leadingAnchor.constraint(equalTo: topBarView.leadingAnchor, constant: 32),
|
||||
homeButton.centerYAnchor.constraint(equalTo: topBarView.centerYAnchor),
|
||||
homeButton.topAnchor.constraint(equalTo: topBarView.topAnchor),
|
||||
homeButton.bottomAnchor.constraint(equalTo: topBarView.bottomAnchor),
|
||||
@@ -1094,47 +1092,18 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
func setupBackgroundColorDropdown() {
|
||||
backgroundColorDropdownButton.setTitle("Background color ▼", for: .normal)
|
||||
backgroundColorDropdownButton.setTitle("Background Color", for: .normal)
|
||||
backgroundColorDropdownButton.setTitleColor(.white, for: .normal)
|
||||
backgroundColorDropdownButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
topBarView.addSubview(backgroundColorDropdownButton)
|
||||
|
||||
backgroundColorDropdownButton.addTarget(
|
||||
self, action: #selector(toggleBackgroundColorDropdown), for: .touchDown
|
||||
self, action: #selector(backgroundColorTapped), for: .touchDown
|
||||
)
|
||||
|
||||
backgroundColorDropdownView.backgroundColor = UIColor.darkGray
|
||||
backgroundColorDropdownView.translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundColorDropdownView.isHidden = true
|
||||
readerView.addSubview(backgroundColorDropdownView)
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .vertical
|
||||
stackView.spacing = 8
|
||||
stackView.distribution = .fillEqually
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.isLayoutMarginsRelativeArrangement = true
|
||||
stackView.layoutMargins = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
|
||||
backgroundColorDropdownView.addSubview(stackView)
|
||||
|
||||
let colorOptions = ["White", "Gray", "Black", "Red", "Blue", "Default"]
|
||||
for title in colorOptions {
|
||||
let button = UIButton(type: .system)
|
||||
button.setTitle(title, for: .normal)
|
||||
button.setTitleColor(.white, for: .normal)
|
||||
button.contentHorizontalAlignment = .left
|
||||
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
|
||||
button.backgroundColor = .clear
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.addTarget(
|
||||
self, action: #selector(handleBackgroundColorOption), for: .touchDown
|
||||
)
|
||||
stackView.addArrangedSubview(button)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
backgroundColorDropdownButton.leadingAnchor.constraint(
|
||||
equalTo: topBarView.leadingAnchor, constant: 32
|
||||
backgroundColorDropdownButton.trailingAnchor.constraint(
|
||||
equalTo: topBarView.trailingAnchor, constant: -32
|
||||
),
|
||||
backgroundColorDropdownButton.centerYAnchor.constraint(
|
||||
equalTo: topBarView.centerYAnchor
|
||||
@@ -1145,70 +1114,22 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
backgroundColorDropdownButton.bottomAnchor.constraint(
|
||||
equalTo: topBarView.bottomAnchor
|
||||
),
|
||||
|
||||
backgroundColorDropdownView.topAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownButton.bottomAnchor
|
||||
),
|
||||
backgroundColorDropdownView.leadingAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownButton.leadingAnchor
|
||||
),
|
||||
backgroundColorDropdownView.trailingAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownButton.trailingAnchor
|
||||
),
|
||||
|
||||
stackView.topAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownView.topAnchor
|
||||
),
|
||||
stackView.bottomAnchor.constraint(equalTo: backgroundColorDropdownView.bottomAnchor),
|
||||
stackView.leadingAnchor.constraint(equalTo: backgroundColorDropdownView.leadingAnchor),
|
||||
stackView.trailingAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownView.trailingAnchor
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
func setupPageTurnDropdown() {
|
||||
pageTurnDropdownButton.setTitle("Page Turn Mode ▼", for: .normal)
|
||||
pageTurnDropdownButton.setTitle("Page Turn Mode", for: .normal)
|
||||
pageTurnDropdownButton.setTitleColor(.white, for: .normal)
|
||||
pageTurnDropdownButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
topBarView.addSubview(pageTurnDropdownButton)
|
||||
|
||||
pageTurnDropdownButton.addTarget(
|
||||
self, action: #selector(togglePageTurnDropdown), for: .touchDown
|
||||
self, action: #selector(pageTurnTapped), for: .touchDown
|
||||
)
|
||||
|
||||
pageTurnDropdownView.backgroundColor = UIColor.darkGray
|
||||
pageTurnDropdownView.translatesAutoresizingMaskIntoConstraints = false
|
||||
pageTurnDropdownView.isHidden = true
|
||||
readerView.addSubview(pageTurnDropdownView)
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .vertical
|
||||
stackView.spacing = 8
|
||||
stackView.distribution = .fillEqually
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.isLayoutMarginsRelativeArrangement = true
|
||||
stackView.layoutMargins = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
|
||||
pageTurnDropdownView.addSubview(stackView)
|
||||
|
||||
let pageTurnOptions = ["Left to right", "Right to left", "Scroll", "Default"]
|
||||
for title in pageTurnOptions {
|
||||
let button = UIButton(type: .system)
|
||||
button.setTitle(title, for: .normal)
|
||||
button.setTitleColor(.white, for: .normal)
|
||||
button.contentHorizontalAlignment = .left
|
||||
button.backgroundColor = .clear
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
|
||||
button.addTarget(
|
||||
self, action: #selector(handlePageTurnOption), for: .touchDown
|
||||
)
|
||||
stackView.addArrangedSubview(button)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
pageTurnDropdownButton.leadingAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownButton.trailingAnchor, constant: 32
|
||||
pageTurnDropdownButton.trailingAnchor.constraint(
|
||||
equalTo: backgroundColorDropdownButton.leadingAnchor, constant: -32
|
||||
),
|
||||
pageTurnDropdownButton.centerYAnchor.constraint(
|
||||
equalTo: topBarView.centerYAnchor
|
||||
@@ -1219,88 +1140,9 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
pageTurnDropdownButton.bottomAnchor.constraint(
|
||||
equalTo: topBarView.bottomAnchor
|
||||
),
|
||||
|
||||
pageTurnDropdownView.topAnchor.constraint(
|
||||
equalTo: pageTurnDropdownButton.bottomAnchor
|
||||
),
|
||||
pageTurnDropdownView.leadingAnchor.constraint(
|
||||
equalTo: pageTurnDropdownButton.leadingAnchor
|
||||
),
|
||||
pageTurnDropdownView.trailingAnchor.constraint(
|
||||
equalTo: pageTurnDropdownButton.trailingAnchor
|
||||
),
|
||||
|
||||
stackView.topAnchor.constraint(
|
||||
equalTo: pageTurnDropdownView.topAnchor
|
||||
),
|
||||
stackView.bottomAnchor.constraint(equalTo: pageTurnDropdownView.bottomAnchor),
|
||||
stackView.leadingAnchor.constraint(equalTo: pageTurnDropdownView.leadingAnchor),
|
||||
stackView.trailingAnchor.constraint(
|
||||
equalTo: pageTurnDropdownView.trailingAnchor
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
@objc func handlePageTurnOption(_ sender: UIButton) {
|
||||
if let title = sender.currentTitle {
|
||||
let prev = mode
|
||||
switch title.lowercased() {
|
||||
case "left to right": mode = .leftToRight
|
||||
case "right to left": mode = .rightToLeft
|
||||
case "scroll": mode = .scroll
|
||||
case "default": mode = settings.defaultPageTurnMode
|
||||
default: break
|
||||
}
|
||||
if prev == mode { return }
|
||||
if mode != .scroll {
|
||||
let archiveURL = getArchiveURL(progress.v)
|
||||
imageLoader.loadImage(
|
||||
archiveURL: archiveURL,
|
||||
filename: getImagePath(progress),
|
||||
scaling: .scaleAspectFit,
|
||||
screenSize: UIScreen.main.bounds.size
|
||||
) { [weak self] image in
|
||||
self?.imageView.image = image
|
||||
}
|
||||
}
|
||||
}
|
||||
scrollingCollectionView.isHidden = mode != .scroll
|
||||
leftView.isHidden = mode == .scroll
|
||||
rightView.isHidden = mode == .scroll
|
||||
imageView.isHidden = mode == .scroll
|
||||
// This does not optmize for the case where you switch between scrolling and non-scrolling in the same comic.
|
||||
// However this is badly supported because of the lack of state conversion.
|
||||
if mode == .scroll {
|
||||
scrollingCollectionView.reloadData()
|
||||
}
|
||||
togglePageTurnDropdown()
|
||||
saveLocalState()
|
||||
}
|
||||
|
||||
@objc func handleBackgroundColorOption(_ sender: UIButton) {
|
||||
if let title = sender.currentTitle {
|
||||
switch title.lowercased() {
|
||||
case "white": readerView.backgroundColor = .white
|
||||
case "gray": readerView.backgroundColor = .gray
|
||||
case "black": readerView.backgroundColor = .black
|
||||
case "red": readerView.backgroundColor = .red
|
||||
case "blue": readerView.backgroundColor = .blue
|
||||
case "default": readerView.backgroundColor = convertStringToColor(settings.defaultReadingBackgroundColor)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
toggleBackgroundColorDropdown()
|
||||
saveLocalState()
|
||||
}
|
||||
|
||||
@objc func togglePageTurnDropdown() {
|
||||
pageTurnDropdownView.isHidden.toggle()
|
||||
}
|
||||
|
||||
@objc func toggleBackgroundColorDropdown() {
|
||||
backgroundColorDropdownView.isHidden.toggle()
|
||||
}
|
||||
|
||||
func gestureRecognizer(
|
||||
_: UIGestureRecognizer,
|
||||
shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer
|
||||
@@ -1311,11 +1153,6 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
func toggleBar() {
|
||||
topBarView.isHidden.toggle()
|
||||
bottomBarView.isHidden.toggle()
|
||||
|
||||
if topBarView.isHidden {
|
||||
pageTurnDropdownView.isHidden = true
|
||||
backgroundColorDropdownView.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
func scrollViewDidEndDecelerating(_: UIScrollView) {
|
||||
@@ -1335,8 +1172,6 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
func hideBar() {
|
||||
topBarView.isHidden = true
|
||||
bottomBarView.isHidden = true
|
||||
pageTurnDropdownView.isHidden = true
|
||||
backgroundColorDropdownView.isHidden = true
|
||||
}
|
||||
|
||||
@objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
|
||||
@@ -2230,7 +2065,7 @@ class SettingsMenuViewController: UITableViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
|
||||
preferredContentSize = CGSize(width: 440, height: items.count * 44)
|
||||
preferredContentSize = CGSize(width: 220, height: items.count * 44)
|
||||
}
|
||||
|
||||
override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
|
||||
@@ -2259,11 +2094,9 @@ class SettingsMenuViewController: UITableViewController {
|
||||
}
|
||||
|
||||
extension ViewController {
|
||||
private func colorLeafItems(applyTo colorHandler: @escaping (UIColor) -> Void) -> [SettingsMenuItem] {
|
||||
let palette: [(String, UIColor)] = [
|
||||
("Black", .black), ("White", .white), ("Red", .red), ("Blue", .blue),
|
||||
]
|
||||
return palette.map { name, color in
|
||||
private func colorItems(applyTo colorHandler: @escaping (UIColor) -> Void) -> [SettingsMenuItem] {
|
||||
let items: [(String, UIColor)] = [("Black", .black), ("White", .white), ("Red", .red), ("Blue", .blue)]
|
||||
return items.map { name, color in
|
||||
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
|
||||
colorHandler(color)
|
||||
self?.dismiss(animated: false)
|
||||
@@ -2271,11 +2104,37 @@ extension ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private func pageTurnLeafItems(applyTo pageTurnHandler: @escaping (PageTurnMode) -> Void) -> [SettingsMenuItem] {
|
||||
let palette: [(String, PageTurnMode)] = [
|
||||
private func colorDefaultItems(applyTo colorHandler: @escaping (UIColor) -> Void) -> [SettingsMenuItem] {
|
||||
let items: [(String, UIColor)] = [
|
||||
("Black", .black), ("White", .white), ("Red", .red), ("Blue", .blue),
|
||||
("Default", convertStringToColor(settings.defaultReadingBackgroundColor)),
|
||||
]
|
||||
return items.map { name, color in
|
||||
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
|
||||
colorHandler(color)
|
||||
self?.dismiss(animated: false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func pageTurnItems(applyTo pageTurnHandler: @escaping (PageTurnMode) -> Void) -> [SettingsMenuItem] {
|
||||
let items: [(String, PageTurnMode)] = [
|
||||
("Left to right", .leftToRight), ("Right to left", .rightToLeft), ("Scroll", .scroll),
|
||||
]
|
||||
return palette.map { name, pageTurnMode in
|
||||
return items.map { name, pageTurnMode in
|
||||
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
|
||||
pageTurnHandler(pageTurnMode)
|
||||
self?.dismiss(animated: false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func pageTurnDefaultItems(applyTo pageTurnHandler: @escaping (PageTurnMode) -> Void) -> [SettingsMenuItem] {
|
||||
let items: [(String, PageTurnMode)] = [
|
||||
("Left to right", .leftToRight), ("Right to left", .rightToLeft), ("Scroll", .scroll),
|
||||
("Default", settings.defaultPageTurnMode),
|
||||
]
|
||||
return items.map { name, pageTurnMode in
|
||||
SettingsMenuItem(title: name, children: nil, action: { [weak self] in
|
||||
pageTurnHandler(pageTurnMode)
|
||||
self?.dismiss(animated: false)
|
||||
@@ -2284,16 +2143,16 @@ extension ViewController {
|
||||
}
|
||||
|
||||
private func makeSettingsTree() -> [SettingsMenuItem] {
|
||||
let backgroundColors = colorLeafItems { [weak self] color in
|
||||
let backgroundColors = colorItems { [weak self] color in
|
||||
self?.homeView.backgroundColor = color
|
||||
self?.settings.homeBackgroundColor = self?.convertColorToString(color) ?? "White"
|
||||
self?.saveSettings()
|
||||
}
|
||||
let defaultReadingBackgroundColor = colorLeafItems { [weak self] color in
|
||||
let defaultReadingBackgroundColor = colorItems { [weak self] color in
|
||||
self?.settings.defaultReadingBackgroundColor = self?.convertColorToString(color) ?? "Black"
|
||||
self?.saveSettings()
|
||||
}
|
||||
let defaultPageTurnMode = pageTurnLeafItems { [weak self] pageTurnMode in
|
||||
let defaultPageTurnMode = pageTurnItems { [weak self] pageTurnMode in
|
||||
self?.settings.defaultPageTurnMode = pageTurnMode
|
||||
self?.saveSettings()
|
||||
}
|
||||
@@ -2311,6 +2170,39 @@ extension ViewController {
|
||||
|
||||
return [colorsMenu, pageTurnMenu]
|
||||
}
|
||||
|
||||
private func makePageTurnTree() -> [SettingsMenuItem] {
|
||||
return pageTurnDefaultItems { [self] pageTurnMode in
|
||||
if self.mode == pageTurnMode { return }
|
||||
|
||||
if self.mode != .scroll {
|
||||
let archiveURL = getArchiveURL(progress.v)
|
||||
imageLoader.loadImage(
|
||||
archiveURL: archiveURL,
|
||||
filename: getImagePath(self.progress),
|
||||
scaling: .scaleAspectFit,
|
||||
screenSize: UIScreen.main.bounds.size
|
||||
) { [weak self] image in
|
||||
self?.imageView.image = image
|
||||
}
|
||||
}
|
||||
scrollingCollectionView.isHidden = mode != .scroll
|
||||
leftView.isHidden = mode == .scroll
|
||||
rightView.isHidden = mode == .scroll
|
||||
imageView.isHidden = mode == .scroll
|
||||
if mode == .scroll {
|
||||
scrollingCollectionView.reloadData()
|
||||
}
|
||||
self.mode = pageTurnMode
|
||||
saveLocalState()
|
||||
}
|
||||
}
|
||||
|
||||
private func makeBackgroundColorTree() -> [SettingsMenuItem] {
|
||||
return colorDefaultItems { [weak self] color in
|
||||
self?.readerView.backgroundColor = color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewController: UIPopoverPresentationControllerDelegate {
|
||||
@@ -2329,6 +2221,36 @@ extension ViewController: UIPopoverPresentationControllerDelegate {
|
||||
present(nav, animated: false)
|
||||
}
|
||||
|
||||
@objc private func pageTurnTapped() {
|
||||
let root = SettingsMenuViewController(title: "Modes", items: makePageTurnTree())
|
||||
let nav = UINavigationController(rootViewController: root)
|
||||
nav.modalPresentationStyle = .popover
|
||||
|
||||
if let popover = nav.popoverPresentationController {
|
||||
popover.sourceView = pageTurnDropdownButton
|
||||
popover.sourceRect = pageTurnDropdownButton.bounds
|
||||
popover.permittedArrowDirections = .up
|
||||
popover.delegate = self
|
||||
}
|
||||
|
||||
present(nav, animated: false)
|
||||
}
|
||||
|
||||
@objc private func backgroundColorTapped() {
|
||||
let root = SettingsMenuViewController(title: "Colors", items: makeBackgroundColorTree())
|
||||
let nav = UINavigationController(rootViewController: root)
|
||||
nav.modalPresentationStyle = .popover
|
||||
|
||||
if let popover = nav.popoverPresentationController {
|
||||
popover.sourceView = backgroundColorDropdownButton
|
||||
popover.sourceRect = backgroundColorDropdownButton.bounds
|
||||
popover.permittedArrowDirections = .up
|
||||
popover.delegate = self
|
||||
}
|
||||
|
||||
present(nav, animated: false)
|
||||
}
|
||||
|
||||
func adaptivePresentationStyle(for _: UIPresentationController) -> UIModalPresentationStyle {
|
||||
return .none // keeps it a real popover on iPhone instead of a full-screen sheet
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user