mattermost-mobile/app/components/navigation_header/index.tsx
Daniel Espino García 23565b5135
Add autotranslations (#9324)
* Add autotranslations

* Develop latest changes and missing features

* i18n-extract

* Fix tests and update api behavior

* Fix minor bugs

* adjustments to shimmer animation, showtranslation modal style

* Update post.tsx

* Update show_translation.tsx

* adjust sizing and opacity of translate icon

* Add channel header translated icon

* Disable auto translation item if it is not a supported language

* Move channel info to the top

* Update edit channel to channel info

* Fix align of option items

* Fix i18n

* Add detox related changes for channel settings changes

* Add tests

* Address changes around the my channel column change

* Address feedback

* Fix test

* Fix bad import

* Fix set my channel autotranslation

* Fix test

* Address feedback

* Add missing files from last commit

* Remove unneeded change

---------

Co-authored-by: Matthew Birtch <mattbirtch@gmail.com>
2026-02-10 17:50:39 +01:00

133 lines
4.3 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {forwardRef} from 'react';
import Animated, {useAnimatedStyle, useDerivedValue} from 'react-native-reanimated';
import {SEARCH_INPUT_HEIGHT, SEARCH_INPUT_MARGIN} from '@constants/view';
import {useTheme} from '@context/theme';
import useHeaderHeight, {MAX_OVERSCROLL} from '@hooks/header';
import {clamp} from '@utils/gallery';
import {makeStyleSheetFromTheme} from '@utils/theme';
import Header, {type HeaderRightButton} from './header';
import NavigationHeaderLargeTitle from './large';
import NavigationSearch from './search';
import type {SearchProps, SearchRef} from '@components/search';
type Props = SearchProps & {
hasSearch?: boolean;
isLargeTitle?: boolean;
leftComponent?: React.ReactElement;
onBackPress?: () => void;
onTitlePress?: () => void;
rightButtons?: HeaderRightButton[];
scrollValue?: Animated.SharedValue<number>;
lockValue?: number;
hideHeader?: () => void;
showBackButton?: boolean;
subtitle?: string;
subtitleCompanion?: React.ReactElement;
title?: string;
titleCompanion?: React.ReactElement;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
backgroundColor: theme.sidebarBg,
position: 'absolute',
width: '100%',
zIndex: 10,
},
}));
const NavigationHeader = forwardRef<SearchRef, Props>(({
hasSearch = false,
isLargeTitle = false,
leftComponent,
onBackPress,
onTitlePress,
rightButtons,
scrollValue,
lockValue,
showBackButton,
subtitle,
subtitleCompanion,
title = '',
titleCompanion,
hideHeader,
...searchProps
}: Props, ref) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
const {largeHeight, defaultHeight, headerOffset} = useHeaderHeight();
const minScrollValue = useDerivedValue(() => scrollValue?.value || 0, [scrollValue]);
const containerHeight = useAnimatedStyle(() => {
const calculatedHeight = (isLargeTitle ? largeHeight : defaultHeight) - minScrollValue.value;
const height = lockValue || calculatedHeight;
return {
height: Math.max(height, defaultHeight),
minHeight: defaultHeight,
maxHeight: largeHeight + MAX_OVERSCROLL,
};
}, [defaultHeight, largeHeight, lockValue, isLargeTitle]);
const translateY = useDerivedValue(() => (
lockValue ? -lockValue : Math.min(-minScrollValue.value, headerOffset)
), [lockValue, headerOffset]);
const searchTopStyle = useAnimatedStyle(() => {
const margin = clamp(-minScrollValue.value, -headerOffset, headerOffset);
const marginTop = (lockValue ? -lockValue : margin) - SEARCH_INPUT_HEIGHT - SEARCH_INPUT_MARGIN;
return {marginTop};
}, [lockValue, headerOffset]);
return (
<Animated.View style={[styles.container, containerHeight]}>
<Header
defaultHeight={defaultHeight}
hasSearch={hasSearch}
isLargeTitle={isLargeTitle}
heightOffset={lockValue || headerOffset}
leftComponent={leftComponent}
onBackPress={onBackPress}
onTitlePress={onTitlePress}
rightButtons={rightButtons}
scrollValue={scrollValue}
showBackButton={showBackButton}
subtitle={subtitle}
subtitleCompanion={subtitleCompanion}
theme={theme}
title={title}
titleCompanion={titleCompanion}
/>
{isLargeTitle &&
<NavigationHeaderLargeTitle
heightOffset={lockValue || headerOffset}
hasSearch={hasSearch}
subtitle={subtitle}
theme={theme}
title={title}
translateY={translateY}
/>
}
{hasSearch &&
<NavigationSearch
{...searchProps}
hideHeader={hideHeader}
theme={theme}
topStyle={searchTopStyle}
ref={ref}
/>
}
</Animated.View>
);
});
NavigationHeader.displayName = 'NavHeader';
export default NavigationHeader;