mirror of
https://github.com/zhigang1992/GitHawk.git
synced 2026-01-12 22:47:34 +08:00
* Add string extension for searching pdf files (#1552) * Create RepositoryWebViewController (#1552) * Initial presenting of the pdf files (#1552) * refactor: Rename String+Resource -> String+BinaryFile (#1552) * Build destination URL (#1552) * Configure title (#1552) * Encode file path * Use EmptyView for errors * Replace UIWebView with WKWebView * Review fixes * refactor: Make binarySuffix computed property * Unify if-else path * Group guard statements
204 lines
5.4 KiB
Swift
204 lines
5.4 KiB
Swift
//
|
|
// RepositoryWebViewController.swift
|
|
// Freetime
|
|
//
|
|
// Created by Ivan Magda on 01/03/2018.
|
|
// Copyright © 2018 Ryan Nystrom. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import WebKit
|
|
|
|
// MARK: RepositoryWebViewController: UIViewController
|
|
|
|
final class RepositoryWebViewController: UIViewController {
|
|
|
|
// MARK: Types
|
|
|
|
private enum State {
|
|
case idle
|
|
case fetching
|
|
case error(String?)
|
|
}
|
|
|
|
// MARK: Instance Variables
|
|
|
|
private let branch: String
|
|
private let path: FilePath
|
|
private let repo: RepositoryDetails
|
|
|
|
private var state = State.idle {
|
|
didSet {
|
|
switch state {
|
|
case .idle:
|
|
activityIndicator.stopAnimating()
|
|
emptyView.isHidden = true
|
|
webView.isHidden = false
|
|
case .fetching:
|
|
activityIndicator.startAnimating()
|
|
emptyView.isHidden = true
|
|
webView.isHidden = false
|
|
case .error(let message):
|
|
activityIndicator.stopAnimating()
|
|
webView.isHidden = true
|
|
emptyView.isHidden = false
|
|
emptyView.label.text = message
|
|
}
|
|
}
|
|
}
|
|
|
|
private var resourceURL: URL? {
|
|
guard let encodedPath = path.path.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
|
|
return nil
|
|
}
|
|
|
|
return URL(string: "https://github.com/\(repo.owner)/\(repo.name)/raw/\(branch)/\(encodedPath)")
|
|
}
|
|
|
|
private lazy var webView: WKWebView = {
|
|
let webView = WKWebView()
|
|
webView.translatesAutoresizingMaskIntoConstraints = false
|
|
webView.navigationDelegate = self
|
|
webView.backgroundColor = .white
|
|
|
|
return webView
|
|
}()
|
|
|
|
private let emptyView = EmptyView()
|
|
|
|
private lazy var activityIndicator: UIActivityIndicatorView = {
|
|
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
|
|
activityIndicator.hidesWhenStopped = true
|
|
|
|
return activityIndicator
|
|
}()
|
|
|
|
// MARK: Init
|
|
|
|
init(
|
|
repo: RepositoryDetails,
|
|
branch: String,
|
|
path: FilePath
|
|
) {
|
|
self.repo = repo
|
|
self.branch = branch
|
|
self.path = path
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
// MARK: UIViewController Lifecycle
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
setup()
|
|
fetch()
|
|
}
|
|
|
|
override func viewWillLayoutSubviews() {
|
|
super.viewWillLayoutSubviews()
|
|
|
|
emptyView.frame = view.bounds
|
|
activityIndicator.center = view.center
|
|
|
|
if let tabBarController = tabBarController {
|
|
webView.scrollView.contentInset.bottom = tabBarController.tabBar.bounds.height
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - RepositoryWebViewController (UIWebViewDelegate) -
|
|
|
|
extension RepositoryWebViewController: WKNavigationDelegate {
|
|
|
|
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
|
state = .fetching
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
state = .idle
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
|
showError(cannotLoad: true)
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - RepositoryWebViewController (Fetch Data) -
|
|
|
|
extension RepositoryWebViewController {
|
|
|
|
private func fetch() {
|
|
guard let url = resourceURL else { return showError(cannotLoad: false) }
|
|
state = .fetching
|
|
|
|
URLSession.shared.dataTask(with: url) { [weak self] (data, _, error) in
|
|
DispatchQueue.main.async {
|
|
guard let strongSelf = self else { return }
|
|
guard error == nil,
|
|
let data = data else { return strongSelf.showError(cannotLoad: true) }
|
|
|
|
strongSelf.webView.load(
|
|
data,
|
|
mimeType: strongSelf.path.mimeType ?? "text/plain",
|
|
characterEncodingName: "UTF-8",
|
|
baseURL: url
|
|
)
|
|
}
|
|
}.resume()
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - RepositoryWebViewController (Actions) -
|
|
|
|
extension RepositoryWebViewController {
|
|
|
|
@objc private func onFileNavigationTitle(sender: UIView) {
|
|
showAlert(filePath: path, sender: sender)
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - RepositoryWebViewController (Private Helpers) -
|
|
|
|
extension RepositoryWebViewController {
|
|
|
|
private func setup() {
|
|
makeBackBarItemEmpty()
|
|
configureTitle(
|
|
filePath: path,
|
|
target: self,
|
|
action: #selector(onFileNavigationTitle(sender:))
|
|
)
|
|
|
|
state = .idle
|
|
emptyView.isHidden = true
|
|
|
|
view.backgroundColor = .white
|
|
view.addSubview(emptyView)
|
|
view.addSubview(webView)
|
|
view.addSubview(activityIndicator)
|
|
|
|
NSLayoutConstraint.activate([
|
|
webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
|
webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
|
webView.topAnchor.constraint(equalTo: view.topAnchor),
|
|
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
|
|
])
|
|
}
|
|
|
|
private func showError(cannotLoad: Bool) {
|
|
state = .error(cannotLoad
|
|
? NSLocalizedString("Cannot display file", comment: "")
|
|
: NSLocalizedString("Error loading file", comment: "")
|
|
)
|
|
}
|
|
|
|
}
|