mirror of
https://github.com/kiwix/kiwix-apple.git
synced 2025-09-27 13:59:04 -04:00
Refactor
This commit is contained in:
parent
c0443cd506
commit
f3d16e7add
@ -12,7 +12,7 @@ import JavaScriptCore
|
|||||||
class JS {
|
class JS {
|
||||||
|
|
||||||
class func inject(webView: UIWebView) {
|
class func inject(webView: UIWebView) {
|
||||||
guard let url = Bundle.main.url(forResource: "injection", withExtension: "js"),
|
guard let url = Bundle.main.url(forResource: "JSInject", withExtension: "js"),
|
||||||
let jString = try? String(contentsOf: url) else {return}
|
let jString = try? String(contentsOf: url) else {return}
|
||||||
webView.stringByEvaluatingJavaScript(from: jString)
|
webView.stringByEvaluatingJavaScript(from: jString)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import WebKit
|
import SafariServices
|
||||||
|
import CoreSpotlight
|
||||||
|
import CloudKit
|
||||||
|
|
||||||
class MainController: UIViewController {
|
class MainController: UIViewController {
|
||||||
|
|
||||||
@ -70,5 +72,347 @@ class MainController: UIViewController {
|
|||||||
tableOfContentsController?.delegate = self
|
tableOfContentsController?.delegate = self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Web
|
||||||
|
|
||||||
|
extension MainController: UIWebViewDelegate, SFSafariViewControllerDelegate {
|
||||||
|
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
|
||||||
|
guard let url = request.url else {return false}
|
||||||
|
if url.isKiwixURL {
|
||||||
|
return true
|
||||||
|
} else if url.scheme == "pagescroll" {
|
||||||
|
let components = URLComponents(string: url.absoluteString)
|
||||||
|
guard let query = components?.queryItems,
|
||||||
|
let startStr = query[0].value, let start = Int(startStr),
|
||||||
|
let lengthStr = query[1].value, let length = Int(lengthStr) else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tableOfContentsController?.visibleRange = (start, length)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
let controller = SFSafariViewController(url: url)
|
||||||
|
controller.delegate = self
|
||||||
|
present(controller, animated: true, completion: nil)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func webViewDidStartLoad(_ webView: UIWebView) {
|
||||||
|
URLResponseCache.shared.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func webViewDidFinishLoad(_ webView: UIWebView) {
|
||||||
|
JS.inject(webView: webView)
|
||||||
|
JS.preventDefaultLongTap(webView: webView)
|
||||||
|
tableOfContentsController?.headings = JS.getTableOfContents(webView: webView)
|
||||||
|
JS.startTOCCallBack(webView: webView)
|
||||||
|
|
||||||
|
URLResponseCache.shared.stop()
|
||||||
|
|
||||||
|
guard let url = webView.request?.url,
|
||||||
|
let article = Article.fetch(url: url, context: AppDelegate.persistentContainer.viewContext) else {return}
|
||||||
|
|
||||||
|
buttons.back.tintColor = webView.canGoBack ? nil : UIColor.gray
|
||||||
|
buttons.forward.tintColor = webView.canGoForward ? nil : UIColor.gray
|
||||||
|
buttons.bookmark.isHighlighted = article.isBookmarked
|
||||||
|
|
||||||
|
guard let title = JS.getTitle(from: webView) else {return}
|
||||||
|
searchBar.title = title
|
||||||
|
|
||||||
|
article.title = title
|
||||||
|
article.snippet = JS.getSnippet(from: webView)
|
||||||
|
article.bookmarkDate = Date()
|
||||||
|
article.thumbImagePath = URLResponseCache.shared.firstImage()?.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Search
|
||||||
|
|
||||||
|
extension MainController: SearchBarDelegate, SearchContainerDelegate {
|
||||||
|
|
||||||
|
func didBecomeFirstResponder(searchBar: SearchBar) {
|
||||||
|
showSearch(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func didResignFirstResponder(searchBar: SearchBar) {
|
||||||
|
hideSearch(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func textDidChange(text: String, searchBar: SearchBar) {
|
||||||
|
controllers.search.searchText = text
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldReturn(searchBar: SearchBar) -> Bool {
|
||||||
|
let controller = controllers.search.resultController!
|
||||||
|
controller.selectFirstResult()
|
||||||
|
return controller.searchResults.count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showSearch(animated: Bool) {
|
||||||
|
let controller = controllers.search
|
||||||
|
controller.delegate = self
|
||||||
|
guard !childViewControllers.contains(controller) else {return}
|
||||||
|
|
||||||
|
// hide toolbar
|
||||||
|
// add cancel button
|
||||||
|
if traitCollection.horizontalSizeClass == .compact {
|
||||||
|
navigationController?.setToolbarHidden(true, animated: animated)
|
||||||
|
navigationItem.setRightBarButton(buttons.cancel, animated: animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
// manage view hierarchy
|
||||||
|
addChildViewController(controller)
|
||||||
|
controller.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.addSubview(controller.view)
|
||||||
|
|
||||||
|
let views = ["view": controller.view]
|
||||||
|
view.addConstraints(NSLayoutConstraint.constraints(
|
||||||
|
withVisualFormat: "H:|[view]|", options: .alignAllCenterY, metrics: nil, views: views))
|
||||||
|
view.addConstraint(controller.view.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor))
|
||||||
|
view.addConstraint(controller.view.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor))
|
||||||
|
|
||||||
|
if animated {
|
||||||
|
controller.view.alpha = 0.5
|
||||||
|
UIView.animate(withDuration: 0.15, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
|
||||||
|
controller.view.alpha = 1.0
|
||||||
|
}, completion: nil)
|
||||||
|
} else {
|
||||||
|
controller.view.alpha = 1.0
|
||||||
|
}
|
||||||
|
controller.didMove(toParentViewController: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func hideSearch(animated: Bool) {
|
||||||
|
guard let searchController = childViewControllers.flatMap({$0 as? SearchContainer}).first else {return}
|
||||||
|
|
||||||
|
// show toolbar
|
||||||
|
// remove cancel button
|
||||||
|
if traitCollection.horizontalSizeClass == .compact {
|
||||||
|
navigationController?.setToolbarHidden(false, animated: animated)
|
||||||
|
navigationItem.setRightBarButton(nil, animated: animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
let completion = { (complete: Bool) -> Void in
|
||||||
|
guard complete else {return}
|
||||||
|
searchController.view.removeFromSuperview()
|
||||||
|
searchController.removeFromParentViewController()
|
||||||
|
guard self.traitCollection.horizontalSizeClass == .compact else {return}
|
||||||
|
self.navigationController?.setToolbarHidden(false, animated: animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
searchController.willMove(toParentViewController: nil)
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.15, delay: 0.0, options: .beginFromCurrentState, animations: {
|
||||||
|
searchController.view.alpha = 0.0
|
||||||
|
}, completion: completion)
|
||||||
|
} else {
|
||||||
|
completion(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func didTapSearchDimView() {
|
||||||
|
_ = searchBar.resignFirstResponder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Button Delegates
|
||||||
|
|
||||||
|
extension MainController: ButtonDelegates {
|
||||||
|
func didTapBackButton() {
|
||||||
|
webView.goBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didTapForwardButton() {
|
||||||
|
webView.goForward()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didTapTOCButton() {
|
||||||
|
isShowingTableOfContents ? hideTableOfContents(animated: true) : showTableOfContents(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func didTapBookmarkButton() {
|
||||||
|
showBookmarkController()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didTapLibraryButton() {
|
||||||
|
present(controllers.library, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func didTapCancelButton() {
|
||||||
|
_ = searchBar.resignFirstResponder()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didLongPressBackButton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func didLongPressForwardButton() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func didLongPressBookmarkButton() {
|
||||||
|
func indexCoreSpotlight(article: Article) {
|
||||||
|
if article.isBookmarked {
|
||||||
|
CSSearchableIndex.default().indexSearchableItems([article.searchableItem], completionHandler: nil)
|
||||||
|
} else {
|
||||||
|
guard let url = article.url else {return}
|
||||||
|
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: [url.absoluteString], completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = AppDelegate.persistentContainer.viewContext
|
||||||
|
guard let url = webView.request?.url,
|
||||||
|
let article = Article.fetch(url: url, context: context) else {return}
|
||||||
|
article.isBookmarked = !article.isBookmarked
|
||||||
|
if article.isBookmarked {article.bookmarkDate = Date()}
|
||||||
|
|
||||||
|
if context.hasChanges {try? context.save()}
|
||||||
|
|
||||||
|
showBookmarkHUD()
|
||||||
|
controllers.bookmarkHUD.bookmarkAdded = article.isBookmarked
|
||||||
|
buttons.bookmark.isHighlighted = article.isBookmarked
|
||||||
|
|
||||||
|
indexCoreSpotlight(article: article)
|
||||||
|
// let operation = BookmarkSyncOperation(articleURL: url)
|
||||||
|
// GlobalQueue.shared.add(operation: operation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Table Of Content
|
||||||
|
|
||||||
|
extension MainController: TableOfContentsDelegate {
|
||||||
|
func showTableOfContents(animated: Bool) {
|
||||||
|
guard welcomeController == nil else {return}
|
||||||
|
isShowingTableOfContents = true
|
||||||
|
tocVisiualEffectView.isHidden = false
|
||||||
|
dimView.isHidden = false
|
||||||
|
dimView.alpha = 0.0
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
|
||||||
|
//configureTableOfContents()
|
||||||
|
configureTOCConstraints()
|
||||||
|
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, options: .curveEaseOut, animations: {
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
self.dimView.alpha = 0.5
|
||||||
|
}) { (completed) in }
|
||||||
|
} else {
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
dimView.alpha = 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hideTableOfContents(animated: Bool) {
|
||||||
|
isShowingTableOfContents = false
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
|
||||||
|
configureTOCConstraints()
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
self.dimView.alpha = 0.0
|
||||||
|
}) { (completed) in
|
||||||
|
self.dimView.isHidden = true
|
||||||
|
self.tocVisiualEffectView.isHidden = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
dimView.alpha = 0.0
|
||||||
|
dimView.isHidden = true
|
||||||
|
tocVisiualEffectView.isHidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureTOCConstraints() {
|
||||||
|
switch traitCollection.horizontalSizeClass {
|
||||||
|
case .compact:
|
||||||
|
let toolBarHeight: CGFloat = traitCollection.horizontalSizeClass == .regular ? 0.0 : (traitCollection.verticalSizeClass == .compact ? 32.0 : 44.0)
|
||||||
|
let tocHeight: CGFloat = {
|
||||||
|
guard let controller = tableOfContentsController else {return floor(view.frame.height * 0.4)}
|
||||||
|
let tocContentHeight = controller.tableView.contentSize.height
|
||||||
|
guard controller.headings.count != 0 else {return floor(view.frame.height * 0.4)}
|
||||||
|
return min(tocContentHeight, floor(view.frame.height * 0.65))
|
||||||
|
}()
|
||||||
|
tocHeightConstraint.constant = tocHeight
|
||||||
|
tocTopToSuperViewBottomSpacing.constant = isShowingTableOfContents ? tocHeight + toolBarHeight + 10 : 0.0
|
||||||
|
case .regular:
|
||||||
|
tocLeadSpacing.constant = isShowingTableOfContents ? 0.0 : 270
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func didSelectHeading(index: Int) {
|
||||||
|
JS.scrollToHeading(webView: webView, index: index)
|
||||||
|
if traitCollection.horizontalSizeClass == .compact {
|
||||||
|
hideTableOfContents(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func didTapTOCDimView(_ sender: UITapGestureRecognizer) {
|
||||||
|
hideTableOfContents(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Welcome
|
||||||
|
|
||||||
|
extension MainController {
|
||||||
|
func showWelcome() {
|
||||||
|
let controller = controllers.welcome
|
||||||
|
controller.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
addChildViewController(controller)
|
||||||
|
view.insertSubview(controller.view, aboveSubview: webView)
|
||||||
|
let views = ["view": controller.view]
|
||||||
|
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: .alignAllTop, metrics: nil, views: views))
|
||||||
|
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: .alignAllLeft, metrics: nil, views: views))
|
||||||
|
controller.didMove(toParentViewController: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hideWelcome() {
|
||||||
|
guard let controller = welcomeController else {return}
|
||||||
|
controller.removeFromParentViewController()
|
||||||
|
controller.view.removeFromSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
var welcomeController: WelcomeController? {
|
||||||
|
return childViewControllers.flatMap({$0 as? WelcomeController}).first
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Bookmark
|
||||||
|
|
||||||
|
extension MainController: UIViewControllerTransitioningDelegate {
|
||||||
|
func showBookmarkController() {
|
||||||
|
let controller = controllers.bookmark
|
||||||
|
controller.modalPresentationStyle = .fullScreen
|
||||||
|
present(controller, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func showBookmarkHUD() {
|
||||||
|
let controller = controllers.bookmarkHUD
|
||||||
|
controller.bookmarkAdded = !controller.bookmarkAdded
|
||||||
|
controller.transitioningDelegate = self
|
||||||
|
controller.modalPresentationStyle = .overFullScreen
|
||||||
|
present(controller, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
|
return BookmarkHUDAnimator(animateIn: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
|
return BookmarkHUDAnimator(animateIn: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SFSafariViewControllerDelegate
|
||||||
|
|
||||||
|
extension MainController {
|
||||||
|
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
|
||||||
|
controller.dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,354 +0,0 @@
|
|||||||
//
|
|
||||||
// MainControllerDelegates.swift
|
|
||||||
// Kiwix
|
|
||||||
//
|
|
||||||
// Created by Chris Li on 11/14/16.
|
|
||||||
// Copyright © 2016 Chris Li. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import SafariServices
|
|
||||||
import CoreSpotlight
|
|
||||||
import CloudKit
|
|
||||||
|
|
||||||
// MARK: - Web
|
|
||||||
|
|
||||||
extension MainController: UIWebViewDelegate, SFSafariViewControllerDelegate {
|
|
||||||
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
|
|
||||||
guard let url = request.url else {return false}
|
|
||||||
if url.isKiwixURL {
|
|
||||||
return true
|
|
||||||
} else if url.scheme == "pagescroll" {
|
|
||||||
let components = URLComponents(string: url.absoluteString)
|
|
||||||
guard let query = components?.queryItems,
|
|
||||||
let startStr = query[0].value, let start = Int(startStr),
|
|
||||||
let lengthStr = query[1].value, let length = Int(lengthStr) else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
tableOfContentsController?.visibleRange = (start, length)
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
let controller = SFSafariViewController(url: url)
|
|
||||||
controller.delegate = self
|
|
||||||
present(controller, animated: true, completion: nil)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func webViewDidStartLoad(_ webView: UIWebView) {
|
|
||||||
URLResponseCache.shared.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func webViewDidFinishLoad(_ webView: UIWebView) {
|
|
||||||
JS.inject(webView: webView)
|
|
||||||
JS.preventDefaultLongTap(webView: webView)
|
|
||||||
tableOfContentsController?.headings = JS.getTableOfContents(webView: webView)
|
|
||||||
JS.startTOCCallBack(webView: webView)
|
|
||||||
|
|
||||||
URLResponseCache.shared.stop()
|
|
||||||
|
|
||||||
guard let url = webView.request?.url,
|
|
||||||
let article = Article.fetch(url: url, context: AppDelegate.persistentContainer.viewContext) else {return}
|
|
||||||
|
|
||||||
buttons.back.tintColor = webView.canGoBack ? nil : UIColor.gray
|
|
||||||
buttons.forward.tintColor = webView.canGoForward ? nil : UIColor.gray
|
|
||||||
buttons.bookmark.isHighlighted = article.isBookmarked
|
|
||||||
|
|
||||||
guard let title = JS.getTitle(from: webView) else {return}
|
|
||||||
searchBar.title = title
|
|
||||||
|
|
||||||
article.title = title
|
|
||||||
article.snippet = JS.getSnippet(from: webView)
|
|
||||||
article.bookmarkDate = Date()
|
|
||||||
article.thumbImagePath = URLResponseCache.shared.firstImage()?.path
|
|
||||||
}
|
|
||||||
|
|
||||||
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Search
|
|
||||||
|
|
||||||
extension MainController: SearchBarDelegate, SearchContainerDelegate {
|
|
||||||
|
|
||||||
func didBecomeFirstResponder(searchBar: SearchBar) {
|
|
||||||
showSearch(animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func didResignFirstResponder(searchBar: SearchBar) {
|
|
||||||
hideSearch(animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func textDidChange(text: String, searchBar: SearchBar) {
|
|
||||||
controllers.search.searchText = text
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldReturn(searchBar: SearchBar) -> Bool {
|
|
||||||
let controller = controllers.search.resultController!
|
|
||||||
controller.selectFirstResult()
|
|
||||||
return controller.searchResults.count > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private func showSearch(animated: Bool) {
|
|
||||||
let controller = controllers.search
|
|
||||||
controller.delegate = self
|
|
||||||
guard !childViewControllers.contains(controller) else {return}
|
|
||||||
|
|
||||||
// hide toolbar
|
|
||||||
// add cancel button
|
|
||||||
if traitCollection.horizontalSizeClass == .compact {
|
|
||||||
navigationController?.setToolbarHidden(true, animated: animated)
|
|
||||||
navigationItem.setRightBarButton(buttons.cancel, animated: animated)
|
|
||||||
}
|
|
||||||
|
|
||||||
// manage view hierarchy
|
|
||||||
addChildViewController(controller)
|
|
||||||
controller.view.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
view.addSubview(controller.view)
|
|
||||||
|
|
||||||
let views = ["view": controller.view]
|
|
||||||
view.addConstraints(NSLayoutConstraint.constraints(
|
|
||||||
withVisualFormat: "H:|[view]|", options: .alignAllCenterY, metrics: nil, views: views))
|
|
||||||
view.addConstraint(controller.view.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor))
|
|
||||||
view.addConstraint(controller.view.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor))
|
|
||||||
|
|
||||||
if animated {
|
|
||||||
controller.view.alpha = 0.5
|
|
||||||
UIView.animate(withDuration: 0.15, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
|
|
||||||
controller.view.alpha = 1.0
|
|
||||||
}, completion: nil)
|
|
||||||
} else {
|
|
||||||
controller.view.alpha = 1.0
|
|
||||||
}
|
|
||||||
controller.didMove(toParentViewController: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func hideSearch(animated: Bool) {
|
|
||||||
guard let searchController = childViewControllers.flatMap({$0 as? SearchContainer}).first else {return}
|
|
||||||
|
|
||||||
// show toolbar
|
|
||||||
// remove cancel button
|
|
||||||
if traitCollection.horizontalSizeClass == .compact {
|
|
||||||
navigationController?.setToolbarHidden(false, animated: animated)
|
|
||||||
navigationItem.setRightBarButton(nil, animated: animated)
|
|
||||||
}
|
|
||||||
|
|
||||||
let completion = { (complete: Bool) -> Void in
|
|
||||||
guard complete else {return}
|
|
||||||
searchController.view.removeFromSuperview()
|
|
||||||
searchController.removeFromParentViewController()
|
|
||||||
guard self.traitCollection.horizontalSizeClass == .compact else {return}
|
|
||||||
self.navigationController?.setToolbarHidden(false, animated: animated)
|
|
||||||
}
|
|
||||||
|
|
||||||
searchController.willMove(toParentViewController: nil)
|
|
||||||
if animated {
|
|
||||||
UIView.animate(withDuration: 0.15, delay: 0.0, options: .beginFromCurrentState, animations: {
|
|
||||||
searchController.view.alpha = 0.0
|
|
||||||
}, completion: completion)
|
|
||||||
} else {
|
|
||||||
completion(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func didTapSearchDimView() {
|
|
||||||
_ = searchBar.resignFirstResponder()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Button Delegates
|
|
||||||
|
|
||||||
extension MainController: ButtonDelegates {
|
|
||||||
func didTapBackButton() {
|
|
||||||
webView.goBack()
|
|
||||||
}
|
|
||||||
|
|
||||||
func didTapForwardButton() {
|
|
||||||
webView.goForward()
|
|
||||||
}
|
|
||||||
|
|
||||||
func didTapTOCButton() {
|
|
||||||
isShowingTableOfContents ? hideTableOfContents(animated: true) : showTableOfContents(animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func didTapBookmarkButton() {
|
|
||||||
showBookmarkController()
|
|
||||||
}
|
|
||||||
|
|
||||||
func didTapLibraryButton() {
|
|
||||||
present(controllers.library, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func didTapCancelButton() {
|
|
||||||
_ = searchBar.resignFirstResponder()
|
|
||||||
}
|
|
||||||
|
|
||||||
func didLongPressBackButton() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func didLongPressForwardButton() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func didLongPressBookmarkButton() {
|
|
||||||
func indexCoreSpotlight(article: Article) {
|
|
||||||
if article.isBookmarked {
|
|
||||||
CSSearchableIndex.default().indexSearchableItems([article.searchableItem], completionHandler: nil)
|
|
||||||
} else {
|
|
||||||
guard let url = article.url else {return}
|
|
||||||
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: [url.absoluteString], completionHandler: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = AppDelegate.persistentContainer.viewContext
|
|
||||||
guard let url = webView.request?.url,
|
|
||||||
let article = Article.fetch(url: url, context: context) else {return}
|
|
||||||
article.isBookmarked = !article.isBookmarked
|
|
||||||
if article.isBookmarked {article.bookmarkDate = Date()}
|
|
||||||
|
|
||||||
if context.hasChanges {try? context.save()}
|
|
||||||
|
|
||||||
showBookmarkHUD()
|
|
||||||
controllers.bookmarkHUD.bookmarkAdded = article.isBookmarked
|
|
||||||
buttons.bookmark.isHighlighted = article.isBookmarked
|
|
||||||
|
|
||||||
indexCoreSpotlight(article: article)
|
|
||||||
// let operation = BookmarkSyncOperation(articleURL: url)
|
|
||||||
// GlobalQueue.shared.add(operation: operation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Table Of Content
|
|
||||||
|
|
||||||
extension MainController: TableOfContentsDelegate {
|
|
||||||
func showTableOfContents(animated: Bool) {
|
|
||||||
guard welcomeController == nil else {return}
|
|
||||||
isShowingTableOfContents = true
|
|
||||||
tocVisiualEffectView.isHidden = false
|
|
||||||
dimView.isHidden = false
|
|
||||||
dimView.alpha = 0.0
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
|
|
||||||
//configureTableOfContents()
|
|
||||||
configureTOCConstraints()
|
|
||||||
|
|
||||||
if animated {
|
|
||||||
UIView.animate(withDuration: 0.3, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, options: .curveEaseOut, animations: {
|
|
||||||
self.view.layoutIfNeeded()
|
|
||||||
self.dimView.alpha = 0.5
|
|
||||||
}) { (completed) in }
|
|
||||||
} else {
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
dimView.alpha = 0.5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func hideTableOfContents(animated: Bool) {
|
|
||||||
isShowingTableOfContents = false
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
|
|
||||||
configureTOCConstraints()
|
|
||||||
if animated {
|
|
||||||
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
|
|
||||||
self.view.layoutIfNeeded()
|
|
||||||
self.dimView.alpha = 0.0
|
|
||||||
}) { (completed) in
|
|
||||||
self.dimView.isHidden = true
|
|
||||||
self.tocVisiualEffectView.isHidden = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
dimView.alpha = 0.0
|
|
||||||
dimView.isHidden = true
|
|
||||||
tocVisiualEffectView.isHidden = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func configureTOCConstraints() {
|
|
||||||
switch traitCollection.horizontalSizeClass {
|
|
||||||
case .compact:
|
|
||||||
let toolBarHeight: CGFloat = traitCollection.horizontalSizeClass == .regular ? 0.0 : (traitCollection.verticalSizeClass == .compact ? 32.0 : 44.0)
|
|
||||||
let tocHeight: CGFloat = {
|
|
||||||
guard let controller = tableOfContentsController else {return floor(view.frame.height * 0.4)}
|
|
||||||
let tocContentHeight = controller.tableView.contentSize.height
|
|
||||||
guard controller.headings.count != 0 else {return floor(view.frame.height * 0.4)}
|
|
||||||
return min(tocContentHeight, floor(view.frame.height * 0.65))
|
|
||||||
}()
|
|
||||||
tocHeightConstraint.constant = tocHeight
|
|
||||||
tocTopToSuperViewBottomSpacing.constant = isShowingTableOfContents ? tocHeight + toolBarHeight + 10 : 0.0
|
|
||||||
case .regular:
|
|
||||||
tocLeadSpacing.constant = isShowingTableOfContents ? 0.0 : 270
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func didSelectHeading(index: Int) {
|
|
||||||
JS.scrollToHeading(webView: webView, index: index)
|
|
||||||
if traitCollection.horizontalSizeClass == .compact {
|
|
||||||
hideTableOfContents(animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@IBAction func didTapTOCDimView(_ sender: UITapGestureRecognizer) {
|
|
||||||
hideTableOfContents(animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Welcome
|
|
||||||
|
|
||||||
extension MainController {
|
|
||||||
func showWelcome() {
|
|
||||||
let controller = controllers.welcome
|
|
||||||
controller.view.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
addChildViewController(controller)
|
|
||||||
view.insertSubview(controller.view, aboveSubview: webView)
|
|
||||||
let views = ["view": controller.view]
|
|
||||||
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: .alignAllTop, metrics: nil, views: views))
|
|
||||||
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: .alignAllLeft, metrics: nil, views: views))
|
|
||||||
controller.didMove(toParentViewController: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hideWelcome() {
|
|
||||||
guard let controller = welcomeController else {return}
|
|
||||||
controller.removeFromParentViewController()
|
|
||||||
controller.view.removeFromSuperview()
|
|
||||||
}
|
|
||||||
|
|
||||||
var welcomeController: WelcomeController? {
|
|
||||||
return childViewControllers.flatMap({$0 as? WelcomeController}).first
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Bookmark
|
|
||||||
|
|
||||||
extension MainController: UIViewControllerTransitioningDelegate {
|
|
||||||
func showBookmarkController() {
|
|
||||||
let controller = controllers.bookmark
|
|
||||||
controller.modalPresentationStyle = .fullScreen
|
|
||||||
present(controller, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func showBookmarkHUD() {
|
|
||||||
let controller = controllers.bookmarkHUD
|
|
||||||
controller.bookmarkAdded = !controller.bookmarkAdded
|
|
||||||
controller.transitioningDelegate = self
|
|
||||||
controller.modalPresentationStyle = .overFullScreen
|
|
||||||
present(controller, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
|
||||||
return BookmarkHUDAnimator(animateIn: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
|
||||||
return BookmarkHUDAnimator(animateIn: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - SFSafariViewControllerDelegate
|
|
||||||
|
|
||||||
extension MainController {
|
|
||||||
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
|
|
||||||
controller.dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
@ -48,7 +48,7 @@
|
|||||||
<constraint firstAttribute="width" constant="32" id="aFo-L8-O71"/>
|
<constraint firstAttribute="width" constant="32" id="aFo-L8-O71"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="justified" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LK0-aY-C9L">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="justified" lineBreakMode="clip" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LK0-aY-C9L">
|
||||||
<rect key="frame" x="8" y="31" width="191" height="17"/>
|
<rect key="frame" x="8" y="31" width="191" height="17"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
|
@ -58,7 +58,6 @@
|
|||||||
973DD4191D343F2F009D45DB /* libzim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 973DD40E1D343F2F009D45DB /* libzim.a */; };
|
973DD4191D343F2F009D45DB /* libzim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 973DD40E1D343F2F009D45DB /* libzim.a */; };
|
||||||
973DD4281D36E3E4009D45DB /* SettingDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973DD4271D36E3E4009D45DB /* SettingDetailController.swift */; };
|
973DD4281D36E3E4009D45DB /* SettingDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 973DD4271D36E3E4009D45DB /* SettingDetailController.swift */; };
|
||||||
974000151DB008C6009A740D /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9788419C1DA2FF2A00D22D3C /* MainInterface.storyboard */; };
|
974000151DB008C6009A740D /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9788419C1DA2FF2A00D22D3C /* MainInterface.storyboard */; };
|
||||||
974C49661DA307FF00E276E1 /* injection.js in Resources */ = {isa = PBXBuildFile; fileRef = 974C49621DA307FF00E276E1 /* injection.js */; };
|
|
||||||
974C49681DA4266200E276E1 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 974C49671DA4266200E276E1 /* CloudKit.framework */; };
|
974C49681DA4266200E276E1 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 974C49671DA4266200E276E1 /* CloudKit.framework */; };
|
||||||
975227CD1D0227E8001D1DDE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 975227CA1D0227E8001D1DDE /* Main.storyboard */; };
|
975227CD1D0227E8001D1DDE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 975227CA1D0227E8001D1DDE /* Main.storyboard */; };
|
||||||
975227CE1D0227E8001D1DDE /* Setting.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 975227CB1D0227E8001D1DDE /* Setting.storyboard */; };
|
975227CE1D0227E8001D1DDE /* Setting.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 975227CB1D0227E8001D1DDE /* Setting.storyboard */; };
|
||||||
@ -95,6 +94,7 @@
|
|||||||
97A1FD421D6F728200A80EE2 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97A1FD3D1D6F728200A80EE2 /* Extensions.swift */; };
|
97A1FD421D6F728200A80EE2 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97A1FD3D1D6F728200A80EE2 /* Extensions.swift */; };
|
||||||
97A1FD441D6F728200A80EE2 /* Preference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97A1FD401D6F728200A80EE2 /* Preference.swift */; };
|
97A1FD441D6F728200A80EE2 /* Preference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97A1FD401D6F728200A80EE2 /* Preference.swift */; };
|
||||||
97A1FD451D6F728200A80EE2 /* StringTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97A1FD411D6F728200A80EE2 /* StringTools.swift */; };
|
97A1FD451D6F728200A80EE2 /* StringTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97A1FD411D6F728200A80EE2 /* StringTools.swift */; };
|
||||||
|
97A9F6F51E2E990500F423AA /* JSInject.js in Resources */ = {isa = PBXBuildFile; fileRef = 97A9F6F41E2E990500F423AA /* JSInject.js */; };
|
||||||
97BC0FBF1DD90A65004BBAD1 /* JSInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */; };
|
97BC0FBF1DD90A65004BBAD1 /* JSInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */; };
|
||||||
97BC0FC01DD90A65004BBAD1 /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FBE1DD90A65004BBAD1 /* MainController.swift */; };
|
97BC0FC01DD90A65004BBAD1 /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FBE1DD90A65004BBAD1 /* MainController.swift */; };
|
||||||
97BC0FC21DD92B62004BBAD1 /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FC11DD92B62004BBAD1 /* Buttons.swift */; };
|
97BC0FC21DD92B62004BBAD1 /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC0FC11DD92B62004BBAD1 /* Buttons.swift */; };
|
||||||
@ -102,7 +102,6 @@
|
|||||||
97C2C26A1DDCC58500A9CC64 /* ArticleOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764CBD21D8083AA00072D6A /* ArticleOperation.swift */; };
|
97C2C26A1DDCC58500A9CC64 /* ArticleOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9764CBD21D8083AA00072D6A /* ArticleOperation.swift */; };
|
||||||
97C601DC1D7F15C400362D4F /* Bookmark.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C601DB1D7F15C400362D4F /* Bookmark.storyboard */; };
|
97C601DC1D7F15C400362D4F /* Bookmark.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C601DB1D7F15C400362D4F /* Bookmark.storyboard */; };
|
||||||
97C601DE1D7F342100362D4F /* HTMLHeading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C601DD1D7F342100362D4F /* HTMLHeading.swift */; };
|
97C601DE1D7F342100362D4F /* HTMLHeading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C601DD1D7F342100362D4F /* HTMLHeading.swift */; };
|
||||||
97D0E98F1DDA12B30029530E /* MainDelegates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D0E98E1DDA12B30029530E /* MainDelegates.swift */; };
|
|
||||||
97D0E9931DDA487E0029530E /* SearchBaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D0E9921DDA487E0029530E /* SearchBaseController.swift */; };
|
97D0E9931DDA487E0029530E /* SearchBaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D0E9921DDA487E0029530E /* SearchBaseController.swift */; };
|
||||||
97D681311D6F70EC00E5FA99 /* 1.5.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */; };
|
97D681311D6F70EC00E5FA99 /* 1.5.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 97D6812F1D6F70EC00E5FA99 /* 1.5.xcmappingmodel */; };
|
||||||
97D681321D6F70EC00E5FA99 /* MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */; };
|
97D681321D6F70EC00E5FA99 /* MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D681301D6F70EC00E5FA99 /* MigrationPolicy.swift */; };
|
||||||
@ -218,7 +217,6 @@
|
|||||||
973DD40D1D343F2F009D45DB /* libxapian.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxapian.a; path = Kiwix/libkiwix/iOS/libxapian.a; sourceTree = "<group>"; };
|
973DD40D1D343F2F009D45DB /* libxapian.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxapian.a; path = Kiwix/libkiwix/iOS/libxapian.a; sourceTree = "<group>"; };
|
||||||
973DD40E1D343F2F009D45DB /* libzim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libzim.a; path = Kiwix/libkiwix/iOS/libzim.a; sourceTree = "<group>"; };
|
973DD40E1D343F2F009D45DB /* libzim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libzim.a; path = Kiwix/libkiwix/iOS/libzim.a; sourceTree = "<group>"; };
|
||||||
973DD4271D36E3E4009D45DB /* SettingDetailController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingDetailController.swift; path = "Kiwix-iOS/Controller/Setting/SettingDetailController.swift"; sourceTree = SOURCE_ROOT; };
|
973DD4271D36E3E4009D45DB /* SettingDetailController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingDetailController.swift; path = "Kiwix-iOS/Controller/Setting/SettingDetailController.swift"; sourceTree = SOURCE_ROOT; };
|
||||||
974C49621DA307FF00E276E1 /* injection.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = injection.js; sourceTree = "<group>"; };
|
|
||||||
974C49671DA4266200E276E1 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
974C49671DA4266200E276E1 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
||||||
975227CA1D0227E8001D1DDE /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = "Kiwix-iOS/Storyboard/Main.storyboard"; sourceTree = SOURCE_ROOT; };
|
975227CA1D0227E8001D1DDE /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = "Kiwix-iOS/Storyboard/Main.storyboard"; sourceTree = SOURCE_ROOT; };
|
||||||
975227CB1D0227E8001D1DDE /* Setting.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Setting.storyboard; path = "Kiwix-iOS/Storyboard/Setting.storyboard"; sourceTree = SOURCE_ROOT; };
|
975227CB1D0227E8001D1DDE /* Setting.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Setting.storyboard; path = "Kiwix-iOS/Storyboard/Setting.storyboard"; sourceTree = SOURCE_ROOT; };
|
||||||
@ -267,6 +265,7 @@
|
|||||||
97A2ABAA1C1B810000052E74 /* Kiwix-iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Kiwix-iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
97A2ABAA1C1B810000052E74 /* Kiwix-iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Kiwix-iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
97A8AD831D6C951A00584ED1 /* LocalBooksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalBooksController.swift; sourceTree = "<group>"; };
|
97A8AD831D6C951A00584ED1 /* LocalBooksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalBooksController.swift; sourceTree = "<group>"; };
|
||||||
97A8AD861D6CF38000584ED1 /* EmptyTableConfigExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyTableConfigExtension.swift; sourceTree = "<group>"; };
|
97A8AD861D6CF38000584ED1 /* EmptyTableConfigExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyTableConfigExtension.swift; sourceTree = "<group>"; };
|
||||||
|
97A9F6F41E2E990500F423AA /* JSInject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSInject.js; sourceTree = "<group>"; };
|
||||||
97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSInjection.swift; sourceTree = "<group>"; };
|
97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSInjection.swift; sourceTree = "<group>"; };
|
||||||
97BC0FBE1DD90A65004BBAD1 /* MainController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = "<group>"; };
|
97BC0FBE1DD90A65004BBAD1 /* MainController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = "<group>"; };
|
||||||
97BC0FC11DD92B62004BBAD1 /* Buttons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = "<group>"; };
|
97BC0FC11DD92B62004BBAD1 /* Buttons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = "<group>"; };
|
||||||
@ -276,7 +275,6 @@
|
|||||||
97C5BD4A1D9AF4B5009692CF /* BookmarkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkController.swift; sourceTree = "<group>"; };
|
97C5BD4A1D9AF4B5009692CF /* BookmarkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarkController.swift; sourceTree = "<group>"; };
|
||||||
97C601DB1D7F15C400362D4F /* Bookmark.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Bookmark.storyboard; sourceTree = "<group>"; };
|
97C601DB1D7F15C400362D4F /* Bookmark.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Bookmark.storyboard; sourceTree = "<group>"; };
|
||||||
97C601DD1D7F342100362D4F /* HTMLHeading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLHeading.swift; sourceTree = "<group>"; };
|
97C601DD1D7F342100362D4F /* HTMLHeading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLHeading.swift; sourceTree = "<group>"; };
|
||||||
97D0E98E1DDA12B30029530E /* MainDelegates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainDelegates.swift; sourceTree = "<group>"; };
|
|
||||||
97D0E9921DDA487E0029530E /* SearchBaseController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBaseController.swift; sourceTree = "<group>"; };
|
97D0E9921DDA487E0029530E /* SearchBaseController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBaseController.swift; sourceTree = "<group>"; };
|
||||||
97D4D64E1D874E6E00C1B065 /* SearchOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchOperation.swift; sourceTree = "<group>"; };
|
97D4D64E1D874E6E00C1B065 /* SearchOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchOperation.swift; sourceTree = "<group>"; };
|
||||||
97D6811A1D6E2A7100E5FA99 /* DownloadTasksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadTasksController.swift; sourceTree = "<group>"; };
|
97D6811A1D6E2A7100E5FA99 /* DownloadTasksController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadTasksController.swift; sourceTree = "<group>"; };
|
||||||
@ -474,7 +472,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
97BC0FBE1DD90A65004BBAD1 /* MainController.swift */,
|
97BC0FBE1DD90A65004BBAD1 /* MainController.swift */,
|
||||||
97D0E98E1DDA12B30029530E /* MainDelegates.swift */,
|
|
||||||
97BC0FC11DD92B62004BBAD1 /* Buttons.swift */,
|
97BC0FC11DD92B62004BBAD1 /* Buttons.swift */,
|
||||||
97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */,
|
97BC0FBD1DD90A65004BBAD1 /* JSInjection.swift */,
|
||||||
972F81581DDC1B71008D7289 /* Controllers.swift */,
|
972F81581DDC1B71008D7289 /* Controllers.swift */,
|
||||||
@ -522,7 +519,6 @@
|
|||||||
977A458A1E14E98F0089C596 /* Cloud */,
|
977A458A1E14E98F0089C596 /* Cloud */,
|
||||||
9711872D1CEB507600B9909D /* CoreData */,
|
9711872D1CEB507600B9909D /* CoreData */,
|
||||||
97163D321CD7E79F008BE2D6 /* Help Docs */,
|
97163D321CD7E79F008BE2D6 /* Help Docs */,
|
||||||
974C495E1DA307FF00E276E1 /* JavaScripts */,
|
|
||||||
971187051CEB426E00B9909D /* libkiwix */,
|
971187051CEB426E00B9909D /* libkiwix */,
|
||||||
97DF259E1D6F9942001648A3 /* Network */,
|
97DF259E1D6F9942001648A3 /* Network */,
|
||||||
97E5712A1CA0525300FF4F1D /* Operation */,
|
97E5712A1CA0525300FF4F1D /* Operation */,
|
||||||
@ -558,14 +554,6 @@
|
|||||||
path = Kiwix;
|
path = Kiwix;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
974C495E1DA307FF00E276E1 /* JavaScripts */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
974C49621DA307FF00E276E1 /* injection.js */,
|
|
||||||
);
|
|
||||||
path = JavaScripts;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
975227A41D020C0F001D1DDE /* indexer */ = {
|
975227A41D020C0F001D1DDE /* indexer */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -684,6 +672,7 @@
|
|||||||
children = (
|
children = (
|
||||||
97A1FD3D1D6F728200A80EE2 /* Extensions.swift */,
|
97A1FD3D1D6F728200A80EE2 /* Extensions.swift */,
|
||||||
97C601DD1D7F342100362D4F /* HTMLHeading.swift */,
|
97C601DD1D7F342100362D4F /* HTMLHeading.swift */,
|
||||||
|
97A9F6F41E2E990500F423AA /* JSInject.js */,
|
||||||
97A1FD401D6F728200A80EE2 /* Preference.swift */,
|
97A1FD401D6F728200A80EE2 /* Preference.swift */,
|
||||||
97A1FD411D6F728200A80EE2 /* StringTools.swift */,
|
97A1FD411D6F728200A80EE2 /* StringTools.swift */,
|
||||||
);
|
);
|
||||||
@ -1000,6 +989,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
97A9F6F51E2E990500F423AA /* JSInject.js in Resources */,
|
||||||
971A10811D022F74007FC62C /* Pic_P.png in Resources */,
|
971A10811D022F74007FC62C /* Pic_P.png in Resources */,
|
||||||
975227D01D022814001D1DDE /* LaunchScreen.storyboard in Resources */,
|
975227D01D022814001D1DDE /* LaunchScreen.storyboard in Resources */,
|
||||||
97F03CE21D2440470040D26E /* Search.storyboard in Resources */,
|
97F03CE21D2440470040D26E /* Search.storyboard in Resources */,
|
||||||
@ -1007,7 +997,6 @@
|
|||||||
971A10161D022872007FC62C /* Assets.xcassets in Resources */,
|
971A10161D022872007FC62C /* Assets.xcassets in Resources */,
|
||||||
97E850CB1D2DA5B300A9F688 /* About.html in Resources */,
|
97E850CB1D2DA5B300A9F688 /* About.html in Resources */,
|
||||||
97C601DC1D7F15C400362D4F /* Bookmark.storyboard in Resources */,
|
97C601DC1D7F15C400362D4F /* Bookmark.storyboard in Resources */,
|
||||||
974C49661DA307FF00E276E1 /* injection.js in Resources */,
|
|
||||||
975227CD1D0227E8001D1DDE /* Main.storyboard in Resources */,
|
975227CD1D0227E8001D1DDE /* Main.storyboard in Resources */,
|
||||||
975227CE1D0227E8001D1DDE /* Setting.storyboard in Resources */,
|
975227CE1D0227E8001D1DDE /* Setting.storyboard in Resources */,
|
||||||
971A10801D022F74007FC62C /* Pic_I.png in Resources */,
|
971A10801D022F74007FC62C /* Pic_I.png in Resources */,
|
||||||
@ -1104,7 +1093,6 @@
|
|||||||
97A1FD161D6F71CE00A80EE2 /* DirectoryMonitor.swift in Sources */,
|
97A1FD161D6F71CE00A80EE2 /* DirectoryMonitor.swift in Sources */,
|
||||||
9726591D1D90A64600D1DFFB /* Notifications.swift in Sources */,
|
9726591D1D90A64600D1DFFB /* Notifications.swift in Sources */,
|
||||||
971A102C1D022AD5007FC62C /* BarButtonItems.swift in Sources */,
|
971A102C1D022AD5007FC62C /* BarButtonItems.swift in Sources */,
|
||||||
97D0E98F1DDA12B30029530E /* MainDelegates.swift in Sources */,
|
|
||||||
970A2A221DD562CB0078BB7C /* BookOperations.swift in Sources */,
|
970A2A221DD562CB0078BB7C /* BookOperations.swift in Sources */,
|
||||||
97A1FD391D6F724E00A80EE2 /* pathTools.cpp in Sources */,
|
97A1FD391D6F724E00A80EE2 /* pathTools.cpp in Sources */,
|
||||||
972F81591DDC1B71008D7289 /* Controllers.swift in Sources */,
|
972F81591DDC1B71008D7289 /* Controllers.swift in Sources */,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user