fix: Android keyboard covering content

This commit is contained in:
Aman Harwara 2025-05-02 14:49:20 +05:30
parent 16df4d327c
commit aa12bd7e60
No known key found for this signature in database
6 changed files with 40 additions and 32 deletions

View file

@ -2,7 +2,7 @@
import { ApplicationEvent, ReactNativeToWebEvent } from '@standardnotes/snjs'
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 { WebView, WebViewMessageEvent } from 'react-native-webview'
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' }))
})
const keyboardShowListener = Keyboard.addListener('keyboardWillShow', () => {
const keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', () => {
device.reloadStatusBarStyle(false)
webViewRef.current?.postMessage(
JSON.stringify({
@ -78,43 +78,54 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
)
})
const keyboardHideListener = Keyboard.addListener('keyboardDidHide', () => {
device.reloadStatusBarStyle(false)
})
const keyboardWillChangeFrame = Keyboard.addListener('keyboardWillChangeFrame', (e) => {
const fireKeyboardSizeChangeEvent = (e: KeyboardEvent) => {
webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.KeyboardFrameWillChange,
reactNativeEvent: ReactNativeToWebEvent.KeyboardSizeChanged,
messageType: 'event',
messageData: {
height: e.endCoordinates.height,
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) => {
webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.KeyboardFrameDidChange,
messageType: 'event',
messageData: { height: e.endCoordinates.height, contentHeight: e.endCoordinates.screenY },
}),
)
const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
// iOS handles this using the `willChangeFrame` event instead
if (Platform.OS === 'android') {
webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.KeyboardDidHide,
messageType: 'event',
}),
)
}
device.reloadStatusBarStyle(false)
})
const keyboardWillChangeFrame = Keyboard.addListener('keyboardWillChangeFrame', (e) => {
fireKeyboardSizeChangeEvent(e)
})
return () => {
removeStateServiceListener()
removeBackHandlerServiceListener()
removeColorSchemeServiceListener()
keyboardShowListener.remove()
keyboardHideListener.remove()
keyboardWillChangeFrame.remove()
keyboardDidChangeFrame.remove()
keyboardWillShowListener.remove()
keyboardWillHideListener.remove()
keyboardDidShowListener.remove()
keyboardDidHideListener.remove()
keyboardWillChangeFrame.remove()
}
}, [webViewRef, stateService, device, androidBackHandlerService, colorSchemeService])

View file

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

View file

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

View file

@ -20,7 +20,7 @@ export interface WebApplicationInterface extends ApplicationInterface {
contentHeight: number
isFloatingKeyboard: boolean
}): void
handleMobileKeyboardDidChangeFrameEvent(frame: { height: number; contentHeight: number }): void
handleMobileKeyboardDidHideEvent(): void
handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void
handleReceivedTextEvent(item: { text: 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)
}
handleMobileKeyboardDidChangeFrameEvent(frame: { height: number; contentHeight: number }): void {
this.notifyWebEvent(WebAppEvent.MobileKeyboardDidChangeFrame, frame)
handleMobileKeyboardDidHideEvent(): void {
setCustomViewportHeight(100, 'vh', true)
}
handleOpenFilePreviewEvent({ id }: { id: string }): void {

View file

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