Skip to content

Commit

Permalink
Autofocus emoji search and send the first result with the return key …
Browse files Browse the repository at this point in the history
…on macOS. (#3644)

* Autofocus emoji search and send the first result with the return key on macOS.

* Add an extra condition to make sure the user has entered a search string before sending.
  • Loading branch information
pixlwave authored Dec 20, 2024
1 parent 888a61a commit 365797c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 4 deletions.
38 changes: 34 additions & 4 deletions ElementX/Sources/Other/SwiftUI/Search.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Please see LICENSE in the repository root for full details.
//

import GameController
import SwiftUI
import SwiftUIIntrospect

Expand Down Expand Up @@ -165,7 +166,18 @@ private struct SearchController: UIViewControllerRepresentable {

// MARK: - Searchable Extensions

struct IsSearchingModifier: ViewModifier {
extension View {
func isSearching(_ isSearching: Binding<Bool>) -> some View {
modifier(IsSearchingModifier(isSearching: isSearching))
}

/// Automatically focusses the view's search field if a hardware keyboard is connected.
func focusSearchIfHardwareKeyboardAvailable() -> some View {
modifier(FocusSearchIfHardwareKeyboardAvailableModifier())
}
}

private struct IsSearchingModifier: ViewModifier {
@Environment(\.isSearching) private var isSearchingEnv
@Binding var isSearching: Bool

Expand All @@ -175,8 +187,26 @@ struct IsSearchingModifier: ViewModifier {
}
}

extension View {
func isSearching(_ isSearching: Binding<Bool>) -> some View {
modifier(IsSearchingModifier(isSearching: isSearching))
private struct FocusSearchIfHardwareKeyboardAvailableModifier: ViewModifier {
@FocusState private var isFocused

func body(content: Content) -> some View {
if #available(iOS 18.0, *) {
content
.searchFocused($isFocused)
.onAppear(perform: focusIfHardwareKeyboardAvailable)
} else {
content
}
}

func focusIfHardwareKeyboardAvailable() {
// The simulator always detects the hardware keyboard as connected
#if !targetEnvironment(simulator)
if GCKeyboard.coalesced != nil {
MXLog.info("Hardware keyboard is connected")
isFocused = true
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct EmojiPickerScreen: View {
.toolbar { toolbar }
.isSearching($isSearching)
.searchable(text: $searchString, placement: .navigationBarDrawer(displayMode: .always))
.focusSearchIfHardwareKeyboardAvailable()
.onSubmit(of: .search, sendFirstEmojiOnMac)
.compoundSearchField()
}
.presentationDetents([.medium, .large])
Expand All @@ -76,6 +78,15 @@ struct EmojiPickerScreen: View {
}
}
}

func sendFirstEmojiOnMac() {
// No sure-fire way to detect that the submit came from a h/w keyboard on iOS/iPadOS.
guard ProcessInfo.processInfo.isiOSAppOnMac else { return }

if !searchString.isBlank, let emoji = context.viewState.categories.first?.emojis.first {
context.send(viewAction: .emojiTapped(emoji: emoji))
}
}
}

// MARK: - Previews
Expand Down

0 comments on commit 365797c

Please sign in to comment.