mattermost-mobile/app/components/option_box/index.tsx
Christopher Poile 17dbfdcb99
MM-45745 - Calls channel info screen options (#6502)
* implement calls_channel_info; joinCall refactoring

* i18n

* Start/Join call as top button; movable copy channel link button

* MM-45971 - Calls v2 PR comments (#6514)

* don't clobber config if api req failed

* combine two loops into one

* update dependencies

* fetch user model on user connected

* fix state exports; spacing; unneeded field in ServerConfig type

* remove useless return in websocket handler

* constant sorting

* move microphone permission request to leave_and_join_alert

* ServerConfig -> ServerCallsConfig

* console.log -> logError

* ternary -> Platform.select

* merge conflicts

* add destructive options to OptionBox; require DismissChannelInfo fn

* add CopyLink option to quick actions list

* showSnackBar on link copied

* adjust quick_options_height

* Screens.Call

* fix CopyLink spacing

* fix observeUsersById, observe needed columns; fix JoinCallBanner mount

* optimized observables; bug fixes

* remove unneeded `return null`

* PR comments

* readable-stream -> 3.6.0

* merge conflicts

* PR comments
2022-07-29 11:10:32 -04:00

125 lines
3.9 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback, useEffect, useState} from 'react';
import {Pressable, PressableStateCallbackType, StyleProp, Text, ViewStyle} from 'react-native';
import CompassIcon from '@components/compass_icon';
import {useTheme} from '@context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
type OptionBoxProps = {
activeIconName?: string;
activeText?: string;
containerStyle?: StyleProp<ViewStyle>;
iconName: string;
isActive?: boolean;
onPress: () => void;
testID?: string;
text: string;
destructiveIconName?: string;
destructiveText?: string;
isDestructive?: boolean;
}
export const OPTIONS_HEIGHT = 62;
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
alignItems: 'center',
backgroundColor: changeOpacity(theme.centerChannelColor, 0.04),
borderRadius: 4,
flex: 1,
maxHeight: OPTIONS_HEIGHT,
justifyContent: 'center',
minWidth: 80,
},
destructiveContainer: {
backgroundColor: changeOpacity(theme.dndIndicator, 0.04),
},
text: {
color: changeOpacity(theme.centerChannelColor, 0.56),
paddingHorizontal: 5,
...typography('Body', 50, 'SemiBold'),
},
}));
const OptionBox = ({
activeIconName,
activeText,
containerStyle,
iconName,
isActive,
onPress,
testID,
text,
destructiveIconName,
destructiveText,
isDestructive,
}: OptionBoxProps) => {
const theme = useTheme();
const [activated, setActivated] = useState(isActive);
const styles = getStyleSheet(theme);
const pressedStyle = useCallback(({pressed}: PressableStateCallbackType) => {
const style = [styles.container, containerStyle, isDestructive && styles.destructiveContainer];
const baseBgColor = isDestructive ? theme.dndIndicator : theme.buttonBg;
if (activated) {
style.push({
backgroundColor: changeOpacity(baseBgColor, 0.08),
});
}
if (pressed) {
style.push({
backgroundColor: changeOpacity(baseBgColor, 0.16),
});
}
return style;
}, [activated, containerStyle, theme, isDestructive]);
const handleOnPress = useCallback(() => {
if (activeIconName || activeText) {
setActivated(!activated);
}
onPress();
}, [activated, activeIconName, activeText, onPress]);
useEffect(() => {
setActivated(isActive);
}, [isActive]);
const destructIconName = (isDestructive && destructiveIconName) ? destructiveIconName : undefined;
const destructColor = isDestructive ? theme.dndIndicator : undefined;
const destructText = (isDestructive && destructiveText) ? destructiveText : undefined;
return (
<Pressable
onPress={handleOnPress}
style={pressedStyle}
testID={testID}
>
{({pressed}) => (
<>
<CompassIcon
color={destructColor || ((pressed || activated) ? theme.buttonBg : changeOpacity(theme.centerChannelColor, 0.56))}
name={destructIconName || (activated && activeIconName ? activeIconName : iconName)}
size={24}
/>
<Text
numberOfLines={1}
style={[styles.text, {color: destructColor || ((pressed || activated) ? theme.buttonBg : changeOpacity(theme.centerChannelColor, 0.56))}]}
testID={`${testID}.label`}
>
{destructText || (activated && activeText ? activeText : text)}
</Text>
</>
)}
</Pressable>
);
};
export default OptionBox;