Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion app/containers/MessageComposer/MessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export const MessageComposer = ({
const messageActionStore = useMessageActionStoreApi();
const actionKind = useMessageActionKind();
const alsoSendThreadToChannel = useAlsoSendThreadToChannel();
const { showEmojiKeyboard, showEmojiSearchbar, openEmojiSearchbar, resetKeyboard, keyboardHeight } = useEmojiKeyboard();
const { showEmojiKeyboard, showEmojiSearchbar, openEmojiSearchbar, collapseEmojiKeyboard, resetKeyboard, keyboardHeight } =
useEmojiKeyboard();
const { setAlsoSendThreadToChannel, setAutocompleteParams, clearAttachments } = useMessageComposerApi();
const recordingAudio = useRecordingAudio();
const { formatShortnameToUnicode } = useShortnameToUnicode();
Expand All @@ -75,6 +76,10 @@ export const MessageComposer = ({
resetKeyboard();
return true;
}
if (showEmojiKeyboard) {
collapseEmojiKeyboard();
return true;
}
return false;
});

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useEffect, type ReactElement, type RefObject } from 'react';
import { BackHandler } from 'react-native';
import { act, render, renderHook, screen, fireEvent, waitFor, userEvent } from '@testing-library/react-native';
import { Provider } from 'react-redux';
import { getRecordingPermissionsAsync, requestRecordingPermissionsAsync, useAudioRecorder, PermissionStatus } from 'expo-audio';

