Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/ExpoMessaging/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
{
"microphonePermission": "$(PRODUCT_NAME) would like to use your microphone for voice recording."
}
]
],
"./plugins/keyboardInsetMainActivityListener.js"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const { withMainActivity, createRunOncePlugin } = require('@expo/config-plugins');

const requiredImports = [
'import android.os.Build',
'import android.os.Bundle',
'import android.view.View',
'import androidx.core.view.ViewCompat',
'import androidx.core.view.WindowInsetsCompat',
'import androidx.core.view.updatePadding',
];

const customInsetHandler = `
if (Build.VERSION.SDK_INT >= 35) {
val rootView = findViewById<View>(android.R.id.content)

ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets ->
val bars = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
or WindowInsetsCompat.Type.displayCutout()
or WindowInsetsCompat.Type.ime()
)
rootView.updatePadding(
left = bars.left,
top = bars.top,
right = bars.right,
bottom = bars.bottom
)
WindowInsetsCompat.CONSUMED
}
}
`;

const withCustomMainActivity = (config) => {
return withMainActivity(config, (mod) => {
if (mod.modResults.language !== 'kt') {
throw new Error('MainActivity must be written in Kotlin for this plugin.');
}

let contents = mod.modResults.contents;

// Add missing imports
const packageLineMatch = contents.match(/^package\s+[^\n]+\n/);
if (packageLineMatch) {
const packageLine = packageLineMatch[0];
for (const imp of requiredImports) {
if (!contents.includes(imp)) {
contents = contents.replace(packageLine, packageLine + imp + '\n');
}
}
}

// Inject inside onCreate(), right after super.onCreate(null)
// Match the full onCreate method
const onCreateMethodRegex = /override fun onCreate\(savedInstanceState: Bundle\?\) \{([\s\S]*?)^\s*}/m;

// If the method exists and doesn't already contain a custom ViewCompat.setOnApplyWindowInsetsListener, inject it
if (onCreateMethodRegex.test(contents) && !contents.includes('ViewCompat.setOnApplyWindowInsetsListener')) {
contents = contents.replace(onCreateMethodRegex, (match, body) => {
// Inject after super.onCreate(null)
const modifiedBody = body.replace(
/super\.onCreate\(null\);?/,
(superLine) => `${superLine}\n${customInsetHandler}`
);

return `override fun onCreate(savedInstanceState: Bundle?) {\n${modifiedBody}\n}`;
});
}

mod.modResults.contents = contents;
return mod;
});
};

module.exports = createRunOncePlugin(
withCustomMainActivity,
'keyboard-inset-main-activity-listener-plugin',
'0.0.1'
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,38 @@ import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate

import android.os.Bundle
import android.os.Build
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding

class MainActivity : ReactActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(null)

if (Build.VERSION.SDK_INT >= 35) {
val rootView = findViewById<View>(android.R.id.content)


ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets ->
val bars = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
or WindowInsetsCompat.Type.displayCutout()
or WindowInsetsCompat.Type.ime() // adding the ime's height
)
rootView.updatePadding(
left = bars.left,
top = bars.top,
right = bars.right,
bottom = bars.bottom
)
WindowInsetsCompat.CONSUMED
}
}
}
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
Expand All @@ -18,4 +49,4 @@ class MainActivity : ReactActivity() {
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
}
8 changes: 4 additions & 4 deletions examples/SampleApp/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2425,7 +2425,7 @@ PODS:
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.10)
- SocketRocket (0.7.1)
- stream-chat-react-native (7.1.1):
- stream-chat-react-native (7.1.2):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -2777,7 +2777,7 @@ SPEC CHECKSUMS:
FirebaseRemoteConfigInterop: 7b74ceaa54e28863ed17fa39da8951692725eced
FirebaseSessions: eaa8ec037e7793769defe4201c20bd4d976f9677
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
GoogleAppMeasurement: 0dfca1a4b534d123de3945e28f77869d10d0d600
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
Expand All @@ -2787,7 +2787,7 @@ SPEC CHECKSUMS:
op-sqlite: 6a5255f36253697406618ceba5212d6572012a9d
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82
RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809
RCTDeprecation: c3e3f5b4ea83e7ff3bc86ce09e2a54b7affd687d
RCTRequired: ee438439880dffc9425930d1dd1a3c883ee6879c
RCTTypeSafety: fe728195791e1a0222aa83596a570cf377cd475e
Expand Down Expand Up @@ -2872,7 +2872,7 @@ SPEC CHECKSUMS:
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
stream-chat-react-native: 963e1146ba5f092aa8f6c59f4e20e431a9265a69
stream-chat-react-native: 45d46c6a3188edf8dfe9c85cd884457ccc232b74
Yoga: b2eaabf17044cd4273a661b14eb83f9fd2c90491

