Skip to content

Commit

Permalink
Merge 9b7a25a into 5764364
Browse files Browse the repository at this point in the history
  • Loading branch information
borisyankov committed Feb 12, 2019
2 parents 5764364 + 9b7a25a commit ebf996f
Show file tree
Hide file tree
Showing 16 changed files with 269 additions and 37 deletions.
18 changes: 2 additions & 16 deletions src/account-info/AccountDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@
import React, { PureComponent } from 'react';
import { View, Dimensions, StyleSheet } from 'react-native';

import type { Dispatch, User } from '../types';
import { Avatar, ComponentList, RawLabel, ZulipButton } from '../common';
import { IconPrivateChat } from '../common/Icons';
import { privateNarrow } from '../utils/narrow';
import type { User } from '../types';
import { Avatar, ComponentList, RawLabel } from '../common';
import PresenceStatusIndicator from '../common/PresenceStatusIndicator';
import ActivityText from '../title/ActivityText';
import { getMediumAvatar } from '../utils/avatar';
import { nowInTimeZone } from '../utils/date';
import { doNarrow } from '../actions';
import styles from '../styles';

const componentStyles = StyleSheet.create({
Expand All @@ -24,16 +21,10 @@ const componentStyles = StyleSheet.create({
});

type Props = {|
dispatch: Dispatch,
user: User,
|};

export default class AccountDetails extends PureComponent<Props, void> {
handleChatPress = () => {
const { user, dispatch } = this.props;
dispatch(doNarrow(privateNarrow(user.email)));
};

render() {
const { user } = this.props;
const screenWidth = Dimensions.get('window').width;
Expand Down Expand Up @@ -63,11 +54,6 @@ export default class AccountDetails extends PureComponent<Props, void> {
/>
</View>
) : null}
<ZulipButton
text="Send private message"
onPress={this.handleChatPress}
Icon={IconPrivateChat}
/>
</ComponentList>
</View>
);
Expand Down
20 changes: 16 additions & 4 deletions src/account-info/AccountDetailsScreen.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
/* @flow */
import { connect } from 'react-redux';

import React, { PureComponent } from 'react';
import { connect } from 'react-redux';

import type { Dispatch, GlobalState, User } from '../types';
import { getAccountDetailsUserFromEmail } from '../selectors';
import { Screen } from '../common';
import { Screen, ZulipButton } from '../common';
import { IconPrivateChat } from '../common/Icons';
import { privateNarrow } from '../utils/narrow';
import AccountDetails from './AccountDetails';
import { doNarrow } from '../actions';

type Props = {|
user: User,
dispatch: Dispatch,
|};

class AccountDetailsScreen extends PureComponent<Props> {
handleChatPress = () => {
const { user, dispatch } = this.props;
dispatch(doNarrow(privateNarrow(user.email)));
};

render() {
const { dispatch, user } = this.props;
const title = {
Expand All @@ -26,7 +33,12 @@ class AccountDetailsScreen extends PureComponent<Props> {

return (
<Screen title={title}>
<AccountDetails dispatch={dispatch} user={user} />
<AccountDetails user={user} />
<ZulipButton
text="Send private message"
onPress={this.handleChatPress}
Icon={IconPrivateChat}
/>
</Screen>
);
}
Expand Down
44 changes: 44 additions & 0 deletions src/account-info/AwayStatusSwitch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* @flow strict-local */
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';

import type { Dispatch, GlobalState, User, UserStatusMapObject } from '../types';
import { OptionRow } from '../common';
import { getSelfUserDetail, getUserStatus } from '../selectors';
import { updateUserAwayStatus } from '../user-status/userStatusActions';

type PropsFromState = {|
selfUserDetail: User,
userStatus: UserStatusMapObject,
|};

type Props = {|
...PropsFromState,
dispatch: Dispatch,
|};

class AwayStatusSwitch extends PureComponent<Props> {
handleUpdateAwayStatus = (away: boolean) => {
const { dispatch } = this.props;
dispatch(updateUserAwayStatus(away));
};

render() {
const { selfUserDetail, userStatus } = this.props;
const selfUserStatus = userStatus[selfUserDetail.user_id];
const away = !!(selfUserStatus && selfUserStatus.away);
console.log(selfUserDetail, userStatus, away);
return (
<OptionRow
label="Show me always as away"
defaultValue={away}
onValueChange={this.handleUpdateAwayStatus}
/>
);
}
}

export default connect((state: GlobalState) => ({
selfUserDetail: getSelfUserDetail(state),
userStatus: getUserStatus(state),
}))(AwayStatusSwitch);
63 changes: 63 additions & 0 deletions src/account-info/ProfileCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* @flow strict-local */
import React, { PureComponent } from 'react';
import { StyleSheet, View } from 'react-native';
import { connect } from 'react-redux';

import type { Dispatch, GlobalState, User } from '../types';
import { getSelfUserDetail } from '../selectors';
import { ZulipButton } from '../common';
import { navigateToUserStatus } from '../actions';
import AccountDetails from './AccountDetails';
import SwitchAccountButton from './SwitchAccountButton';
import LogoutButton from './LogoutButton';
import AwayStatusSwitch from './AwayStatusSwitch';

const componentStyles = StyleSheet.create({
accountButtons: {
alignItems: 'flex-end',
flexDirection: 'row',
marginHorizontal: 8,
},
});

type PropsFromState = {|
selfUserDetail: User,
|};

type Props = {|
...PropsFromState,
dispatch: Dispatch,
|};

class ProfileCard extends PureComponent<Props> {
handleSetUserStatus = () => {
const { dispatch } = this.props;
dispatch(navigateToUserStatus());
};

handleUpdateAwayStatus = () => {};

render() {
const { selfUserDetail } = this.props;

return (
<View>
<AccountDetails user={selfUserDetail} />
<ZulipButton
style={componentStyles.accountButtons}
secondary
text="Set a status"
onPress={this.handleSetUserStatus}
/>
<View style={componentStyles.accountButtons}>
<SwitchAccountButton />
<LogoutButton />
</View>
</View>
);
}
}

export default connect((state: GlobalState, props: PropsFromState) => ({
selfUserDetail: getSelfUserDetail(state),
}))(ProfileCard);
41 changes: 41 additions & 0 deletions src/common/OwnAvatar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* @flow strict-local */
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';

import type { GlobalState, User } from '../types';
import { getCurrentRealm, getSelfUserDetail } from '../selectors';
import ImageAvatar from './ImageAvatar';
import { getAvatarFromUser } from '../utils/avatar';

type Props = {|
user: User,
size: number,
realm: string,
shape: 'square' | 'rounded' | 'circle',
|};

/**
* Renders an image of the current user's avatar
*
* @prop [size] - Sets width and height in pixels.
* @prop [user] - Current presence for this user used to determine status.
* @prop [realm] - Current realm url, used if avatarUrl is relative.
* @prop [shape] - One of 'square', 'rounded', 'circle'.
*/
class OwnAvatar extends PureComponent<Props> {
static defaultProps = {
size: 32,
shape: 'rounded',
};

render() {
const { user, size, realm, shape } = this.props;
const fullAvatarUrl = getAvatarFromUser(user, realm);
return <ImageAvatar avatarUrl={fullAvatarUrl} size={size} shape={shape} />;
}
}

export default connect((state: GlobalState) => ({
realm: getCurrentRealm(state),
user: getSelfUserDetail(state),
}))(OwnAvatar);
1 change: 1 addition & 0 deletions src/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export { default as OfflineNotice } from './OfflineNotice';
export { default as OptionButton } from './OptionButton';
export { default as OptionDivider } from './OptionDivider';
export { default as OptionRow } from './OptionRow';
export { default as OwnAvatar } from './OwnAvatar';
export { default as PasswordInput } from './PasswordInput';
export { default as Popup } from './Popup';
export { default as RawLabel } from './RawLabel';
Expand Down
4 changes: 2 additions & 2 deletions src/lightbox/Lightbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import LightboxHeader from './LightboxHeader';
import LightboxFooter from './LightboxFooter';
import { constructActionSheetButtons, executeActionSheetAction } from './LightboxActionSheet';
import { NAVBAR_SIZE } from '../styles';
import { getGravatarFromEmail } from '../utils/avatar';
import { getAvatarFromMessage } from '../utils/avatar';
import { navigateBack } from '../actions';

const styles = StyleSheet.create({
Expand Down Expand Up @@ -113,7 +113,7 @@ class Lightbox extends PureComponent<Props, State> {
<LightboxHeader
onPressBack={this.handlePressBack}
timestamp={message.timestamp}
avatarUrl={message.avatar_url || getGravatarFromEmail(message.sender_email)}
avatarUrl={getAvatarFromMessage(message)}
senderName={message.sender_full_name}
/>
</SlideAnimationView>
Expand Down
13 changes: 12 additions & 1 deletion src/main/MainTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import HomeTab from './HomeTab';
import StreamTabs from './StreamTabs';
import PmConversationsCard from '../pm-conversations/PmConversationsCard';
import SettingsCard from '../settings/SettingsCard';
import { IconHome, IconStream, IconSettings } from '../common/Icons';
import { IconHome, IconSettings, IconStream } from '../common/Icons';
import { OwnAvatar } from '../common';
import IconUnreadConversations from '../nav/IconUnreadConversations';
import ProfileCard from '../account-info/ProfileCard';

export default TabNavigator(
{
Expand Down Expand Up @@ -50,6 +52,15 @@ export default TabNavigator(
),
},
},
profile: {
screen: ProfileCard,
navigationOptions: {
tabBarLabel: 'Profile',
tabBarIcon: (props: TabNavigationOptionsPropsType) => (
<OwnAvatar size={24} shape="circle" />
),
},
},
},
{
backBehavior: 'none',
Expand Down
2 changes: 2 additions & 0 deletions src/nav/AppNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import WelcomeHelpScreen from '../start/WelcomeHelpScreen';
import WelcomeScreen from '../start/WelcomeScreen';
import EmojiPickerScreen from '../emoji/EmojiPickerScreen';
import LegalScreen from '../settings/LegalScreen';
import UserStatusScreen from '../user-status/UserStatusScreen';

export default StackNavigator(
{
Expand Down Expand Up @@ -68,6 +69,7 @@ export default StackNavigator(
'welcome-help': { screen: WelcomeHelpScreen },
welcome: { screen: WelcomeScreen },
legal: { screen: LegalScreen },
'user-status': { screen: UserStatusScreen },
},
{
initialRouteName: 'main',
Expand Down
3 changes: 3 additions & 0 deletions src/nav/navActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,6 @@ export const navigateToNotifications = (): NavigateAction =>

export const navigateToLegal = (): NavigateAction =>
NavigationActions.navigate({ routeName: 'legal' });

export const navigateToUserStatus = (): NavigateAction =>
NavigationActions.navigate({ routeName: 'user-status' });
56 changes: 56 additions & 0 deletions src/user-status/UserStatusScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* @flow strict-local */
import { connect } from 'react-redux';

import React, { PureComponent } from 'react';
import { StyleSheet } from 'react-native';

import { Input, OptionButton, Screen } from '../common';
import statusSuggestions from './userStatusTextSuggestions';

const styles = StyleSheet.create({
statusTextInput: {
margin: 16,
},
});

type Props = {};

type Status = {
statusText: string,
};

class UserStatusScreen extends PureComponent<Props, Status> {
state = {
statusText: '',
};

handleStatusTextChangeText = (statusText: string) => {
this.setState({
statusText,
});
};

render() {
const { statusText } = this.state;
return (
<Screen title="User status">
<Input
style={styles.statusTextInput}
placeholder="What's your status?"
value={statusText}
onChangeText={this.handleStatusTextChangeText}
/>
{statusSuggestions.map(statusSuggestion => (
<OptionButton
key={statusSuggestion}
label={statusSuggestion}
onPress={() => {
this.handleStatusTextChangeText(statusSuggestion);
}}
/>
))}
</Screen>
);
}
}
export default connect()(UserStatusScreen);
8 changes: 8 additions & 0 deletions src/user-status/userStatusTextSuggestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* @flow strict-local */
export default [
'📅 In a meeting',
'🚌 Commuting',
'🤒 Out sick',
'🌴 Vacationing',
'🏠 Working remotely',
];
2 changes: 1 addition & 1 deletion src/utils/__tests__/avatar-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* @flow strict */
/* @flow strict-local */
import { getMediumAvatar, getGravatarFromEmail } from '../avatar';

// avatarUrl can be converted to retrieve medium sized avatars(mediumAvatarUrl) if and only if
Expand Down

0 comments on commit ebf996f

Please sign in to comment.