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

Commit

Permalink
Fix #7686: Voice search not detecting sound (#7727)
Browse files Browse the repository at this point in the history
  • Loading branch information
soner-yuksel authored Jul 13, 2023
1 parent dd57a16 commit 2b5091e
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 28 deletions.
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
52 changes: 34 additions & 18 deletions Sources/Brave/Frontend/Browser/Toolbars/UrlBar/TopToolbarView.swift
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

0 comments on commit 2b5091e

Please sign in to comment.