mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 17:31:47 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
232
mobile/ios/Client/Frontend/Browser/OpenInHelper.swift
Normal file
232
mobile/ios/Client/Frontend/Browser/OpenInHelper.swift
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import Foundation
|
||||
import PassKit
|
||||
import WebKit
|
||||
import SnapKit
|
||||
|
||||
import Shared
|
||||
|
||||
import XCGLogger
|
||||
|
||||
private let log = Logger.browserLogger
|
||||
|
||||
struct OpenInViewUX {
|
||||
static let ViewHeight: CGFloat = 40.0
|
||||
static let TextFont = UIFont.systemFont(ofSize: 16)
|
||||
static let TextColor = UIColor(red: 74.0/255.0, green: 144.0/255.0, blue: 226.0/255.0, alpha: 1.0)
|
||||
static let TextOffset = -15
|
||||
static let OpenInString = NSLocalizedString("Open in…", comment: "String indicating that the file can be opened in another application on the device")
|
||||
}
|
||||
|
||||
enum MimeType: String {
|
||||
case PDF = "application/pdf"
|
||||
case PASS = "application/vnd.apple.pkpass"
|
||||
}
|
||||
|
||||
protocol OpenInHelper {
|
||||
init?(response: URLResponse)
|
||||
var openInView: UIView? { get set }
|
||||
func open()
|
||||
}
|
||||
|
||||
struct OpenIn {
|
||||
static let helpers: [OpenInHelper.Type] = [OpenPdfInHelper.self, OpenPassBookHelper.self, ShareFileHelper.self]
|
||||
|
||||
static func helperForResponse(_ response: URLResponse) -> OpenInHelper? {
|
||||
return helpers.flatMap { $0.init(response: response) }.first
|
||||
}
|
||||
}
|
||||
|
||||
class ShareFileHelper: NSObject, OpenInHelper {
|
||||
var openInView: UIView?
|
||||
|
||||
fileprivate var url: URL
|
||||
var pathExtension: String?
|
||||
|
||||
required init?(response: URLResponse) {
|
||||
guard let MIMEType = response.mimeType, !(MIMEType == MimeType.PASS.rawValue || MIMEType == MimeType.PDF.rawValue),
|
||||
let responseURL = response.url else { return nil }
|
||||
url = (responseURL as NSURL) as URL
|
||||
super.init()
|
||||
}
|
||||
|
||||
func open() {
|
||||
let alertController = UIAlertController(
|
||||
title: Strings.OpenInDownloadHelperAlertTitle,
|
||||
message: Strings.OpenInDownloadHelperAlertMessage,
|
||||
preferredStyle: UIAlertControllerStyle.alert)
|
||||
alertController.addAction( UIAlertAction(title: Strings.OpenInDownloadHelperAlertCancel, style: .cancel, handler: nil))
|
||||
alertController.addAction(UIAlertAction(title: Strings.OpenInDownloadHelperAlertConfirm, style: .default) { (action) in
|
||||
let objectsToShare = [self.url]
|
||||
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
|
||||
if let sourceView = self.openInView, let popoverController = activityVC.popoverPresentationController {
|
||||
popoverController.sourceView = sourceView
|
||||
popoverController.sourceRect = CGRect(origin: CGPoint(x: sourceView.bounds.midX, y: sourceView.bounds.maxY), size: .zero)
|
||||
popoverController.permittedArrowDirections = .up
|
||||
}
|
||||
UIApplication.shared.keyWindow?.rootViewController?.present(activityVC, animated: true, completion: nil)
|
||||
})
|
||||
UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
class OpenPassBookHelper: NSObject, OpenInHelper {
|
||||
var openInView: UIView?
|
||||
|
||||
fileprivate var url: URL
|
||||
|
||||
required init?(response: URLResponse) {
|
||||
guard let MIMEType = response.mimeType, MIMEType == MimeType.PASS.rawValue && PKAddPassesViewController.canAddPasses(),
|
||||
let responseURL = response.url else { return nil }
|
||||
url = responseURL
|
||||
super.init()
|
||||
}
|
||||
|
||||
func open() {
|
||||
guard let passData = try? Data(contentsOf: url) else { return }
|
||||
var error: NSError? = nil
|
||||
let pass = PKPass(data: passData, error: &error)
|
||||
if let _ = error {
|
||||
// display an error
|
||||
let alertController = UIAlertController(
|
||||
title: Strings.UnableToAddPassErrorTitle,
|
||||
message: Strings.UnableToAddPassErrorMessage,
|
||||
preferredStyle: UIAlertControllerStyle.alert)
|
||||
alertController.addAction(
|
||||
UIAlertAction(title: Strings.UnableToAddPassErrorDismiss, style: .cancel) { (action) in
|
||||
// Do nothing.
|
||||
})
|
||||
UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
|
||||
return
|
||||
}
|
||||
let passLibrary = PKPassLibrary()
|
||||
if passLibrary.containsPass(pass) {
|
||||
UIApplication.shared.openURL(pass.passURL!)
|
||||
} else {
|
||||
let addController = PKAddPassesViewController(pass: pass)
|
||||
UIApplication.shared.keyWindow?.rootViewController?.present(addController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class OpenPdfInHelper: NSObject, OpenInHelper, UIDocumentInteractionControllerDelegate {
|
||||
fileprivate var url: URL
|
||||
fileprivate var docController: UIDocumentInteractionController?
|
||||
fileprivate var openInURL: URL?
|
||||
|
||||
lazy var openInView: UIView? = getOpenInView(self)()
|
||||
|
||||
lazy var documentDirectory: URL = {
|
||||
return URL(string: NSTemporaryDirectory())!.appendingPathComponent("pdfs")
|
||||
}()
|
||||
|
||||
fileprivate var filepath: URL?
|
||||
|
||||
required init?(response: URLResponse) {
|
||||
guard let MIMEType = response.mimeType, MIMEType == MimeType.PDF.rawValue && UIApplication.shared.canOpenURL(URL(string: "itms-books:")!),
|
||||
let responseURL = response.url else { return nil }
|
||||
url = responseURL
|
||||
super.init()
|
||||
setFilePath(response.suggestedFilename ?? url.lastPathComponent )
|
||||
}
|
||||
|
||||
fileprivate func setFilePath(_ suggestedFilename: String) {
|
||||
var filename = suggestedFilename
|
||||
let pathExtension = filename.asURL?.pathExtension
|
||||
if pathExtension == nil {
|
||||
filename.append(".pdf")
|
||||
}
|
||||
filepath = documentDirectory.appendingPathComponent(filename)
|
||||
}
|
||||
|
||||
deinit {
|
||||
guard let url = openInURL else { return }
|
||||
let fileManager = FileManager.default
|
||||
do {
|
||||
try fileManager.removeItem(at: url)
|
||||
} catch {
|
||||
log.error("failed to delete file at \(url): \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func getOpenInView() -> OpenInView {
|
||||
let overlayView = OpenInView()
|
||||
|
||||
overlayView.openInButton.addTarget(self, action: #selector(OpenPdfInHelper.open), for: .touchUpInside)
|
||||
return overlayView
|
||||
}
|
||||
|
||||
func createDocumentControllerForURL(url: URL) {
|
||||
docController = UIDocumentInteractionController(url: url)
|
||||
docController?.delegate = self
|
||||
self.openInURL = url
|
||||
}
|
||||
|
||||
func createLocalCopyOfPDF() {
|
||||
guard let filePath = filepath else {
|
||||
log.error("failed to create proper URL")
|
||||
return
|
||||
}
|
||||
if docController == nil {
|
||||
// if we already have a URL but no document controller, just create the document controller
|
||||
if let url = openInURL {
|
||||
createDocumentControllerForURL(url: url)
|
||||
return
|
||||
}
|
||||
let contentsOfFile = try? Data(contentsOf: url)
|
||||
let fileManager = FileManager.default
|
||||
do {
|
||||
try fileManager.createDirectory(atPath: documentDirectory.absoluteString, withIntermediateDirectories: true, attributes: nil)
|
||||
if fileManager.createFile(atPath: filePath.absoluteString, contents: contentsOfFile, attributes: nil) {
|
||||
let openInURL = URL(fileURLWithPath: filePath.absoluteString)
|
||||
createDocumentControllerForURL(url: openInURL)
|
||||
} else {
|
||||
log.error("Unable to create local version of PDF file at \(filePath)")
|
||||
}
|
||||
} catch {
|
||||
log.error("Error on creating directory at \(self.documentDirectory)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func open() {
|
||||
createLocalCopyOfPDF()
|
||||
guard let _parentView = self.openInView!.superview, let docController = self.docController else { log.error("view doesn't have a superview so can't open anything"); return }
|
||||
// iBooks should be installed by default on all devices we care about, so regardless of whether or not there are other pdf-capable
|
||||
// apps on this device, if we can open in iBooks we can open this PDF
|
||||
// simulators do not have iBooks so the open in view will not work on the simulator
|
||||
if UIApplication.shared.canOpenURL(URL(string: "itms-books:")!) {
|
||||
log.info("iBooks installed: attempting to open pdf")
|
||||
docController.presentOpenInMenu(from: .zero, in: _parentView, animated: true)
|
||||
} else {
|
||||
log.info("iBooks is not installed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OpenInView: UIView {
|
||||
let openInButton = UIButton()
|
||||
|
||||
init() {
|
||||
super.init(frame: .zero)
|
||||
openInButton.setTitleColor(OpenInViewUX.TextColor, for: UIControlState.normal)
|
||||
openInButton.setTitle(OpenInViewUX.OpenInString, for: UIControlState.normal)
|
||||
openInButton.titleLabel?.font = OpenInViewUX.TextFont
|
||||
openInButton.sizeToFit()
|
||||
self.addSubview(openInButton)
|
||||
openInButton.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(self)
|
||||
make.height.equalTo(self)
|
||||
make.trailing.equalTo(self).offset(OpenInViewUX.TextOffset)
|
||||
}
|
||||
self.backgroundColor = UIColor.white
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue