[MM-48515] Reuse ChannelListRow component to make it selectable maintaining compatibility (#6778)
* Moving ChannelListRow to component * selectable
This commit is contained in:
parent
4bacba92bb
commit
da31c9c3cf
4 changed files with 645 additions and 3 deletions
|
|
@ -0,0 +1,470 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/channel_list_row should be selected 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"paddingVertical": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel"
|
||||
>
|
||||
<Icon
|
||||
name="circle-multiple-outline"
|
||||
size={20}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.56)",
|
||||
"padding": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flexDirection": "column",
|
||||
"marginLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel.display_name"
|
||||
>
|
||||
channel
|
||||
</Text>
|
||||
<Text
|
||||
ellipsizeMode="tail"
|
||||
numberOfLines={1}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.64)",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 12,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
My purpose
|
||||
</Text>
|
||||
</View>
|
||||
<View>
|
||||
<Icon
|
||||
color="#1c58d9"
|
||||
name="check-circle"
|
||||
size={28}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`components/channel_list_row should match snapshot with delete_at filled in 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"paddingVertical": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel"
|
||||
>
|
||||
<Icon
|
||||
name="archive-outline"
|
||||
size={20}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.56)",
|
||||
"padding": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flexDirection": "column",
|
||||
"marginLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel.display_name"
|
||||
>
|
||||
channel
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`components/channel_list_row should match snapshot with open channel icon 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"paddingVertical": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel"
|
||||
>
|
||||
<Icon
|
||||
name="circle-multiple-outline"
|
||||
size={20}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.56)",
|
||||
"padding": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flexDirection": "column",
|
||||
"marginLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel.display_name"
|
||||
>
|
||||
channel
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`components/channel_list_row should match snapshot with private channel icon 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"paddingVertical": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel"
|
||||
>
|
||||
<Icon
|
||||
name="circle-multiple-outline"
|
||||
size={20}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.56)",
|
||||
"padding": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flexDirection": "column",
|
||||
"marginLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel.display_name"
|
||||
>
|
||||
channel
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`components/channel_list_row should match snapshot with purpose filled in 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"paddingVertical": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel"
|
||||
>
|
||||
<Icon
|
||||
name="circle-multiple-outline"
|
||||
size={20}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.56)",
|
||||
"padding": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flexDirection": "column",
|
||||
"marginLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel.display_name"
|
||||
>
|
||||
channel
|
||||
</Text>
|
||||
<Text
|
||||
ellipsizeMode="tail"
|
||||
numberOfLines={1}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.64)",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 12,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
My purpose
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`components/channel_list_row should match snapshot with shared filled in 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"paddingVertical": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel"
|
||||
>
|
||||
<Icon
|
||||
name="circle-multiple-outline"
|
||||
size={20}
|
||||
style={
|
||||
{
|
||||
"color": "rgba(63,67,80,0.56)",
|
||||
"padding": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flexDirection": "column",
|
||||
"marginLeft": 16,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
{
|
||||
"color": "#3f4350",
|
||||
"fontFamily": "OpenSans",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "400",
|
||||
"lineHeight": 24,
|
||||
}
|
||||
}
|
||||
testID="ChannelListRow.channel.display_name"
|
||||
>
|
||||
channel
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
151
app/components/channel_list_row/index.test.tsx
Normal file
151
app/components/channel_list_row/index.test.tsx
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import Database from '@nozbe/watermelondb/Database';
|
||||
import React from 'react';
|
||||
|
||||
import {renderWithEverything} from '@test/intl-test-helper';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import ChannelListRow from '.';
|
||||
|
||||
describe('components/channel_list_row', () => {
|
||||
let database: Database;
|
||||
const channel: Channel = {
|
||||
id: '1',
|
||||
create_at: 1111,
|
||||
update_at: 1111,
|
||||
delete_at: 0,
|
||||
team_id: 'my team',
|
||||
type: 'O',
|
||||
display_name: 'channel',
|
||||
name: 'channel',
|
||||
header: 'channel',
|
||||
purpose: '',
|
||||
last_post_at: 1,
|
||||
total_msg_count: 1,
|
||||
extra_update_at: 1,
|
||||
creator_id: '1',
|
||||
scheme_id: null,
|
||||
group_constrained: null,
|
||||
shared: true,
|
||||
};
|
||||
beforeAll(async () => {
|
||||
const server = await TestHelper.setupServerDatabase();
|
||||
database = server.database;
|
||||
});
|
||||
|
||||
it('should match snapshot with open channel icon', () => {
|
||||
const wrapper = renderWithEverything(
|
||||
<ChannelListRow
|
||||
channel={channel}
|
||||
selected={false}
|
||||
selectable={false}
|
||||
testID='ChannelListRow'
|
||||
onPress={() => {
|
||||
// noop
|
||||
}}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
expect(wrapper.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with private channel icon', () => {
|
||||
channel.type = 'P';
|
||||
|
||||
const wrapper = renderWithEverything(
|
||||
<ChannelListRow
|
||||
channel={channel}
|
||||
selected={false}
|
||||
selectable={false}
|
||||
testID='ChannelListRow'
|
||||
onPress={() => {
|
||||
// noop
|
||||
}}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
expect(wrapper.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with delete_at filled in', () => {
|
||||
channel.delete_at = 1111;
|
||||
channel.shared = false;
|
||||
channel.type = 'O';
|
||||
|
||||
const wrapper = renderWithEverything(
|
||||
<ChannelListRow
|
||||
channel={channel}
|
||||
testID='ChannelListRow'
|
||||
selectable={false}
|
||||
selected={false}
|
||||
onPress={() => {
|
||||
// noop
|
||||
}}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
expect(wrapper.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with shared filled in', () => {
|
||||
channel.delete_at = 0;
|
||||
channel.shared = true;
|
||||
channel.type = 'O';
|
||||
|
||||
const wrapper = renderWithEverything(
|
||||
<ChannelListRow
|
||||
channel={channel}
|
||||
testID='ChannelListRow'
|
||||
selectable={false}
|
||||
selected={false}
|
||||
onPress={() => {
|
||||
// noop
|
||||
}}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
expect(wrapper.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with purpose filled in', () => {
|
||||
channel.purpose = 'My purpose';
|
||||
|
||||
const wrapper = renderWithEverything(
|
||||
<ChannelListRow
|
||||
channel={channel}
|
||||
testID='ChannelListRow'
|
||||
selectable={false}
|
||||
selected={false}
|
||||
onPress={() => {
|
||||
// noop
|
||||
}}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
expect(wrapper.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should be selected', () => {
|
||||
const wrapper = renderWithEverything(
|
||||
<ChannelListRow
|
||||
channel={channel}
|
||||
testID='ChannelListRow'
|
||||
selectable={true}
|
||||
selected={true}
|
||||
onPress={() => {
|
||||
// noop
|
||||
}}
|
||||
/>,
|
||||
{database},
|
||||
);
|
||||
|
||||
expect(wrapper.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import React, {useMemo} from 'react';
|
||||
import {
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
|
|
@ -17,6 +17,8 @@ type Props = {
|
|||
channel: Channel;
|
||||
onPress: (channel: Channel) => void;
|
||||
testID?: string;
|
||||
selectable?: boolean;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
|
||||
|
|
@ -51,6 +53,8 @@ export default function ChannelListRow({
|
|||
channel,
|
||||
onPress,
|
||||
testID,
|
||||
selectable = false,
|
||||
selected = false,
|
||||
}: Props) {
|
||||
const theme = useTheme();
|
||||
const style = getStyleFromTheme(theme);
|
||||
|
|
@ -59,6 +63,23 @@ export default function ChannelListRow({
|
|||
onPress(channel);
|
||||
};
|
||||
|
||||
const selectionIcon = useMemo(() => {
|
||||
if (!selectable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const color = selected ? theme.buttonBg : theme.centerChannelColor;
|
||||
return (
|
||||
<View style={style.selector}>
|
||||
<CompassIcon
|
||||
name={selected ? 'check-circle' : 'circle-outline'}
|
||||
size={28}
|
||||
color={color}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}, [selectable, selected, theme]);
|
||||
|
||||
let purposeComponent;
|
||||
if (channel.purpose) {
|
||||
purposeComponent = (
|
||||
|
|
@ -105,6 +126,7 @@ export default function ChannelListRow({
|
|||
</Text>
|
||||
{purposeComponent}
|
||||
</View>
|
||||
{selectionIcon}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
import React, {useCallback, useMemo} from 'react';
|
||||
import {View, FlatList} from 'react-native';
|
||||
|
||||
import ChannelListRow from '@components/channel_list_row';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import Loading from '@components/loading';
|
||||
import NoResultsWithTerm from '@components/no_results_with_term';
|
||||
|
|
@ -11,8 +12,6 @@ import {useTheme} from '@context/theme';
|
|||
import {useKeyboardHeight} from '@hooks/device';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import ChannelListRow from './channel_list_row';
|
||||
|
||||
type Props = {
|
||||
onEndReached: () => void;
|
||||
loading: boolean;
|
||||
|
|
|
|||
Loading…
Reference in a new issue