Improve channel’s layout

This commit is contained in:
Rodrigo Nascimento 2017-08-13 00:19:14 -03:00
parent 03b97c25b1
commit 196e91cf4b
5 changed files with 89 additions and 23 deletions

View File

@ -4,6 +4,7 @@ import { View, Text, StyleSheet } from 'react-native';
import { CachedImage } from 'react-native-img-cache';
import { emojify } from 'react-emojione';
import Markdown from 'react-native-easy-markdown';
import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
const styles = StyleSheet.create({
message: {
@ -45,8 +46,6 @@ const styles = StyleSheet.create({
}
});
const colors = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B'];
export default class Message extends React.PureComponent {
static propTypes = {
item: PropTypes.object.isRequired,
@ -61,16 +60,8 @@ export default class Message extends React.PureComponent {
const msg = emojify(this.props.item.msg, { output: 'unicode' });
let username = this.props.item.u.username;
const position = username.length % colors.length;
const { initials, color } = avatarInitialsAndColor(this.props.item.u.username);
const color = colors[position];
username = username.replace(/[^A-Za-z0-9]/g, '.').replace(/\.+/g, '.').replace(/(^\.)|(\.$)/g, '');
const usernameParts = username.split('.');
let initials = usernameParts.length > 1 ? usernameParts[0][0] + usernameParts[usernameParts.length - 1][0] : username.replace(/[^A-Za-z0-9]/g, '').substr(0, 2);
initials = initials.toUpperCase();
return (
<View style={[styles.message, extraStyle]}>
<View style={[styles.avatarContainer, { backgroundColor: color }]}>

View File

@ -1,14 +1,17 @@
import React from 'react';
import { CachedImage } from 'react-native-img-cache';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import PropTypes from 'prop-types';
import { View, Text, StyleSheet } from 'react-native';
import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
padding: 24,
padding: 10,
paddingLeft: 14,
alignItems: 'center'
},
number: {
@ -27,17 +30,43 @@ const styles = StyleSheet.create({
fontSize: 20,
color: '#444'
},
icon: {
fontSize: 18,
iconContainer: {
marginTop: 5,
marginRight: 5,
color: '#aaa'
marginRight: 10,
backgroundColor: '#ccc',
height: 40,
width: 40,
borderRadius: 20,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'center'
},
icon: {
fontSize: 20,
color: '#fff',
backgroundColor: '#ccc',
height: 36,
width: 36,
borderRadius: 18,
overflow: 'hidden',
textAlign: 'center',
lineHeight: 36
},
avatar: {
width: 40,
height: 40,
position: 'absolute'
},
avatarInitials: {
fontSize: 22,
color: '#ffffff'
}
});
export default class RoomItem extends React.PureComponent {
static propTypes = {
item: PropTypes.object.isRequired
item: PropTypes.object.isRequired,
baseUrl: PropTypes.string.isRequired
}
get icon() {
const icon = {
@ -46,11 +75,29 @@ export default class RoomItem extends React.PureComponent {
p: 'lock',
l: 'account'
}[this.props.item.t];
if (!icon) {
return null;
}
return <MaterialCommunityIcons name={icon} style={styles.icon} />;
if (this.props.item.t === 'd') {
const { name } = this.props.item;
const { initials, color } = avatarInitialsAndColor(name);
return (
<View style={[styles.iconContainer, { backgroundColor: color }]}>
<Text style={styles.avatarInitials}>{initials}</Text>
<CachedImage style={styles.avatar} source={{ uri: `${ this.props.baseUrl }/avatar/${ name }` }} />
</View>
);
}
return (
<View style={styles.iconContainer}>
<MaterialCommunityIcons name={icon} style={styles.icon} />
</View>
);
}
renderNumber = (item) => {
if (item.unread) {
return (
@ -62,7 +109,7 @@ export default class RoomItem extends React.PureComponent {
}
render() {
const name = this.props.item.name;
const { name } = this.props.item;
return (
<View style={styles.container}>
{this.icon}

2
app/constants/colors.js Normal file
View File

@ -0,0 +1,2 @@
export const AVATAR_COLORS = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B'];
export const ESLINT_FIX = null;

View File

@ -0,0 +1,15 @@
import { AVATAR_COLORS } from '../constants/colors';
export default function(username = '') {
const position = username.length % AVATAR_COLORS.length;
const color = AVATAR_COLORS[position];
username = username.replace(/[^A-Za-z0-9]/g, '.').replace(/\.+/g, '.').replace(/(^\.)|(\.$)/g, '');
const usernameParts = username.split('.');
let initials = usernameParts.length > 1 ? usernameParts[0][0] + usernameParts[usernameParts.length - 1][0] : username.replace(/[^A-Za-z0-9]/g, '').substr(0, 2);
initials = initials.toUpperCase();
return { initials, color };
}

View File

@ -78,7 +78,8 @@ const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
class RoomsListItem extends React.PureComponent {
static propTypes = {
item: PropTypes.object.isRequired,
onPress: PropTypes.func.isRequired
onPress: PropTypes.func.isRequired,
baseUrl: PropTypes.string.isRequired
}
_onPress = (...args) => {
this.props.onPress(...args);
@ -91,6 +92,7 @@ class RoomsListItem extends React.PureComponent {
<RoomItem
id={item._id}
item={item}
baseUrl={this.props.baseUrl}
/>
</TouchableOpacity>
);
@ -111,6 +113,10 @@ export default class RoomsListView extends React.Component {
constructor(props) {
super(props);
this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server);
const siteUrl = realm.objectForPrimaryKey('settings', 'Site_Url');
if (siteUrl) {
this.url = siteUrl.value;
}
this.state = {
dataSource: ds.cloneWithRows([]),
searching: false,
@ -243,6 +249,7 @@ export default class RoomsListView extends React.Component {
getSubscriptions = () => this.data.sorted('_updatedAt', true)
updateState = debounce(() => {
this.url = realm.objectForPrimaryKey('settings', 'Site_Url').value;
this.setState({
dataSource: ds.cloneWithRows(this.data.filtered('_server.id = $0', this.props.server).sorted('ls', true))
});
@ -309,7 +316,11 @@ export default class RoomsListView extends React.Component {
}
renderItem = ({ item }) => (
<RoomsListItem item={item} onPress={() => this._onPressItem(item._id, item)} />
<RoomsListItem
item={item}
onPress={() => this._onPressItem(item._id, item)}
baseUrl={this.url}
/>
);
renderSeparator = () => (
@ -346,6 +357,7 @@ export default class RoomsListView extends React.Component {
dataSource={this.state.dataSource}
style={styles.list}
renderRow={item => this.renderItem({ item })}
renderHeader={this.renderSearchBar}
enableEmptySections
/>
)
@ -362,7 +374,6 @@ export default class RoomsListView extends React.Component {
return (
<View style={styles.container}>
{this.renderBanner()}
{this.renderSearchBar()}
{this.renderList()}
{this.renderCreateButtons()}
</View>