Add expo-keyboard-language native module
New Expo module that exposes keyboard language detection via a node handle. On iOS it resolves the React Native view tag to the underlying UITextField/UITextView and returns textInputMode.primaryLanguage (BCP 47 tag). Android and web return null for now. https://claude.ai/code/session_01AMCp4M56WtFPz1pZtwgcvx
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
group = 'expo.modules.keyboardlanguage'
|
||||||
|
version = '1.0.0'
|
||||||
|
|
||||||
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
||||||
|
apply from: expoModulesCorePlugin
|
||||||
|
applyKotlinExpoModulesCorePlugin()
|
||||||
|
useCoreDependencies()
|
||||||
|
useExpoPublishing()
|
||||||
|
|
||||||
|
def useManagedAndroidSdkVersions = false
|
||||||
|
if (useManagedAndroidSdkVersions) {
|
||||||
|
useDefaultAndroidSdkVersions()
|
||||||
|
} else {
|
||||||
|
buildscript {
|
||||||
|
ext.safeExtGet = { prop, fallback ->
|
||||||
|
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project.android {
|
||||||
|
compileSdkVersion safeExtGet("compileSdkVersion", 34)
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
||||||
|
targetSdkVersion safeExtGet("targetSdkVersion", 34)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace "expo.modules.keyboardlanguage"
|
||||||
|
defaultConfig {
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0.0"
|
||||||
|
}
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package expo.modules.keyboardlanguage
|
||||||
|
|
||||||
|
import expo.modules.kotlin.modules.Module
|
||||||
|
import expo.modules.kotlin.modules.ModuleDefinition
|
||||||
|
|
||||||
|
class ExpoKeyboardLanguageModule : Module() {
|
||||||
|
override fun definition() =
|
||||||
|
ModuleDefinition {
|
||||||
|
Name("ExpoKeyboardLanguage")
|
||||||
|
|
||||||
|
Function("getKeyboardLanguage") { _: Int ->
|
||||||
|
return@Function null as String?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"platforms": ["ios", "android"],
|
||||||
|
"ios": {
|
||||||
|
"modules": ["ExpoKeyboardLanguageModule"]
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"modules": ["expo.modules.keyboardlanguage.ExpoKeyboardLanguageModule"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export {getKeyboardLanguage} from './src/ExpoKeyboardLanguage'
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = 'ExpoKeyboardLanguage'
|
||||||
|
s.version = '1.0.0'
|
||||||
|
s.summary = 'Get keyboard language for a text input'
|
||||||
|
s.description = 'Get the keyboard language (textInputMode) for a specific text input by node handle'
|
||||||
|
s.author = 'bluesky-social'
|
||||||
|
s.homepage = 'https://github.com/bluesky-social/social-app'
|
||||||
|
s.platforms = { :ios => '13.4', :tvos => '13.4' }
|
||||||
|
s.source = { git: '' }
|
||||||
|
s.static_framework = true
|
||||||
|
|
||||||
|
s.dependency 'ExpoModulesCore'
|
||||||
|
|
||||||
|
s.pod_target_xcconfig = {
|
||||||
|
'DEFINES_MODULE' => 'YES',
|
||||||
|
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
||||||
|
}
|
||||||
|
|
||||||
|
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
||||||
|
end
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import ExpoModulesCore
|
||||||
|
|
||||||
|
public class ExpoKeyboardLanguageModule: Module {
|
||||||
|
public func definition() -> ModuleDefinition {
|
||||||
|
Name("ExpoKeyboardLanguage")
|
||||||
|
|
||||||
|
Function("getKeyboardLanguage") { (nodeHandle: Int) -> String? in
|
||||||
|
guard let view = self.appContext?.findView(withTag: nodeHandle, ofType: UIView.self) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let textInput = self.findTextInput(in: view) {
|
||||||
|
return textInput.textInputMode?.primaryLanguage
|
||||||
|
}
|
||||||
|
|
||||||
|
return view.textInputMode?.primaryLanguage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func findTextInput(in view: UIView) -> UIView? {
|
||||||
|
if view is UITextField || view is UITextView {
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
for subview in view.subviews {
|
||||||
|
if let found = findTextInput(in: subview) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import {requireNativeModule} from 'expo-modules-core'
|
||||||
|
|
||||||
|
const NativeModule = requireNativeModule('ExpoKeyboardLanguage')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the keyboard language (BCP 47 tag) for the text input identified
|
||||||
|
* by the given node handle. Returns `null` when unavailable.
|
||||||
|
*/
|
||||||
|
export function getKeyboardLanguage(nodeHandle: number): string | null {
|
||||||
|
return NativeModule.getKeyboardLanguage(nodeHandle)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export function getKeyboardLanguage(_nodeHandle: number): string | null {
|
||||||
|
return null
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user