d1666345ae
adds a new expo-keyboard-language native module that reads the current keyboard language on iOS (via first responder's textInputMode) and Android (via InputMethodManager). iOS also gets real-time updates when the keyboard language changes. users opt in via Settings > Languages > "Automatically detect post language from keyboard" (native only, marked experimental). when enabled, the composer language tracks the keyboard language. users can override per-session by selecting a language manually, and re-enable auto mode via the "Automatic" item in the language menu. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
76 lines
1.9 KiB
Swift
76 lines
1.9 KiB
Swift
import ExpoModulesCore
|
|
|
|
public class ExpoKeyboardLanguageModule: Module {
|
|
public func definition() -> ModuleDefinition {
|
|
Name("ExpoKeyboardLanguage")
|
|
|
|
Events("onKeyboardLanguageChange")
|
|
|
|
Function("getCurrentKeyboardLanguage") {
|
|
return self.currentKeyboardLanguage()
|
|
}
|
|
|
|
OnStartObserving {
|
|
NotificationCenter.default.addObserver(
|
|
self,
|
|
selector: #selector(self.onInputModeOrResponderChange),
|
|
name: UITextInputMode.currentInputModeDidChangeNotification,
|
|
object: nil
|
|
)
|
|
NotificationCenter.default.addObserver(
|
|
self,
|
|
selector: #selector(self.onInputModeOrResponderChange),
|
|
name: UIResponder.keyboardDidShowNotification,
|
|
object: nil
|
|
)
|
|
}
|
|
|
|
OnStopObserving {
|
|
NotificationCenter.default.removeObserver(
|
|
self,
|
|
name: UITextInputMode.currentInputModeDidChangeNotification,
|
|
object: nil
|
|
)
|
|
NotificationCenter.default.removeObserver(
|
|
self,
|
|
name: UIResponder.keyboardDidShowNotification,
|
|
object: nil
|
|
)
|
|
}
|
|
}
|
|
|
|
private var lastLanguage: String?
|
|
|
|
@objc
|
|
private func onInputModeOrResponderChange() {
|
|
let language = currentKeyboardLanguage()
|
|
if language != lastLanguage {
|
|
lastLanguage = language
|
|
sendEvent("onKeyboardLanguageChange", [
|
|
"language": language as Any
|
|
])
|
|
}
|
|
}
|
|
|
|
private func currentKeyboardLanguage() -> String? {
|
|
let keyWindow = UIApplication.shared.connectedScenes
|
|
.compactMap { $0 as? UIWindowScene }
|
|
.flatMap { $0.windows }
|
|
.first { $0.isKeyWindow }
|
|
|
|
return keyWindow?.findFirstResponder()?.textInputMode?.primaryLanguage
|
|
}
|
|
}
|
|
|
|
private extension UIView {
|
|
func findFirstResponder() -> UIView? {
|
|
if isFirstResponder { return self }
|
|
for subview in subviews {
|
|
if let found = subview.findFirstResponder() {
|
|
return found
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
}
|