Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Fix #7686: Voice search not detecting sound #7727

Merged
merged 1 commit into from
Jul 13, 2023
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
5 changes: 3 additions & 2 deletions Sources/Brave/Frontend/Browser/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class BrowserViewController: UIViewController {

private(set) lazy var topToolbar: TopToolbarView = {
// Setup the URL bar, wrapped in a view to get transparency effect
let topToolbar = TopToolbarView()
let topToolbar = TopToolbarView(voiceSearchSupported: speechRecognizer.isVoiceSearchAvailable)
topToolbar.translatesAutoresizingMaskIntoConstraints = false
topToolbar.delegate = self
topToolbar.tabToolbarDelegate = self
Expand Down Expand Up @@ -145,7 +145,8 @@ public class BrowserViewController: UIViewController {
/// Voice Search
var voiceSearchViewController: PopupViewController<VoiceSearchInputView>?
var voiceSearchCancelable: AnyCancellable?

let speechRecognizer = SpeechRecognizer()

/// Custom Search Engine
var openSearchEngine: OpenSearchReference?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,6 @@ extension BrowserViewController: TopToolbarDelegate {

func topToolbarDidPressVoiceSearchButton(_ urlBar: TopToolbarView) {
Task { @MainActor in
let speechRecognizer = SpeechRecognizer()

onPendingRequestUpdatedCancellable = speechRecognizer.$finalizedRecognition.sink { [weak self] finalizedRecognition in
guard let self else { return }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class SpeechRecognizer: ObservableObject {
@Published private(set) var animationType: AnimationType = .pulse(scale: 1)

var isVoiceSearchAvailable: Bool {
if let recognizer, recognizer.isAvailable {
if let recognizer, recognizer.isAvailable, recognizer.supportsOnDeviceRecognition {
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class TabLocationView: UIView {
$0.accessibilityIdentifier = "TabToolbar.voiceSearchButton"
$0.isAccessibilityElement = true
$0.accessibilityLabel = Strings.tabToolbarVoiceSearchButtonAccessibilityLabel
$0.isHidden = !isVoiceSearchAvailable
$0.setImage(UIImage(braveSystemNamed: "leo.microphone", compatibleWith: nil), for: .normal)
$0.tintColor = .braveLabel
$0.addTarget(self, action: #selector(didTapVoiceSearchButton), for: .touchUpInside)
Expand Down Expand Up @@ -248,12 +249,16 @@ class TabLocationView: UIView {
$0.insetsLayoutMarginsFromSafeArea = false
}

override init(frame: CGRect) {
super.init(frame: frame)
private var isVoiceSearchAvailable: Bool

init(voiceSearchSupported: Bool) {
isVoiceSearchAvailable = voiceSearchSupported

super.init(frame: .zero)

backgroundColor = .braveBackground

self.tabObservers = registerFor(.didChangeContentBlocking, .didGainFocus, queue: .main)
tabObservers = registerFor(.didChangeContentBlocking, .didGainFocus, queue: .main)

longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(didLongPressLocationBar))
longPressRecognizer.delegate = self
Expand All @@ -264,7 +269,12 @@ class TabLocationView: UIView {
addGestureRecognizer(longPressRecognizer)
addGestureRecognizer(tapRecognizer)

let optionSubviews = [readerModeButton, walletButton, playlistButton, voiceSearchButton, reloadButton, separatorLine, shieldsButton, rewardsButton]
var optionSubviews: [UIView] = [readerModeButton, walletButton, playlistButton]
if isVoiceSearchAvailable {
optionSubviews.append(voiceSearchButton)
}
optionSubviews.append(contentsOf: [reloadButton, separatorLine, shieldsButton, rewardsButton])

optionSubviews.forEach {
($0 as? UIButton)?.contentEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
$0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
Expand Down Expand Up @@ -375,7 +385,7 @@ class TabLocationView: UIView {
urlTextField.text = URLFormatter.formatURL(url?.withoutWWW.absoluteString ?? "", formatTypes: [.omitDefaults], unescapeOptions: []).removeSchemeFromURLString(url?.scheme)

reloadButton.isHidden = url == nil
voiceSearchButton.isHidden = url != nil
voiceSearchButton.isHidden = (url != nil) || !isVoiceSearchAvailable
}

// MARK: Long Press Actions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class TopToolbarView: UIView, ToolbarProtocol {

private var locationTextField: AutocompleteTextField?

lazy var locationView = TabLocationView().then {
lazy var locationView = TabLocationView(voiceSearchSupported: isVoiceSearchAvailable).then {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.readerModeState = ReaderModeState.unavailable
$0.delegate = self
Expand Down Expand Up @@ -198,7 +198,7 @@ class TopToolbarView: UIView, ToolbarProtocol {

private var locationTextContentView: UIStackView?

private var qrCodeButton = ToolbarButton().then {
private lazy var qrCodeButton = ToolbarButton().then {
$0.accessibilityIdentifier = "TabToolbar.qrCodeButton"
$0.isAccessibilityElement = true
$0.accessibilityLabel = Strings.quickActionScanQRCode
Expand All @@ -211,12 +211,13 @@ class TopToolbarView: UIView, ToolbarProtocol {
$0.setContentHuggingPriority(.defaultHigh, for: .vertical)
}

private var voiceSearchButton = ToolbarButton().then {
private lazy var voiceSearchButton = ToolbarButton().then {
$0.accessibilityIdentifier = "TabToolbar.voiceSearchButton"
$0.isAccessibilityElement = true
$0.accessibilityLabel = Strings.tabToolbarVoiceSearchButtonAccessibilityLabel
$0.setImage(UIImage(braveSystemNamed: "leo.microphone", compatibleWith: nil), for: .normal)
$0.tintColor = .braveLabel
$0.isHidden = !isVoiceSearchAvailable
$0.contentEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
$0.setContentCompressionResistancePriority(.required, for: .horizontal)
$0.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
Expand All @@ -226,6 +227,7 @@ class TopToolbarView: UIView, ToolbarProtocol {

private lazy var locationBarOptionsStackView = UIStackView().then {
$0.alignment = .center
$0.isHidden = true
$0.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 3)
$0.isLayoutMarginsRelativeArrangement = true
$0.insetsLayoutMarginsFromSafeArea = false
Expand All @@ -238,12 +240,16 @@ class TopToolbarView: UIView, ToolbarProtocol {
$0.layer.cornerCurve = .continuous
$0.layer.masksToBounds = true
}

private var isVoiceSearchAvailable: Bool

// MARK: Lifecycle

override init(frame: CGRect) {
super.init(frame: frame)

init(voiceSearchSupported: Bool) {
isVoiceSearchAvailable = voiceSearchSupported

super.init(frame: .zero)

backgroundColor = Preferences.General.nightModeEnabled.value ? .nightModeBackground : .urlBarBackground

locationContainer.addSubview(locationView)
Expand Down Expand Up @@ -417,8 +423,12 @@ class TopToolbarView: UIView, ToolbarProtocol {
let dragInteraction = UIDragInteraction(delegate: self)
locationTextField.addInteraction(dragInteraction)

locationBarOptionsStackView.addArrangedSubview(qrCodeButton)
locationBarOptionsStackView.addArrangedSubview(voiceSearchButton)
if RecentSearchQRCodeScannerController.hasCameraSupport {
locationBarOptionsStackView.addArrangedSubview(qrCodeButton)
}
if isVoiceSearchAvailable {
locationBarOptionsStackView.addArrangedSubview(voiceSearchButton)
}

let subviews = [locationTextField, locationBarOptionsStackView]
locationTextContentView = UIStackView(arrangedSubviews: subviews).then {
Expand Down Expand Up @@ -513,11 +523,11 @@ class TopToolbarView: UIView, ToolbarProtocol {
func setLocation(_ location: String?, search: Bool) {
guard let text = location, !text.isEmpty else {
locationTextField?.text = location
updateLocationBarRightView(showQrCodeButton: true)
updateLocationBarRightView(showToolbarActions: true)
return
}

updateLocationBarRightView(showQrCodeButton: false)
updateLocationBarRightView(showToolbarActions: false)

if search {
locationTextField?.text = text
Expand Down Expand Up @@ -620,14 +630,20 @@ class TopToolbarView: UIView, ToolbarProtocol {
layoutIfNeeded()
}

private func updateLocationBarRightView(showQrCodeButton: Bool) {
private func updateLocationBarRightView(showToolbarActions: Bool) {
locationBarOptionsStackView.isHidden = !showToolbarActions

if RecentSearchQRCodeScannerController.hasCameraSupport {
qrCodeButton.isHidden = !showQrCodeButton
qrCodeButton.isHidden = !showToolbarActions
} else {
qrCodeButton.isHidden = true
}

locationBarOptionsStackView.isHidden = !showQrCodeButton
if isVoiceSearchAvailable {
voiceSearchButton.isHidden = !showToolbarActions
} else {
voiceSearchButton.isHidden = true
}
}

/// Update the shields icon based on whether or not shields are enabled for this site
Expand Down Expand Up @@ -787,27 +803,27 @@ extension TopToolbarView: AutocompleteTextFieldDelegate {

func autocompleteTextField(_ autocompleteTextField: AutocompleteTextField, didEnterText text: String) {
delegate?.topToolbar(self, didEnterText: text)
updateLocationBarRightView(showQrCodeButton: text.isEmpty)
updateLocationBarRightView(showToolbarActions: text.isEmpty)
}

func autocompleteTextField(_ autocompleteTextField: AutocompleteTextField, didDeleteAutoSelectedText text: String) {
updateLocationBarRightView(showQrCodeButton: text.isEmpty)
updateLocationBarRightView(showToolbarActions: text.isEmpty)
}

func autocompleteTextFieldDidBeginEditing(_ autocompleteTextField: AutocompleteTextField) {
autocompleteTextField.highlightAll()
updateLocationBarRightView(showQrCodeButton: locationView.urlTextField.text?.isEmpty == true)
updateLocationBarRightView(showToolbarActions: locationView.urlTextField.text?.isEmpty == true)
}

func autocompleteTextFieldShouldClear(_ autocompleteTextField: AutocompleteTextField) -> Bool {
delegate?.topToolbar(self, didEnterText: "")
updateLocationBarRightView(showQrCodeButton: true)
updateLocationBarRightView(showToolbarActions: true)
return true
}

func autocompleteTextFieldDidCancel(_ autocompleteTextField: AutocompleteTextField) {
leaveOverlayMode(didCancel: true)
updateLocationBarRightView(showQrCodeButton: false)
updateLocationBarRightView(showToolbarActions: false)
}
}

Expand Down