Skip to content

Commit c01db96

Browse files
committed
ActionSheet [nfc]: Modify code to use stream_id instead of stream name.
This commit removes stream name as a parameter to functions related to `TopicActionSheet` and instead introduces streamId in its place. Stream ID is a better parameter since it always remains constant. Related: #3918
1 parent 2afa453 commit c01db96

File tree

6 files changed

+97
-73
lines changed

6 files changed

+97
-73
lines changed

src/message/__tests__/messageActionSheet-test.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// @flow strict-local
22
import deepFreeze from 'deep-freeze';
33
import { HOME_NARROW } from '../../utils/narrow';
4-
import { streamNameOfStreamMessage } from '../../utils/recipient';
54

65
import * as eg from '../../__tests__/lib/exampleData';
76
import { constructMessageActionButtons, constructTopicActionButtons } from '../messageActionSheet';
@@ -66,7 +65,7 @@ describe('constructTopicActionButtons', () => {
6665
]);
6766
const buttons = constructTopicActionButtons({
6867
backgroundData: { ...baseBackgroundData, subscriptions, unreadStreams },
69-
stream: 'test stream',
68+
streamId: stream.stream_id,
7069
topic: 'test topic',
7170
});
7271
expect(buttonTitles(buttons)).toContain('Mark topic as read');
@@ -80,65 +79,75 @@ describe('constructTopicActionButtons', () => {
8079
]);
8180
const buttons = constructTopicActionButtons({
8281
backgroundData: { ...baseBackgroundData, subscriptions, unreadStreams },
83-
stream: 'test stream',
82+
streamId: stream.stream_id,
8483
topic: 'read topic',
8584
});
8685
expect(buttonTitles(buttons)).not.toContain('Mark topic as read');
8786
});
8887

8988
test('show Unmute topic option if topic is muted', () => {
9089
const mute = deepFreeze([['electron issues', 'issue #556']]);
90+
const stream = eg.makeStream({ name: 'electron issues' });
91+
const subscriptions = [{ ...eg.subscription, ...stream }];
9192
const buttons = constructTopicActionButtons({
92-
backgroundData: { ...baseBackgroundData, mute },
93-
stream: 'electron issues',
93+
backgroundData: { ...baseBackgroundData, subscriptions, mute },
94+
streamId: stream.stream_id,
9495
topic: 'issue #556',
9596
});
9697
expect(buttonTitles(buttons)).toContain('Unmute topic');
9798
});
9899

99100
test('show mute topic option if topic is not muted', () => {
101+
const stream = eg.makeStream();
102+
const subscriptions = [{ ...eg.subscription, ...stream }];
100103
const buttons = constructTopicActionButtons({
101-
backgroundData: { ...baseBackgroundData, mute: [] },
102-
stream: streamNameOfStreamMessage(eg.streamMessage()),
104+
backgroundData: { ...baseBackgroundData, subscriptions, mute: [] },
105+
streamId: stream.stream_id,
103106
topic: eg.streamMessage().subject,
104107
});
105108
expect(buttonTitles(buttons)).toContain('Mute topic');
106109
});
107110

108111
test('show Unmute stream option if stream is not in home view', () => {
109-
const subscriptions = [{ ...eg.subscription, in_home_view: false }];
112+
const stream = eg.makeStream();
113+
const subscriptions = [{ ...eg.subscription, in_home_view: false, ...stream }];
110114
const buttons = constructTopicActionButtons({
111115
backgroundData: { ...baseBackgroundData, subscriptions },
112-
stream: streamNameOfStreamMessage(eg.streamMessage()),
116+
streamId: stream.stream_id,
113117
topic: eg.streamMessage().subject,
114118
});
115119
expect(buttonTitles(buttons)).toContain('Unmute stream');
116120
});
117121

118122
test('show mute stream option if stream is in home view', () => {
119-
const subscriptions = [{ ...eg.subscription, in_home_view: true }];
123+
const stream = eg.makeStream();
124+
const subscriptions = [{ ...eg.subscription, in_home_view: true, ...stream }];
120125
const buttons = constructTopicActionButtons({
121126
backgroundData: { ...baseBackgroundData, subscriptions },
122-
stream: streamNameOfStreamMessage(eg.streamMessage()),
127+
streamId: stream.stream_id,
123128
topic: eg.streamMessage().subject,
124129
});
125130
expect(buttonTitles(buttons)).toContain('Mute stream');
126131
});
127132

