[NEW] Basic support to Teams (#3016)
* Database migration * RoomItem icon * Team icons * Teams group * Small tweak on RoomTypeIcon * RoomView Header * Add team's channels to RoomView header * Starting TeamChannelsView * Icon size * o data found * Update TeamChannelsView, add teams subscriptions and send params to TeamChannelsView * Use teams.ListRooms endpoint, render rooms list, remove unused functions * Show team main on TeamChannelsView * Disable swipe * Pagination working * Fix blinking no data found * Search working * Refactor to use BackgroundContainer while loading * Go to room * Cleanup * Go to actions * Events * Lint * Add debounce to go room * Fix for tablet * i18n * Small fix * Minor refactor * Use local data when it exists * Show last message * Force teams migration * Add stories to BackgroundContainer * Remove unused component * Move RoomViewHeader into containers folder * Refactoring * Testing RoomHeader * i18n * Fix server endpoint version * Fix events Co-authored-by: Gerzon Z <gerzonzcanario@gmail.com>
This commit is contained in:
parent
5a96f1ff6b
commit
d04d0f27b6
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
ImageBackground, StyleSheet, Text, View
|
ImageBackground, StyleSheet, Text, View, ActivityIndicator
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -29,15 +29,17 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const EmptyRoom = ({ theme, text }) => (
|
const BackgroundContainer = ({ theme, text, loading }) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<ImageBackground source={{ uri: `message_empty_${ theme }` }} style={styles.image} />
|
<ImageBackground source={{ uri: `message_empty_${ theme }` }} style={styles.image} />
|
||||||
<Text style={[styles.text, { color: themes[theme].auxiliaryTintColor }]}>{text}</Text>
|
{text ? <Text style={[styles.text, { color: themes[theme].auxiliaryTintColor }]}>{text}</Text> : null}
|
||||||
|
{loading ? <ActivityIndicator style={[styles.text, { color: themes[theme].auxiliaryTintColor }]} /> : null}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
EmptyRoom.propTypes = {
|
BackgroundContainer.propTypes = {
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
theme: PropTypes.string
|
theme: PropTypes.string,
|
||||||
|
loading: PropTypes.bool
|
||||||
};
|
};
|
||||||
export default withTheme(EmptyRoom);
|
export default withTheme(BackgroundContainer);
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types */
|
||||||
|
import React from 'react';
|
||||||
|
import { storiesOf } from '@storybook/react-native';
|
||||||
|
|
||||||
|
import BackgroundContainer from '.';
|
||||||
|
import { ThemeContext } from '../../theme';
|
||||||
|
import { longText } from '../../../storybook/utils';
|
||||||
|
|
||||||
|
const stories = storiesOf('BackgroundContainer', module);
|
||||||
|
|
||||||
|
stories.add('basic', () => (
|
||||||
|
<BackgroundContainer />
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('loading', () => (
|
||||||
|
<BackgroundContainer loading />
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('text', () => (
|
||||||
|
<BackgroundContainer text='Text here' />
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('long text', () => (
|
||||||
|
<BackgroundContainer text={longText} />
|
||||||
|
));
|
||||||
|
|
||||||
|
const ThemeStory = ({ theme, ...props }) => (
|
||||||
|
<ThemeContext.Provider
|
||||||
|
value={{ theme }}
|
||||||
|
>
|
||||||
|
<BackgroundContainer {...props} />
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
|
||||||
|
stories.add('dark theme - loading', () => (
|
||||||
|
<ThemeStory theme='dark' loading />
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('dark theme - text', () => (
|
||||||
|
<ThemeStory theme='dark' text={longText} />
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('black theme - loading', () => (
|
||||||
|
<ThemeStory theme='black' loading />
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('black theme - text', () => (
|
||||||
|
<ThemeStory theme='black' text={longText} />
|
||||||
|
));
|
|
@ -4,16 +4,21 @@ import {
|
||||||
View, Text, StyleSheet, TouchableOpacity
|
View, Text, StyleSheet, TouchableOpacity
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
import I18n from '../../../i18n';
|
import I18n from '../../i18n';
|
||||||
import sharedStyles from '../../Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import Markdown from '../../../containers/markdown';
|
import Markdown from '../markdown';
|
||||||
import RoomTypeIcon from '../../../containers/RoomTypeIcon';
|
import RoomTypeIcon from '../RoomTypeIcon';
|
||||||
|
import { withTheme } from '../../theme';
|
||||||
|
|
||||||
const HIT_SLOP = {
|
const HIT_SLOP = {
|
||||||
top: 5, right: 5, bottom: 5, left: 5
|
top: 5, right: 5, bottom: 5, left: 5
|
||||||
};
|
};
|
||||||
const TITLE_SIZE = 16;
|
const TITLE_SIZE = 16;
|
||||||
|
const SUBTITLE_SIZE = 12;
|
||||||
|
|
||||||
|
const getSubTitleSize = scale => SUBTITLE_SIZE * scale;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -24,12 +29,12 @@ const styles = StyleSheet.create({
|
||||||
flexDirection: 'row'
|
flexDirection: 'row'
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
...sharedStyles.textSemibold,
|
flexShrink: 1,
|
||||||
fontSize: TITLE_SIZE
|
...sharedStyles.textSemibold
|
||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
...sharedStyles.textRegular,
|
flexShrink: 1,
|
||||||
fontSize: 12
|
...sharedStyles.textRegular
|
||||||
},
|
},
|
||||||
typingUsers: {
|
typingUsers: {
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold
|
||||||
|
@ -37,8 +42,9 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
const SubTitle = React.memo(({
|
const SubTitle = React.memo(({
|
||||||
usersTyping, subtitle, renderFunc, theme
|
usersTyping, subtitle, renderFunc, theme, scale
|
||||||
}) => {
|
}) => {
|
||||||
|
const fontSize = getSubTitleSize(scale);
|
||||||
// typing
|
// typing
|
||||||
if (usersTyping.length) {
|
if (usersTyping.length) {
|
||||||
let usersText;
|
let usersText;
|
||||||
|
@ -48,7 +54,7 @@ const SubTitle = React.memo(({
|
||||||
usersText = usersTyping.join(', ');
|
usersText = usersTyping.join(', ');
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>
|
<Text style={[styles.subtitle, { fontSize, color: themes[theme].auxiliaryText }]} numberOfLines={1}>
|
||||||
<Text style={styles.typingUsers}>{usersText} </Text>
|
<Text style={styles.typingUsers}>{usersText} </Text>
|
||||||
{ usersTyping.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing') }...
|
{ usersTyping.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing') }...
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -66,7 +72,7 @@ const SubTitle = React.memo(({
|
||||||
<Markdown
|
<Markdown
|
||||||
preview
|
preview
|
||||||
msg={subtitle}
|
msg={subtitle}
|
||||||
style={[styles.subtitle, { color: themes[theme].auxiliaryText }]}
|
style={[styles.subtitle, { fontSize, color: themes[theme].auxiliaryText }]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
|
@ -80,18 +86,20 @@ SubTitle.propTypes = {
|
||||||
usersTyping: PropTypes.array,
|
usersTyping: PropTypes.array,
|
||||||
theme: PropTypes.string,
|
theme: PropTypes.string,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.string,
|
||||||
renderFunc: PropTypes.func
|
renderFunc: PropTypes.func,
|
||||||
|
scale: PropTypes.number
|
||||||
};
|
};
|
||||||
|
|
||||||
const HeaderTitle = React.memo(({
|
const HeaderTitle = React.memo(({
|
||||||
title, tmid, prid, scale, theme
|
title, tmid, prid, scale, theme, testID
|
||||||
}) => {
|
}) => {
|
||||||
|
const titleStyle = { fontSize: TITLE_SIZE * scale, color: themes[theme].headerTitleColor };
|
||||||
if (!tmid && !prid) {
|
if (!tmid && !prid) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
style={[styles.title, { fontSize: TITLE_SIZE * scale, color: themes[theme].headerTitleColor }]}
|
style={[styles.title, titleStyle]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
testID={`room-view-title-${ title }`}
|
testID={testID}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -102,10 +110,10 @@ const HeaderTitle = React.memo(({
|
||||||
<Markdown
|
<Markdown
|
||||||
preview
|
preview
|
||||||
msg={title}
|
msg={title}
|
||||||
style={[styles.title, { fontSize: TITLE_SIZE * scale, color: themes[theme].headerTitleColor }]}
|
style={[styles.title, titleStyle]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
testID={`room-view-title-${ title }`}
|
testID={testID}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -115,11 +123,12 @@ HeaderTitle.propTypes = {
|
||||||
tmid: PropTypes.string,
|
tmid: PropTypes.string,
|
||||||
prid: PropTypes.string,
|
prid: PropTypes.string,
|
||||||
scale: PropTypes.number,
|
scale: PropTypes.number,
|
||||||
theme: PropTypes.string
|
theme: PropTypes.string,
|
||||||
|
testID: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = React.memo(({
|
const Header = React.memo(({
|
||||||
title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, connecting, goRoomActionsView, theme, isGroupChat
|
title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID
|
||||||
}) => {
|
}) => {
|
||||||
const portrait = height > width;
|
const portrait = height > width;
|
||||||
let scale = 1;
|
let scale = 1;
|
||||||
|
@ -130,13 +139,11 @@ const Header = React.memo(({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPress = () => goRoomActionsView();
|
|
||||||
|
|
||||||
let renderFunc;
|
let renderFunc;
|
||||||
if (tmid) {
|
if (tmid) {
|
||||||
renderFunc = () => (
|
renderFunc = () => (
|
||||||
<View style={styles.titleContainer}>
|
<View style={styles.titleContainer}>
|
||||||
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />
|
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />
|
||||||
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{parentTitle}</Text>
|
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{parentTitle}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@ -144,7 +151,7 @@ const Header = React.memo(({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID='room-view-header-actions'
|
testID='room-header'
|
||||||
accessibilityLabel={title}
|
accessibilityLabel={title}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
style={styles.container}
|
style={styles.container}
|
||||||
|
@ -152,17 +159,23 @@ const Header = React.memo(({
|
||||||
hitSlop={HIT_SLOP}
|
hitSlop={HIT_SLOP}
|
||||||
>
|
>
|
||||||
<View style={styles.titleContainer}>
|
<View style={styles.titleContainer}>
|
||||||
{tmid ? null : <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />}
|
{tmid ? null : <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />}
|
||||||
<HeaderTitle
|
<HeaderTitle
|
||||||
title={title}
|
title={title}
|
||||||
tmid={tmid}
|
tmid={tmid}
|
||||||
prid={prid}
|
prid={prid}
|
||||||
scale={scale}
|
scale={scale}
|
||||||
connecting={connecting}
|
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
testID={testID}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<SubTitle usersTyping={tmid ? [] : usersTyping} subtitle={subtitle} theme={theme} renderFunc={renderFunc} />
|
<SubTitle
|
||||||
|
usersTyping={tmid ? [] : usersTyping}
|
||||||
|
subtitle={subtitle}
|
||||||
|
theme={theme}
|
||||||
|
renderFunc={renderFunc}
|
||||||
|
scale={scale}
|
||||||
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -175,17 +188,18 @@ Header.propTypes = {
|
||||||
height: PropTypes.number.isRequired,
|
height: PropTypes.number.isRequired,
|
||||||
prid: PropTypes.string,
|
prid: PropTypes.string,
|
||||||
tmid: PropTypes.string,
|
tmid: PropTypes.string,
|
||||||
|
teamMain: PropTypes.bool,
|
||||||
status: PropTypes.string,
|
status: PropTypes.string,
|
||||||
theme: PropTypes.string,
|
theme: PropTypes.string,
|
||||||
usersTyping: PropTypes.array,
|
usersTyping: PropTypes.array,
|
||||||
connecting: PropTypes.bool,
|
|
||||||
isGroupChat: PropTypes.bool,
|
isGroupChat: PropTypes.bool,
|
||||||
parentTitle: PropTypes.string,
|
parentTitle: PropTypes.string,
|
||||||
goRoomActionsView: PropTypes.func
|
onPress: PropTypes.func,
|
||||||
|
testID: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
Header.defaultProps = {
|
Header.defaultProps = {
|
||||||
usersTyping: []
|
usersTyping: []
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Header;
|
export default withTheme(Header);
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types, react/destructuring-assignment */
|
||||||
|
import React from 'react';
|
||||||
|
import { View, Dimensions } from 'react-native';
|
||||||
|
import { storiesOf } from '@storybook/react-native';
|
||||||
|
|
||||||
|
import RoomHeaderComponent from './RoomHeader';
|
||||||
|
import Header from '../Header';
|
||||||
|
import { longText } from '../../../storybook/utils';
|
||||||
|
import { ThemeContext } from '../../theme';
|
||||||
|
|
||||||
|
const stories = storiesOf('RoomHeader', module);
|
||||||
|
|
||||||
|
// TODO: refactor after react-navigation v6
|
||||||
|
const HeaderExample = ({ title }) => (
|
||||||
|
<Header
|
||||||
|
headerTitle={() => (
|
||||||
|
<View style={{ flex: 1, paddingHorizontal: 12 }}>
|
||||||
|
{title()}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const { width, height } = Dimensions.get('window');
|
||||||
|
|
||||||
|
const RoomHeader = ({ ...props }) => (
|
||||||
|
<RoomHeaderComponent width={width} height={height} title='title' type='p' testID={props.title} onPress={() => alert('header pressed!')} {...props} />
|
||||||
|
);
|
||||||
|
|
||||||
|
stories.add('title and subtitle', () => (
|
||||||
|
<>
|
||||||
|
<HeaderExample title={() => <RoomHeader title='title' type='p' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title={longText} type='p' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader subtitle='subtitle' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader subtitle={longText} />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title={longText} subtitle={longText} />} />
|
||||||
|
</>
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('icons', () => (
|
||||||
|
<>
|
||||||
|
<HeaderExample title={() => <RoomHeader title='private channel' type='p' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='public channel' type='c' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='discussion' prid='asd' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='omnichannel' type='l' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='private team' type='p' teamMain />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='public team' type='c' teamMain />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='group dm' type='d' isGroupChat />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='online dm' type='d' status='online' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='away dm' type='d' status='away' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='busy dm' type='d' status='busy' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='loading dm' type='d' status='loading' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader title='offline dm' type='d' />} />
|
||||||
|
</>
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('typing', () => (
|
||||||
|
<>
|
||||||
|
<HeaderExample title={() => <RoomHeader usersTyping={['user 1']} />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader usersTyping={['user 1', 'user 2']} />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader usersTyping={['user 1', 'user 2', 'user 3', 'user 4', 'user 5']} />} />
|
||||||
|
</>
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('landscape', () => (
|
||||||
|
<>
|
||||||
|
<HeaderExample title={() => <RoomHeader width={height} height={width} />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader width={height} height={width} subtitle='subtitle' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader width={height} height={width} title={longText} subtitle={longText} />} />
|
||||||
|
</>
|
||||||
|
));
|
||||||
|
|
||||||
|
stories.add('thread', () => (
|
||||||
|
<>
|
||||||
|
<HeaderExample title={() => <RoomHeader tmid='123' parentTitle='parent title' />} />
|
||||||
|
<HeaderExample title={() => <RoomHeader tmid='123' title={'markdown\npreview\n#3\n4\n5'} parentTitle={longText} />} />
|
||||||
|
</>
|
||||||
|
));
|
||||||
|
|
||||||
|
const ThemeStory = ({ theme }) => (
|
||||||
|
<ThemeContext.Provider
|
||||||
|
value={{ theme }}
|
||||||
|
>
|
||||||
|
<HeaderExample title={() => <RoomHeader subtitle='subtitle' />} />
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
|
||||||
|
stories.add('themes', () => (
|
||||||
|
<>
|
||||||
|
<ThemeStory theme='light' />
|
||||||
|
<ThemeStory theme='dark' />
|
||||||
|
<ThemeStory theme='black' />
|
||||||
|
</>
|
||||||
|
));
|
|
@ -3,42 +3,37 @@ import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
|
||||||
import Header from './Header';
|
import RoomHeader from './RoomHeader';
|
||||||
import LeftButtons from './LeftButtons';
|
import { withDimensions } from '../../dimensions';
|
||||||
import RightButtons from './RightButtons';
|
import I18n from '../../i18n';
|
||||||
import { withTheme } from '../../../theme';
|
|
||||||
import { withDimensions } from '../../../dimensions';
|
|
||||||
import I18n from '../../../i18n';
|
|
||||||
|
|
||||||
class RoomHeaderView extends Component {
|
class RoomHeaderContainer extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.string,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
prid: PropTypes.string,
|
prid: PropTypes.string,
|
||||||
tmid: PropTypes.string,
|
tmid: PropTypes.string,
|
||||||
|
teamMain: PropTypes.bool,
|
||||||
usersTyping: PropTypes.string,
|
usersTyping: PropTypes.string,
|
||||||
status: PropTypes.string,
|
status: PropTypes.string,
|
||||||
statusText: PropTypes.string,
|
statusText: PropTypes.string,
|
||||||
connecting: PropTypes.bool,
|
connecting: PropTypes.bool,
|
||||||
connected: PropTypes.bool,
|
connected: PropTypes.bool,
|
||||||
theme: PropTypes.string,
|
|
||||||
roomUserId: PropTypes.string,
|
roomUserId: PropTypes.string,
|
||||||
widthOffset: PropTypes.number,
|
widthOffset: PropTypes.number,
|
||||||
goRoomActionsView: PropTypes.func,
|
onPress: PropTypes.func,
|
||||||
width: PropTypes.number,
|
width: PropTypes.number,
|
||||||
height: PropTypes.number,
|
height: PropTypes.number,
|
||||||
parentTitle: PropTypes.string,
|
parentTitle: PropTypes.string,
|
||||||
isGroupChat: PropTypes.bool
|
isGroupChat: PropTypes.bool,
|
||||||
|
testID: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
const {
|
const {
|
||||||
type, title, subtitle, status, statusText, connecting, connected, goRoomActionsView, usersTyping, theme, width, height
|
type, title, subtitle, status, statusText, connecting, connected, onPress, usersTyping, width, height
|
||||||
} = this.props;
|
} = this.props;
|
||||||
if (nextProps.theme !== theme) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.type !== type) {
|
if (nextProps.type !== type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +64,7 @@ class RoomHeaderView extends Component {
|
||||||
if (!dequal(nextProps.usersTyping, usersTyping)) {
|
if (!dequal(nextProps.usersTyping, usersTyping)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (nextProps.goRoomActionsView !== goRoomActionsView) {
|
if (nextProps.onPress !== onPress) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,6 +75,7 @@ class RoomHeaderView extends Component {
|
||||||
title,
|
title,
|
||||||
subtitle: subtitleProp,
|
subtitle: subtitleProp,
|
||||||
type,
|
type,
|
||||||
|
teamMain,
|
||||||
prid,
|
prid,
|
||||||
tmid,
|
tmid,
|
||||||
widthOffset,
|
widthOffset,
|
||||||
|
@ -88,13 +84,13 @@ class RoomHeaderView extends Component {
|
||||||
connecting,
|
connecting,
|
||||||
connected,
|
connected,
|
||||||
usersTyping,
|
usersTyping,
|
||||||
goRoomActionsView,
|
onPress,
|
||||||
roomUserId,
|
roomUserId,
|
||||||
theme,
|
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
parentTitle,
|
parentTitle,
|
||||||
isGroupChat
|
isGroupChat,
|
||||||
|
testID
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let subtitle;
|
let subtitle;
|
||||||
|
@ -107,23 +103,24 @@ class RoomHeaderView extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header
|
<RoomHeader
|
||||||
prid={prid}
|
prid={prid}
|
||||||
tmid={tmid}
|
tmid={tmid}
|
||||||
title={title}
|
title={title}
|
||||||
subtitle={type === 'd' ? statusText : subtitle}
|
subtitle={type === 'd' ? statusText : subtitle}
|
||||||
type={type}
|
type={type}
|
||||||
|
teamMain={teamMain}
|
||||||
status={status}
|
status={status}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
theme={theme}
|
|
||||||
usersTyping={usersTyping}
|
usersTyping={usersTyping}
|
||||||
widthOffset={widthOffset}
|
widthOffset={widthOffset}
|
||||||
roomUserId={roomUserId}
|
roomUserId={roomUserId}
|
||||||
goRoomActionsView={goRoomActionsView}
|
|
||||||
connecting={connecting}
|
connecting={connecting}
|
||||||
parentTitle={parentTitle}
|
parentTitle={parentTitle}
|
||||||
isGroupChat={isGroupChat}
|
isGroupChat={isGroupChat}
|
||||||
|
testID={testID}
|
||||||
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -153,6 +150,4 @@ const mapStateToProps = (state, ownProps) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withDimensions(withTheme(RoomHeaderView)));
|
export default connect(mapStateToProps)(withDimensions(RoomHeaderContainer));
|
||||||
|
|
||||||
export { RightButtons, LeftButtons };
|
|
|
@ -13,7 +13,7 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
const RoomTypeIcon = React.memo(({
|
const RoomTypeIcon = React.memo(({
|
||||||
type, size, isGroupChat, status, style, theme
|
type, size, isGroupChat, status, style, theme, teamMain
|
||||||
}) => {
|
}) => {
|
||||||
if (!type) {
|
if (!type) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -31,7 +31,9 @@ const RoomTypeIcon = React.memo(({
|
||||||
}
|
}
|
||||||
|
|
||||||
let icon = 'channel-private';
|
let icon = 'channel-private';
|
||||||
if (type === 'discussion') {
|
if (teamMain) {
|
||||||
|
icon = `teams${ type === 'p' ? '-private' : '' }`;
|
||||||
|
} else if (type === 'discussion') {
|
||||||
icon = 'discussions';
|
icon = 'discussions';
|
||||||
} else if (type === 'c') {
|
} else if (type === 'c') {
|
||||||
icon = 'channel-public';
|
icon = 'channel-public';
|
||||||
|
@ -58,6 +60,7 @@ RoomTypeIcon.propTypes = {
|
||||||
theme: PropTypes.string,
|
theme: PropTypes.string,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
isGroupChat: PropTypes.bool,
|
isGroupChat: PropTypes.bool,
|
||||||
|
teamMain: PropTypes.bool,
|
||||||
status: PropTypes.string,
|
status: PropTypes.string,
|
||||||
size: PropTypes.number,
|
size: PropTypes.number,
|
||||||
style: PropTypes.object
|
style: PropTypes.object
|
||||||
|
|
|
@ -706,5 +706,8 @@
|
||||||
"Enter_workspace_URL": "Enter workspace URL",
|
"Enter_workspace_URL": "Enter workspace URL",
|
||||||
"Workspace_URL_Example": "Ex. your-company.rocket.chat",
|
"Workspace_URL_Example": "Ex. your-company.rocket.chat",
|
||||||
"This_room_encryption_has_been_enabled_by__username_": "This room's encryption has been enabled by {{username}}",
|
"This_room_encryption_has_been_enabled_by__username_": "This room's encryption has been enabled by {{username}}",
|
||||||
"This_room_encryption_has_been_disabled_by__username_": "This room's encryption has been disabled by {{username}}"
|
"This_room_encryption_has_been_disabled_by__username_": "This room's encryption has been disabled by {{username}}",
|
||||||
|
"Teams": "Teams",
|
||||||
|
"No_team_channels_found": "No channels found",
|
||||||
|
"Team_not_found": "Team not found"
|
||||||
}
|
}
|
|
@ -656,5 +656,8 @@
|
||||||
"This_room_encryption_has_been_disabled_by__username_": "A criptografia para essa sala foi desabilitada por {{username}}",
|
"This_room_encryption_has_been_disabled_by__username_": "A criptografia para essa sala foi desabilitada por {{username}}",
|
||||||
"Apply_Your_Certificate": "Aplicar certificado",
|
"Apply_Your_Certificate": "Aplicar certificado",
|
||||||
"Do_you_have_a_certificate": "Você tem um certificado?",
|
"Do_you_have_a_certificate": "Você tem um certificado?",
|
||||||
"Your_certificate": "Seu certificado"
|
"Your_certificate": "Seu certificado",
|
||||||
|
"Teams": "Times",
|
||||||
|
"No_team_channels_found": "Nenhum canal encontrado",
|
||||||
|
"Team_not_found": "Time não encontrado"
|
||||||
}
|
}
|
|
@ -125,4 +125,8 @@ export default class Subscription extends Model {
|
||||||
@field('e2e_key_id') e2eKeyId;
|
@field('e2e_key_id') e2eKeyId;
|
||||||
|
|
||||||
@field('avatar_etag') avatarETag;
|
@field('avatar_etag') avatarETag;
|
||||||
|
|
||||||
|
@field('team_id') teamId;
|
||||||
|
|
||||||
|
@field('team_main') teamMain;
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,18 @@ export default schemaMigrations({
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toVersion: 13,
|
||||||
|
steps: [
|
||||||
|
addColumns({
|
||||||
|
table: 'subscriptions',
|
||||||
|
columns: [
|
||||||
|
{ name: 'team_id', type: 'string', isIndexed: true },
|
||||||
|
{ name: 'team_main', type: 'boolean', isOptional: true }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { appSchema, tableSchema } from '@nozbe/watermelondb';
|
import { appSchema, tableSchema } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
export default appSchema({
|
export default appSchema({
|
||||||
version: 12,
|
version: 13,
|
||||||
tables: [
|
tables: [
|
||||||
tableSchema({
|
tableSchema({
|
||||||
name: 'subscriptions',
|
name: 'subscriptions',
|
||||||
|
@ -57,7 +57,9 @@ export default appSchema({
|
||||||
{ name: 'e2e_key', type: 'string', isOptional: true },
|
{ name: 'e2e_key', type: 'string', isOptional: true },
|
||||||
{ name: 'encrypted', type: 'boolean', isOptional: true },
|
{ name: 'encrypted', type: 'boolean', isOptional: true },
|
||||||
{ name: 'e2e_key_id', type: 'string', isOptional: true },
|
{ name: 'e2e_key_id', type: 'string', isOptional: true },
|
||||||
{ name: 'avatar_etag', type: 'string', isOptional: true }
|
{ name: 'avatar_etag', type: 'string', isOptional: true },
|
||||||
|
{ name: 'team_id', type: 'string', isIndexed: true },
|
||||||
|
{ name: 'team_main', type: 'boolean', isOptional: true }
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
tableSchema({
|
tableSchema({
|
||||||
|
|
|
@ -42,6 +42,8 @@ export const merge = (subscription, room) => {
|
||||||
subscription.encrypted = room.encrypted;
|
subscription.encrypted = room.encrypted;
|
||||||
subscription.e2eKeyId = room.e2eKeyId;
|
subscription.e2eKeyId = room.e2eKeyId;
|
||||||
subscription.avatarETag = room.avatarETag;
|
subscription.avatarETag = room.avatarETag;
|
||||||
|
subscription.teamId = room.teamId;
|
||||||
|
subscription.teamMain = room.teamMain;
|
||||||
if (!subscription.roles || !subscription.roles.length) {
|
if (!subscription.roles || !subscription.roles.length) {
|
||||||
subscription.roles = [];
|
subscription.roles = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -931,6 +931,19 @@ const RocketChat = {
|
||||||
// RC 2.3.0
|
// RC 2.3.0
|
||||||
return this.sdk.get('livechat/visitors.info', { visitorId });
|
return this.sdk.get('livechat/visitors.info', { visitorId });
|
||||||
},
|
},
|
||||||
|
getTeamListRoom({
|
||||||
|
teamId, count, offset, type, filter
|
||||||
|
}) {
|
||||||
|
const params = {
|
||||||
|
teamId, count, offset, type
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
params.filter = filter;
|
||||||
|
}
|
||||||
|
// RC 3.13.0
|
||||||
|
return this.sdk.get('teams.listRooms', params);
|
||||||
|
},
|
||||||
closeLivechat(rid, comment) {
|
closeLivechat(rid, comment) {
|
||||||
// RC 0.29.0
|
// RC 0.29.0
|
||||||
return this.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true });
|
return this.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true });
|
||||||
|
|
|
@ -44,7 +44,8 @@ const RoomItem = ({
|
||||||
onPress,
|
onPress,
|
||||||
toggleFav,
|
toggleFav,
|
||||||
toggleRead,
|
toggleRead,
|
||||||
hideChannel
|
hideChannel,
|
||||||
|
teamMain
|
||||||
}) => (
|
}) => (
|
||||||
<Touchable
|
<Touchable
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
|
@ -78,6 +79,8 @@ const RoomItem = ({
|
||||||
prid={prid}
|
prid={prid}
|
||||||
status={status}
|
status={status}
|
||||||
isGroupChat={isGroupChat}
|
isGroupChat={isGroupChat}
|
||||||
|
theme={theme}
|
||||||
|
teamMain={teamMain}
|
||||||
/>
|
/>
|
||||||
<Title
|
<Title
|
||||||
name={name}
|
name={name}
|
||||||
|
@ -120,6 +123,8 @@ const RoomItem = ({
|
||||||
prid={prid}
|
prid={prid}
|
||||||
status={status}
|
status={status}
|
||||||
isGroupChat={isGroupChat}
|
isGroupChat={isGroupChat}
|
||||||
|
theme={theme}
|
||||||
|
teamMain={teamMain}
|
||||||
/>
|
/>
|
||||||
<Title
|
<Title
|
||||||
name={name}
|
name={name}
|
||||||
|
@ -159,6 +164,7 @@ RoomItem.propTypes = {
|
||||||
isFocused: PropTypes.bool,
|
isFocused: PropTypes.bool,
|
||||||
isGroupChat: PropTypes.bool,
|
isGroupChat: PropTypes.bool,
|
||||||
isRead: PropTypes.bool,
|
isRead: PropTypes.bool,
|
||||||
|
teamMain: PropTypes.bool,
|
||||||
date: PropTypes.string,
|
date: PropTypes.string,
|
||||||
accessibilityLabel: PropTypes.string,
|
accessibilityLabel: PropTypes.string,
|
||||||
lastMessage: PropTypes.object,
|
lastMessage: PropTypes.object,
|
||||||
|
|
|
@ -4,14 +4,15 @@ import PropTypes from 'prop-types';
|
||||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||||
|
|
||||||
const TypeIcon = React.memo(({
|
const TypeIcon = React.memo(({
|
||||||
type, prid, status, isGroupChat
|
type, prid, status, isGroupChat, teamMain
|
||||||
}) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />);
|
}) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />);
|
||||||
|
|
||||||
TypeIcon.propTypes = {
|
TypeIcon.propTypes = {
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
status: PropTypes.string,
|
status: PropTypes.string,
|
||||||
prid: PropTypes.string,
|
prid: PropTypes.string,
|
||||||
isGroupChat: PropTypes.bool
|
isGroupChat: PropTypes.bool,
|
||||||
|
teamMain: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TypeIcon;
|
export default TypeIcon;
|
||||||
|
|
|
@ -188,6 +188,7 @@ class RoomItemContainer extends React.Component {
|
||||||
tunreadUser={item.tunreadUser}
|
tunreadUser={item.tunreadUser}
|
||||||
tunreadGroup={item.tunreadGroup}
|
tunreadGroup={item.tunreadGroup}
|
||||||
swipeEnabled={swipeEnabled}
|
swipeEnabled={swipeEnabled}
|
||||||
|
teamMain={item.teamMain}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import mergeSubscriptionsRooms from '../lib/methods/helpers/mergeSubscriptionsRo
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import buildMessage from '../lib/methods/helpers/buildMessage';
|
import buildMessage from '../lib/methods/helpers/buildMessage';
|
||||||
import protectedFunction from '../lib/methods/helpers/protectedFunction';
|
import protectedFunction from '../lib/methods/helpers/protectedFunction';
|
||||||
|
import UserPreferences from '../lib/userPreferences';
|
||||||
|
|
||||||
const updateRooms = function* updateRooms({ server, newRoomsUpdatedAt }) {
|
const updateRooms = function* updateRooms({ server, newRoomsUpdatedAt }) {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
|
@ -47,6 +48,16 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
|
||||||
// Server not found
|
// Server not found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force fetch all subscriptions to update columns related to Teams feature
|
||||||
|
// TODO: remove it a couple of releases
|
||||||
|
const teamsMigrationKey = `${ server }_TEAMS_MIGRATION`;
|
||||||
|
const teamsMigration = yield UserPreferences.getBoolAsync(teamsMigrationKey);
|
||||||
|
if (!teamsMigration) {
|
||||||
|
roomsUpdatedAt = null;
|
||||||
|
UserPreferences.setBoolAsync(teamsMigrationKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
|
||||||
const { subscriptions } = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
const { subscriptions } = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import ForwardLivechatView from '../views/ForwardLivechatView';
|
||||||
import LivechatEditView from '../views/LivechatEditView';
|
import LivechatEditView from '../views/LivechatEditView';
|
||||||
import PickerView from '../views/PickerView';
|
import PickerView from '../views/PickerView';
|
||||||
import ThreadMessagesView from '../views/ThreadMessagesView';
|
import ThreadMessagesView from '../views/ThreadMessagesView';
|
||||||
|
import TeamChannelsView from '../views/TeamChannelsView';
|
||||||
import MarkdownTableView from '../views/MarkdownTableView';
|
import MarkdownTableView from '../views/MarkdownTableView';
|
||||||
import ReadReceiptsView from '../views/ReadReceiptView';
|
import ReadReceiptsView from '../views/ReadReceiptView';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
|
@ -168,6 +169,11 @@ const ChatsStackNavigator = () => {
|
||||||
component={ThreadMessagesView}
|
component={ThreadMessagesView}
|
||||||
options={ThreadMessagesView.navigationOptions}
|
options={ThreadMessagesView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
|
<ChatsStack.Screen
|
||||||
|
name='TeamChannelsView'
|
||||||
|
component={TeamChannelsView}
|
||||||
|
options={TeamChannelsView.navigationOptions}
|
||||||
|
/>
|
||||||
<ChatsStack.Screen
|
<ChatsStack.Screen
|
||||||
name='MarkdownTableView'
|
name='MarkdownTableView'
|
||||||
component={MarkdownTableView}
|
component={MarkdownTableView}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import ForwardLivechatView from '../../views/ForwardLivechatView';
|
||||||
import LivechatEditView from '../../views/LivechatEditView';
|
import LivechatEditView from '../../views/LivechatEditView';
|
||||||
import PickerView from '../../views/PickerView';
|
import PickerView from '../../views/PickerView';
|
||||||
import ThreadMessagesView from '../../views/ThreadMessagesView';
|
import ThreadMessagesView from '../../views/ThreadMessagesView';
|
||||||
|
import TeamChannelsView from '../../views/TeamChannelsView';
|
||||||
import MarkdownTableView from '../../views/MarkdownTableView';
|
import MarkdownTableView from '../../views/MarkdownTableView';
|
||||||
import ReadReceiptsView from '../../views/ReadReceiptView';
|
import ReadReceiptsView from '../../views/ReadReceiptView';
|
||||||
import ProfileView from '../../views/ProfileView';
|
import ProfileView from '../../views/ProfileView';
|
||||||
|
@ -193,6 +194,11 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
|
||||||
name='ThreadMessagesView'
|
name='ThreadMessagesView'
|
||||||
component={ThreadMessagesView}
|
component={ThreadMessagesView}
|
||||||
/>
|
/>
|
||||||
|
<ModalStack.Screen
|
||||||
|
name='TeamChannelsView'
|
||||||
|
component={TeamChannelsView}
|
||||||
|
options={TeamChannelsView.navigationOptions}
|
||||||
|
/>
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name='MarkdownTableView'
|
name='MarkdownTableView'
|
||||||
component={MarkdownTableView}
|
component={MarkdownTableView}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Navigation from '../lib/Navigation';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
const navigate = ({ item, isMasterDetail, ...props }) => {
|
const navigate = ({ item, isMasterDetail, ...props }) => {
|
||||||
let navigationMethod = Navigation.navigate;
|
let navigationMethod = props.navigationMethod ?? Navigation.navigate;
|
||||||
|
|
||||||
if (isMasterDetail) {
|
if (isMasterDetail) {
|
||||||
navigationMethod = Navigation.replace;
|
navigationMethod = Navigation.replace;
|
||||||
|
|
|
@ -212,6 +212,7 @@ export default {
|
||||||
ROOM_JOIN: 'room_join',
|
ROOM_JOIN: 'room_join',
|
||||||
ROOM_GO_RA: 'room_go_ra',
|
ROOM_GO_RA: 'room_go_ra',
|
||||||
ROOM_TOGGLE_FOLLOW_THREADS: 'room_toggle_follow_threads',
|
ROOM_TOGGLE_FOLLOW_THREADS: 'room_toggle_follow_threads',
|
||||||
|
ROOM_GO_TEAM_CHANNELS: 'room_go_team_channels',
|
||||||
ROOM_GO_SEARCH: 'room_go_search',
|
ROOM_GO_SEARCH: 'room_go_search',
|
||||||
ROOM_GO_THREADS: 'room_go_threads',
|
ROOM_GO_THREADS: 'room_go_threads',
|
||||||
ROOM_GO_ROOM_INFO: 'room_go_room_info',
|
ROOM_GO_ROOM_INFO: 'room_go_room_info',
|
||||||
|
@ -310,5 +311,11 @@ export default {
|
||||||
|
|
||||||
// E2E ENCRYPTION SECURITY VIEW
|
// E2E ENCRYPTION SECURITY VIEW
|
||||||
E2E_SEC_CHANGE_PASSWORD: 'e2e_sec_change_password',
|
E2E_SEC_CHANGE_PASSWORD: 'e2e_sec_change_password',
|
||||||
E2E_SEC_RESET_OWN_KEY: 'e2e_sec_reset_own_key'
|
E2E_SEC_RESET_OWN_KEY: 'e2e_sec_reset_own_key',
|
||||||
|
|
||||||
|
// TEAM CHANNELS VIEW
|
||||||
|
TC_SEARCH: 'tc_search',
|
||||||
|
TC_CANCEL_SEARCH: 'tc_cancel_search',
|
||||||
|
TC_GO_ACTIONS: 'tc_go_actions',
|
||||||
|
TC_GO_ROOM: 'tc_go_room'
|
||||||
};
|
};
|
||||||
|
|
|
@ -175,7 +175,7 @@ class NewMessageView extends React.Component {
|
||||||
{maxUsers > 2 ? this.renderButton({
|
{maxUsers > 2 ? this.renderButton({
|
||||||
onPress: this.createGroupChat,
|
onPress: this.createGroupChat,
|
||||||
title: I18n.t('Create_Direct_Messages'),
|
title: I18n.t('Create_Direct_Messages'),
|
||||||
icon: 'team',
|
icon: 'message',
|
||||||
testID: 'new-message-view-create-direct-message'
|
testID: 'new-message-view-create-direct-message'
|
||||||
}) : null}
|
}) : null}
|
||||||
{this.renderButton({
|
{this.renderButton({
|
||||||
|
|
|
@ -461,7 +461,7 @@ class RoomActionsView extends React.Component {
|
||||||
? <Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{room.fname}</Text>
|
? <Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{room.fname}</Text>
|
||||||
: (
|
: (
|
||||||
<View style={styles.roomTitleRow}>
|
<View style={styles.roomTitleRow}>
|
||||||
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} status={room.visitor?.status} />
|
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} teamMain={room.teamMain} status={room.visitor?.status} />
|
||||||
<Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{RocketChat.getRoomTitle(room)}</Text>
|
<Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{RocketChat.getRoomTitle(room)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
|
@ -41,7 +41,7 @@ const getRoomTitle = (room, type, name, username, statusText, theme) => (type ==
|
||||||
)
|
)
|
||||||
: (
|
: (
|
||||||
<View style={styles.roomTitleRow}>
|
<View style={styles.roomTitleRow}>
|
||||||
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} key='room-info-type' status={room.visitor?.status} />
|
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} teamMain={room.teamMain} key='room-info-type' status={room.visitor?.status} />
|
||||||
<Text testID='room-info-view-name' style={[styles.roomTitle, { color: themes[theme].titleText }]} key='room-info-name'>{RocketChat.getRoomTitle(room)}</Text>
|
<Text testID='room-info-view-name' style={[styles.roomTitle, { color: themes[theme].titleText }]} key='room-info-name'>{RocketChat.getRoomTitle(room)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
import { HeaderBackButton } from '@react-navigation/stack';
|
import { HeaderBackButton } from '@react-navigation/stack';
|
||||||
|
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import Avatar from '../../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
avatar: {
|
avatar: {
|
|
@ -3,10 +3,10 @@ import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
|
||||||
import * as HeaderButton from '../../../containers/HeaderButton';
|
import * as HeaderButton from '../../containers/HeaderButton';
|
||||||
import database from '../../../lib/database';
|
import database from '../../lib/database';
|
||||||
import { getUserSelector } from '../../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import { logEvent, events } from '../../../utils/log';
|
import { logEvent, events } from '../../utils/log';
|
||||||
|
|
||||||
class RightButtonsContainer extends Component {
|
class RightButtonsContainer extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -15,6 +15,7 @@ class RightButtonsContainer extends Component {
|
||||||
rid: PropTypes.string,
|
rid: PropTypes.string,
|
||||||
t: PropTypes.string,
|
t: PropTypes.string,
|
||||||
tmid: PropTypes.string,
|
tmid: PropTypes.string,
|
||||||
|
teamId: PropTypes.bool,
|
||||||
navigation: PropTypes.object,
|
navigation: PropTypes.object,
|
||||||
isMasterDetail: PropTypes.bool,
|
isMasterDetail: PropTypes.bool,
|
||||||
toggleFollowThread: PropTypes.func
|
toggleFollowThread: PropTypes.func
|
||||||
|
@ -109,6 +110,21 @@ class RightButtonsContainer extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goTeamChannels = () => {
|
||||||
|
logEvent(events.ROOM_GO_TEAM_CHANNELS);
|
||||||
|
const {
|
||||||
|
navigation, isMasterDetail, teamId
|
||||||
|
} = this.props;
|
||||||
|
if (isMasterDetail) {
|
||||||
|
navigation.navigate('ModalStackNavigator', {
|
||||||
|
screen: 'TeamChannelsView',
|
||||||
|
params: { teamId }
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
navigation.navigate('TeamChannelsView', { teamId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
goThreadsView = () => {
|
goThreadsView = () => {
|
||||||
logEvent(events.ROOM_GO_THREADS);
|
logEvent(events.ROOM_GO_THREADS);
|
||||||
const {
|
const {
|
||||||
|
@ -146,7 +162,9 @@ class RightButtonsContainer extends Component {
|
||||||
const {
|
const {
|
||||||
isFollowingThread, tunread, tunreadUser, tunreadGroup
|
isFollowingThread, tunread, tunreadUser, tunreadGroup
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { t, tmid, threadsEnabled } = this.props;
|
const {
|
||||||
|
t, tmid, threadsEnabled, teamId
|
||||||
|
} = this.props;
|
||||||
if (t === 'l') {
|
if (t === 'l') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -163,6 +181,13 @@ class RightButtonsContainer extends Component {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<HeaderButton.Container>
|
<HeaderButton.Container>
|
||||||
|
{teamId ? (
|
||||||
|
<HeaderButton.Item
|
||||||
|
iconName='channel-public'
|
||||||
|
onPress={this.goTeamChannels}
|
||||||
|
testID='room-view-header-team-channels'
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{threadsEnabled ? (
|
{threadsEnabled ? (
|
||||||
<HeaderButton.Item
|
<HeaderButton.Item
|
||||||
iconName='threads'
|
iconName='threads'
|
|
@ -29,7 +29,9 @@ import styles from './styles';
|
||||||
import log, { logEvent, events } from '../../utils/log';
|
import log, { logEvent, events } from '../../utils/log';
|
||||||
import EventEmitter from '../../utils/events';
|
import EventEmitter from '../../utils/events';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import RoomHeaderView, { RightButtons, LeftButtons } from './Header';
|
import RoomHeader from '../../containers/RoomHeader';
|
||||||
|
import LeftButtons from './LeftButtons';
|
||||||
|
import RightButtons from './RightButtons';
|
||||||
import StatusBar from '../../containers/StatusBar';
|
import StatusBar from '../../containers/StatusBar';
|
||||||
import Separator from './Separator';
|
import Separator from './Separator';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
@ -317,13 +319,23 @@ class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
const subtitle = room?.topic;
|
const subtitle = room?.topic;
|
||||||
const t = room?.t;
|
const t = room?.t;
|
||||||
|
const teamMain = room?.teamMain;
|
||||||
|
const teamId = room?.teamId;
|
||||||
const { id: userId, token } = user;
|
const { id: userId, token } = user;
|
||||||
const avatar = room?.name;
|
const avatar = room?.name;
|
||||||
const visitor = room?.visitor;
|
const visitor = room?.visitor;
|
||||||
if (!room?.rid) {
|
if (!room?.rid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight: tmid ? 1 : 2 });
|
|
||||||
|
let numIconsRight = 2;
|
||||||
|
if (tmid) {
|
||||||
|
numIconsRight = 1;
|
||||||
|
} else if (teamId) {
|
||||||
|
numIconsRight = 3;
|
||||||
|
}
|
||||||
|
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight });
|
||||||
|
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerShown: true,
|
headerShown: true,
|
||||||
headerTitleAlign: 'left',
|
headerTitleAlign: 'left',
|
||||||
|
@ -347,24 +359,27 @@ class RoomView extends React.Component {
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
headerTitle: () => (
|
headerTitle: () => (
|
||||||
<RoomHeaderView
|
<RoomHeader
|
||||||
rid={rid}
|
rid={rid}
|
||||||
prid={prid}
|
prid={prid}
|
||||||
tmid={tmid}
|
tmid={tmid}
|
||||||
title={title}
|
title={title}
|
||||||
|
teamMain={teamMain}
|
||||||
parentTitle={parentTitle}
|
parentTitle={parentTitle}
|
||||||
subtitle={subtitle}
|
subtitle={subtitle}
|
||||||
type={t}
|
type={t}
|
||||||
roomUserId={roomUserId}
|
roomUserId={roomUserId}
|
||||||
visitor={visitor}
|
visitor={visitor}
|
||||||
isGroupChat={isGroupChat}
|
isGroupChat={isGroupChat}
|
||||||
goRoomActionsView={this.goRoomActionsView}
|
onPress={this.goRoomActionsView}
|
||||||
|
testID={`room-view-title-${ title }`}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
<RightButtons
|
<RightButtons
|
||||||
rid={rid}
|
rid={rid}
|
||||||
tmid={tmid}
|
tmid={tmid}
|
||||||
|
teamId={teamId}
|
||||||
t={t}
|
t={t}
|
||||||
navigation={navigation}
|
navigation={navigation}
|
||||||
toggleFollowThread={this.toggleFollowThread}
|
toggleFollowThread={this.toggleFollowThread}
|
||||||
|
|
|
@ -68,6 +68,7 @@ const CHATS_HEADER = 'Chats';
|
||||||
const UNREAD_HEADER = 'Unread';
|
const UNREAD_HEADER = 'Unread';
|
||||||
const FAVORITES_HEADER = 'Favorites';
|
const FAVORITES_HEADER = 'Favorites';
|
||||||
const DISCUSSIONS_HEADER = 'Discussions';
|
const DISCUSSIONS_HEADER = 'Discussions';
|
||||||
|
const TEAMS_HEADER = 'Teams';
|
||||||
const CHANNELS_HEADER = 'Channels';
|
const CHANNELS_HEADER = 'Channels';
|
||||||
const DM_HEADER = 'Direct_Messages';
|
const DM_HEADER = 'Direct_Messages';
|
||||||
const GROUPS_HEADER = 'Private_Groups';
|
const GROUPS_HEADER = 'Private_Groups';
|
||||||
|
@ -77,6 +78,8 @@ const QUERY_SIZE = 20;
|
||||||
const filterIsUnread = s => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
|
const filterIsUnread = s => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
|
||||||
const filterIsFavorite = s => s.f;
|
const filterIsFavorite = s => s.f;
|
||||||
const filterIsOmnichannel = s => s.t === 'l';
|
const filterIsOmnichannel = s => s.t === 'l';
|
||||||
|
const filterIsTeam = s => s.teamMain;
|
||||||
|
const filterIsDiscussion = s => s.prid;
|
||||||
|
|
||||||
const shouldUpdateProps = [
|
const shouldUpdateProps = [
|
||||||
'searchText',
|
'searchText',
|
||||||
|
@ -475,10 +478,12 @@ class RoomsListView extends React.Component {
|
||||||
|
|
||||||
// type
|
// type
|
||||||
if (groupByType) {
|
if (groupByType) {
|
||||||
const discussions = chats.filter(s => s.prid);
|
const teams = chats.filter(s => filterIsTeam(s));
|
||||||
const channels = chats.filter(s => s.t === 'c' && !s.prid);
|
const discussions = chats.filter(s => filterIsDiscussion(s));
|
||||||
const privateGroup = chats.filter(s => s.t === 'p' && !s.prid);
|
const channels = chats.filter(s => s.t === 'c' && !filterIsDiscussion(s) && !filterIsTeam(s));
|
||||||
const direct = chats.filter(s => s.t === 'd' && !s.prid);
|
const privateGroup = chats.filter(s => s.t === 'p' && !filterIsDiscussion(s) && !filterIsTeam(s));
|
||||||
|
const direct = chats.filter(s => s.t === 'd' && !filterIsDiscussion(s) && !filterIsTeam(s));
|
||||||
|
tempChats = this.addRoomsGroup(teams, TEAMS_HEADER, tempChats);
|
||||||
tempChats = this.addRoomsGroup(discussions, DISCUSSIONS_HEADER, tempChats);
|
tempChats = this.addRoomsGroup(discussions, DISCUSSIONS_HEADER, tempChats);
|
||||||
tempChats = this.addRoomsGroup(channels, CHANNELS_HEADER, tempChats);
|
tempChats = this.addRoomsGroup(channels, CHANNELS_HEADER, tempChats);
|
||||||
tempChats = this.addRoomsGroup(privateGroup, GROUPS_HEADER, tempChats);
|
tempChats = this.addRoomsGroup(privateGroup, GROUPS_HEADER, tempChats);
|
||||||
|
|
|
@ -0,0 +1,369 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Keyboard } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { FlatList } from 'react-native-gesture-handler';
|
||||||
|
import { HeaderBackButton } from '@react-navigation/stack';
|
||||||
|
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
import RoomHeader from '../containers/RoomHeader';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
|
import SearchHeader from './ThreadMessagesView/SearchHeader';
|
||||||
|
import log, { events, logEvent } from '../utils/log';
|
||||||
|
import database from '../lib/database';
|
||||||
|
import { getUserSelector } from '../selectors/login';
|
||||||
|
import { getHeaderTitlePosition } from '../containers/Header';
|
||||||
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
|
import BackgroundContainer from '../containers/BackgroundContainer';
|
||||||
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
|
import ActivityIndicator from '../containers/ActivityIndicator';
|
||||||
|
import RoomItem, { ROW_HEIGHT } from '../presentation/RoomItem';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import { withDimensions } from '../dimensions';
|
||||||
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
|
import { themes } from '../constants/colors';
|
||||||
|
import debounce from '../utils/debounce';
|
||||||
|
import { showErrorAlert } from '../utils/info';
|
||||||
|
import { goRoom } from '../utils/goRoom';
|
||||||
|
import I18n from '../i18n';
|
||||||
|
|
||||||
|
const API_FETCH_COUNT = 50;
|
||||||
|
|
||||||
|
const getItemLayout = (data, index) => ({
|
||||||
|
length: data.length,
|
||||||
|
offset: ROW_HEIGHT * index,
|
||||||
|
index
|
||||||
|
});
|
||||||
|
const keyExtractor = item => item._id;
|
||||||
|
|
||||||
|
class TeamChannelsView extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
route: PropTypes.object,
|
||||||
|
navigation: PropTypes.object,
|
||||||
|
isMasterDetail: PropTypes.bool,
|
||||||
|
insets: PropTypes.object,
|
||||||
|
theme: PropTypes.string,
|
||||||
|
useRealName: PropTypes.bool,
|
||||||
|
width: PropTypes.number,
|
||||||
|
StoreLastMessage: PropTypes.bool
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.teamId = props.route.params?.teamId;
|
||||||
|
this.state = {
|
||||||
|
loading: true,
|
||||||
|
loadingMore: false,
|
||||||
|
data: [],
|
||||||
|
total: -1,
|
||||||
|
isSearching: false,
|
||||||
|
searchText: '',
|
||||||
|
search: []
|
||||||
|
};
|
||||||
|
this.loadTeam();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTeam = async() => {
|
||||||
|
const db = database.active;
|
||||||
|
try {
|
||||||
|
const subCollection = db.get('subscriptions');
|
||||||
|
this.teamChannels = await subCollection.query(
|
||||||
|
Q.where('team_id', Q.eq(this.teamId))
|
||||||
|
);
|
||||||
|
this.team = this.teamChannels?.find(channel => channel.teamMain);
|
||||||
|
this.setHeader();
|
||||||
|
|
||||||
|
if (!this.team) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.pop();
|
||||||
|
showErrorAlert(I18n.t('Team_not_found'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load = debounce(async() => {
|
||||||
|
const {
|
||||||
|
loadingMore, total, data, search, isSearching, searchText
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
const length = isSearching ? search.length : data.length;
|
||||||
|
if (loadingMore || length === total) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loadingMore: true });
|
||||||
|
try {
|
||||||
|
const result = await RocketChat.getTeamListRoom({
|
||||||
|
teamId: this.teamId,
|
||||||
|
offset: length,
|
||||||
|
count: API_FETCH_COUNT,
|
||||||
|
type: 'all',
|
||||||
|
filter: searchText
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
const newState = {
|
||||||
|
loading: false,
|
||||||
|
loadingMore: false,
|
||||||
|
total: result.total
|
||||||
|
};
|
||||||
|
const rooms = result.rooms.map((room) => {
|
||||||
|
const record = this.teamChannels?.find(c => c.rid === room._id);
|
||||||
|
return record ?? room;
|
||||||
|
});
|
||||||
|
if (isSearching) {
|
||||||
|
newState.search = [...search, ...rooms];
|
||||||
|
} else {
|
||||||
|
newState.data = [...data, ...rooms];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(newState);
|
||||||
|
} else {
|
||||||
|
this.setState({ loading: false, loadingMore: false });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
|
this.setState({ loading: false, loadingMore: false });
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
getHeader = () => {
|
||||||
|
const { isSearching } = this.state;
|
||||||
|
const {
|
||||||
|
navigation, isMasterDetail, insets, theme
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const { team } = this;
|
||||||
|
if (!team) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight: 1 });
|
||||||
|
|
||||||
|
if (isSearching) {
|
||||||
|
return {
|
||||||
|
headerTitleAlign: 'left',
|
||||||
|
headerLeft: () => (
|
||||||
|
<HeaderButton.Container left>
|
||||||
|
<HeaderButton.Item
|
||||||
|
iconName='close'
|
||||||
|
onPress={this.onCancelSearchPress}
|
||||||
|
/>
|
||||||
|
</HeaderButton.Container>
|
||||||
|
),
|
||||||
|
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} />,
|
||||||
|
headerTitleContainerStyle: {
|
||||||
|
left: headerTitlePosition.left,
|
||||||
|
right: headerTitlePosition.right
|
||||||
|
},
|
||||||
|
headerRight: () => null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
headerShown: true,
|
||||||
|
headerTitleAlign: 'left',
|
||||||
|
headerTitleContainerStyle: {
|
||||||
|
left: headerTitlePosition.left,
|
||||||
|
right: headerTitlePosition.right
|
||||||
|
},
|
||||||
|
headerTitle: () => (
|
||||||
|
<RoomHeader
|
||||||
|
title={RocketChat.getRoomTitle(team)}
|
||||||
|
subtitle={team.topic}
|
||||||
|
type={team.t}
|
||||||
|
onPress={this.goRoomActionsView}
|
||||||
|
teamMain
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isMasterDetail) {
|
||||||
|
options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} />;
|
||||||
|
} else {
|
||||||
|
options.headerLeft = () => (
|
||||||
|
<HeaderBackButton
|
||||||
|
labelVisible={false}
|
||||||
|
onPress={() => navigation.pop()}
|
||||||
|
tintColor={themes[theme].headerTintColor}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.headerRight = () => (
|
||||||
|
<HeaderButton.Container>
|
||||||
|
<HeaderButton.Item iconName='search' onPress={this.onSearchPress} />
|
||||||
|
</HeaderButton.Container>
|
||||||
|
);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHeader = () => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
const options = this.getHeader();
|
||||||
|
navigation.setOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchPress = () => {
|
||||||
|
logEvent(events.TC_SEARCH);
|
||||||
|
this.setState({ isSearching: true }, () => this.setHeader());
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchChangeText = debounce((searchText) => {
|
||||||
|
this.setState({
|
||||||
|
searchText, search: [], loading: !!searchText, loadingMore: false, total: -1
|
||||||
|
}, () => {
|
||||||
|
if (searchText) {
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
onCancelSearchPress = () => {
|
||||||
|
logEvent(events.TC_CANCEL_SEARCH);
|
||||||
|
const { isSearching } = this.state;
|
||||||
|
if (!isSearching) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Keyboard.dismiss();
|
||||||
|
this.setState({ isSearching: false, search: [] }, () => {
|
||||||
|
this.setHeader();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
goRoomActionsView = (screen) => {
|
||||||
|
logEvent(events.TC_GO_ACTIONS);
|
||||||
|
const { team } = this;
|
||||||
|
const {
|
||||||
|
navigation, isMasterDetail
|
||||||
|
} = this.props;
|
||||||
|
if (isMasterDetail) {
|
||||||
|
navigation.navigate('ModalStackNavigator', {
|
||||||
|
screen: screen ?? 'RoomActionsView',
|
||||||
|
params: {
|
||||||
|
rid: team.rid, t: team.t, room: team, showCloseModal: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
navigation.navigate('RoomActionsView', {
|
||||||
|
rid: team.rid, t: team.t, room: team
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoomTitle = item => RocketChat.getRoomTitle(item)
|
||||||
|
|
||||||
|
getRoomAvatar = item => RocketChat.getRoomAvatar(item)
|
||||||
|
|
||||||
|
onPressItem = debounce(async(item) => {
|
||||||
|
logEvent(events.TC_GO_ROOM);
|
||||||
|
const { navigation, isMasterDetail } = this.props;
|
||||||
|
try {
|
||||||
|
let params = {};
|
||||||
|
if (item.rid) {
|
||||||
|
params = item;
|
||||||
|
} else {
|
||||||
|
const { room } = await RocketChat.getRoomInfo(item._id);
|
||||||
|
params = {
|
||||||
|
rid: item._id, name: RocketChat.getRoomTitle(room), joinCodeRequired: room.joinCodeRequired, t: room.t, teamId: room.teamId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (isMasterDetail) {
|
||||||
|
navigation.pop();
|
||||||
|
}
|
||||||
|
goRoom({ item: params, isMasterDetail, navigationMethod: navigation.push });
|
||||||
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}, 1000, true);
|
||||||
|
|
||||||
|
renderItem = ({ item }) => {
|
||||||
|
const {
|
||||||
|
StoreLastMessage,
|
||||||
|
useRealName,
|
||||||
|
theme,
|
||||||
|
width
|
||||||
|
} = this.props;
|
||||||
|
return (
|
||||||
|
<RoomItem
|
||||||
|
item={item}
|
||||||
|
theme={theme}
|
||||||
|
type={item.t}
|
||||||
|
showLastMessage={StoreLastMessage}
|
||||||
|
onPress={this.onPressItem}
|
||||||
|
width={width}
|
||||||
|
useRealName={useRealName}
|
||||||
|
getRoomTitle={this.getRoomTitle}
|
||||||
|
getRoomAvatar={this.getRoomAvatar}
|
||||||
|
swipeEnabled={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderFooter = () => {
|
||||||
|
const { loadingMore } = this.state;
|
||||||
|
const { theme } = this.props;
|
||||||
|
if (loadingMore) {
|
||||||
|
return <ActivityIndicator theme={theme} />;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderScroll = () => {
|
||||||
|
const {
|
||||||
|
loading, data, search, isSearching, searchText
|
||||||
|
} = this.state;
|
||||||
|
if (loading) {
|
||||||
|
return <BackgroundContainer loading />;
|
||||||
|
}
|
||||||
|
if (isSearching && !search.length) {
|
||||||
|
return <BackgroundContainer text={searchText ? I18n.t('No_team_channels_found') : ''} />;
|
||||||
|
}
|
||||||
|
if (!isSearching && !data.length) {
|
||||||
|
return <BackgroundContainer text={I18n.t('No_team_channels_found')} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
data={isSearching ? search : data}
|
||||||
|
extraData={isSearching ? search : data}
|
||||||
|
keyExtractor={keyExtractor}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
getItemLayout={getItemLayout}
|
||||||
|
removeClippedSubviews={isIOS}
|
||||||
|
keyboardShouldPersistTaps='always'
|
||||||
|
onEndReached={() => this.load()}
|
||||||
|
onEndReachedThreshold={0.5}
|
||||||
|
ListFooterComponent={this.renderFooter}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.count(`${ this.constructor.name }.render calls`);
|
||||||
|
return (
|
||||||
|
<SafeAreaView testID='team-channels-view'>
|
||||||
|
<StatusBar />
|
||||||
|
{this.renderScroll()}
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
baseUrl: state.server.server,
|
||||||
|
user: getUserSelector(state),
|
||||||
|
useRealName: state.settings.UI_Use_Real_Name,
|
||||||
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
|
StoreLastMessage: state.settings.Store_Last_Message
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(withDimensions(withSafeAreaInsets(withTheme(TeamChannelsView))));
|
|
@ -28,7 +28,7 @@ import * as List from '../../containers/List';
|
||||||
import Dropdown from './Dropdown';
|
import Dropdown from './Dropdown';
|
||||||
import DropdownItemHeader from './Dropdown/DropdownItemHeader';
|
import DropdownItemHeader from './Dropdown/DropdownItemHeader';
|
||||||
import { FILTER } from './filters';
|
import { FILTER } from './filters';
|
||||||
import NoDataFound from './NoDataFound';
|
import BackgroundContainer from '../../containers/BackgroundContainer';
|
||||||
import { isIOS } from '../../utils/deviceInfo';
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
import { getBadgeColor, makeThreadName } from '../../utils/room';
|
import { getBadgeColor, makeThreadName } from '../../utils/room';
|
||||||
import { getHeaderTitlePosition } from '../../containers/Header';
|
import { getHeaderTitlePosition } from '../../containers/Header';
|
||||||
|
@ -463,7 +463,7 @@ class ThreadMessagesView extends React.Component {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{this.renderHeader()}
|
{this.renderHeader()}
|
||||||
<NoDataFound text={text} />
|
<BackgroundContainer text={text} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ describe('Broadcast room', () => {
|
||||||
await element(by.id('create-channel-submit')).tap();
|
await element(by.id('create-channel-submit')).tap();
|
||||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||||
await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||||
await element(by.id('room-actions-info')).tap();
|
await element(by.id('room-actions-info')).tap();
|
||||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||||
|
|
|
@ -15,7 +15,7 @@ async function navigateToRoom() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToRoomActions() {
|
async function navigateToRoomActions() {
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ describe('Join public room', () => {
|
||||||
// Render - Header
|
// Render - Header
|
||||||
describe('Header', async() => {
|
describe('Header', async() => {
|
||||||
it('should have actions button ', async() => {
|
it('should have actions button ', async() => {
|
||||||
await expect(element(by.id('room-view-header-actions'))).toBeVisible();
|
await expect(element(by.id('room-header'))).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ async function navigateToRoom() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function navigateToRoomActions() {
|
async function navigateToRoomActions() {
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ describe('Room screen', () => {
|
||||||
// Render - Header
|
// Render - Header
|
||||||
describe('Header', async() => {
|
describe('Header', async() => {
|
||||||
it('should have actions button ', async() => {
|
it('should have actions button ', async() => {
|
||||||
await expect(element(by.id('room-view-header-actions'))).toExist();
|
await expect(element(by.id('room-header'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have threads button ', async() => {
|
it('should have threads button ', async() => {
|
||||||
|
|
|
@ -16,7 +16,7 @@ async function navigateToRoomActions(type) {
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
|
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
|
||||||
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
||||||
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
|
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ describe('Room actions screen', () => {
|
||||||
await starMessage('messageToStar')
|
await starMessage('messageToStar')
|
||||||
|
|
||||||
//Back into Room Actions
|
//Back into Room Actions
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||||
|
|
||||||
//Go to starred messages
|
//Go to starred messages
|
||||||
|
@ -246,7 +246,7 @@ describe('Room actions screen', () => {
|
||||||
await pinMessage('messageToPin')
|
await pinMessage('messageToPin')
|
||||||
|
|
||||||
//Back into Room Actions
|
//Back into Room Actions
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||||
await element(by.type('UIScrollView')).atIndex(1).scrollTo('bottom');
|
await element(by.type('UIScrollView')).atIndex(1).scrollTo('bottom');
|
||||||
await waitFor(element(by.id('room-actions-pinned'))).toExist();
|
await waitFor(element(by.id('room-actions-pinned'))).toExist();
|
||||||
|
@ -270,7 +270,7 @@ describe('Room actions screen', () => {
|
||||||
await mockMessage('messageToFind');
|
await mockMessage('messageToFind');
|
||||||
|
|
||||||
//Back into Room Actions
|
//Back into Room Actions
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||||
|
|
||||||
await element(by.id('room-actions-search')).tap();
|
await element(by.id('room-actions-search')).tap();
|
||||||
|
@ -499,7 +499,7 @@ describe('Room actions screen', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to direct message', async() => {
|
it('should navigate to direct message', async() => {
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('room-actions-members')).tap();
|
await element(by.id('room-actions-members')).tap();
|
||||||
await waitFor(element(by.id('room-members-view'))).toExist().withTimeout(2000);
|
await waitFor(element(by.id('room-members-view'))).toExist().withTimeout(2000);
|
||||||
|
|
|
@ -74,8 +74,8 @@ describe('Discussion', () => {
|
||||||
|
|
||||||
describe('Check RoomActionsView render', async() => {
|
describe('Check RoomActionsView render', async() => {
|
||||||
it('should navigete to RoomActionsView', async() => {
|
it('should navigete to RoomActionsView', async() => {
|
||||||
await waitFor(element(by.id('room-view-header-actions'))).toBeVisible().withTimeout(5000);
|
await waitFor(element(by.id('room-header'))).toBeVisible().withTimeout(5000);
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ describe('Threads', () => {
|
||||||
// Render - Header
|
// Render - Header
|
||||||
describe('Header', async() => {
|
describe('Header', async() => {
|
||||||
it('should have actions button ', async() => {
|
it('should have actions button ', async() => {
|
||||||
await expect(element(by.id('room-view-header-actions'))).toExist();
|
await expect(element(by.id('room-header'))).toExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have threads button ', async() => {
|
it('should have threads button ', async() => {
|
||||||
|
@ -105,8 +105,8 @@ describe('Threads', () => {
|
||||||
const messageText = 'threadonly';
|
const messageText = 'threadonly';
|
||||||
await mockMessage(messageText);
|
await mockMessage(messageText);
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-header').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-header').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
|
||||||
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
||||||
await waitFor(element(by.label(`${ data.random }${ messageText }`)).atIndex(0)).toNotExist().withTimeout(2000);
|
await waitFor(element(by.label(`${ data.random }${ messageText }`)).atIndex(0)).toNotExist().withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
@ -118,8 +118,8 @@ describe('Threads', () => {
|
||||||
await element(by.id('messagebox-send-to-channel')).tap();
|
await element(by.id('messagebox-send-to-channel')).tap();
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-header').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-header').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
|
||||||
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
||||||
await waitFor(element(by.label(messageText)).atIndex(0)).toExist().withTimeout(2000);
|
await waitFor(element(by.label(messageText)).atIndex(0)).toExist().withTimeout(2000);
|
||||||
});
|
});
|
||||||
|
@ -133,8 +133,8 @@ describe('Threads', () => {
|
||||||
await element(by.id('messagebox-send-to-channel')).tap();
|
await element(by.id('messagebox-send-to-channel')).tap();
|
||||||
await element(by.id('messagebox-send-message')).tap();
|
await element(by.id('messagebox-send-message')).tap();
|
||||||
await tapBack();
|
await tapBack();
|
||||||
await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-header').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
|
||||||
await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
|
await waitFor(element(by.id('room-header').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
|
||||||
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
|
||||||
|
|
||||||
await element(by.id(`message-thread-replied-on-${ thread }`)).tap();
|
await element(by.id(`message-thread-replied-on-${ thread }`)).tap();
|
||||||
|
|
|
@ -17,7 +17,7 @@ async function navigateToRoomInfo(type) {
|
||||||
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
|
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
|
||||||
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
|
||||||
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
|
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
|
||||||
await element(by.id('room-view-header-actions')).tap();
|
await element(by.id('room-header')).tap();
|
||||||
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
|
||||||
await element(by.id('room-actions-info')).tap();
|
await element(by.id('room-actions-info')).tap();
|
||||||
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
|
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { ScrollView, View, StyleSheet } from 'react-native';
|
|
||||||
import { HeaderBackButton } from '@react-navigation/stack';
|
|
||||||
|
|
||||||
import HeaderComponent from '../../app/views/RoomView/Header/Header';
|
|
||||||
// import { CustomHeaderButtons, Item } from '../../app/containers/HeaderButton';
|
|
||||||
import StoriesSeparator from './StoriesSeparator';
|
|
||||||
import { isIOS } from '../../app/utils/deviceInfo';
|
|
||||||
import { themes } from '../../app/constants/colors';
|
|
||||||
|
|
||||||
let _theme = 'light';
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
height: isIOS ? 44 : 56,
|
|
||||||
borderTopWidth: 1,
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
marginVertical: 6
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Header = props => (
|
|
||||||
<View style={[styles.container, { backgroundColor: themes[_theme].headerBackground }]}>
|
|
||||||
<HeaderBackButton />
|
|
||||||
<HeaderComponent
|
|
||||||
title='test'
|
|
||||||
type='d'
|
|
||||||
width={375}
|
|
||||||
height={480}
|
|
||||||
theme={_theme}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
{/* not working because we use withTheme */}
|
|
||||||
{/* <CustomHeaderButtons>
|
|
||||||
<Item title='thread' iconName='thread' />
|
|
||||||
</CustomHeaderButtons>
|
|
||||||
<CustomHeaderButtons>
|
|
||||||
<Item title='more' iconName='menu' />
|
|
||||||
</CustomHeaderButtons> */}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line react/prop-types
|
|
||||||
export default ({ theme }) => {
|
|
||||||
_theme = theme;
|
|
||||||
return (
|
|
||||||
<ScrollView style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
|
||||||
<StoriesSeparator title='Basic' theme={theme} />
|
|
||||||
<Header />
|
|
||||||
|
|
||||||
<StoriesSeparator title='Types' theme={theme} />
|
|
||||||
<Header type='d' />
|
|
||||||
<Header type='c' />
|
|
||||||
<Header type='p' />
|
|
||||||
<Header type='discussion' />
|
|
||||||
<Header type='thread' />
|
|
||||||
|
|
||||||
<StoriesSeparator title='Typing' theme={theme} />
|
|
||||||
<Header usersTyping={['diego.mello']} />
|
|
||||||
<Header usersTyping={['diego.mello', 'rocket.cat']} />
|
|
||||||
<Header usersTyping={['diego.mello', 'rocket.cat', 'detoxrn']} />
|
|
||||||
|
|
||||||
<StoriesSeparator title='Title scroll' theme={theme} />
|
|
||||||
<Header title='Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' />
|
|
||||||
<Header
|
|
||||||
title='Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
|
|
||||||
usersTyping={['diego.mello', 'rocket.cat', 'detoxrn']}
|
|
||||||
/>
|
|
||||||
</ScrollView>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -14,6 +14,8 @@ import Markdown from './Markdown';
|
||||||
import './HeaderButtons';
|
import './HeaderButtons';
|
||||||
import './UnreadBadge';
|
import './UnreadBadge';
|
||||||
import '../../app/views/ThreadMessagesView/Item.stories.js';
|
import '../../app/views/ThreadMessagesView/Item.stories.js';
|
||||||
|
import '../../app/containers/BackgroundContainer/index.stories.js';
|
||||||
|
import '../../app/containers/RoomHeader/RoomHeader.stories.js';
|
||||||
import Avatar from './Avatar';
|
import Avatar from './Avatar';
|
||||||
// import RoomViewHeader from './RoomViewHeader';
|
// import RoomViewHeader from './RoomViewHeader';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue