Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 15 additions & 27 deletions src/account-info/AwayStatusSwitch.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,29 @@
/* @flow strict-local */
import React, { PureComponent } from 'react';
import React from 'react';

import type { Dispatch } from '../types';
import { connect } from '../react-redux';
import { useSelector, useDispatch } from '../react-redux';
import { OptionRow } from '../common';
import { getSelfUserAwayStatus } from '../selectors';
import { updateUserAwayStatus } from '../user-status/userStatusActions';

type Props = $ReadOnly<{|
awayStatus: boolean,
dispatch: Dispatch,
|}>;
type Props = $ReadOnly<{||}>;

/**
* This is a stand-alone component that:
* * retrieves the current user's `user status` data and presents it
* * allows by switching it to control the `away` status
*/
class AwayStatusSwitch extends PureComponent<Props> {
handleUpdateAwayStatus = (away: boolean) => {
const { dispatch } = this.props;
dispatch(updateUserAwayStatus(away));
};
export default function AwayStatusSwitch(props: Props) {
const awayStatus = useSelector(getSelfUserAwayStatus);
const dispatch = useDispatch();

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

return (
<OptionRow
label="Set yourself to away"
value={awayStatus}
onValueChange={this.handleUpdateAwayStatus}
/>
);
}
return (
<OptionRow
label="Set yourself to away"
value={awayStatus}
onValueChange={(away: boolean) => {
dispatch(updateUserAwayStatus(away));
}}
/>
);
}

export default connect(state => ({
awayStatus: getSelfUserAwayStatus(state),
}))(AwayStatusSwitch);
20 changes: 6 additions & 14 deletions src/common/OwnAvatar.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
/* @flow strict-local */
import React, { PureComponent } from 'react';
import React from 'react';

import type { User, Dispatch } from '../types';
import { connect } from '../react-redux';
import { useSelector } from '../react-redux';
import UserAvatar from './UserAvatar';
import { getOwnUser } from '../users/userSelectors';

type Props = $ReadOnly<{|
dispatch: Dispatch,
user: User,
size: number,
|}>;

Expand All @@ -17,13 +14,8 @@ type Props = $ReadOnly<{|
*
* @prop size - Sets width and height in logical pixels.
*/
class OwnAvatar extends PureComponent<Props> {
render() {
const { user, size } = this.props;
return <UserAvatar avatarUrl={user.avatar_url} size={size} />;
}
export default function OwnAvatar(props: Props) {
const { size } = props;
const user = useSelector(getOwnUser);
return <UserAvatar avatarUrl={user.avatar_url} size={size} />;
}

export default connect(state => ({
user: getOwnUser(state),
}))(OwnAvatar);
135 changes: 61 additions & 74 deletions src/unread/UnreadCards.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* @flow strict-local */

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

import type { Dispatch, PmConversationData, UnreadStreamItem } from '../types';
import { connect } from '../react-redux';
import type { UnreadStreamItem } from '../types';
import { useDispatch, useSelector } from '../react-redux';
import { SearchEmptyState } from '../common';
import PmConversationList from '../pm-conversations/PmConversationList';
import StreamItem from '../streams/StreamItem';
Expand All @@ -13,79 +13,66 @@ import { streamNarrow, topicNarrow } from '../utils/narrow';
import { getUnreadConversations, getUnreadStreamsAndTopicsSansMuted } from '../selectors';
import { doNarrow } from '../actions';

type Props = $ReadOnly<{|
conversations: PmConversationData[],
dispatch: Dispatch,
unreadStreamsAndTopics: UnreadStreamItem[],
|}>;
type Props = $ReadOnly<{||}>;

class UnreadCards extends PureComponent<Props> {
handleStreamPress = (stream: string) => {
setTimeout(() => this.props.dispatch(doNarrow(streamNarrow(stream))));
};
export default function UnreadCards(props: Props) {
const dispatch = useDispatch();
const conversations = useSelector(getUnreadConversations);
const unreadStreamsAndTopics = useSelector(getUnreadStreamsAndTopicsSansMuted);
type Card =
| UnreadStreamItem
| { key: 'private', data: Array<React$ElementConfig<typeof PmConversationList>> };
const unreadCards: Array<Card> = [
{
key: 'private',
data: [{ conversations, dispatch }],
},
...unreadStreamsAndTopics,
];

handleTopicPress = (stream: string, topic: string) => {
setTimeout(() => this.props.dispatch(doNarrow(topicNarrow(stream, topic))));
};

render() {
const { conversations, dispatch, unreadStreamsAndTopics } = this.props;
type Card =
| UnreadStreamItem
| { key: 'private', data: Array<React$ElementConfig<typeof PmConversationList>> };
const unreadCards: Array<Card> = [
{
key: 'private',
data: [{ conversations, dispatch }],
},
...unreadStreamsAndTopics,
];

if (unreadStreamsAndTopics.length === 0 && conversations.length === 0) {
return <SearchEmptyState text="No unread messages" />;
}
if (unreadStreamsAndTopics.length === 0 && conversations.length === 0) {
return <SearchEmptyState text="No unread messages" />;
}

return (
/* $FlowFixMe[prop-missing]: SectionList libdef seems confused;
return (
/* $FlowFixMe[prop-missing]: SectionList libdef seems confused;
should take $ReadOnly objects. */
<SectionList
stickySectionHeadersEnabled
initialNumToRender={20}
sections={unreadCards}
keyExtractor={item => item.key}
renderSectionHeader={({ section }) =>
section.key === 'private' ? null : (
<StreamItem
name={section.streamName}
iconSize={16}
isMuted={section.isMuted}
isPrivate={section.isPrivate}
backgroundColor={section.color}
unreadCount={section.unread}
onPress={this.handleStreamPress}
/>
)
}
renderItem={({ item, section }) =>
section.key === 'private' ? (
<PmConversationList {...item} />
) : (
<TopicItem
name={item.topic}
stream={section.streamName || ''}
isMuted={section.isMuted || item.isMuted}
isSelected={false}
unreadCount={item.unread}
onPress={this.handleTopicPress}
/>
)
}
/>
);
}
<SectionList
stickySectionHeadersEnabled
initialNumToRender={20}
sections={unreadCards}
keyExtractor={item => item.key}
renderSectionHeader={({ section }) =>
section.key === 'private' ? null : (
<StreamItem
name={section.streamName}
iconSize={16}
isMuted={section.isMuted}
isPrivate={section.isPrivate}
backgroundColor={section.color}
unreadCount={section.unread}
onPress={(stream: string) => {
setTimeout(() => dispatch(doNarrow(streamNarrow(stream))));
}}
/>
)
}
renderItem={({ item, section }) =>
section.key === 'private' ? (
<PmConversationList {...item} />
) : (
<TopicItem
name={item.topic}
stream={section.streamName || ''}
isMuted={section.isMuted || item.isMuted}
isSelected={false}
unreadCount={item.unread}
onPress={(stream: string, topic: string) => {
setTimeout(() => dispatch(doNarrow(topicNarrow(stream, topic))));
}}
/>
)
}
/>
);
}

export default connect(state => ({
conversations: getUnreadConversations(state),
unreadStreamsAndTopics: getUnreadStreamsAndTopicsSansMuted(state),
}))(UnreadCards);