Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FXIOS-6047 - iOS No Longer Asking For Permission To Paste URL #20200

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2411,20 +2411,58 @@ class BrowserViewController: UIViewController,

extension BrowserViewController: ClipboardBarDisplayHandlerDelegate {
func shouldDisplay(clipBoardURL url: URL) {
let viewModel = ButtonToastViewModel(labelText: .GoToCopiedLink,
descriptionText: url.absoluteDisplayString,
buttonText: .GoButtonTittle)
let toast = ButtonToast(viewModel: viewModel,
theme: currentTheme(),
completion: { [weak self] buttonPressed in
if buttonPressed {
let isPrivate = self?.tabManager.selectedTab?.isPrivate ?? false
self?.openURLInNewTab(url, isPrivate: isPrivate)
let viewModel = ButtonToastViewModel(
labelText: .GoToCopiedLink,
descriptionText: url.absoluteDisplayString,
buttonText: .GoButtonTittle
)

let toast = ButtonToast(
viewModel: viewModel,
theme: currentTheme(),
completion: { [weak self] buttonPressed in
if buttonPressed {
let isPrivate = self?.tabManager.selectedTab?.isPrivate ?? false
self?.openURLInNewTab(url, isPrivate: isPrivate)
}
}
})
)

clipboardBarDisplayHandler?.clipboardToast = toast
show(toast: toast, duration: ClipboardBarDisplayHandler.UX.toastDelay)
}

@available(iOS 16.0, *)
func shouldDisplay() {
let viewModel = ButtonToastViewModel(
labelText: .GoToCopiedLink,
descriptionText: "",
buttonText: .GoButtonTittle
)

pasteConfiguration = UIPasteConfiguration(acceptableTypeIdentifiers: [UTType.url.identifier])

let toast = PasteControlToast(
viewModel: viewModel,
theme: currentTheme(),
target: self
)

clipboardBarDisplayHandler?.clipboardToast = toast
show(toast: toast, duration: ClipboardBarDisplayHandler.UX.toastDelay)
}

override func paste(itemProviders: [NSItemProvider]) {
for provider in itemProviders where provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) {
_ = provider.loadObject(ofClass: URL.self) { [weak self] url, error in
let isPrivate = self?.tabManager.selectedTab?.isPrivate ?? false

DispatchQueue.main.async {
self?.openURLInNewTab(url, isPrivate: isPrivate)
}
}
}
}
}

/**
Expand Down
53 changes: 53 additions & 0 deletions firefox-ios/Client/Frontend/Browser/ButtonToast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,56 @@ class ButtonToast: Toast {
dismiss(true)
}
}

@available(iOS 16.0, *)
class PasteControlToast: ButtonToast {
private var theme: Theme?
private var pasteControlTarget: UIViewController?

private lazy var pasteControl: UIPasteControl = {
let pasteControlConfig = UIPasteControl.Configuration()
pasteControlConfig.displayMode = .iconAndLabel
pasteControlConfig.baseForegroundColor = theme?.colors.textInverted
pasteControlConfig.baseBackgroundColor = theme?.colors.actionPrimary

let pasteControl = UIPasteControl(configuration: pasteControlConfig)
pasteControl.target = pasteControlTarget
pasteControl.translatesAutoresizingMaskIntoConstraints = false
pasteControl.layer.borderWidth = UX.buttonBorderWidth
pasteControl.layer.cornerRadius = UX.buttonBorderRadius
pasteControl.widthAnchor.constraint(equalToConstant: 90).isActive = true

return pasteControl
}()

init(viewModel: ButtonToastViewModel, theme: Theme?, target: UIViewController?) {
self.theme = theme
self.pasteControlTarget = target
super.init(viewModel: viewModel, theme: theme)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func setupPaddedButton(stackView: UIStackView, buttonText: String?) {
let paddedView = UIView()
paddedView.translatesAutoresizingMaskIntoConstraints = false
paddedView.addSubview(pasteControl)
stackView.addArrangedSubview(paddedView)

NSLayoutConstraint.activate([
pasteControl.centerYAnchor.constraint(equalTo: paddedView.centerYAnchor),
pasteControl.centerXAnchor.constraint(equalTo: paddedView.centerXAnchor),

paddedView.topAnchor.constraint(equalTo: stackView.topAnchor),
paddedView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor),
paddedView.widthAnchor.constraint(equalTo: pasteControl.widthAnchor, constant: UX.widthOffset)
])
}

override func applyTheme(theme: Theme) {
super.applyTheme(theme: theme)
pasteControl.layer.borderColor = theme.colors.borderInverted.cgColor
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import Shared

protocol ClipboardBarDisplayHandlerDelegate: AnyObject {
func shouldDisplay(clipBoardURL url: URL)

@available(iOS 16.0, *)
func shouldDisplay()
}

class ClipboardBarDisplayHandler: NSObject {
Expand All @@ -19,6 +22,7 @@ class ClipboardBarDisplayHandler: NSObject {
weak var tabManager: TabManager?
private var prefs: Prefs
private var lastDisplayedURL: String?
private var lastPasteBoardChangeCount: Int?
private weak var firstTab: Tab?
var clipboardToast: ButtonToast?
private let windowUUID: UUID
Expand Down Expand Up @@ -81,6 +85,14 @@ class ClipboardBarDisplayHandler: NSObject {
return true
}

private func shouldDisplayBar(_ pasteBoardChangeCount: Int) -> Bool {
if pasteBoardChangeCount == lastPasteBoardChangeCount ||
IntroScreenManager(prefs: prefs).shouldShowIntroScreen {
return false
}
return true
}

// If we already displayed this URL on the previous session, or in an already open
// tab, we shouldn't display it again
private func isClipboardURLAlreadyDisplayed(_ clipboardURL: String) -> Bool {
Expand All @@ -98,16 +110,31 @@ class ClipboardBarDisplayHandler: NSObject {

func checkIfShouldDisplayBar() {
// Clipboard bar feature needs to be enabled by users to be activated in the user settings
guard prefs.boolForKey("showClipboardBar") ?? false else { return }
guard
prefs.boolForKey("showClipboardBar") ?? false,
UIPasteboard.general.hasURLs
else { return }

if #available(iOS 16.0, *) {
let pasteBoardChangeCount = UIPasteboard.general.changeCount
guard shouldDisplayBar(pasteBoardChangeCount) else { return }

guard UIPasteboard.general.hasURLs,
let url = UIPasteboard.general.url,
shouldDisplayBar(url.absoluteString) else { return }
lastPasteBoardChangeCount = pasteBoardChangeCount

lastDisplayedURL = url.absoluteString
AppEventQueue.wait(for: [.startupFlowComplete, .tabRestoration(windowUUID)]) { [weak self] in
self?.delegate?.shouldDisplay()
}
} else {
guard
let url = UIPasteboard.general.url,
shouldDisplayBar(url.absoluteString)
else { return }

AppEventQueue.wait(for: [.startupFlowComplete, .tabRestoration(windowUUID)]) { [weak self] in
self?.delegate?.shouldDisplay(clipBoardURL: url)
lastDisplayedURL = url.absoluteString

AppEventQueue.wait(for: [.startupFlowComplete, .tabRestoration(windowUUID)]) { [weak self] in
self?.delegate?.shouldDisplay(clipBoardURL: url)
}
}
}
}