128133
test('show delete topic option if current user is an admin', () => {
134+
const stream = eg.makeStream();
135+
const subscriptions = [{ ...eg.subscription, ...stream }];
129136
const ownUser = { ...eg.selfUser, is_admin: true };
130137
const buttons = constructTopicActionButtons({
131-
backgroundData: { ...baseBackgroundData, ownUser },
132-
stream: streamNameOfStreamMessage(eg.streamMessage()),
138+
backgroundData: { ...baseBackgroundData, ownUser, subscriptions },
139+
streamId: stream.stream_id,
133140
topic: eg.streamMessage().subject,
134141
});
135142
expect(buttonTitles(buttons)).toContain('Delete topic');
136143
});
137144

138145
test('do not show delete topic option if current user is not an admin', () => {
146+
const stream = eg.makeStream();
147+
const subscriptions = [{ ...eg.subscription, ...stream }];
139148
const buttons = constructTopicActionButtons({
140-
backgroundData: baseBackgroundData,
141-
stream: streamNameOfStreamMessage(eg.streamMessage()),
149+
backgroundData: { ...baseBackgroundData, subscriptions },
150+
streamId: stream.stream_id,
142151
topic: eg.streamMessage().subject,
143152
});
144153
expect(buttonTitles(buttons)).not.toContain('Delete topic');

src/message/messageActionSheet.js

Lines changed: 41 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ export type ShowActionSheetWithOptions = (
3838

3939
type TopicArgs = {
4040
auth: Auth,
41-
stream: string,
4241
topic: string,
42+
streamId: number,
4343
subscriptions: Subscription[],
4444
dispatch: Dispatch,
4545
_: GetText,
@@ -119,34 +119,25 @@ const deleteMessage = async ({ auth, message, dispatch }) => {
119119
deleteMessage.title = 'Delete message';
120120
deleteMessage.errorMessage = 'Failed to delete message';
121121

122-
const markTopicAsRead = async ({ auth, stream, topic, subscriptions }) => {
123-
const sub = subscriptions.find(x => x.name === stream);
124-
if (sub) {
125-
await api.markTopicAsRead(auth, sub.stream_id, topic);
126-
}
122+
const markTopicAsRead = async ({ auth, streamId, topic }) => {
123+
await api.markTopicAsRead(auth, streamId, topic);
127124
};
128125
markTopicAsRead.title = 'Mark topic as read';
129126
markTopicAsRead.errorMessage = 'Failed to mark topic as read';
130127

131-
const unmuteTopic = async ({ auth, stream, topic, subscriptions }) => {
132-
const sub = subscriptions.find(x => x.name === stream);
133-
if (sub) {
134-
await api.unmuteTopic(auth, sub.stream_id, topic);
135-
}
128+
const unmuteTopic = async ({ auth, streamId, topic }) => {
129+
await api.unmuteTopic(auth, streamId, topic);
136130
};
137131
unmuteTopic.title = 'Unmute topic';
138132
unmuteTopic.errorMessage = 'Failed to unmute topic';
139133

140-
const muteTopic = async ({ auth, stream, topic, subscriptions }) => {
141-
const sub = subscriptions.find(x => x.name === stream);
142-
if (sub) {
143-
await api.muteTopic(auth, sub.stream_id, topic);
144-
}
134+
const muteTopic = async ({ auth, streamId, topic }) => {
135+
await api.muteTopic(auth, streamId, topic);
145136
};
146137
muteTopic.title = 'Mute topic';
147138
muteTopic.errorMessage = 'Failed to mute topic';
148139

149-
const deleteTopic = async ({ auth, stream, topic, subscriptions, dispatch, _ }) => {
140+
const deleteTopic = async ({ auth, streamId, topic, dispatch, _ }) => {
150141
const alertTitle = _('Are you sure you want to delete the topic “{topic}”?', { topic });
151142
const AsyncAlert = async (): Promise<boolean> =>
152143
new Promise((resolve, reject) => {
@@ -173,38 +164,26 @@ const deleteTopic = async ({ auth, stream, topic, subscriptions, dispatch, _ })
173164
);
174165
});
175166
if (await AsyncAlert()) {
176-
const sub = subscriptions.find(x => x.name === stream);
177-
if (sub) {
178-
await dispatch(deleteMessagesForTopic(sub.stream_id, topic));
179-
}
167+
await dispatch(deleteMessagesForTopic(streamId, topic));
180168
}
181169
};
182170
deleteTopic.title = 'Delete topic';
183171
deleteTopic.errorMessage = 'Failed to delete topic';
184172

185-
const unmuteStream = async ({ auth, stream, subscriptions }) => {
186-
const sub = subscriptions.find(x => x.name === stream);
187-
if (sub) {
188-
await api.toggleMuteStream(auth, sub.stream_id, false);
189-
}
173+
const unmuteStream = async ({ auth, streamId }) => {
174+
await api.toggleMuteStream(auth, streamId, false);
190175
};
191176
unmuteStream.title = 'Unmute stream';
192177
unmuteStream.errorMessage = 'Failed to unmute stream';
193178

194-
const muteStream = async ({ auth, stream, subscriptions }) => {
195-
const sub = subscriptions.find(x => x.name === stream);
196-
if (sub) {
197-
await api.toggleMuteStream(auth, sub.stream_id, true);
198-
}
179+
const muteStream = async ({ auth, streamId }) => {
180+
await api.toggleMuteStream(auth, streamId, true);
199181
};
200182
muteStream.title = 'Mute stream';
201183
muteStream.errorMessage = 'Failed to mute stream';
202184

203-
const showStreamSettings = ({ stream, subscriptions }) => {
204-
const sub = subscriptions.find(x => x.name === stream);
205-
if (sub) {
206-
NavigationService.dispatch(navigateToStream(sub.stream_id));
207-
}
185+
const showStreamSettings = ({ streamId }) => {
186+
NavigationService.dispatch(navigateToStream(streamId));
208187
};
209188
showStreamSettings.title = 'Stream settings';
210189
showStreamSettings.errorMessage = 'Failed to show stream settings';
@@ -247,8 +226,8 @@ cancel.errorMessage = 'Failed to hide menu';
247226

248227
export const constructTopicActionButtons = ({
249228
backgroundData: { mute, subscriptions, ownUser, unreadStreams },
250-
stream,
251229
topic,
230+
streamId,
252231
}: {|
253232
backgroundData: $ReadOnly<{
254233
mute: MuteState,
@@ -257,29 +236,27 @@ export const constructTopicActionButtons = ({
257236
unreadStreams: UnreadStreamsState,
258237
...
259238
}>,
260-
stream: string,
239+
streamId: number,
261240
topic: string,
262241
|}): Button<TopicArgs>[] => {
242+
const sub = subscriptions.find(x => x.stream_id === streamId);
263243
const buttons = [];
264244
if (ownUser.is_admin) {
265245
buttons.push(deleteTopic);
266246
}
267-
if (isTopicMuted(stream, topic, mute)) {
247+
if (sub && isTopicMuted(sub.name, topic, mute)) {
268248
buttons.push(unmuteTopic);
269249
} else {
270250
buttons.push(muteTopic);
271251
}
272-
const sub = subscriptions.find(x => x.name === stream);
273-
if (sub) {
274-
const unreadCount = unreadStreams.get(sub.stream_id)?.get(topic)?.size;
275-
if (unreadCount !== undefined && unreadCount > 0) {
276-
buttons.push(markTopicAsRead);
277-
}
278-
if (!sub.in_home_view) {
279-
buttons.push(unmuteStream);
280-
} else {
281-
buttons.push(muteStream);
282-
}
252+
const unreadCount = unreadStreams.get(streamId)?.get(topic)?.size;
253+
if (unreadCount !== undefined && unreadCount > 0) {
254+
buttons.push(markTopicAsRead);
255+
}
256+
if (sub && !sub.in_home_view) {
257+
buttons.push(unmuteStream);
258+
} else {
259+
buttons.push(muteStream);
283260
}
284261
buttons.push(showStreamSettings);
285262
buttons.push(cancel);
@@ -420,7 +397,7 @@ export const showTopicActionSheet = ({
420397
callbacks,
421398
backgroundData,
422399
topic,
423-
stream,
400+
streamId,
424401
}: {|
425402
showActionSheetWithOptions: ShowActionSheetWithOptions,
426403
callbacks: {|
@@ -436,12 +413,22 @@ export const showTopicActionSheet = ({
436413
unreadStreams: UnreadStreamsState,
437414
...
438415
}>,
439-
stream: string,
416+
streamId: number,
440417
topic: string,
441418
|}): void => {
419+
const sub = backgroundData.subscriptions.find(x => x.stream_id === streamId);
420+
try {
421+
if (!sub) {
422+
throw Error('Stream id does not exist.');
423+
}
424+
} catch (err) {
425+
logging.error(err);
426+
return;
427+
}
428+
const stream = sub.name;
442429
const buttonList = constructTopicActionButtons({
443430
backgroundData,
444-
stream,
431+
streamId,
445432
topic,
446433
});
447434
showActionSheetWithOptions(
@@ -453,7 +440,7 @@ export const showTopicActionSheet = ({
453440
makeButtonCallback(buttonList, {
454441
...backgroundData,
455442
...callbacks,
456-
stream,
443+
streamId,
457444
topic,
458445
}),
459446
);

src/streams/TopicItem.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { TranslationContext } from '../boot/TranslationProvider';
1111
import { useDispatch, useSelector } from '../react-redux';
1212
import { getAuth, getMute, getFlags, getSubscriptions, getOwnUser } from '../selectors';
1313
import { getUnreadStreams } from '../unread/unreadModel';
14+
import { showToast } from '../utils/info';
15+
import * as logging from '../utils/logging';
1416

1517
const componentStyles = createStyleSheet({
1618
selectedRow: {
@@ -52,15 +54,27 @@ export default function TopicItem(props: Props) {
5254
unreadStreams: getUnreadStreams(state),
5355
}));
5456

57+
const subscription = backgroundData.subscriptions.find(x => x.name === stream);
58+
5559
return (
5660
<Touchable
5761
onPress={() => onPress(stream, name)}
5862
onLongPress={() => {
63+
try {
64+
if (!subscription) {
65+
throw Error('Could not find subscription with given stream name.');
66+
}
67+
} catch (err) {
68+
logging.error(err);
69+
showToast(_('Something went wrong.'));
70+
return;
71+
}
72+
5973
showTopicActionSheet({
6074
showActionSheetWithOptions,
6175
callbacks: { dispatch, _ },
6276
backgroundData,
63-
stream,
77+
streamId: subscription.stream_id,
6478
topic: name,
6579
});
6680
}}

src/title/TitleStream.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const TitleStream = (props: Props) => {
8080
showActionSheetWithOptions,
8181
callbacks: { dispatch, _ },
8282
backgroundData,
83-
stream: stream.name,
83+
streamId: stream.stream_id,
8484
topic: topicOfNarrow(narrow),
8585
});
8686
}

src/webview/handleOutboundEvents.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,24 @@ const handleLongPress = (
214214
const { dispatch, showActionSheetWithOptions, backgroundData, narrow, startEditMessage } = props;
215215
if (target === 'header') {
216216
if (message.type === 'stream') {
217+
const stream = streamNameOfStreamMessage(message);
218+
const subscription = backgroundData.subscriptions.find(x => x.name === stream);
219+
220+
try {
221+
if (!subscription) {
222+
throw Error('Could not find subscription with given stream name.');
223+
}
224+
} catch (err) {
225+
logging.error(err);
226+
showToast(_('Something went wrong.'));
227+
return;
228+
}
229+
217230
showTopicActionSheet({
218231
showActionSheetWithOptions,
219232
callbacks: { dispatch, _ },
220233
backgroundData,
221-
stream: streamNameOfStreamMessage(message),
234+
streamId: subscription.stream_id,
222235
topic: message.subject,
223236
});
224237
} else if (message.type === 'private') {

static/translations/messages_en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,5 +232,6 @@
232232
"Signed out": "Signed out",
233233
"Remove account?": "Remove account?",
234234
"This will make the mobile app on this device forget {email} on {realmUrl}.": "This will make the mobile app on this device forget {email} on {realmUrl}.",
235-
"Remove account": "Remove account"
235+
"Remove account": "Remove account",
236+
"Something went wrong.": "Something went wrong."
236237
}

0 commit comments

Comments
 (0)