Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show action sheet on long press of header #801

Merged
merged 2 commits into from
Jul 5, 2017
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
4 changes: 3 additions & 1 deletion src/common/Touchable.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ const background = Platform.Version >= 21 ?

type Props = {
onPress?: () => void | Promise<any>,
onLongPress?: () => void,
style?: StyleObj,
children?: [],
};

export default ({ onPress, style, children }: Props) => (
export default ({ onPress, style, children, onLongPress }: Props) => (
<TouchableNativeFeedback
style={style}
background={background}
onPress={onPress}
onLongPress={onLongPress}
>
<View>
{children}
Expand Down
4 changes: 3 additions & 1 deletion src/common/Touchable.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ import { HIGHLIGHT_COLOR } from '../styles';

type Props = {
onPress?: () => void | Promise<any>,
onLongPress?: () => void,
style?: StyleObj,
children?: [],
};

export default ({ onPress, style, children }: Props) => (
export default ({ onPress, style, children, onLongPress }: Props) => (
<TouchableHighlight
underlayColor={HIGHLIGHT_COLOR}
style={style}
onPress={onPress}
onLongPress={onLongPress}
>
<View>
{children}
Expand Down
41 changes: 29 additions & 12 deletions src/message/MessageList.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { LoadingIndicator } from '../common';
import MessageTyping from '../message/MessageTyping';
import InfiniteScrollView from './InfiniteScrollView';
import renderMessages from './renderMessages';
import { constructActionButtons, executeActionSheetAction } from './messageActionSheet';
import { constructActionButtons, executeActionSheetAction, constructHeaderActionButtons } from './messageActionSheet';

class MessageList extends React.PureComponent {

Expand All @@ -25,22 +25,38 @@ class MessageList extends React.PureComponent {
this.autoScrollToBottom = this.props.caughtUp.newer && nextProps.caughtUp.newer;
}

handleLongPress = (message) => {
const { auth, narrow, subscriptions, mute, flags } = this.props;
const options = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });
const cancelButtonIndex = options.length - 1;
handleHeaderLongPress = (item) => {
const { subscriptions, mute } = this.props;
const options = constructHeaderActionButtons({ item, subscriptions, mute });
const callback = (buttonIndex) => {
executeActionSheetAction({
title: options[buttonIndex],
message: item,
header: true,
...this.props
});
};
this.showActionSheet({ options, cancelButtonIndex: options.length - 1, callback });
}

showActionSheet = ({ options, cancelButtonIndex, callback }) => {
this.props.showActionSheetWithOptions({
options,
cancelButtonIndex,
},
(buttonIndex) => {
executeActionSheetAction({
title: options[buttonIndex],
message,
...this.props
});
}, callback);
}

handleLongPress = (message) => {
const { auth, narrow, subscriptions, mute, flags } = this.props;
const options = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });
const callback = (buttonIndex) => {
executeActionSheetAction({
title: options[buttonIndex],
message,
...this.props
});
};
this.showActionSheet({ options, cancelButtonIndex: options.length - 1, callback });
}

render() {
Expand All @@ -58,6 +74,7 @@ class MessageList extends React.PureComponent {

const messageList = renderMessages({
onLongPress: this.handleLongPress,
onHeaderLongPress: this.handleHeaderLongPress,
...this.props,
});

Expand Down
72 changes: 41 additions & 31 deletions src/message/__tests__/messageActionSheet-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { constructActionButtons } from '../messageActionSheet';
import { constructActionButtons, constructHeaderActionButtons } from '../messageActionSheet';
import {
streamNarrow,
homeNarrow,
Expand All @@ -15,8 +15,8 @@ describe('constructActionButtons', () => {
};

let message = {};
let subscriptions = [];
let mute = [];
const subscriptions = [];
const mute = [];
const narrow = [];
const flags = {
starred: {
Expand Down Expand Up @@ -90,8 +90,38 @@ describe('constructActionButtons', () => {
expect(streamButtons).toContain('Narrow to conversation');
});

test('show Unmute topic option if topic is muted', () => {
test('show star message option if message is not starred', () => {
message = {
id: 3,
};

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });

expect(buttons).toContain('Star Message');
});

test('show unstar message option if message is starred', () => {
message = {
id: 1,
};

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });

expect(buttons).toContain('Unstar Message');
});
});


describe('constructHeaderActionButtons', () => {
let subscriptions = [
{ name: 'denmark', in_home_view: true },
{ name: 'donald', in_home_view: false },
];
let mute = [];
let item = {};

test('show Unmute topic option if topic is muted', () => {
item = {
type: 'stream',
display_recipient: 'electron issues',
subject: 'issue #556'
Expand All @@ -100,25 +130,25 @@ describe('constructActionButtons', () => {
'electron issues', 'issue #556'
]];

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });
const buttons = constructHeaderActionButtons({ item, subscriptions, mute });

expect(buttons).toContain('Unmute topic');
});

test('show mute topic option if topic is not muted', () => {
message = {
item = {
type: 'stream',
display_recipient: 'electron issues',
subject: 'PR #558'
};

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });
const buttons = constructHeaderActionButtons({ item, subscriptions, mute });

expect(buttons).toContain('Mute topic');
});

test('show Unmute stream option if stream is not in home view', () => {
message = {
item = {
type: 'stream',
display_recipient: 'electron issues',
};
Expand All @@ -127,38 +157,18 @@ describe('constructActionButtons', () => {
in_home_view: false,
}];

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });
const buttons = constructHeaderActionButtons({ item, subscriptions, mute });

expect(buttons).toContain('Unmute stream');
});

test('show mute stream option if stream is in home view', () => {
message = {
item = {
type: 'stream',
};

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });
const buttons = constructHeaderActionButtons({ item, subscriptions, mute });

expect(buttons).toContain('Mute stream');
});

test('show star message option if message is not starred', () => {
message = {
id: 3,
};

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });

expect(buttons).toContain('Star Message');
});

