snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { HeaderHeightContext } from '@react-navigation/elements';
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import {
|
||||
Keyboard,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
StatusBar,
|
||||
ViewStyle
|
||||
} from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
||||
import { StyleType } from '../../styles/functions.any';
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Adds bottom padding.
|
||||
*/
|
||||
addBottomPadding?: boolean;
|
||||
|
||||
/**
|
||||
* The children component(s) of the Modal, to be rendered.
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView content container.
|
||||
*/
|
||||
contentContainerStyle?: StyleType;
|
||||
|
||||
/**
|
||||
* Disable forced keyboard dismiss?
|
||||
*/
|
||||
disableForcedKeyboardDismiss?: boolean;
|
||||
|
||||
/**
|
||||
* Is a text input rendered at the bottom of the screen?
|
||||
*/
|
||||
hasBottomTextInput: boolean;
|
||||
|
||||
/**
|
||||
* Is the screen header having an extra height?
|
||||
*/
|
||||
hasExtraHeaderHeight?: boolean;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView.
|
||||
*/
|
||||
style?: StyleType;
|
||||
}
|
||||
|
||||
const JitsiKeyboardAvoidingView = (
|
||||
{
|
||||
addBottomPadding = true,
|
||||
children,
|
||||
contentContainerStyle,
|
||||
disableForcedKeyboardDismiss,
|
||||
hasBottomTextInput,
|
||||
hasExtraHeaderHeight,
|
||||
style
|
||||
}: IProps) => {
|
||||
// Default to 0 when outside a navigator.
|
||||
const headerHeight = useContext(HeaderHeightContext) ?? 0;
|
||||
const insets = useSafeAreaInsets();
|
||||
const [ bottomPadding, setBottomPadding ] = useState(insets.bottom);
|
||||
|
||||
useEffect(() => {
|
||||
// This useEffect is needed because insets are undefined at first for some reason
|
||||
// https://github.com/th3rdwave/react-native-safe-area-context/issues/54
|
||||
setBottomPadding(insets.bottom);
|
||||
}, [ insets.bottom ]);
|
||||
|
||||
|
||||
const extraHeaderHeight
|
||||
= hasExtraHeaderHeight ? headerHeight : 0;
|
||||
const extraBottomPadding
|
||||
= addBottomPadding ? bottomPadding : 0;
|
||||
const noNotchDevicePadding = extraBottomPadding || 10;
|
||||
const iosVerticalOffset
|
||||
= headerHeight + noNotchDevicePadding + extraHeaderHeight;
|
||||
const androidVerticalOffset = hasBottomTextInput
|
||||
? headerHeight + Number(StatusBar.currentHeight) : headerHeight;
|
||||
|
||||
// Tells the view what to do with taps
|
||||
const shouldSetResponse = useCallback(() => !disableForcedKeyboardDismiss, []);
|
||||
const onRelease = useCallback(() => Keyboard.dismiss(), []);
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
behavior = { 'padding' }
|
||||
contentContainerStyle = { contentContainerStyle as ViewStyle }
|
||||
enabled = { true }
|
||||
keyboardVerticalOffset = {
|
||||
Platform.OS === 'ios'
|
||||
? iosVerticalOffset
|
||||
: androidVerticalOffset
|
||||
}
|
||||
onResponderRelease = { onRelease }
|
||||
onStartShouldSetResponder = { shouldSetResponse }
|
||||
style = { style as ViewStyle }>
|
||||
{ children }
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default JitsiKeyboardAvoidingView;
|
||||
109
react/features/base/modal/components/JitsiScreen.tsx
Normal file
109
react/features/base/modal/components/JitsiScreen.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { Edge, SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
import { StyleType } from '../../styles/functions.any';
|
||||
import BaseTheme from '../../ui/components/BaseTheme.native';
|
||||
import { useKeyboardVisible } from '../hooks.native';
|
||||
|
||||
import JitsiKeyboardAvoidingView from './JitsiKeyboardAvoidingView';
|
||||
import styles from './styles';
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Adds bottom padding.
|
||||
*/
|
||||
addBottomPadding?: boolean;
|
||||
|
||||
/**
|
||||
* The children component(s) of the Modal, to be rendered.
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView content container.
|
||||
*/
|
||||
contentContainerStyle?: StyleType;
|
||||
|
||||
/**
|
||||
* Disabled forced keyboard dismiss?
|
||||
*/
|
||||
disableForcedKeyboardDismiss?: boolean;
|
||||
|
||||
/**
|
||||
* Optional function that renders a footer component, if needed.
|
||||
*/
|
||||
footerComponent?: React.ComponentType<any> | (() => React.ReactNode);
|
||||
|
||||
/**
|
||||
* Extra bottom padding applied to the footer when keyboard is visible.
|
||||
*/
|
||||
footerKeyboardSpacing?: number;
|
||||
|
||||
/**
|
||||
* Is a text input rendered at the bottom of the screen?
|
||||
*/
|
||||
hasBottomTextInput?: boolean;
|
||||
|
||||
/**
|
||||
* Is the screen header having an extra height?
|
||||
*/
|
||||
hasExtraHeaderHeight?: boolean;
|
||||
|
||||
/**
|
||||
* Insets for the SafeAreaView.
|
||||
*/
|
||||
safeAreaInsets?: Edge[];
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView containing the content of the modal.
|
||||
*/
|
||||
style?: StyleType;
|
||||
}
|
||||
|
||||
const JitsiScreen = ({
|
||||
addBottomPadding,
|
||||
contentContainerStyle,
|
||||
children,
|
||||
disableForcedKeyboardDismiss = false,
|
||||
footerComponent,
|
||||
footerKeyboardSpacing = BaseTheme.spacing[3],
|
||||
hasBottomTextInput = false,
|
||||
hasExtraHeaderHeight = false,
|
||||
safeAreaInsets = [ 'bottom', 'left', 'right' ],
|
||||
style
|
||||
}: IProps) => {
|
||||
const keyboardVisible = useKeyboardVisible();
|
||||
const FooterComponent = footerComponent as React.ComponentType<any> | undefined;
|
||||
|
||||
const renderContent = () => (
|
||||
<JitsiKeyboardAvoidingView
|
||||
addBottomPadding = { addBottomPadding }
|
||||
contentContainerStyle = { contentContainerStyle }
|
||||
disableForcedKeyboardDismiss = { disableForcedKeyboardDismiss }
|
||||
hasBottomTextInput = { hasBottomTextInput }
|
||||
hasExtraHeaderHeight = { hasExtraHeaderHeight }
|
||||
style = { style }>
|
||||
<SafeAreaView
|
||||
edges = { safeAreaInsets }
|
||||
style = { styles.safeArea }>
|
||||
{ children }
|
||||
{ FooterComponent && (
|
||||
<View style = { keyboardVisible && { paddingBottom: footerKeyboardSpacing } }>
|
||||
<FooterComponent />
|
||||
</View>
|
||||
) }
|
||||
</SafeAreaView>
|
||||
</JitsiKeyboardAvoidingView>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style = { styles.jitsiScreenContainer }>
|
||||
{ renderContent() }
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default JitsiScreen;
|
||||
32
react/features/base/modal/components/functions.native.ts
Normal file
32
react/features/base/modal/components/functions.native.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { IStateful } from '../../app/types';
|
||||
import { toState } from '../../redux/functions';
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the client width.
|
||||
*
|
||||
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state
|
||||
* features/base/config.
|
||||
* @returns {number}
|
||||
*/
|
||||
export function getClientWidth(stateful: IStateful) {
|
||||
const state = toState(stateful)['features/base/responsive-ui'];
|
||||
|
||||
return state.clientWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the client height.
|
||||
*
|
||||
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state
|
||||
* features/base/config.
|
||||
* @returns {number}
|
||||
*/
|
||||
export function getClientHeight(stateful: IStateful) {
|
||||
const state = toState(stateful)['features/base/responsive-ui'];
|
||||
|
||||
return state.clientHeight;
|
||||
}
|
||||
11
react/features/base/modal/components/styles.ts
Normal file
11
react/features/base/modal/components/styles.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
export default {
|
||||
|
||||
jitsiScreenContainer: {
|
||||
flex: 1
|
||||
},
|
||||
|
||||
safeArea: {
|
||||
flex: 1
|
||||
}
|
||||
};
|
||||
26
react/features/base/modal/hooks.native.ts
Normal file
26
react/features/base/modal/hooks.native.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Keyboard, Platform } from 'react-native';
|
||||
|
||||
const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
|
||||
const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
|
||||
|
||||
/**
|
||||
* A hook that tracks whether the native keyboard is visible.
|
||||
*
|
||||
* @returns {boolean} - Whether the keyboard is visible.
|
||||
*/
|
||||
export const useKeyboardVisible = (): boolean => {
|
||||
const [ keyboardVisible, setKeyboardVisible ] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const showSub = Keyboard.addListener(showEvent, () => setKeyboardVisible(true));
|
||||
const hideSub = Keyboard.addListener(hideEvent, () => setKeyboardVisible(false));
|
||||
|
||||
return () => {
|
||||
showSub.remove();
|
||||
hideSub.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return keyboardVisible;
|
||||
};
|
||||
Reference in New Issue
Block a user