import { MessageComposerContainer } from './MessageComposerContainer';
import { ComposerAttachments } from './components/Attachments/ComposerAttachments';
import { MessageComposerContainer } from '../MessageComposerContainer';
import { ComposerAttachments } from '../components/Attachments/ComposerAttachments';
import { setPermissions } from '~/actions/permissions';
import { addSettings } from '~/actions/settings';
import { selectServerRequest } from '~/actions/server';
Expand All @@ -13,15 +14,15 @@ import { mockedStore } from '~/reducers/mockedStore';
import { type IPermissionsState } from '~/reducers/permissions';
import { type IMessage, type IShareAttachment, type TMessageActionState } from '~/definitions';
import { colors } from '~/lib/constants/colors';
import { type ComposerState } from './ComposerStore';
import { ComposerProvider } from './ComposerStore';
import { MessageActionProvider } from '../message/stores/MessageActionStore';
import * as EmojiKeyboardHook from './hooks/useEmojiKeyboard';
import { type ComposerState } from '../ComposerStore';
import { ComposerProvider } from '../ComposerStore';
import { MessageActionProvider } from '~/containers/message/stores/MessageActionStore';
import * as EmojiKeyboardHook from '../hooks/useEmojiKeyboard';
import { initStore } from '~/lib/store/auxStore';
import { searchRemote } from '~/lib/methods/search';
import database from '~/lib/database';
import { useMessageComposerApi } from './context';
import { type IMessageComposerRef } from './interfaces';
import { useMessageComposerApi } from '../context';
import { type IMessageComposerRef } from '../interfaces';
import { sendFileMessage } from '~/lib/methods/sendFileMessage';
import { runSlashCommand } from '~/lib/services/restApi';
import log from '~/lib/methods/helpers/log';
Expand Down Expand Up @@ -200,6 +201,7 @@ beforeEach(() => {
showEmojiKeyboard,
openEmojiKeyboard: jest.fn(),
closeEmojiKeyboard: jest.fn(),
collapseEmojiKeyboard: jest.fn(),
showEmojiSearchbarSharedValue: sharedValueSearchbar,
showEmojiSearchbar,
openEmojiSearchbar: jest.fn(),
Expand Down Expand Up @@ -236,6 +238,7 @@ describe('MessageComposer', () => {
showEmojiKeyboard,
openEmojiKeyboard: jest.fn(),
closeEmojiKeyboard: jest.fn(),
collapseEmojiKeyboard: jest.fn(),
showEmojiSearchbarSharedValue: sharedValueSearchbar,
showEmojiSearchbar,
openEmojiSearchbar: jest.fn(),
Expand Down Expand Up @@ -718,7 +721,7 @@ describe('MessageComposer', () => {
});

const messageIds = ['abc', 'def'];
jest.mock('./hooks/useMessage', () => ({
jest.mock('../hooks/useMessage', () => ({
useMessage: (messageId: string) => {
if (!messageIds.includes(messageId)) {
return null;
Expand Down Expand Up @@ -906,4 +909,65 @@ describe('MessageComposer', () => {
expect(screen.getByTestId('composer-quote-abc')).toBeOnTheScreen();
});
});

describe('Hardware back', () => {
const renderWithEmojiKeyboardState = ({ pickerOpen, searchbarOpen }: { pickerOpen: boolean; searchbarOpen: boolean }) => {
const collapseEmojiKeyboard = jest.fn();
const resetKeyboard = jest.fn();
jest.spyOn(EmojiKeyboardHook, 'useEmojiKeyboard').mockReturnValue({
showEmojiPickerSharedValue: sharedValue,
showEmojiKeyboard: pickerOpen,
openEmojiKeyboard: jest.fn(),
closeEmojiKeyboard: jest.fn(),
collapseEmojiKeyboard,
showEmojiSearchbarSharedValue: sharedValueSearchbar,
showEmojiSearchbar: searchbarOpen,
openEmojiSearchbar: jest.fn(),
closeEmojiSearchbar: jest.fn(),
resetKeyboard,
keyboardHeight: keyboardHeightSharedValue
});
const addEventListener = jest.spyOn(BackHandler, 'addEventListener').mockReturnValue({ remove: jest.fn() });
render(<Render />);
const registered = addEventListener.mock.calls.filter(([eventName]) => eventName === 'hardwareBackPress').pop();
return { handleBackPress: registered![1] as () => boolean, collapseEmojiKeyboard, resetKeyboard };
};

afterEach(() => {
jest.mocked(BackHandler.addEventListener).mockRestore();
});

test('closes only the emoji keyboard when it is open', () => {
const { handleBackPress, collapseEmojiKeyboard, resetKeyboard } = renderWithEmojiKeyboardState({
pickerOpen: true,
searchbarOpen: false
});

expect(handleBackPress()).toBe(true);
expect(collapseEmojiKeyboard).toHaveBeenCalledTimes(1);
expect(resetKeyboard).not.toHaveBeenCalled();
});

test('resets the keyboard when the emoji searchbar is open', () => {
const { handleBackPress, collapseEmojiKeyboard, resetKeyboard } = renderWithEmojiKeyboardState({
pickerOpen: true,
searchbarOpen: true
});

expect(handleBackPress()).toBe(true);
expect(resetKeyboard).toHaveBeenCalledTimes(1);
expect(collapseEmojiKeyboard).not.toHaveBeenCalled();
});

test('lets back navigate when no emoji keyboard is open', () => {
const { handleBackPress, collapseEmojiKeyboard, resetKeyboard } = renderWithEmojiKeyboardState({
pickerOpen: false,
searchbarOpen: false
});

expect(handleBackPress()).toBe(false);
expect(collapseEmojiKeyboard).not.toHaveBeenCalled();
expect(resetKeyboard).not.toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { type ReactElement } from 'react';
import { renderHook, act } from '@testing-library/react-native';
import { useSharedValue } from 'react-native-reanimated';

import { EmojiKeyboardProvider, useEmojiKeyboard } from './useEmojiKeyboard';
import { MessageInnerContext } from '../context';
import { EmojiKeyboardProvider, useEmojiKeyboard } from '../useEmojiKeyboard';
import { MessageInnerContext } from '../../context';

describe('useEmojiKeyboard', () => {
let mockSharedValue: any;
Expand Down Expand Up @@ -182,6 +182,21 @@ describe('useEmojiKeyboard', () => {
expect(mockSearchbarSharedValue.value).toBe(false);
});

test('should collapse the keyboard space without focusing the input', () => {
const wrapper = createWrapper();
mockSharedValue.value = true;
mockKeyboardHeightSharedValue.value = 770;
const { result } = renderHook(() => useEmojiKeyboard(), { wrapper });

act(() => {
result.current.collapseEmojiKeyboard();
});

expect(mockSharedValue.value).toBe(false);
expect(mockKeyboardHeightSharedValue.value).toBe(0);
expect(mockFocus).not.toHaveBeenCalled();
});

test('should handle multiple open/close operations', () => {
const wrapper = createWrapper();
const { result } = renderHook(() => useEmojiKeyboard(), { wrapper });
Expand Down
7 changes: 6 additions & 1 deletion app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,13 @@ export const useEmojiKeyboard = () => {
focus && focus();
};

const resetKeyboard = () => {
const collapseEmojiKeyboard = () => {
updateHeight(true);
closeEmojiKeyboard();
};

const resetKeyboard = () => {
collapseEmojiKeyboard();
closeEmojiSearchbar();
};

Expand Down Expand Up @@ -179,6 +183,7 @@ export const useEmojiKeyboard = () => {
// Functions
openEmojiKeyboard,
closeEmojiKeyboard,
collapseEmojiKeyboard,
openEmojiSearchbar,
closeEmojiSearchbar,
resetKeyboard
Expand Down
Loading