mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-22 12:23:08 +09:00
174 lines
7.7 KiB
Swift
174 lines
7.7 KiB
Swift
/* 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 UIKit
|
|
import Shared
|
|
import Storage
|
|
import ReadingList
|
|
import WebKit
|
|
|
|
protocol TabPeekDelegate: class {
|
|
func tabPeekDidAddBookmark(_ tab: Tab)
|
|
@discardableResult func tabPeekDidAddToReadingList(_ tab: Tab) -> ReadingListClientRecord?
|
|
func tabPeekRequestsPresentationOf(_ viewController: UIViewController)
|
|
func tabPeekDidCloseTab(_ tab: Tab)
|
|
}
|
|
|
|
class TabPeekViewController: UIViewController, WKNavigationDelegate {
|
|
|
|
fileprivate static let PreviewActionAddToBookmarks = NSLocalizedString("Add to Bookmarks", tableName: "3DTouchActions", comment: "Label for preview action on Tab Tray Tab to add current tab to Bookmarks")
|
|
fileprivate static let PreviewActionAddToReadingList = NSLocalizedString("Add to Reading List", tableName: "3DTouchActions", comment: "Label for preview action on Tab Tray Tab to add current tab to Reading List")
|
|
fileprivate static let PreviewActionCopyURL = NSLocalizedString("Copy URL", tableName: "3DTouchActions", comment: "Label for preview action on Tab Tray Tab to copy the URL of the current tab to clipboard")
|
|
fileprivate static let PreviewActionCloseTab = NSLocalizedString("Close Tab", tableName: "3DTouchActions", comment: "Label for preview action on Tab Tray Tab to close the current tab")
|
|
|
|
weak var tab: Tab?
|
|
|
|
fileprivate weak var delegate: TabPeekDelegate?
|
|
fileprivate var clientPicker: UINavigationController?
|
|
fileprivate var isBookmarked: Bool = false
|
|
fileprivate var isInReadingList: Bool = false
|
|
fileprivate var hasRemoteClients: Bool = false
|
|
fileprivate var ignoreURL: Bool = false
|
|
|
|
fileprivate var screenShot: UIImageView?
|
|
fileprivate var previewAccessibilityLabel: String!
|
|
|
|
// Preview action items.
|
|
lazy var previewActions: [UIPreviewActionItem] = {
|
|
var actions = [UIPreviewActionItem]()
|
|
|
|
let urlIsTooLongToSave = self.tab?.urlIsTooLong ?? false
|
|
if !self.ignoreURL && !urlIsTooLongToSave {
|
|
if !self.isInReadingList {
|
|
actions.append(UIPreviewAction(title: TabPeekViewController.PreviewActionAddToReadingList, style: .default) { previewAction, viewController in
|
|
guard let tab = self.tab else { return }
|
|
_ = self.delegate?.tabPeekDidAddToReadingList(tab)
|
|
})
|
|
}
|
|
|
|
if !self.isBookmarked {
|
|
actions.append(UIPreviewAction(title: TabPeekViewController.PreviewActionAddToBookmarks, style: .default) { previewAction, viewController in
|
|
guard let tab = self.tab else { return }
|
|
self.delegate?.tabPeekDidAddBookmark(tab)
|
|
})
|
|
}
|
|
if self.hasRemoteClients {
|
|
actions.append(UIPreviewAction(title: Strings.SendToDeviceTitle, style: .default) { previewAction, viewController in
|
|
guard let clientPicker = self.clientPicker else { return }
|
|
self.delegate?.tabPeekRequestsPresentationOf(clientPicker)
|
|
})
|
|
}
|
|
// only add the copy URL action if we don't already have 3 items in our list
|
|
// as we are only allowed 4 in total and we always want to display close tab
|
|
if actions.count < 3 {
|
|
actions.append(UIPreviewAction(title: TabPeekViewController.PreviewActionCopyURL, style: .default) { previewAction, viewController in
|
|
guard let url = self.tab?.canonicalURL else { return }
|
|
UIPasteboard.general.url = url
|
|
SimpleToast().showAlertWithText(Strings.AppMenuCopyURLConfirmMessage, bottomContainer: self.view)
|
|
})
|
|
}
|
|
}
|
|
actions.append(UIPreviewAction(title: TabPeekViewController.PreviewActionCloseTab, style: .destructive) { previewAction, viewController in
|
|
guard let tab = self.tab else { return }
|
|
self.delegate?.tabPeekDidCloseTab(tab)
|
|
})
|
|
|
|
return actions
|
|
}()
|
|
|
|
init(tab: Tab, delegate: TabPeekDelegate?) {
|
|
self.tab = tab
|
|
self.delegate = delegate
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
if let webViewAccessibilityLabel = tab?.webView?.accessibilityLabel {
|
|
previewAccessibilityLabel = String(format: NSLocalizedString("Preview of %@", tableName: "3DTouchActions", comment: "Accessibility label, associated to the 3D Touch action on the current tab in the tab tray, used to display a larger preview of the tab."), webViewAccessibilityLabel)
|
|
}
|
|
// if there is no screenshot, load the URL in a web page
|
|
// otherwise just show the screenshot
|
|
setupWebView(tab?.webView)
|
|
guard let screenshot = tab?.screenshot else { return }
|
|
setupWithScreenshot(screenshot)
|
|
}
|
|
|
|
fileprivate func setupWithScreenshot(_ screenshot: UIImage) {
|
|
let imageView = UIImageView(image: screenshot)
|
|
self.view.addSubview(imageView)
|
|
|
|
imageView.snp.makeConstraints { make in
|
|
make.edges.equalTo(self.view)
|
|
}
|
|
|
|
screenShot = imageView
|
|
screenShot?.accessibilityLabel = previewAccessibilityLabel
|
|
}
|
|
|
|
fileprivate func setupWebView(_ webView: WKWebView?) {
|
|
guard let webView = webView, let url = webView.url, !isIgnoredURL(url) else { return }
|
|
let clonedWebView = WKWebView(frame: webView.frame, configuration: webView.configuration)
|
|
clonedWebView.allowsLinkPreview = false
|
|
webView.accessibilityLabel = previewAccessibilityLabel
|
|
self.view.addSubview(clonedWebView)
|
|
|
|
clonedWebView.snp.makeConstraints { make in
|
|
make.edges.equalTo(self.view)
|
|
}
|
|
|
|
clonedWebView.navigationDelegate = self
|
|
|
|
clonedWebView.load(URLRequest(url: url))
|
|
}
|
|
|
|
func setState(withProfile browserProfile: BrowserProfile, clientPickerDelegate: ClientPickerViewControllerDelegate) {
|
|
assert(Thread.current.isMainThread)
|
|
|
|
guard let tab = self.tab else {
|
|
return
|
|
}
|
|
|
|
guard let displayURL = tab.url?.absoluteString, displayURL.characters.count > 0 else {
|
|
return
|
|
}
|
|
|
|
let mainQueue = DispatchQueue.main
|
|
browserProfile.bookmarks.modelFactory >>== {
|
|
$0.isBookmarked(displayURL).uponQueue(mainQueue) {
|
|
self.isBookmarked = $0.successValue ?? false
|
|
}
|
|
}
|
|
|
|
browserProfile.remoteClientsAndTabs.getClientGUIDs().uponQueue(mainQueue) {
|
|
guard let clientGUIDs = $0.successValue else {
|
|
return
|
|
}
|
|
|
|
self.hasRemoteClients = !clientGUIDs.isEmpty
|
|
let clientPickerController = ClientPickerViewController()
|
|
clientPickerController.clientPickerDelegate = clientPickerDelegate
|
|
clientPickerController.profile = browserProfile
|
|
if let url = tab.url?.absoluteString {
|
|
clientPickerController.shareItem = ShareItem(url: url, title: tab.title, favicon: nil)
|
|
}
|
|
|
|
self.clientPicker = UINavigationController(rootViewController: clientPickerController)
|
|
}
|
|
|
|
let result = browserProfile.readingList?.getRecordWithURL(displayURL).successValue!
|
|
|
|
self.isInReadingList = (result?.url.characters.count ?? 0) > 0
|
|
self.ignoreURL = isIgnoredURL(displayURL)
|
|
}
|
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
screenShot?.removeFromSuperview()
|
|
screenShot = nil
|
|
}
|
|
}
|