Implemented find on page UI

This commit is contained in:
James Magahern
2020-09-30 18:06:47 -07:00
parent 1d27674d7d
commit 3769f5bbbf
12 changed files with 372 additions and 9 deletions

View File

@@ -0,0 +1,71 @@
//
// FindOnPageView.swift
// App
//
// Created by James Magahern on 9/30/20.
//
import UIKit
class FindOnPageView: UIView
{
let textField = UISearchTextField(frame: .zero)
let doneButton = ReliefButton()
let nextResultButton = ReliefButton()
let prevResultButton = ReliefButton()
private let arrowControls = SegmentedReliefButton(children: [])
let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial))
convenience init() {
self.init(frame: .zero)
arrowControls.children = [ prevResultButton, nextResultButton ]
addSubview(backgroundView)
addSubview(textField)
addSubview(doneButton)
addSubview(arrowControls)
textField.autocapitalizationType = .none
textField.autocorrectionType = .no
doneButton.setTitle("Done", for: .normal)
doneButton.setTitleColor(.label, for: .normal)
doneButton.constrainedToSquare = false
nextResultButton.setImage(UIImage(systemName: "chevron.down"), for: .normal)
prevResultButton.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundView.frame = bounds
let bounds = self.bounds
.insetBy(dx: 8.0, dy: 8.0)
.inset(by: safeAreaInsets)
let doneButtonPadding: CGFloat = 8.0
let doneButtonSize = doneButton.sizeThatFits(bounds.size)
doneButton.frame = CGRect(
x: bounds.width - doneButtonSize.width, y: bounds.minY,
width: doneButtonSize.width + doneButtonPadding, height: bounds.height
)
let arrowControlsSize = arrowControls.sizeThatFits(bounds.size)
arrowControls.frame = CGRect(
x: doneButton.frame.minX - doneButtonPadding - arrowControlsSize.width, y: bounds.minY,
width: arrowControlsSize.width, height: bounds.height
)
textField.frame = CGRect(
x: bounds.minX, y: bounds.minY,
width: arrowControls.frame.minX - bounds.minX - doneButtonPadding,
height: bounds.height
)
}
}

View File

@@ -0,0 +1,98 @@
//
// FindOnPageViewController.swift
// App
//
// Created by James Magahern on 9/30/20.
//
import UIKit
class FindOnPageViewController: UIViewController, _WKFindDelegate
{
let findOnPageView = FindOnPageView()
weak var webView: WKWebView? {
didSet { webView?._findDelegate = self }
}
private var findString: String?
private let findOptions: _WKFindOptions = [
.caseInsensitive,
.atWordStarts,
.treatMedialCapitalAsWordStart,
.wrapAround,
.showFindIndicator,
.showOverlay,
.showHighlight,
.determineMatchIndex,
]
private let maxCount: UInt = 1000
convenience init() {
self.init(nibName: nil, bundle: nil)
findOnPageView.textField.addAction(UIAction(handler: { [unowned self] _ in
self.findString = findOnPageView.textField.text
webView?._find(self.findString, options: self.findOptions, maxCount: self.maxCount)
}), for: .editingChanged)
findOnPageView.prevResultButton.addAction(UIAction(handler: { [unowned self] _ in
findPrevious(nil)
}), for: .touchUpInside)
findOnPageView.nextResultButton.addAction(UIAction(handler: { [unowned self] _ in
findNext(nil)
}), for: .touchUpInside)
findOnPageView.doneButton.addAction(UIAction(handler: { [unowned self] _ in
doneFinding(nil)
}), for: .touchUpInside)
// Escape to cancel
addKeyCommand(UIKeyCommand(input: UIKeyCommand.inputEscape, modifierFlags: [], action: #selector(Self.doneFinding)))
// Return goes to next
addKeyCommand(UIKeyCommand(input: "\n", modifierFlags: [], action: #selector(Self.findNext)))
// Cmd+G next
addKeyCommand(UIKeyCommand(input: "G", modifierFlags: [.command], action: #selector(Self.findNext)))
// Shift return goes to prev
addKeyCommand(UIKeyCommand(input: "\n", modifierFlags: [.shift], action: #selector(Self.findPrevious)))
// Shift+Cmd+G prev
addKeyCommand(UIKeyCommand(input: "G", modifierFlags: [.command, .shift], action: #selector(Self.findPrevious)))
self.view = findOnPageView
}
@objc
func doneFinding(_ sender: Any?) {
findOnPageView.textField.resignFirstResponder()
webView?._hideFindUI()
}
@objc
func findNext(_ sender: Any?) {
webView?._find(self.findString, options: self.findOptions, maxCount: self.maxCount)
}
@objc
func findPrevious(_ sender: Any?) {
let options: _WKFindOptions = self.findOptions.union(.backwards)
webView?._find(self.findString, options: options, maxCount: self.maxCount)
}
func _webView(_ webView: WKWebView!, didFailToFind string: String!) {
// ??
}
func _webView(_ webView: WKWebView!, didCountMatches matches: UInt, for string: String!) {
// TODO: Update a label
}
func _webView(_ webView: WKWebView!, didFindMatches matches: UInt, for string: String!, withMatch matchIndex: Int) {
findOnPageView.nextResultButton.isEnabled = matches > 0
findOnPageView.prevResultButton.isEnabled = matches > 0
}
}