PODFILE CHECKSUM: 4f662370295f8f9cee909f1a4c59a614999a209d
Expand Down
4 changes: 2 additions & 2 deletions examples/SampleApp/src/screens/ThreadScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import { StyleSheet, View } from 'react-native';
import { Platform, StyleSheet, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import {
Channel,
Expand Down Expand Up @@ -79,7 +79,7 @@ export const ThreadScreen: React.FC<ThreadScreenProps> = ({
audioRecordingEnabled={true}
channel={channel}
enforceUniqueReaction
keyboardVerticalOffset={0}
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : -300}
thread={thread}
threadList
>
Expand Down
74 changes: 17 additions & 57 deletions examples/SampleApp/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1373,14 +1373,6 @@
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz#a73bab8eb491d7b8b7be2f0e6c310647835afe83"
integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==

"@gorhom/bottom-sheet@^5.1.1":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.1.1.tgz#43ecb9e7b4d4ca4b4cefdf3b6b497f7715f350bc"
integrity sha512-Y8FiuRmeZYaP+ZGQ0axDwWrrKqVp4ByYRs1D2fTJTxHMt081MHHRQsqmZ3SK7AFp3cSID+vTqnD8w/KAASpy+w==
dependencies:
"@gorhom/portal" "1.0.14"
invariant "^2.2.4"

"@gorhom/bottom-sheet@^5.1.6":
version "5.1.6"
resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.1.6.tgz#92365894ae4d4eefdbaa577408cfaf62463a9490"
Expand Down Expand Up @@ -3881,11 +3873,6 @@ data-view-byte-offset@^1.0.1:
es-errors "^1.3.0"
is-data-view "^1.0.1"

dayjs@1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.5.tgz#5600df4548fc2453b3f163ebb2abbe965ccfb986"
integrity sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==

dayjs@1.11.13, dayjs@^1.8.15:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
Expand Down Expand Up @@ -4067,7 +4054,7 @@ emittery@^0.13.1:
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==

emoji-regex@^10.3.0, emoji-regex@^10.4.0:
emoji-regex@^10.4.0:
version "10.4.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4"
integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==
Expand Down Expand Up @@ -5108,7 +5095,7 @@ hyochan-welcome@^1.0.0:
resolved "https://registry.yarnpkg.com/hyochan-welcome/-/hyochan-welcome-1.0.1.tgz#a949de8bc3c1e18fe096016bc273aa191c844971"
integrity sha512-WRZNH5grESkOXP/r7xc7TMhO9cUqxaJIuZcQDAjzHWs6viGP+sWtVbiBigxc9YVRrw3hnkESQWwzqg+oOga65A==

i18next@^21.10.0, i18next@^21.6.14:
i18next@^21.10.0:
version "21.10.0"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.10.0.tgz#85429af55fdca4858345d0e16b584ec29520197d"
integrity sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==
Expand Down Expand Up @@ -6197,7 +6184,7 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==

linkifyjs@^4.1.1, linkifyjs@^4.2.0:
linkifyjs@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.2.0.tgz#9dd30222b9cbabec9c950e725ec00031c7fa3f08"
integrity sha512-pCj3PrQyATaoTYKHrgWRF3SJwsm61udVh+vuls/Rl6SptiDhgE7ziUIudAedRY9QEfynmM7/RmLEfPUyw1HPCw==
Expand Down Expand Up @@ -6594,7 +6581,7 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447"
integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==

mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.34, mime-types@^2.1.35, mime-types@~2.1.24, mime-types@~2.1.34:
mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.35, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
Expand Down Expand Up @@ -7332,13 +7319,6 @@ react-native-svg@^15.12.0:
css-tree "^1.1.3"
warn-once "0.1.1"

react-native-url-polyfill@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz#c1763de0f2a8c22cc3e959b654c8790622b6ef6a"
integrity sha512-w9JfSkvpqqlix9UjDvJjm1EjSt652zVQ6iwCIj1cVVkwXf4jQhQgTNXY6EVTwuAmUjg6BC6k9RHCBynoLFo3IQ==
dependencies:
whatwg-url-without-unicode "8.0.0-3"

react-native-url-polyfill@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589"
Expand Down Expand Up @@ -7887,24 +7867,24 @@ statuses@~1.5.0:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==

stream-chat-react-native-core@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-7.1.1.tgz#b22faf35fa5defd24c730873aeba30c172556089"
integrity sha512-9AkSKWzywN2FfsMgDfeoCatr/qoG+zJzM2u5j3PU6WU7qIhZtM/7+2UB0WKAY7fA5MjaoMEzV1mBF+hILP1KOw==
stream-chat-react-native-core@7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-7.1.2.tgz#5870a1188ecbf8c3b705d74379d19ff77efce2c5"
integrity sha512-Ob+V8tt+7L+7BRkWyWbFlju6E/8MAoB/NUZ8ENtEEijq5QBNWnVvZctQSZuekIOVrfoP9EenlIOPadHnN/mvYA==
dependencies:
"@gorhom/bottom-sheet" "^5.1.1"
dayjs "1.10.5"
emoji-regex "^10.3.0"
i18next "^21.6.14"
"@gorhom/bottom-sheet" "^5.1.6"
dayjs "1.11.13"
emoji-regex "^10.4.0"
i18next "^21.10.0"
intl-pluralrules "^2.0.1"
linkifyjs "^4.1.1"
linkifyjs "^4.3.1"
lodash-es "4.17.21"
mime-types "^2.1.34"
mime-types "^2.1.35"
path "0.12.7"
react-native-markdown-package "1.8.2"
react-native-url-polyfill "^1.3.0"
stream-chat "^9.3.0"
use-sync-external-store "^1.4.0"
react-native-url-polyfill "^2.0.0"
stream-chat "^9.7.0"
use-sync-external-store "^1.5.0"

"stream-chat-react-native-core@link:../../package":
version "0.0.0"
Expand All @@ -7914,21 +7894,6 @@ stream-chat-react-native-core@7.1.1:
version "0.0.0"
uid ""

stream-chat@^9.3.0:
version "9.3.0"
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.3.0.tgz#35ca4db9e841eb92d07413ae156de0500ad77b23"
integrity sha512-S73B3HrvmQvJjq58Zjo50vh74juhsWsVRpT+OBjGAxSGxlA+ITkZ3vKs8Y/r2eDK7mBTMmX5QCruFaDJH5dRuw==
dependencies:
"@types/jsonwebtoken" "^9.0.8"
"@types/ws" "^8.5.14"
axios "^1.6.0"
base64-js "^1.5.1"
form-data "^4.0.0"
isomorphic-ws "^5.0.0"
jsonwebtoken "^9.0.2"
linkifyjs "^4.2.0"
ws "^8.18.1"

stream-chat@^9.7.0:
version "9.7.0"
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.7.0.tgz#8302a4dfd2b68115c57cd0a102976542a79cf132"
Expand Down Expand Up @@ -8391,11 +8356,6 @@ use-latest-callback@^0.2.3:
resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.3.tgz#2d644d3063040b9bc2d4c55bb525a13ae3de9e16"
integrity sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ==

use-sync-external-store@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc"
integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==

use-sync-external-store@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,38 @@ import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate

import android.os.Bundle
import android.os.Build
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding

class MainActivity : ReactActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(null)

if (Build.VERSION.SDK_INT >= 35) {
val rootView = findViewById<View>(android.R.id.content)


ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets ->
val bars = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
or WindowInsetsCompat.Type.displayCutout()
or WindowInsetsCompat.Type.ime() // adding the ime's height
)
rootView.updatePadding(
left = bars.left,
top = bars.top,
right = bars.right,
bottom = bars.bottom
)
WindowInsetsCompat.CONSUMED
}
}
}
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
Expand All @@ -18,4 +49,4 @@ class MainActivity : ReactActivity() {
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
}
Loading