Skip to content

Commit

Permalink
feat: appearance (#723)
Browse files Browse the repository at this point in the history
## 📜 Description

Added `appearance` property to `KeyboardEventData`.

## 💡 Motivation and Context

If user uses `light` theme but prefer dark keyboard, then
`KeyboardToolbar` will be white (though it should be `dark` to match the
keyboard color). So I thought it will be useful to add this property
(additionally this property can be needed for
`KeyboardController.retain()` API).

On Android keyboard color is controlled via settings and the keyboard
color is not exposed through the public API. But on most of Android
devices keyboard color by default matches system settings, so in
`appearance` I expose system preference (this is the best what I can do
to try to match this).

## 📢 Changelog

<!-- High level overview of important changes -->
<!-- For example: fixed status bar manipulation; added new types
declarations; -->
<!-- If your changes don't affect one of platform/language below - then
remove this platform/language -->

### Docs

- added a reference about `appearance` property in `KeyboardEvents`
section;

### JS

- updated `KeyboardEventData` type;

### iOS

- added `UIKeyboardAppearance` extension;

### Android

- added `ReactThemedContext.appearance` extension;

## 🤔 How Has This Been Tested?

Tested manually on:
- iPhone 15 Pro
- Pixel 7 Pro (API 35).

## 📸 Screenshots (if appropriate):


![image](https://github.com/user-attachments/assets/54398782-2054-4a7c-8b41-8495532b50b1)

## 📝 Checklist

- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed
  • Loading branch information
kirillzyusko authored Dec 10, 2024
1 parent 76942c5 commit 4886f74
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.reactnativekeyboardcontroller.extensions

import android.content.Context
import android.os.Build
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
Expand Down Expand Up @@ -34,3 +36,19 @@ fun ThemedReactContext?.emitEvent(

Logger.i("ThemedReactContext", event)
}

val ThemedReactContext?.appearance: String
get() =
when {
this == null -> "default"
isSystemDarkMode(this) -> "dark"
else -> "light"
}

private fun isSystemDarkMode(context: Context): Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
(context.getSystemService(Context.UI_MODE_SERVICE) as? android.app.UiModeManager)
?.nightMode == android.app.UiModeManager.MODE_NIGHT_YES
} else {
false
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.facebook.react.views.textinput.ReactEditText
import com.facebook.react.views.view.ReactViewGroup
import com.reactnativekeyboardcontroller.constants.Keyboard
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
import com.reactnativekeyboardcontroller.extensions.appearance
import com.reactnativekeyboardcontroller.extensions.dispatchEvent
import com.reactnativekeyboardcontroller.extensions.dp
import com.reactnativekeyboardcontroller.extensions.emitEvent
Expand Down Expand Up @@ -428,6 +429,7 @@ class KeyboardAnimationCallback(
params.putDouble("timestamp", System.currentTimeMillis().toDouble())
params.putInt("target", viewTagFocused)
params.putString("type", FocusedInputHolder.get()?.keyboardType)
params.putString("appearance", context.appearance)

return params
}
Expand Down
1 change: 1 addition & 0 deletions docs/docs/api/keyboard-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type KeyboardEventData = {
timestamp: number; // timestamp of the event from native thread
target: number; // tag of the focused TextInput
type: string; // `keyboardType` property from focused `TextInput`
appearance: string; // `keyboardAppearance` property from focused `TextInput`
};
```

Expand Down
1 change: 1 addition & 0 deletions ios/events/KeyboardEventEmitterPayload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public func buildEventParams(_ height: Double, _ duration: Int, _ tag: NSNumber)
data["timestamp"] = Date.currentTimeStamp
data["target"] = tag
data["type"] = input?.keyboardType.name ?? "default"
data["appearance"] = input?.keyboardAppearance.name ?? "default"

return data
}
21 changes: 21 additions & 0 deletions ios/extensions/UIKeyboardAppearance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// UIKeyboardAppearance.swift
// Pods
//
// Created by Kiryl Ziusko on 08/12/2024.
//

import Foundation
import UIKit

public extension UIKeyboardAppearance {
var name: String {
switch self {
case .default: return "default"
case .dark: return "dark"
case .light: return "light"
@unknown default:
return "default"
}
}
}
1 change: 1 addition & 0 deletions ios/protocols/TextInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import UIKit

public protocol TextInput: AnyObject {
var keyboardType: UIKeyboardType { get }
var keyboardAppearance: UIKeyboardAppearance { get }
func focus()
}

Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ export type KeyboardEventData = {
duration: number;
timestamp: number;
target: number;
type: TextInputProps["keyboardType"];
type: NonNullable<TextInputProps["keyboardType"]>;
appearance: NonNullable<TextInputProps["keyboardAppearance"]>;
};
export type KeyboardEventsModule = {
addListener: (
Expand Down

0 comments on commit 4886f74

Please sign in to comment.