test('show unstar message option if message is starred', () => {
message = {
id: 1,
};

const buttons = constructActionButtons({ message, auth, narrow, subscriptions, mute, flags });

expect(buttons).toContain('Unstar Message');
});
});
10 changes: 10 additions & 0 deletions src/message/headers/MessageHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,15 @@ export default class MessageHeader extends React.PureComponent {
narrow: Narrow,
subscriptions: any[],
doNarrow: () => void,
narrow: () => {},
onHeaderLongPress: () => void,
}

onLongPress = () => {
const { item, onHeaderLongPress } = this.props;
onHeaderLongPress(item);
};

render() {
const { item, subscriptions, auth, narrow, doNarrow } = this.props;

Expand All @@ -37,6 +44,7 @@ export default class MessageHeader extends React.PureComponent {
topic={item.subject}
doNarrow={doNarrow}
style={styles.margin}
onLongPress={this.onLongPress}
/>
);
}
Expand All @@ -56,6 +64,7 @@ export default class MessageHeader extends React.PureComponent {
itemId={item.id}
doNarrow={doNarrow}
style={styles.margin}
onLongPress={this.onLongPress}
/>
);
}
Expand All @@ -72,6 +81,7 @@ export default class MessageHeader extends React.PureComponent {
itemId={item.id}
doNarrow={doNarrow}
style={styles.margin}
onLongPress={this.onLongPress}
/>
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/message/headers/PrivateMessageHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default class PrivateMessageHeader extends React.PureComponent {
itemId: number,
recipients: Object[],
doNarrow: () => void,
onLongPress: () => void,
}

performNarrow = () => {
Expand All @@ -45,12 +46,12 @@ export default class PrivateMessageHeader extends React.PureComponent {
}

render() {
const { recipients, style } = this.props;
const { recipients, style, onLongPress } = this.props;
const others = recipients.map(r => r.full_name).sort().join(', ');

return (
<View style={[styles.container, style]}>
<Touchable onPress={this.performNarrow}>
<Touchable onPress={this.performNarrow} onLongPress={onLongPress}>
<View style={styles.header}>
<IconPrivateChat color="white" size={16} style={styles.icon} />
<Text style={styles.private}>
Expand Down
7 changes: 5 additions & 2 deletions src/message/headers/StreamMessageHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default class StreamMessageHeader extends React.PureComponent {
isMuted: boolean,
isPrivate: boolean,
doNarrow: () => void,
onLongPress: () => void,
}

static contextTypes = {
Expand All @@ -59,13 +60,14 @@ export default class StreamMessageHeader extends React.PureComponent {

render() {
const { styles } = this.context;
const { stream, isPrivate, isMuted, topic, color, itemId, doNarrow, style } = this.props;
const { stream, isPrivate, isMuted, topic, color, itemId,
doNarrow, style, onLongPress } = this.props;
const textColor = foregroundColorFromBackground(color);
const iconType = isPrivate ? 'lock' : 'hashtag';

return (
<View style={[componentStyles.header, style, styles.background]}>
<Touchable onPress={this.performStreamNarrow}>
<Touchable onPress={this.performStreamNarrow} onLongPress={onLongPress}>
<View style={[componentStyles.header, { backgroundColor: color }]}>
<StreamIcon
name={iconType}
Expand All @@ -86,6 +88,7 @@ export default class StreamMessageHeader extends React.PureComponent {
stream={stream}
topic={topic}
doNarrow={doNarrow}
onLongPress={onLongPress}
/>
</View>
);
Expand Down
9 changes: 7 additions & 2 deletions src/message/headers/TopicMessageHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default class TopicMessageHeader extends React.PureComponent {
stream: string,
topic: string,
doNarrow: () => void,
onLongPress: () => void,
}

performTopicNarrow = () => {
Expand All @@ -44,11 +45,15 @@ export default class TopicMessageHeader extends React.PureComponent {

render() {
const { styles } = this.context;
const { topic, style } = this.props;
const { topic, style, onLongPress } = this.props;

return (
<View style={[componentStyles.wrapper, styles.background, style]}>
<Touchable style={componentStyles.touch} onPress={this.performTopicNarrow}>
<Touchable
style={componentStyles.touch}
onPress={this.performTopicNarrow}
onLongPress={onLongPress}
>
<Text
style={[componentStyles.topic, styles.color]}
numberOfLines={1}
Expand Down
Loading