fix: Fixed issue with keyboard on Android covering content (#2899)

This commit is contained in:
Aman Harwara
2025-05-02 15:16:32 +05:30
committed by GitHub
parent 16df4d327c
commit c4e0138ce3
6 changed files with 40 additions and 32 deletions

View File

@@ -2,7 +2,7 @@
import { ApplicationEvent, ReactNativeToWebEvent } from '@standardnotes/snjs' import { ApplicationEvent, ReactNativeToWebEvent } from '@standardnotes/snjs'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Button, Dimensions, Keyboard, Platform, Text, View } from 'react-native' import { Button, Dimensions, Keyboard, KeyboardEvent, Platform, Text, View } from 'react-native'
import VersionInfo from 'react-native-version-info' import VersionInfo from 'react-native-version-info'
import { WebView, WebViewMessageEvent } from 'react-native-webview' import { WebView, WebViewMessageEvent } from 'react-native-webview'
import { OnShouldStartLoadWithRequest, WebViewNativeConfig } from 'react-native-webview/lib/WebViewTypes' import { OnShouldStartLoadWithRequest, WebViewNativeConfig } from 'react-native-webview/lib/WebViewTypes'
@@ -58,7 +58,7 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
webViewRef.current?.postMessage(JSON.stringify({ reactNativeEvent: event, messageType: 'event' })) webViewRef.current?.postMessage(JSON.stringify({ reactNativeEvent: event, messageType: 'event' }))
}) })
const keyboardShowListener = Keyboard.addListener('keyboardWillShow', () => { const keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', () => {
device.reloadStatusBarStyle(false) device.reloadStatusBarStyle(false)
webViewRef.current?.postMessage( webViewRef.current?.postMessage(
JSON.stringify({ JSON.stringify({
@@ -78,43 +78,54 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
) )
}) })
const keyboardHideListener = Keyboard.addListener('keyboardDidHide', () => { const fireKeyboardSizeChangeEvent = (e: KeyboardEvent) => {
device.reloadStatusBarStyle(false)
})
const keyboardWillChangeFrame = Keyboard.addListener('keyboardWillChangeFrame', (e) => {
webViewRef.current?.postMessage( webViewRef.current?.postMessage(
JSON.stringify({ JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.KeyboardFrameWillChange, reactNativeEvent: ReactNativeToWebEvent.KeyboardSizeChanged,
messageType: 'event', messageType: 'event',
messageData: { messageData: {
height: e.endCoordinates.height, height: e.endCoordinates.height,
contentHeight: e.endCoordinates.screenY, contentHeight: e.endCoordinates.screenY,
isFloatingKeyboard: e.endCoordinates.width !== Dimensions.get('window').width, isFloatingKeyboard: Math.floor(e.endCoordinates.width) !== Math.floor(Dimensions.get('window').width),
}, },
}), }),
) )
}
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', (e) => {
// iOS handles this using the `willChangeFrame` event instead
if (Platform.OS === 'android') {
fireKeyboardSizeChangeEvent(e)
}
device.reloadStatusBarStyle(false)
}) })
const keyboardDidChangeFrame = Keyboard.addListener('keyboardDidChangeFrame', (e) => { const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
webViewRef.current?.postMessage( // iOS handles this using the `willChangeFrame` event instead
JSON.stringify({ if (Platform.OS === 'android') {
reactNativeEvent: ReactNativeToWebEvent.KeyboardFrameDidChange, webViewRef.current?.postMessage(
messageType: 'event', JSON.stringify({
messageData: { height: e.endCoordinates.height, contentHeight: e.endCoordinates.screenY }, reactNativeEvent: ReactNativeToWebEvent.KeyboardDidHide,
}), messageType: 'event',
) }),
)
}
device.reloadStatusBarStyle(false)
})
const keyboardWillChangeFrame = Keyboard.addListener('keyboardWillChangeFrame', (e) => {
fireKeyboardSizeChangeEvent(e)
}) })
return () => { return () => {
removeStateServiceListener() removeStateServiceListener()
removeBackHandlerServiceListener() removeBackHandlerServiceListener()
removeColorSchemeServiceListener() removeColorSchemeServiceListener()
keyboardShowListener.remove() keyboardWillShowListener.remove()
keyboardHideListener.remove()
keyboardWillChangeFrame.remove()
keyboardDidChangeFrame.remove()
keyboardWillHideListener.remove() keyboardWillHideListener.remove()
keyboardDidShowListener.remove()
keyboardDidHideListener.remove()
keyboardWillChangeFrame.remove()
} }
}, [webViewRef, stateService, device, androidBackHandlerService, colorSchemeService]) }, [webViewRef, stateService, device, androidBackHandlerService, colorSchemeService])

