diff --git a/app/components/autocomplete/autocomplete.test.tsx b/app/components/autocomplete/autocomplete.test.tsx
index 5c7b50769..a56c4a032 100644
--- a/app/components/autocomplete/autocomplete.test.tsx
+++ b/app/components/autocomplete/autocomplete.test.tsx
@@ -120,4 +120,36 @@ describe('Autocomplete', () => {
expect(getByTestId('slash-suggestion-mock')).toBeTruthy();
expect(getByTestId('app-slash-suggestion-mock')).toBeTruthy();
});
+
+ it('should render with the correct horizontal padding', () => {
+ const props = getBaseProps();
+ const {getByTestId, rerender} = render();
+
+ // Default horizontal padding is 8
+ expect(getByTestId('autocomplete')).toHaveStyle({left: 8, right: 8});
+
+ // Set horizontal padding to 20
+ props.horizontalPadding = 20;
+ rerender();
+
+ expect(getByTestId('autocomplete')).toHaveStyle({left: 20, right: 20});
+ });
+
+ it('should set the correct max height by default', () => {
+ const props = getBaseProps();
+ props.availableSpace = {value: 1000} as SharedValue;
+ const {getByTestId} = render();
+
+ // Default max height is 230
+ expect(getByTestId('autocomplete')).toHaveStyle({maxHeight: 230});
+ });
+
+ it('should set the correct max height when useAllAvailableSpace is true', () => {
+ const props = getBaseProps();
+ props.availableSpace = {value: 1000} as SharedValue;
+ props.useAllAvailableSpace = true;
+ const {getByTestId} = render();
+
+ expect(getByTestId('autocomplete')).toHaveStyle({maxHeight: 1000});
+ });
});
diff --git a/app/components/autocomplete/autocomplete.tsx b/app/components/autocomplete/autocomplete.tsx
index 31939af21..a0c1f4c10 100644
--- a/app/components/autocomplete/autocomplete.tsx
+++ b/app/components/autocomplete/autocomplete.tsx
@@ -19,8 +19,6 @@ import AppSlashSuggestion from './slash_suggestion/app_slash_suggestion/';
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
base: {
- left: 8,
- right: 8,
position: 'absolute',
},
borders: {
@@ -65,6 +63,8 @@ type Props = {
teamId?: string;
containerStyle?: StyleProp;
autocompleteProviders?: AutocompleteProviders;
+ useAllAvailableSpace?: boolean;
+ horizontalPadding?: number;
}
type AutocompleteProviders = {
@@ -99,6 +99,8 @@ const Autocomplete = ({
containerStyle,
teamId,
autocompleteProviders = defaultAutocompleteProviders,
+ useAllAvailableSpace = false,
+ horizontalPadding = 8,
}: Props) => {
const theme = useTheme();
const isTablet = useIsTablet();
@@ -121,8 +123,8 @@ const Autocomplete = ({
const maxHeightAdjust = (isTablet && isLandscape) ? MAX_LIST_TABLET_DIFF : 0;
const defaultMaxHeight = MAX_LIST_HEIGHT - maxHeightAdjust;
const maxHeight = useDerivedValue(() => {
- return Math.min(availableSpace.value, defaultMaxHeight);
- }, [defaultMaxHeight]);
+ return useAllAvailableSpace ? availableSpace.value : Math.min(availableSpace.value, defaultMaxHeight);
+ }, [defaultMaxHeight, useAllAvailableSpace, availableSpace]);
const containerAnimatedStyle = useAnimatedStyle(() => {
return growDown ?
@@ -131,7 +133,7 @@ const Autocomplete = ({
}, [growDown, position]);
const containerStyles = useMemo(() => {
- const s: StyleProp = [style.base, containerAnimatedStyle];
+ const s: StyleProp = [style.base, {left: horizontalPadding, right: horizontalPadding}, containerAnimatedStyle];
if (hasElements) {
s.push(style.borders);
}
@@ -142,7 +144,7 @@ const Autocomplete = ({
s.push(containerStyle);
}
return s;
- }, [hasElements, style, containerStyle, containerAnimatedStyle]);
+ }, [style.base, style.borders, style.shadow, horizontalPadding, containerAnimatedStyle, hasElements, containerStyle]);
return (
{
expect(editCommandForm.props.channelId).toBe(props.channelId);
});
- it('renders correctly without saved command', () => {
+ it('renders correctly without saved command, adding a slash automatically', () => {
const props = getBaseProps();
props.savedCommand = undefined;
const {getByTestId} = renderWithEverything(, {database});
const editCommandForm = getByTestId('edit-command-form');
- expect(editCommandForm.props.command).toBe('');
+ expect(editCommandForm.props.command).toBe('/');
});
it('sets up navigation buttons correctly', () => {
diff --git a/app/products/playbooks/screens/edit_command/edit_command.tsx b/app/products/playbooks/screens/edit_command/edit_command.tsx
index 0cdb75e9c..72e02c513 100644
--- a/app/products/playbooks/screens/edit_command/edit_command.tsx
+++ b/app/products/playbooks/screens/edit_command/edit_command.tsx
@@ -46,7 +46,7 @@ const CreateOrEditChannel = ({
const theme = useTheme();
const [canSave, setCanSave] = useState(false);
- const [command, setCommand] = useState(savedCommand || '');
+ const [command, setCommand] = useState(savedCommand || '/');
const rightButton = useMemo(() => {
const base = buildNavigationButton(
diff --git a/app/products/playbooks/screens/edit_command/edit_command_form.test.tsx b/app/products/playbooks/screens/edit_command/edit_command_form.test.tsx
index ffc90ebb3..cab071deb 100644
--- a/app/products/playbooks/screens/edit_command/edit_command_form.test.tsx
+++ b/app/products/playbooks/screens/edit_command/edit_command_form.test.tsx
@@ -63,6 +63,7 @@ describe('EditCommandForm', () => {
expect(floatingTextInput).toHaveProp('showErrorIcon', false);
expect(floatingTextInput).toHaveProp('spellCheck', false);
expect(floatingTextInput).toHaveProp('disableFullscreenUI', true);
+ expect(floatingTextInput).toHaveProp('autoFocus', true);
const autocomplete = getByTestId('autocomplete');
expect(autocomplete).toBeTruthy();
@@ -78,6 +79,8 @@ describe('EditCommandForm', () => {
emoji: false,
slash: true,
});
+ expect(autocomplete).toHaveProp('useAllAvailableSpace', true);
+ expect(autocomplete).toHaveProp('horizontalPadding', 20);
});
it('calls onCommandChange when text input changes', () => {
diff --git a/app/products/playbooks/screens/edit_command/edit_command_form.tsx b/app/products/playbooks/screens/edit_command/edit_command_form.tsx
index d3f05f191..050402337 100644
--- a/app/products/playbooks/screens/edit_command/edit_command_form.tsx
+++ b/app/products/playbooks/screens/edit_command/edit_command_form.tsx
@@ -1,12 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import React, {useState, useCallback} from 'react';
+import React, {useState, useCallback, useRef} from 'react';
import {useIntl} from 'react-intl';
import {
type LayoutChangeEvent,
View,
- Platform,
StyleSheet,
} from 'react-native';
import {SafeAreaView, type Edges} from 'react-native-safe-area-context';
@@ -15,13 +14,13 @@ import Autocomplete from '@components/autocomplete';
import FloatingTextInput from '@components/floating_text_input_label';
import {useTheme} from '@context/theme';
import {useAutocompleteDefaultAnimatedValues} from '@hooks/autocomplete';
+import {useKeyboardOverlap} from '@hooks/device';
import {
getKeyboardAppearanceFromTheme,
} from '@utils/theme';
-const BOTTOM_AUTOCOMPLETE_SEPARATION = Platform.select({ios: 10, default: 10});
+const BOTTOM_AUTOCOMPLETE_SEPARATION = 4;
const LIST_PADDING = 32;
-const AUTOCOMPLETE_ADJUST = 5;
const styles = StyleSheet.create({
container: {
@@ -60,6 +59,9 @@ export default function EditCommandForm({
const [commandFieldHeight, setCommandFieldHeight] = useState(0);
+ const mainView = useRef(null);
+ const keyboardOverlap = useKeyboardOverlap(mainView, wrapperHeight);
+
const labelCommand = formatMessage({id: 'playbooks.edit_command.label', defaultMessage: 'Command'});
const placeholderCommand = formatMessage({id: 'playbooks.edit_command.placeholder', defaultMessage: 'Type a command here'});
@@ -70,14 +72,13 @@ export default function EditCommandForm({
setWrapperHeight(e.nativeEvent.layout.height);
}, []);
- const spaceOnTop = LIST_PADDING - AUTOCOMPLETE_ADJUST;
- const spaceOnBottom = (wrapperHeight) - (LIST_PADDING + commandFieldHeight + BOTTOM_AUTOCOMPLETE_SEPARATION);
+ const workingSpace = wrapperHeight - keyboardOverlap;
+ const spaceOnBottom = (workingSpace) - (LIST_PADDING + commandFieldHeight + (BOTTOM_AUTOCOMPLETE_SEPARATION * 2));
- const bottomPosition = (LIST_PADDING + commandFieldHeight);
- const topPosition = (wrapperHeight + AUTOCOMPLETE_ADJUST) - LIST_PADDING;
- const autocompletePosition = spaceOnBottom > spaceOnTop ? bottomPosition : topPosition;
- const autocompleteAvailableSpace = spaceOnBottom > spaceOnTop ? spaceOnBottom : spaceOnTop;
- const growDown = spaceOnBottom > spaceOnTop;
+ const bottomPosition = (LIST_PADDING + commandFieldHeight + BOTTOM_AUTOCOMPLETE_SEPARATION);
+ const autocompletePosition = bottomPosition;
+ const autocompleteAvailableSpace = spaceOnBottom;
+ const growDown = true;
const [animatedAutocompletePosition, animatedAutocompleteAvailableSpace] = useAutocompleteDefaultAnimatedValues(autocompletePosition, autocompleteAvailableSpace);
@@ -87,6 +88,7 @@ export default function EditCommandForm({
style={styles.container}
testID='playbooks.edit_command.form'
onLayout={onLayoutWrapper}
+ ref={mainView}
>
);