diff --git a/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt b/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt index 811fdb9fd1..64cda0a19c 100644 --- a/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +++ b/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt @@ -11,6 +11,8 @@ class KeyboardControllerModule( override fun getName(): String = KeyboardControllerModuleImpl.NAME + override fun getTypedExportedConstants(): Map = module.getConstants() + override fun setInputMode(mode: Double) { module.setInputMode(mode.toInt()) } diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt b/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt index 0a5b7262e2..489b181c06 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/modules/KeyboardControllerModuleImpl.kt @@ -23,6 +23,7 @@ class KeyboardControllerModuleImpl( private val controller = KeyboardAnimationController() private val mDefaultMode: Int = getCurrentMode() + // region Module methods fun setInputMode(mode: Int) { setSoftInputMode(mode) } @@ -102,7 +103,9 @@ class KeyboardControllerModuleImpl( promise.resolve(map) } } + // endregion + // region Helpers private fun setSoftInputMode(mode: Int) { UiThreadUtil.runOnUiThread { if (getCurrentMode() != mode) { @@ -118,8 +121,13 @@ class KeyboardControllerModuleImpl( ?.attributes ?.softInputMode ?: WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED + // endregion + + // region Module constants + fun getConstants(): MutableMap = mutableMapOf("keyboardBorderRadius" to 0) companion object { const val NAME = "KeyboardController" } + // endregion } diff --git a/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt b/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt index f54f59566e..dcc66985b8 100644 --- a/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt +++ b/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerModule.kt @@ -13,6 +13,8 @@ class KeyboardControllerModule( override fun getName(): String = KeyboardControllerModuleImpl.NAME + override fun getConstants(): MutableMap = module.getConstants() + @ReactMethod fun setInputMode(mode: Int) { module.setInputMode(mode) diff --git a/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarAllButtonsEnabled.png b/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarAllButtonsEnabled.png index 9c3c44c5e0..02eb3abfff 100644 Binary files a/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarAllButtonsEnabled.png and b/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarAllButtonsEnabled.png differ diff --git a/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarFirstInputFocused.png b/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarFirstInputFocused.png index 457f225e1c..c8e39cd855 100644 Binary files a/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarFirstInputFocused.png and b/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarFirstInputFocused.png differ diff --git a/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarLastInputFocused.png b/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarLastInputFocused.png index c1c081c3df..794bb98dc8 100644 Binary files a/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarLastInputFocused.png and b/e2e/kit/assets/ios/iPhone 17 Pro/ToolbarLastInputFocused.png differ diff --git a/ios/KeyboardControllerModule.mm b/ios/KeyboardControllerModule.mm index 41d0a81ca1..e8a7ac3a6b 100644 --- a/ios/KeyboardControllerModule.mm +++ b/ios/KeyboardControllerModule.mm @@ -53,6 +53,18 @@ + (BOOL)requiresMainQueueSetup return NO; } +- (NSDictionary *)constantsToExport +{ + return @{ + @"keyboardBorderRadius" : @([KeyboardExtenderContainerView keyboardBorderRadius]), + }; +} + +- (NSDictionary *)getConstants +{ + return [self constantsToExport]; +} + #ifdef RCT_NEW_ARCH_ENABLED - (void)setDefaultMode #else diff --git a/ios/views/KeyboardExtenderContainerView.swift b/ios/views/KeyboardExtenderContainerView.swift index 4cafd0268a..0b4f18841a 100644 --- a/ios/views/KeyboardExtenderContainerView.swift +++ b/ios/views/KeyboardExtenderContainerView.swift @@ -9,16 +9,26 @@ import UIKit @objc public class KeyboardExtenderContainerView: NSObject { - @objc public static func create(frame: CGRect, contentView: UIView) -> UIView { + private static func usesModernKeyboard() -> Bool { #if canImport(UIKit.UIGlassEffect) if #available(iOS 26.0, *) { let requiresCompat = Bundle.main.object(forInfoDictionaryKey: "UIDesignRequiresCompatibility") as? Bool ?? false - if !requiresCompat { - return ModernContainerView(frame: frame, contentView: contentView) - } + return !requiresCompat } #endif + return false + } + + @objc public static func keyboardBorderRadius() -> CGFloat { + return usesModernKeyboard() ? 30 : 0 + } + @objc public static func create(frame: CGRect, contentView: UIView) -> UIView { + if usesModernKeyboard() { + if #available(iOS 26.0, *) { + return ModernContainerView(frame: frame, contentView: contentView) + } + } return LegacyContainerView(frame: frame, contentView: contentView) } } diff --git a/src/bindings.ts b/src/bindings.ts index 96e40ac91b..c968aa43a5 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -27,6 +27,9 @@ export const KeyboardControllerNative: KeyboardControllerNativeModule = { Promise.resolve({ x: 0, y: 0, width: 0, height: 0 }), addListener: NOOP, removeListeners: NOOP, + getConstants: () => ({ + keyboardBorderRadius: 0, + }), }; /** * An event emitter that provides a way to subscribe to next keyboard events: diff --git a/src/components/KeyboardToolbar/constants.ts b/src/components/KeyboardToolbar/constants.ts index 5ebe24b062..5ad47132d6 100644 --- a/src/components/KeyboardToolbar/constants.ts +++ b/src/components/KeyboardToolbar/constants.ts @@ -1,4 +1,4 @@ -import { Platform } from "react-native"; +import { KEYBOARD_BORDER_RADIUS } from "../../constants"; import type { HEX } from "./types"; @@ -10,6 +10,5 @@ export const TEST_ID_KEYBOARD_TOOLBAR_DONE = `${TEST_ID_KEYBOARD_TOOLBAR}.done`; export const KEYBOARD_TOOLBAR_HEIGHT = 42; export const DEFAULT_OPACITY: HEX = "FF"; -export const KEYBOARD_HAS_ROUNDED_CORNERS = - Platform.OS === "ios" && parseInt(Platform.Version, 10) >= 26; +export const KEYBOARD_HAS_ROUNDED_CORNERS = KEYBOARD_BORDER_RADIUS > 0; export const OPENED_OFFSET = KEYBOARD_HAS_ROUNDED_CORNERS ? -11 : 0; diff --git a/src/constants.ts b/src/constants.ts index 16904cff96..0884fe8cc7 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,3 +1,5 @@ +import { KeyboardControllerNative } from "./bindings"; + // copied from `android.view.WindowManager.LayoutParams` export enum AndroidSoftInputModes { SOFT_INPUT_ADJUST_NOTHING = 48, @@ -17,3 +19,5 @@ export enum AndroidSoftInputModes { SOFT_INPUT_STATE_UNSPECIFIED = 0, SOFT_INPUT_STATE_VISIBLE = 4, } +export const KEYBOARD_BORDER_RADIUS = + KeyboardControllerNative.getConstants().keyboardBorderRadius; diff --git a/src/specs/NativeKeyboardController.ts b/src/specs/NativeKeyboardController.ts index b0acdade2e..7a2bc67cd8 100644 --- a/src/specs/NativeKeyboardController.ts +++ b/src/specs/NativeKeyboardController.ts @@ -3,7 +3,9 @@ import { TurboModuleRegistry } from "react-native"; import type { TurboModule } from "react-native"; export interface Spec extends TurboModule { - readonly getConstants: () => {}; + readonly getConstants: () => { + keyboardBorderRadius: number; + }; // methods setInputMode(mode: number): void; diff --git a/src/types/module.ts b/src/types/module.ts index 86117d6b9a..0d60d5577a 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -130,4 +130,8 @@ export type KeyboardControllerNativeModule = { // native event module stuff addListener: (eventName: string) => void; removeListeners: (count: number) => void; + // constants + getConstants: () => { + keyboardBorderRadius: number; + }; };