chore: handle safe area insets better on android (skip e2e)
This commit is contained in:
BIN
.yarn/cache/react-native-safe-area-context-npm-5.4.0-835ad1d4d4-7d7f9a8278.zip
vendored
Normal file
BIN
.yarn/cache/react-native-safe-area-context-npm-5.4.0-835ad1d4d4-7d7f9a8278.zip
vendored
Normal file
Binary file not shown.
@@ -1261,6 +1261,72 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
|
- react-native-safe-area-context (5.4.0):
|
||||||
|
- DoubleConversion
|
||||||
|
- glog
|
||||||
|
- hermes-engine
|
||||||
|
- RCT-Folly (= 2024.11.18.00)
|
||||||
|
- RCTRequired
|
||||||
|
- RCTTypeSafety
|
||||||
|
- React-Core
|
||||||
|
- React-debug
|
||||||
|
- React-Fabric
|
||||||
|
- React-featureflags
|
||||||
|
- React-graphics
|
||||||
|
- React-ImageManager
|
||||||
|
- react-native-safe-area-context/common (= 5.4.0)
|
||||||
|
- react-native-safe-area-context/fabric (= 5.4.0)
|
||||||
|
- React-NativeModulesApple
|
||||||
|
- React-RCTFabric
|
||||||
|
- React-rendererdebug
|
||||||
|
- React-utils
|
||||||
|
- ReactCodegen
|
||||||
|
- ReactCommon/turbomodule/bridging
|
||||||
|
- ReactCommon/turbomodule/core
|
||||||
|
- Yoga
|
||||||
|
- react-native-safe-area-context/common (5.4.0):
|
||||||
|
- DoubleConversion
|
||||||
|
- glog
|
||||||
|
- hermes-engine
|
||||||
|
- RCT-Folly (= 2024.11.18.00)
|
||||||
|
- RCTRequired
|
||||||
|
- RCTTypeSafety
|
||||||
|
- React-Core
|
||||||
|
- React-debug
|
||||||
|
- React-Fabric
|
||||||
|
- React-featureflags
|
||||||
|
- React-graphics
|
||||||
|
- React-ImageManager
|
||||||
|
- React-NativeModulesApple
|
||||||
|
- React-RCTFabric
|
||||||
|
- React-rendererdebug
|
||||||
|
- React-utils
|
||||||
|
- ReactCodegen
|
||||||
|
- ReactCommon/turbomodule/bridging
|
||||||
|
- ReactCommon/turbomodule/core
|
||||||
|
- Yoga
|
||||||
|
- react-native-safe-area-context/fabric (5.4.0):
|
||||||
|
- DoubleConversion
|
||||||
|
- glog
|
||||||
|
- hermes-engine
|
||||||
|
- RCT-Folly (= 2024.11.18.00)
|
||||||
|
- RCTRequired
|
||||||
|
- RCTTypeSafety
|
||||||
|
- React-Core
|
||||||
|
- React-debug
|
||||||
|
- React-Fabric
|
||||||
|
- React-featureflags
|
||||||
|
- React-graphics
|
||||||
|
- React-ImageManager
|
||||||
|
- react-native-safe-area-context/common
|
||||||
|
- React-NativeModulesApple
|
||||||
|
- React-RCTFabric
|
||||||
|
- React-rendererdebug
|
||||||
|
- React-utils
|
||||||
|
- ReactCodegen
|
||||||
|
- ReactCommon/turbomodule/bridging
|
||||||
|
- ReactCommon/turbomodule/core
|
||||||
|
- Yoga
|
||||||
- react-native-version-info (1.1.1):
|
- react-native-version-info (1.1.1):
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-webview (13.13.5):
|
- react-native-webview (13.13.5):
|
||||||
@@ -1701,6 +1767,7 @@ DEPENDENCIES:
|
|||||||
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
|
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
|
||||||
- react-native-fingerprint-scanner (from `../node_modules/react-native-fingerprint-scanner`)
|
- react-native-fingerprint-scanner (from `../node_modules/react-native-fingerprint-scanner`)
|
||||||
- react-native-mmkv (from `../node_modules/react-native-mmkv`)
|
- react-native-mmkv (from `../node_modules/react-native-mmkv`)
|
||||||
|
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||||
- react-native-version-info (from `../node_modules/react-native-version-info`)
|
- react-native-version-info (from `../node_modules/react-native-version-info`)
|
||||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||||
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||||
@@ -1829,6 +1896,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/react-native-fingerprint-scanner"
|
:path: "../node_modules/react-native-fingerprint-scanner"
|
||||||
react-native-mmkv:
|
react-native-mmkv:
|
||||||
:path: "../node_modules/react-native-mmkv"
|
:path: "../node_modules/react-native-mmkv"
|
||||||
|
react-native-safe-area-context:
|
||||||
|
:path: "../node_modules/react-native-safe-area-context"
|
||||||
react-native-version-info:
|
react-native-version-info:
|
||||||
:path: "../node_modules/react-native-version-info"
|
:path: "../node_modules/react-native-version-info"
|
||||||
react-native-webview:
|
react-native-webview:
|
||||||
@@ -1952,6 +2021,7 @@ SPEC CHECKSUMS:
|
|||||||
React-microtasksnativemodule: b740ebae7fad70aa78bc24cc0dfc15ac9637b6eb
|
React-microtasksnativemodule: b740ebae7fad70aa78bc24cc0dfc15ac9637b6eb
|
||||||
react-native-fingerprint-scanner: 562585260768cad51ae48e4b505d28c8731aecfa
|
react-native-fingerprint-scanner: 562585260768cad51ae48e4b505d28c8731aecfa
|
||||||
react-native-mmkv: 24917f0685641ccfd37c9b7004b26c00551128be
|
react-native-mmkv: 24917f0685641ccfd37c9b7004b26c00551128be
|
||||||
|
react-native-safe-area-context: afcc2e2b3e78ae8ef90d81e658aacee34ebc27ea
|
||||||
react-native-version-info: f0b04e16111c4016749235ff6d9a757039189141
|
react-native-version-info: f0b04e16111c4016749235ff6d9a757039189141
|
||||||
react-native-webview: 5095dd03fc98a529e44a6bb81aed21062b5f879e
|
react-native-webview: 5095dd03fc98a529e44a6bb81aed21062b5f879e
|
||||||
React-NativeModulesApple: af0571ac115d09c9a669ed45ce6a4ca960598a2d
|
React-NativeModulesApple: af0571ac115d09c9a669ed45ce6a4ca960598a2d
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@notifee/react-native": "^9.1.8",
|
"@notifee/react-native": "^9.1.8",
|
||||||
|
"react-native-safe-area-context": "^5.4.0",
|
||||||
"react-native-store-review": "^0.4.3"
|
"react-native-store-review": "^0.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { MobileWebAppContainer } from './MobileWebAppContainer'
|
import { MobileWebAppContainer } from './MobileWebAppContainer'
|
||||||
|
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
||||||
const AppComponent: React.FC = () => {
|
|
||||||
return <MobileWebAppContainer />
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MobileWebApp = () => {
|
export const MobileWebApp = () => {
|
||||||
return <AppComponent />
|
return (
|
||||||
|
<SafeAreaProvider>
|
||||||
|
<MobileWebAppContainer />
|
||||||
|
</SafeAreaProvider>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { IsDev } from './Lib/Utils'
|
|||||||
import { ReceivedSharedItemsHandler } from './ReceivedSharedItemsHandler'
|
import { ReceivedSharedItemsHandler } from './ReceivedSharedItemsHandler'
|
||||||
import { ReviewService } from './ReviewService'
|
import { ReviewService } from './ReviewService'
|
||||||
import notifee, { EventType } from '@notifee/react-native'
|
import notifee, { EventType } from '@notifee/react-native'
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
|
|
||||||
const LoggingEnabled = IsDev
|
const LoggingEnabled = IsDev
|
||||||
|
|
||||||
@@ -96,6 +97,12 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
|||||||
// iOS handles this using the `willChangeFrame` event instead
|
// iOS handles this using the `willChangeFrame` event instead
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
fireKeyboardSizeChangeEvent(e)
|
fireKeyboardSizeChangeEvent(e)
|
||||||
|
webViewRef.current?.postMessage(
|
||||||
|
JSON.stringify({
|
||||||
|
reactNativeEvent: ReactNativeToWebEvent.KeyboardDidShow,
|
||||||
|
messageType: 'event',
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
device.reloadStatusBarStyle(false)
|
device.reloadStatusBarStyle(false)
|
||||||
})
|
})
|
||||||
@@ -344,14 +351,31 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
|
|||||||
receivedSharedItemsHandlerInstance.deinit()
|
receivedSharedItemsHandlerInstance.deinit()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const [didAppLaunch, setDidAppLaunch] = useState(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return device.addApplicationEventReceiver((event) => {
|
return device.addApplicationEventReceiver((event) => {
|
||||||
if (event === ApplicationEvent.Launched) {
|
if (event === ApplicationEvent.Launched) {
|
||||||
receivedSharedItemsHandler.current.setIsApplicationLaunched(true)
|
receivedSharedItemsHandler.current.setIsApplicationLaunched(true)
|
||||||
|
setDidAppLaunch(true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [device])
|
}, [device])
|
||||||
|
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
|
useEffect(() => {
|
||||||
|
if (!didAppLaunch) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
webViewRef.current?.postMessage(
|
||||||
|
JSON.stringify({
|
||||||
|
reactNativeEvent: ReactNativeToWebEvent.UpdateSafeAreaInsets,
|
||||||
|
messageType: 'event',
|
||||||
|
messageData: insets,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}, [didAppLaunch, insets])
|
||||||
|
|
||||||
const [didLoadEnd, setDidLoadEnd] = useState(false)
|
const [didLoadEnd, setDidLoadEnd] = useState(false)
|
||||||
|
|
||||||
if (showAndroidWebviewUpdatePrompt) {
|
if (showAndroidWebviewUpdatePrompt) {
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ export enum ReactNativeToWebEvent {
|
|||||||
KeyboardSizeChanged = 'KeyboardSizeChanged',
|
KeyboardSizeChanged = 'KeyboardSizeChanged',
|
||||||
KeyboardWillShow = 'KeyboardWillShow',
|
KeyboardWillShow = 'KeyboardWillShow',
|
||||||
KeyboardWillHide = 'KeyboardWillHide',
|
KeyboardWillHide = 'KeyboardWillHide',
|
||||||
|
KeyboardDidShow = 'KeyboardDidShow',
|
||||||
KeyboardDidHide = 'KeyboardDidHide',
|
KeyboardDidHide = 'KeyboardDidHide',
|
||||||
|
UpdateSafeAreaInsets = 'UpdateSafeAreaInsets',
|
||||||
ReceivedFile = 'ReceivedFile',
|
ReceivedFile = 'ReceivedFile',
|
||||||
ReceivedLink = 'ReceivedLink',
|
ReceivedLink = 'ReceivedLink',
|
||||||
ReceivedText = 'ReceivedText',
|
ReceivedText = 'ReceivedText',
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export interface WebApplicationInterface extends ApplicationInterface {
|
|||||||
isFloatingKeyboard: boolean
|
isFloatingKeyboard: boolean
|
||||||
}): void
|
}): void
|
||||||
handleMobileKeyboardDidHideEvent(): void
|
handleMobileKeyboardDidHideEvent(): void
|
||||||
|
handleUpdateSafeAreaInsets(insets: { top: number; bottom: number; left: number; right: number }): 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>
|
||||||
|
|||||||
@@ -361,6 +361,12 @@ export class WebApplication extends SNApplication implements WebApplicationInter
|
|||||||
setCustomViewportHeight(100, 'vh', true)
|
setCustomViewportHeight(100, 'vh', true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleUpdateSafeAreaInsets(insets: { top: number; bottom: number; left: number; right: number }) {
|
||||||
|
for (const [key, value] of Object.entries(insets)) {
|
||||||
|
document.documentElement.style.setProperty(`--safe-area-inset-${key}`, `${value}px`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleOpenFilePreviewEvent({ id }: { id: string }): void {
|
handleOpenFilePreviewEvent({ id }: { id: string }): void {
|
||||||
const file = this.items.findItem<FileItem>(id)
|
const file = this.items.findItem<FileItem>(id)
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { classNames } from '@standardnotes/snjs'
|
import { classNames } from '@standardnotes/snjs'
|
||||||
import { ButtonStyle, getColorsForPrimaryVariant } from '../Button/Button'
|
import { ButtonStyle, getColorsForPrimaryVariant } from '../Button/Button'
|
||||||
import Icon from '../Icon/Icon'
|
import Icon from '../Icon/Icon'
|
||||||
|
import { useAvailableSafeAreaPadding } from '@/Hooks/useSafeAreaPadding'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string
|
label: string
|
||||||
@@ -14,12 +15,15 @@ const PropertiesRequiredForFixedPositioningToWorkOnIOSSafari: React.CSSPropertie
|
|||||||
|
|
||||||
const FloatingAddButton = ({ label, style, onClick }: Props) => {
|
const FloatingAddButton = ({ label, style, onClick }: Props) => {
|
||||||
const buttonClasses = getColorsForPrimaryVariant(style)
|
const buttonClasses = getColorsForPrimaryVariant(style)
|
||||||
|
const { hasBottomInset } = useAvailableSafeAreaPadding()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'fixed bottom-6 right-6 z-editor-title-bar ml-3 flex h-15 w-15 cursor-pointer items-center',
|
'fixed right-6 z-editor-title-bar ml-3 flex h-15 w-15 cursor-pointer items-center',
|
||||||
`justify-center rounded-full border border-solid border-transparent ${buttonClasses}`,
|
`justify-center rounded-full border border-solid border-transparent ${buttonClasses}`,
|
||||||
'hover:brightness-125',
|
'hover:brightness-125',
|
||||||
|
hasBottomInset ? 'bottom-[calc(var(--safe-area-inset-bottom)+0.5rem)]' : 'bottom-6',
|
||||||
)}
|
)}
|
||||||
title={label}
|
title={label}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import { ReactNativeToWebEvent } from '@standardnotes/snjs'
|
||||||
|
import { useApplication } from '@/Components/ApplicationProvider'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export const useAvailableSafeAreaPadding = () => {
|
export const useAvailableSafeAreaPadding = () => {
|
||||||
const documentStyle = getComputedStyle(document.documentElement)
|
const documentStyle = getComputedStyle(document.documentElement)
|
||||||
|
|
||||||
@@ -6,10 +10,22 @@ export const useAvailableSafeAreaPadding = () => {
|
|||||||
const bottom = parseInt(documentStyle.getPropertyValue('--safe-area-inset-bottom'))
|
const bottom = parseInt(documentStyle.getPropertyValue('--safe-area-inset-bottom'))
|
||||||
const left = parseInt(documentStyle.getPropertyValue('--safe-area-inset-left'))
|
const left = parseInt(documentStyle.getPropertyValue('--safe-area-inset-left'))
|
||||||
|
|
||||||
|
const application = useApplication()
|
||||||
|
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false)
|
||||||
|
useEffect(() => {
|
||||||
|
return application.addNativeMobileEventListener((event) => {
|
||||||
|
if (event === ReactNativeToWebEvent.KeyboardDidShow) {
|
||||||
|
setIsKeyboardVisible(true)
|
||||||
|
} else if (event === ReactNativeToWebEvent.KeyboardDidHide) {
|
||||||
|
setIsKeyboardVisible(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [application])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hasTopInset: !!top,
|
hasTopInset: !!top,
|
||||||
hasRightInset: !!right,
|
hasRightInset: !!right,
|
||||||
hasBottomInset: !!bottom,
|
hasBottomInset: !!bottom && !isKeyboardVisible,
|
||||||
hasLeftInset: !!left,
|
hasLeftInset: !!left,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ export class MobileWebReceiver {
|
|||||||
case ReactNativeToWebEvent.KeyboardDidHide:
|
case ReactNativeToWebEvent.KeyboardDidHide:
|
||||||
void this.application.handleMobileKeyboardDidHideEvent()
|
void this.application.handleMobileKeyboardDidHideEvent()
|
||||||
break
|
break
|
||||||
|
case ReactNativeToWebEvent.UpdateSafeAreaInsets:
|
||||||
|
void this.application.handleUpdateSafeAreaInsets(
|
||||||
|
messageData as { top: number; left: number; bottom: number; right: number },
|
||||||
|
)
|
||||||
|
break
|
||||||
case ReactNativeToWebEvent.ReceivedFile:
|
case ReactNativeToWebEvent.ReceivedFile:
|
||||||
void this.application.handleReceivedFileEvent(
|
void this.application.handleReceivedFileEvent(
|
||||||
messageData as {
|
messageData as {
|
||||||
|
|||||||
@@ -25,10 +25,10 @@
|
|||||||
|
|
||||||
--reach-checkbox: 1;
|
--reach-checkbox: 1;
|
||||||
|
|
||||||
--safe-area-inset-top: env(safe-area-inset-top, 0);
|
--safe-area-inset-top: 0;
|
||||||
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0);
|
--safe-area-inset-bottom: 0;
|
||||||
--safe-area-inset-left: env(safe-area-inset-left, 0);
|
--safe-area-inset-left: 0;
|
||||||
--safe-area-inset-right: env(safe-area-inset-right, 0);
|
--safe-area-inset-right: 0;
|
||||||
|
|
||||||
--sn-stylekit-font-size-editor: 0.9375rem;
|
--sn-stylekit-font-size-editor: 0.9375rem;
|
||||||
|
|
||||||
|
|||||||
11
yarn.lock
11
yarn.lock
@@ -8255,6 +8255,7 @@ __metadata:
|
|||||||
react-native-keychain: "standardnotes/react-native-keychain#4fd687461cecfa26d482d820ee43c0de61b964d4"
|
react-native-keychain: "standardnotes/react-native-keychain#4fd687461cecfa26d482d820ee43c0de61b964d4"
|
||||||
react-native-mmkv: ^3.2.0
|
react-native-mmkv: ^3.2.0
|
||||||
react-native-privacy-snapshot: "standardnotes/react-native-privacy-snapshot#653e904c90fc6f2b578da59138f2bfe5d7f942fe"
|
react-native-privacy-snapshot: "standardnotes/react-native-privacy-snapshot#653e904c90fc6f2b578da59138f2bfe5d7f942fe"
|
||||||
|
react-native-safe-area-context: ^5.4.0
|
||||||
react-native-share: ^12.0.9
|
react-native-share: ^12.0.9
|
||||||
react-native-store-review: ^0.4.3
|
react-native-store-review: ^0.4.3
|
||||||
react-native-version-info: ^1.1.1
|
react-native-version-info: ^1.1.1
|
||||||
@@ -24260,6 +24261,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"react-native-safe-area-context@npm:^5.4.0":
|
||||||
|
version: 5.4.0
|
||||||
|
resolution: "react-native-safe-area-context@npm:5.4.0"
|
||||||
|
peerDependencies:
|
||||||
|
react: "*"
|
||||||
|
react-native: "*"
|
||||||
|
checksum: 7d7f9a8278048650fd207d436798bd062d6f78d771cb0665b92aef69dba870251339e6812e1d669fd1958345288bd0f9ac98fbfe353c13958d18b58dc946c341
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-native-share@npm:^12.0.9":
|
"react-native-share@npm:^12.0.9":
|
||||||
version: 12.0.9
|
version: 12.0.9
|
||||||
resolution: "react-native-share@npm:12.0.9"
|
resolution: "react-native-share@npm:12.0.9"
|
||||||
|
|||||||
Reference in New Issue
Block a user