(cherry picked from commit f2383f8bc5)
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
parent
84badb448a
commit
6f29392a2e
6 changed files with 28 additions and 143 deletions
|
|
@ -199,6 +199,8 @@ export const SCREENS_AS_BOTTOM_SHEET = new Set<string>([
|
|||
CALL_HOST_CONTROLS,
|
||||
]);
|
||||
|
||||
export const SCREENS_WITH_EXTRA_KEYBOARD = new Set<string>([CHANNEL, THREAD]);
|
||||
|
||||
export const NOT_READY = [
|
||||
CREATE_TEAM,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import RNUtils from '@mattermost/rnutils';
|
||||
import {renderHook} from '@testing-library/react-hooks';
|
||||
import {Keyboard} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import {useAndroidAdjustSoftKeyboard} from '.'; // Update with the correct path
|
||||
|
||||
jest.mock('react-native', () => ({
|
||||
Keyboard: {
|
||||
isVisible: jest.fn(),
|
||||
dismiss: jest.fn(),
|
||||
},
|
||||
Platform: {
|
||||
OS: 'android',
|
||||
select: jest.fn((options) => options.android ?? options.default),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('react-native-navigation', () => {
|
||||
const registerComponentListenerMock = jest.fn();
|
||||
return {
|
||||
Navigation: {
|
||||
events: jest.fn(() => ({
|
||||
registerComponentListener: registerComponentListenerMock,
|
||||
})),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@mattermost/rnutils', () => ({
|
||||
setSoftKeyboardToAdjustNothing: jest.fn(),
|
||||
setSoftKeyboardToAdjustResize: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('useAndroidAdjustSoftKeyboard', () => {
|
||||
let registerComponentListenerMock: jest.SpyInstance;
|
||||
const unsubscribeMock = {remove: jest.fn()};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
const events = Navigation.events();
|
||||
registerComponentListenerMock = jest.spyOn(events, 'registerComponentListener');
|
||||
registerComponentListenerMock.mockReturnValue(unsubscribeMock);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should register component listener and handle lifecycle events', () => {
|
||||
renderHook(() => useAndroidAdjustSoftKeyboard('Channel'));
|
||||
|
||||
expect(registerComponentListenerMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
componentDidAppear: expect.any(Function),
|
||||
componentDidDisappear: expect.any(Function),
|
||||
}),
|
||||
'Channel',
|
||||
);
|
||||
|
||||
const listener = registerComponentListenerMock.mock.calls[0][0];
|
||||
|
||||
jest.mocked(Keyboard.isVisible).mockReturnValue(true);
|
||||
listener.componentDidAppear();
|
||||
|
||||
expect(Keyboard.dismiss).toHaveBeenCalled();
|
||||
|
||||
jest.runAllTimers();
|
||||
expect(RNUtils.setSoftKeyboardToAdjustNothing).toHaveBeenCalled();
|
||||
|
||||
listener.componentDidDisappear();
|
||||
expect(RNUtils.setSoftKeyboardToAdjustResize).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should register component listener and handle lifecycle events when the screen is undefined', () => {
|
||||
renderHook(() => useAndroidAdjustSoftKeyboard(undefined));
|
||||
|
||||
expect(registerComponentListenerMock).not.toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
componentDidAppear: expect.any(Function),
|
||||
componentDidDisappear: expect.any(Function),
|
||||
}),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
it('should clean up on unmount', () => {
|
||||
const {unmount} = renderHook(() => useAndroidAdjustSoftKeyboard('Channel'));
|
||||
|
||||
unmount();
|
||||
|
||||
expect(unsubscribeMock.remove).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import RNUtils from '@mattermost/rnutils';
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {Keyboard} from 'react-native';
|
||||
import {Navigation, type EventSubscription} from 'react-native-navigation';
|
||||
|
||||
import type {AvailableScreens} from '@typings/screens/navigation';
|
||||
|
||||
export function useAndroidAdjustSoftKeyboard(screen?: AvailableScreens) {
|
||||
const timeout = useRef<NodeJS.Timeout>();
|
||||
|
||||
useEffect(() => {
|
||||
let unsubscribe: EventSubscription;
|
||||
const listener = {
|
||||
componentDidAppear: () => {
|
||||
if (Keyboard.isVisible()) {
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
timeout.current = setTimeout(() => {
|
||||
RNUtils.setSoftKeyboardToAdjustNothing();
|
||||
}, 10);
|
||||
},
|
||||
componentDidDisappear: () => {
|
||||
RNUtils.setSoftKeyboardToAdjustResize();
|
||||
},
|
||||
};
|
||||
|
||||
if (screen) {
|
||||
unsubscribe = Navigation.events().registerComponentListener(listener, screen);
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout.current);
|
||||
unsubscribe?.remove();
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
|
|
@ -10,7 +10,6 @@ import FloatingCallContainer from '@calls/components/floating_call_container';
|
|||
import FreezeScreen from '@components/freeze_screen';
|
||||
import PostDraft from '@components/post_draft';
|
||||
import {ExtraKeyboardProvider} from '@context/extra_keyboard';
|
||||
import {useAndroidAdjustSoftKeyboard} from '@hooks/android_adjust_soft_keyboard';
|
||||
import useAndroidHardwareBackHandler from '@hooks/android_back_handler';
|
||||
import {useChannelSwitch} from '@hooks/channel_switch';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
|
|
@ -79,7 +78,6 @@ const Channel = ({
|
|||
}, [componentId]);
|
||||
|
||||
useAndroidHardwareBackHandler(componentId, handleBack);
|
||||
useAndroidAdjustSoftKeyboard(componentId);
|
||||
|
||||
const marginTop = defaultHeight + (isTablet ? 0 : -insets.top);
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,15 @@
|
|||
|
||||
/* eslint-disable max-lines */
|
||||
|
||||
import RNUtils from '@mattermost/rnutils';
|
||||
import merge from 'deepmerge';
|
||||
import {Appearance, DeviceEventEmitter, StatusBar, Platform, Alert, type EmitterSubscription} from 'react-native';
|
||||
import {type ComponentWillAppearEvent, type ImageResource, type LayoutOrientation, Navigation, type Options, OptionsModalPresentationStyle, type OptionsTopBarButton, type ScreenPoppedEvent, type EventSubscription} from 'react-native-navigation';
|
||||
import {type ComponentWillAppearEvent, type ImageResource, type LayoutOrientation, Navigation, type Options, OptionsModalPresentationStyle, type OptionsTopBarButton, type ScreenPoppedEvent, type EventSubscription, type ComponentDidAppearEvent} from 'react-native-navigation';
|
||||
import tinyColor from 'tinycolor2';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {Events, Screens, Launch} from '@constants';
|
||||
import {NOT_READY} from '@constants/screens';
|
||||
import {NOT_READY, SCREENS_WITH_EXTRA_KEYBOARD} from '@constants/screens';
|
||||
import {getDefaultThemeByAppearance} from '@context/theme';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
|
|
@ -39,6 +40,8 @@ export function registerNavigationListeners() {
|
|||
Navigation.events().registerScreenPoppedListener(onPoppedListener),
|
||||
Navigation.events().registerCommandListener(onCommandListener),
|
||||
Navigation.events().registerComponentWillAppearListener(onScreenWillAppear),
|
||||
Navigation.events().registerComponentDidAppearListener(onScreenDidAppear),
|
||||
Navigation.events().registerComponentDidDisappearListener(onScreenDidDisappear),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -76,12 +79,33 @@ function onPoppedListener({componentId}: ScreenPoppedEvent) {
|
|||
NavigationStore.removeScreenFromStack(componentId as AvailableScreens);
|
||||
}
|
||||
|
||||
function setAndroidSoftKeyboard(screen: AvailableScreens) {
|
||||
if (Platform.OS !== 'android') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SCREENS_WITH_EXTRA_KEYBOARD.has(screen) || (isTablet() && screen === Screens.HOME)) {
|
||||
RNUtils.setSoftKeyboardToAdjustNothing();
|
||||
} else {
|
||||
RNUtils.setSoftKeyboardToAdjustResize();
|
||||
}
|
||||
}
|
||||
|
||||
function onScreenWillAppear(event: ComponentWillAppearEvent) {
|
||||
if (event.componentId === Screens.HOME) {
|
||||
DeviceEventEmitter.emit(Events.TAB_BAR_VISIBLE, true);
|
||||
}
|
||||
}
|
||||
|
||||
function onScreenDidAppear(event: ComponentDidAppearEvent) {
|
||||
setAndroidSoftKeyboard(event.componentId as AvailableScreens);
|
||||
}
|
||||
|
||||
function onScreenDidDisappear() {
|
||||
const screen = NavigationStore.getVisibleScreen();
|
||||
setAndroidSoftKeyboard(screen);
|
||||
}
|
||||
|
||||
export const loginAnimationOptions = () => {
|
||||
const theme = getThemeFromState();
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import PostDraft from '@components/post_draft';
|
|||
import RoundedHeaderContext from '@components/rounded_header_context';
|
||||
import {Screens} from '@constants';
|
||||
import {ExtraKeyboardProvider} from '@context/extra_keyboard';
|
||||
import {useAndroidAdjustSoftKeyboard} from '@hooks/android_adjust_soft_keyboard';
|
||||
import useAndroidHardwareBackHandler from '@hooks/android_back_handler';
|
||||
import useDidUpdate from '@hooks/did_update';
|
||||
import {popTopScreen, setButtons} from '@screens/navigation';
|
||||
|
|
@ -57,7 +56,6 @@ const Thread = ({
|
|||
}, [componentId]);
|
||||
|
||||
useAndroidHardwareBackHandler(componentId, close);
|
||||
useAndroidAdjustSoftKeyboard(componentId);
|
||||
|
||||
useEffect(() => {
|
||||
if (isCRTEnabled && rootId) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue