Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7d5c626
fix: remove mobile offline indicator in start chat page
chrispader May 4, 2025
c7597c0
fix: disable mobile offline indicator completely on Start chat page
chrispader May 4, 2025
1aa0b34
fix: add useOnyx canBeMissing
chrispader May 4, 2025
4a3cf99
fix: eslint errors
chrispader May 4, 2025
65d2835
fix: move ScreenWrapper into own directory
chrispader May 5, 2025
b27e369
fix: import order and paths
chrispader May 5, 2025
90d5003
fix: encapsulate logic in useScreenWrapperTransitionStatus
chrispader May 5, 2025
c7c9804
feat: introduce offline indicator context to globally disable offline…
chrispader May 5, 2025
f2708df
fix: make offline indicator bottom safe area padding prop explicit
chrispader May 5, 2025
447896a
fix: simplfiy logic in RHP modal navigator
chrispader May 5, 2025
007e404
fix: disable rendering any nested offline indicator, except modals
chrispader May 5, 2025
1c722e8
fix: offline indicators on NewChat and NewRoom pages
chrispader May 5, 2025
db2a7a2
simplify RHP offline indicator setting
chrispader May 5, 2025
e5c45cf
feat: extract narrow pane context provider and apply to other narrow …
chrispader May 5, 2025
6a13901
import React
chrispader May 5, 2025
1bfd2e7
fix: apply offline indicator bottom safe area padding by default
chrispader May 5, 2025
ae958d9
refactor: remove default `addBottomSafeAreaPadding` values when we de…
chrispader May 5, 2025
b2ab9aa
fix: don't apply offline indicator padding in ScreenWrapper styles
chrispader May 5, 2025
bf87b7d
fix: extract EmptyWorkspaceView to make automatic handling work
chrispader May 5, 2025
c07ee06
fix: use EmptyWorkspaceView
chrispader May 5, 2025
37ed586
fix: simplify screen wrapper code
chrispader May 5, 2025
bfa1bd3
Merge branch 'main' into @chrispader/fix-offline-indicator-start-chat…
chrispader May 9, 2025
86412e4
fix: pass down original values for Modal safe area fix
chrispader May 9, 2025
591cf8c
fix: move context provider out
chrispader May 9, 2025
fd39a4f
Merge branch 'main' into @chrispader/fix-offline-indicator-start-chat…
chrispader May 9, 2025
1032600
Merge branch 'main' into @chrispader/fix-offline-indicator-start-chat…
chrispader May 10, 2025
ed8c612
fix: extract narrow pane logic to own context
chrispader May 10, 2025
b97236e
fix: reload issue
chrispader May 10, 2025
e1d643a
fix: use isSmallScreenWidth instead of shouldUseNarrowLayout in Scree…
chrispader May 10, 2025
9b44ea5
fix: unnecesassary extra padding in CategoryPicker
chrispader May 10, 2025
9dbe05c
Merge branch 'main' into @chrispader/fix-offline-indicator-start-chat…
chrispader May 13, 2025
e82a4a8
fix: ValueSelectorModal bottom safe area padding
chrispader May 13, 2025
5a8f82a
fix: also add bottom safe area padding to ValueSelectionList
chrispader May 13, 2025
d546c61
Merge branch 'main' into @chrispader/fix-offline-indicator-start-chat…
chrispader May 13, 2025
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
4 changes: 2 additions & 2 deletions src/components/BlockingViews/BlockingView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ function BlockingView({
CustomSubtitle,
contentFitImage,
containerStyle: containerStyleProp,
addBottomSafeAreaPadding = false,
addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
addBottomSafeAreaPadding,
addOfflineIndicatorBottomSafeAreaPadding,
testID,
}: BlockingViewProps) {
const styles = useThemeStyles();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ function CategorySelectorModal({policyID, isVisible, currentCategory, onCategory
policyID={policyID}
selectedCategory={currentCategory}
onSubmit={onCategorySelected}
contentContainerStyle={styles.pb5}
addBottomSafeAreaPadding
/>
</ScreenWrapper>
Expand Down
8 changes: 1 addition & 7 deletions src/components/FixedFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,7 @@ type FixedFooterProps = {
shouldStickToBottom?: boolean;
};

function FixedFooter({
style,
children,
addBottomSafeAreaPadding = false,
addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
shouldStickToBottom = false,
}: FixedFooterProps) {
function FixedFooter({style, children, addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, shouldStickToBottom = false}: FixedFooterProps) {
const styles = useThemeStyles();

const bottomSafeAreaPaddingStyle = useBottomSafeSafeAreaPaddingStyle({
Expand Down
4 changes: 2 additions & 2 deletions src/components/Form/FormWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function FormWrapper({
isLoading = false,
shouldScrollToEnd = false,
addBottomSafeAreaPadding,
addOfflineIndicatorBottomSafeAreaPadding: addOfflineIndicatorBottomSafeAreaPaddingProp,
addOfflineIndicatorBottomSafeAreaPadding,
shouldSubmitButtonStickToBottom: shouldSubmitButtonStickToBottomProp,
shouldSubmitButtonBlendOpacity = false,
}: FormWrapperProps) {
Expand Down Expand Up @@ -137,13 +137,13 @@ function FormWrapper({
// If the paddingBottom is 0, it has already been applied to a parent component and we don't want to apply the padding again.
const isLegacyBottomSafeAreaPaddingAlreadyApplied = paddingBottom === 0;
const shouldApplyBottomSafeAreaPadding = addBottomSafeAreaPadding ?? !isLegacyBottomSafeAreaPaddingAlreadyApplied;
const addOfflineIndicatorBottomSafeAreaPadding = addOfflineIndicatorBottomSafeAreaPaddingProp ?? addBottomSafeAreaPadding === true;

// We need to add bottom safe area padding to the submit button when we don't use a scroll view or
// when the submit button is sticking to the bottom.
const addSubmitButtonBottomSafeAreaPadding = addBottomSafeAreaPadding && (!shouldUseScrollView || shouldSubmitButtonStickToBottom);
const submitButtonStylesWithBottomSafeAreaPadding = useBottomSafeSafeAreaPaddingStyle({
addBottomSafeAreaPadding: addSubmitButtonBottomSafeAreaPadding,
addOfflineIndicatorBottomSafeAreaPadding,
styleProperty: shouldSubmitButtonStickToBottom ? 'bottom' : 'paddingBottom',
additionalPaddingBottom: shouldSubmitButtonStickToBottom ? styles.pb5.paddingBottom : 0,
style: submitButtonStyles,
Expand Down
136 changes: 73 additions & 63 deletions src/components/Modal/BaseModal.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, {forwardRef, useCallback, useEffect, useMemo, useRef} from 'react';
import React, {forwardRef, useCallback, useContext, useEffect, useMemo, useRef} from 'react';
import {View} from 'react-native';
import type {ModalProps as ReactNativeModalProps} from 'react-native-modal';
import ReactNativeModal from 'react-native-modal';
import type {ValueOf} from 'type-fest';
import ColorSchemeWrapper from '@components/ColorSchemeWrapper';
import FocusTrapForModal from '@components/FocusTrap/FocusTrapForModal';
import NavigationBar from '@components/NavigationBar';
import ScreenWrapperOfflineIndicatorContext from '@components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext';
import useKeyboardState from '@hooks/useKeyboardState';
import usePrevious from '@hooks/usePrevious';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
Expand All @@ -16,6 +17,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import ComposerFocusManager from '@libs/ComposerFocusManager';
import NarrowPaneContext from '@libs/Navigation/AppNavigator/Navigators/NarrowPaneContext';
import Overlay from '@libs/Navigation/AppNavigator/Navigators/Overlay';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
Expand Down Expand Up @@ -249,76 +251,84 @@ function BaseModal(
[isVisible, type],
);

// In Modals we need to reset the ScreenWrapperOfflineIndicatorContext to allow nested ScreenWrapper components to render offline indicators,
// except if we are in a narrow pane navigator. In this case, we use the narrow pane's original values.
const {isInNarrowPane} = useContext(NarrowPaneContext);
const {originalValues} = useContext(ScreenWrapperOfflineIndicatorContext);
const offlineIndicatorContextValue = useMemo(() => (isInNarrowPane ? originalValues ?? {} : {}), [isInNarrowPane, originalValues]);

return (
<ModalContext.Provider value={modalContextValue}>
<View
// this is a workaround for modal not being visible on the new arch in some cases
// it's necessary to have a non-collapsible view as a parent of the modal to prevent
// a conflict between RN core and Reanimated shadow tree operations
// position absolute is needed to prevent the view from interfering with flex layout
collapsable={false}
style={[styles.pAbsolute, {zIndex: 1}]}
>
<ModalComponent
// Prevent the parent element to capture a click. This is useful when the modal component is put inside a pressable.
onClick={(e) => e.stopPropagation()}
onBackdropPress={handleBackdropPress}
// Note: Escape key on web/desktop will trigger onBackButtonPress callback
// eslint-disable-next-line react/jsx-props-no-multi-spaces
onBackButtonPress={closeTop}
onModalShow={handleShowModal}
propagateSwipe={propagateSwipe}
onModalHide={hideModal}
onModalWillShow={saveFocusState}
onDismiss={handleDismissModal}
onSwipeComplete={() => onClose?.()}
swipeDirection={swipeDirection}
swipeThreshold={swipeThreshold}
isVisible={isVisible}
backdropColor={theme.overlay}
backdropOpacity={!shouldUseCustomBackdrop && hideBackdrop ? 0 : variables.overlayOpacity}
backdropTransitionOutTiming={0}
hasBackdrop={fullscreen}
coverScreen={fullscreen}
style={[modalStyle, sidePanelStyle]}
deviceHeight={windowHeight}
deviceWidth={windowWidth}
animationIn={animationIn ?? modalStyleAnimationIn}
animationInDelay={animationInDelay}
animationOut={animationOut ?? modalStyleAnimationOut}
useNativeDriver={useNativeDriver}
useNativeDriverForBackdrop={useNativeDriverForBackdrop}
hideModalContentWhileAnimating={hideModalContentWhileAnimating}
animationInTiming={animationInTiming}
animationOutTiming={animationOutTiming}
statusBarTranslucent={statusBarTranslucent}
navigationBarTranslucent={navigationBarTranslucent}
onLayout={onLayout}
avoidKeyboard={avoidKeyboard}
customBackdrop={shouldUseCustomBackdrop ? <Overlay onPress={handleBackdropPress} /> : undefined}
type={type}
shouldUseNewModal={shouldUseNewModal}
<ScreenWrapperOfflineIndicatorContext.Provider value={offlineIndicatorContextValue}>
<View
// this is a workaround for modal not being visible on the new arch in some cases
// it's necessary to have a non-collapsible view as a parent of the modal to prevent
// a conflict between RN core and Reanimated shadow tree operations
// position absolute is needed to prevent the view from interfering with flex layout
collapsable={false}
style={[styles.pAbsolute, {zIndex: 1}]}
>
<ModalContent
<ModalComponent
// Prevent the parent element to capture a click. This is useful when the modal component is put inside a pressable.
onClick={(e) => e.stopPropagation()}
onBackdropPress={handleBackdropPress}
// Note: Escape key on web/desktop will trigger onBackButtonPress callback
// eslint-disable-next-line react/jsx-props-no-multi-spaces
onBackButtonPress={closeTop}
onModalShow={handleShowModal}
propagateSwipe={propagateSwipe}
onModalHide={hideModal}
onModalWillShow={saveFocusState}
onDismiss={handleDismissModal}
onSwipeComplete={() => onClose?.()}
swipeDirection={swipeDirection}
swipeThreshold={swipeThreshold}
isVisible={isVisible}
backdropColor={theme.overlay}
backdropOpacity={!shouldUseCustomBackdrop && hideBackdrop ? 0 : variables.overlayOpacity}
backdropTransitionOutTiming={0}
hasBackdrop={fullscreen}
coverScreen={fullscreen}
style={[modalStyle, sidePanelStyle]}
deviceHeight={windowHeight}
deviceWidth={windowWidth}
animationIn={animationIn ?? modalStyleAnimationIn}
animationInDelay={animationInDelay}
animationOut={animationOut ?? modalStyleAnimationOut}
useNativeDriver={useNativeDriver}
useNativeDriverForBackdrop={useNativeDriverForBackdrop}
hideModalContentWhileAnimating={hideModalContentWhileAnimating}
animationInTiming={animationInTiming}
animationOutTiming={animationOutTiming}
statusBarTranslucent={statusBarTranslucent}
navigationBarTranslucent={navigationBarTranslucent}
onLayout={onLayout}
avoidKeyboard={avoidKeyboard}
customBackdrop={shouldUseCustomBackdrop ? <Overlay onPress={handleBackdropPress} /> : undefined}
type={type}
shouldUseNewModal={shouldUseNewModal}
>
<FocusTrapForModal
active={isVisible}
initialFocus={initialFocus}
shouldPreventScroll={shouldPreventScrollOnFocus}
<ModalContent
onModalWillShow={saveFocusState}
onDismiss={handleDismissModal}
>
<View
style={[styles.defaultModalContainer, modalContainerStyle, modalPaddingStyles, !isVisible && styles.pointerEventsNone]}
ref={ref}
<FocusTrapForModal
active={isVisible}
initialFocus={initialFocus}
shouldPreventScroll={shouldPreventScrollOnFocus}
>
<ColorSchemeWrapper>{children}</ColorSchemeWrapper>
</View>
</FocusTrapForModal>
</ModalContent>
{!keyboardStateContextValue?.isKeyboardActive && <NavigationBar />}
</ModalComponent>
</View>
<View
style={[styles.defaultModalContainer, modalContainerStyle, modalPaddingStyles, !isVisible && styles.pointerEventsNone]}
ref={ref}
>
<ColorSchemeWrapper>{children}</ColorSchemeWrapper>
</View>
</FocusTrapForModal>
</ModalContent>
{!keyboardStateContextValue?.isKeyboardActive && <NavigationBar />}
</ModalComponent>
</View>
</ScreenWrapperOfflineIndicatorContext.Provider>
</ModalContext.Provider>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/components/OfflineIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ function OfflineIndicator({style, containerStyles: containerStylesProp, addBotto
const fallbackStyle = useMemo(() => [styles.offlineIndicatorContainer, containerStylesProp], [styles.offlineIndicatorContainer, containerStylesProp]);
const containerStyles = useBottomSafeSafeAreaPaddingStyle({
addBottomSafeAreaPadding,
addOfflineIndicatorBottomSafeAreaPadding: false,
style: fallbackStyle,
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {createContext} from 'react';

type ScreenWrapperOfflineIndicatorBaseContext = {
showOnSmallScreens?: boolean;
showOnWideScreens?: boolean;
addSafeAreaPadding?: boolean;
};

type ScreenWrapperOfflineIndicatorContextType = {
showOnSmallScreens?: boolean;
showOnWideScreens?: boolean;
addSafeAreaPadding?: boolean;
originalValues?: ScreenWrapperOfflineIndicatorBaseContext;
};

const ScreenWrapperOfflineIndicatorContext = createContext<ScreenWrapperOfflineIndicatorContextType>({});

export default ScreenWrapperOfflineIndicatorContext;
export type {ScreenWrapperOfflineIndicatorContextType};
Loading
Loading