View File

@@ -6,6 +6,5 @@ export enum WebAppEvent {
PanelResized = 'PanelResized', PanelResized = 'PanelResized',
WindowDidFocus = 'WindowDidFocus', WindowDidFocus = 'WindowDidFocus',
WindowDidBlur = 'WindowDidBlur', WindowDidBlur = 'WindowDidBlur',
MobileKeyboardDidChangeFrame = 'MobileKeyboardDidChangeFrame',
MobileKeyboardWillChangeFrame = 'MobileKeyboardWillChangeFrame', MobileKeyboardWillChangeFrame = 'MobileKeyboardWillChangeFrame',
} }

View File

@@ -5,10 +5,10 @@ export enum ReactNativeToWebEvent {
LosingFocus = 'LosingFocus', LosingFocus = 'LosingFocus',
AndroidBackButtonPressed = 'AndroidBackButtonPressed', AndroidBackButtonPressed = 'AndroidBackButtonPressed',
ColorSchemeChanged = 'ColorSchemeChanged', ColorSchemeChanged = 'ColorSchemeChanged',
KeyboardFrameWillChange = 'KeyboardFrameWillChange', KeyboardSizeChanged = 'KeyboardSizeChanged',
KeyboardFrameDidChange = 'KeyboardFrameDidChange',
KeyboardWillShow = 'KeyboardWillShow', KeyboardWillShow = 'KeyboardWillShow',
KeyboardWillHide = 'KeyboardWillHide', KeyboardWillHide = 'KeyboardWillHide',
KeyboardDidHide = 'KeyboardDidHide',
ReceivedFile = 'ReceivedFile', ReceivedFile = 'ReceivedFile',
ReceivedLink = 'ReceivedLink', ReceivedLink = 'ReceivedLink',
ReceivedText = 'ReceivedText', ReceivedText = 'ReceivedText',

View File

@@ -20,7 +20,7 @@ export interface WebApplicationInterface extends ApplicationInterface {
contentHeight: number contentHeight: number
isFloatingKeyboard: boolean isFloatingKeyboard: boolean
}): void }): void
handleMobileKeyboardDidChangeFrameEvent(frame: { height: number; contentHeight: number }): void handleMobileKeyboardDidHideEvent(): void
handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void
handleReceivedTextEvent(item: { text: string; title?: string }): Promise<void> handleReceivedTextEvent(item: { text: string; title?: string }): Promise<void>
handleReceivedLinkEvent(item: { link: string; title: string }): Promise<void> handleReceivedLinkEvent(item: { link: string; title: string }): Promise<void>

View File

@@ -357,8 +357,8 @@ export class WebApplication extends SNApplication implements WebApplicationInter
this.notifyWebEvent(WebAppEvent.MobileKeyboardWillChangeFrame, frame) this.notifyWebEvent(WebAppEvent.MobileKeyboardWillChangeFrame, frame)
} }
handleMobileKeyboardDidChangeFrameEvent(frame: { height: number; contentHeight: number }): void { handleMobileKeyboardDidHideEvent(): void {
this.notifyWebEvent(WebAppEvent.MobileKeyboardDidChangeFrame, frame) setCustomViewportHeight(100, 'vh', true)
} }
handleOpenFilePreviewEvent({ id }: { id: string }): void { handleOpenFilePreviewEvent({ id }: { id: string }): void {

View File

@@ -73,15 +73,13 @@ export class MobileWebReceiver {
case ReactNativeToWebEvent.ColorSchemeChanged: case ReactNativeToWebEvent.ColorSchemeChanged:
void this.application.handleMobileColorSchemeChangeEvent() void this.application.handleMobileColorSchemeChangeEvent()
break break
case ReactNativeToWebEvent.KeyboardFrameWillChange: case ReactNativeToWebEvent.KeyboardSizeChanged:
void this.application.handleMobileKeyboardWillChangeFrameEvent( void this.application.handleMobileKeyboardWillChangeFrameEvent(
messageData as { height: number; contentHeight: number; isFloatingKeyboard: boolean }, messageData as { height: number; contentHeight: number; isFloatingKeyboard: boolean },
) )
break break
case ReactNativeToWebEvent.KeyboardFrameDidChange: case ReactNativeToWebEvent.KeyboardDidHide:
void this.application.handleMobileKeyboardDidChangeFrameEvent( void this.application.handleMobileKeyboardDidHideEvent()
messageData as { height: number; contentHeight: number },
)
break break
case ReactNativeToWebEvent.ReceivedFile: case ReactNativeToWebEvent.ReceivedFile:
void this.application.handleReceivedFileEvent( void this.application.handleReceivedFileEvent(